Skip to content

Commit d4c3879

Browse files
committedJan 24, 2025·
Include additional core headers conditionally
1 parent 60b1abc commit d4c3879

14 files changed

+310
-215
lines changed
 

‎.github/workflows/opencv-rust.yml

+11-1
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,19 @@ jobs:
6868
- macos-14
6969
vcpkg-version:
7070
- 2025.01.13 # https://github.com/microsoft/vcpkg/releases
71+
vcpkg-features-cache-key:
72+
- full
73+
vcpkg-features:
74+
- contrib,nonfree,ade,opencl
75+
include:
76+
- os-image: windows-2022
77+
vcpkg-version: 2025.01.13
78+
vcpkg-features-cache-key: min
79+
vcpkg-features: contrib
7180
runs-on: ${{ matrix.os-image }}
7281
env:
7382
VCPKG_VERSION: ${{ matrix.vcpkg-version }}
83+
VCPKG_FEATURES: ${{ matrix.vcpkg-features }}
7484
SCCACHE_GHA_ENABLED: "true"
7585
RUSTC_WRAPPER: "sccache"
7686
steps:
@@ -80,7 +90,7 @@ jobs:
8090
- uses: actions/cache@v4
8191
with:
8292
path: ~/build
83-
key: vcpkg-${{ matrix.vcpkg-version }}-${{ matrix.os-image }}
93+
key: vcpkg-${{ matrix.vcpkg-version }}-${{ matrix.os-image }}-${{ matrix.vcpkg-features-cache-key }}
8494

8595
- name: Install dependencies
8696
run: ci/install.sh

‎INSTALL.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Installing OpenCV is easy through the following sources:
5656
* from [vcpkg](https://docs.microsoft.com/en-us/cpp/build/vcpkg), also install `llvm` package,
5757
necessary for building:
5858
```shell script
59-
vcpkg install llvm opencv4[contrib,nonfree,opencl]
59+
vcpkg install llvm opencv4[contrib,nonfree]
6060
```
6161
You most probably want to set environment variable `VCPKGRS_DYNAMIC` to "1" unless you're specifically
6262
targeting a static build.

‎build.rs

+20-70
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
use std::collections::{HashMap, HashSet};
22
use std::env;
33
use std::ffi::OsStr;
4-
use std::fs::File;
5-
use std::io::{BufRead, BufReader};
64
use std::path::{Path, PathBuf};
75
use std::time::Instant;
86

97
use binding_generator::handle_running_binding_generator;
108
use docs::handle_running_in_docsrs;
119
use generator::BindingGenerator;
10+
use header::IncludePath;
1211
use library::Library;
1312
use once_cell::sync::Lazy;
1413
use semver::{Version, VersionReq};
@@ -21,6 +20,8 @@ pub mod cmake_probe;
2120
mod docs;
2221
#[path = "build/generator.rs"]
2322
mod generator;
23+
#[path = "build/header.rs"]
24+
mod header;
2425
#[path = "build/library.rs"]
2526
pub mod library;
2627

@@ -144,6 +145,8 @@ static SUPPORTED_MODULES: [&str; 73] = [
144145
"xstereo",
145146
];
146147

148+
static SUPPORTED_INHERENT_FEATURES: [&str; 2] = ["hfloat", "opencl"];
149+
147150
/// The contents of these vars will be present in the debug log, but will not cause the source rebuild
148151
static DEBUG_ENV_VARS: [&str; 1] = ["PATH"];
149152

@@ -169,64 +172,6 @@ fn files_with_extension<'e>(dir: &Path, extension: impl AsRef<OsStr> + 'e) -> Re
169172
})
170173
}
171174

172-
fn get_module_header_dir(header_dir: &Path) -> Option<PathBuf> {
173-
let mut out = header_dir.join("opencv2.framework/Headers");
174-
if out.exists() {
175-
return Some(out);
176-
}
177-
out = header_dir.join("opencv2");
178-
if out.exists() {
179-
return Some(out);
180-
}
181-
None
182-
}
183-
184-
fn get_version_header(header_dir: &Path) -> Option<PathBuf> {
185-
get_module_header_dir(header_dir)
186-
.map(|dir| dir.join("core/version.hpp"))
187-
.filter(|hdr| hdr.is_file())
188-
}
189-
190-
fn get_version_from_headers(header_dir: &Path) -> Option<Version> {
191-
let version_hpp = get_version_header(header_dir)?;
192-
let mut major = None;
193-
let mut minor = None;
194-
let mut revision = None;
195-
let mut line = String::with_capacity(256);
196-
let mut reader = BufReader::new(File::open(version_hpp).ok()?);
197-
while let Ok(bytes_read) = reader.read_line(&mut line) {
198-
if bytes_read == 0 {
199-
break;
200-
}
201-
if let Some(line) = line.strip_prefix("#define CV_VERSION_") {
202-
let mut parts = line.split_whitespace();
203-
if let (Some(ver_spec), Some(version)) = (parts.next(), parts.next()) {
204-
match ver_spec {
205-
"MAJOR" => {
206-
major = Some(version.parse().ok()?);
207-
}
208-
"MINOR" => {
209-
minor = Some(version.parse().ok()?);
210-
}
211-
"REVISION" => {
212-
revision = Some(version.parse().ok()?);
213-
}
214-
_ => {}
215-
}
216-
}
217-
if major.is_some() && minor.is_some() && revision.is_some() {
218-
break;
219-
}
220-
}
221-
line.clear();
222-
}
223-
if let (Some(major), Some(minor), Some(revision)) = (major, minor, revision) {
224-
Some(Version::new(major, minor, revision))
225-
} else {
226-
None
227-
}
228-
}
229-
230175
fn make_modules_and_alises(
231176
opencv_dir: &Path,
232177
opencv_version: &Version,
@@ -264,13 +209,18 @@ fn make_modules_and_alises(
264209
Ok((modules, aliases))
265210
}
266211

267-
fn emit_inherent_features(opencv_version: &Version) {
212+
fn emit_inherent_features(opencv: &Library) {
268213
if VersionReq::parse(">=4.10")
269214
.expect("Static version requirement")
270-
.matches(opencv_version)
215+
.matches(&opencv.version)
271216
{
272217
println!("cargo::rustc-cfg=ocvrs_has_inherent_feature_hfloat");
273218
}
219+
for feature in &opencv.enabled_features {
220+
if SUPPORTED_INHERENT_FEATURES.contains(&feature.as_str()) {
221+
println!("cargo::rustc-cfg=ocvrs_has_inherent_feature_{feature}");
222+
}
223+
}
274224
}
275225

276226
fn make_compiler(opencv: &Library, ffi_export_suffix: &str) -> cc::Build {
@@ -374,9 +324,7 @@ fn main() -> Result<()> {
374324
for module in SUPPORTED_MODULES {
375325
println!("cargo::rustc-check-cfg=cfg(ocvrs_has_module_{module})");
376326
}
377-
// MSRV: switch to #[expect] when MSRV is 1.81
378-
#[allow(clippy::single_element_loop)]
379-
for inherent_feature in ["hfloat"] {
327+
for inherent_feature in SUPPORTED_INHERENT_FEATURES {
380328
println!("cargo::rustc-check-cfg=cfg(ocvrs_has_inherent_feature_{inherent_feature})");
381329
}
382330

@@ -419,10 +367,10 @@ fn main() -> Result<()> {
419367
let opencv_header_dir = opencv
420368
.include_paths
421369
.iter()
422-
.find(|p| get_version_header(p).is_some())
423-
.expect("Discovered OpenCV include paths is empty or contains non-existent paths");
370+
.find(|p| p.get_version_header().is_some())
371+
.expect("Discovered OpenCV include paths do not contain valid OpenCV headers");
424372

425-
if let Some(header_version) = get_version_from_headers(opencv_header_dir) {
373+
if let Some(header_version) = opencv_header_dir.find_version() {
426374
if header_version != opencv.version {
427375
panic!(
428376
"OpenCV version from the headers: {header_version} (at {}) must match version of the OpenCV library: {} (include paths: {:?})",
@@ -442,7 +390,9 @@ fn main() -> Result<()> {
442390
)
443391
}
444392

445-
let opencv_module_header_dir = get_module_header_dir(opencv_header_dir).expect("Can't find OpenCV module header dir");
393+
let opencv_module_header_dir = opencv_header_dir
394+
.get_module_header_dir()
395+
.expect("Can't find OpenCV module header dir");
446396
eprintln!(
447397
"=== Detected OpenCV module header dir at: {}",
448398
opencv_module_header_dir.display()
@@ -452,7 +402,7 @@ fn main() -> Result<()> {
452402
println!("cargo::rustc-cfg=ocvrs_has_module_{module}");
453403
}
454404

455-
emit_inherent_features(&opencv.version);
405+
emit_inherent_features(&opencv);
456406

457407
setup_rerun()?;
458408

‎build/binding-generator.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use std::path::{Path, PathBuf};
55
use opencv_binding_generator::writer::RustNativeBindingWriter;
66
use opencv_binding_generator::Generator;
77

8-
use super::{get_version_from_headers, GenerateFullBindings, Result};
8+
use super::header::IncludePath;
9+
use super::{GenerateFullBindings, Result};
910

1011
/// Because clang can't be used from multiple threads we run the binding generator helper for each
1112
/// module as a separate process. Building an additional helper binary from the build script is problematic,
@@ -27,7 +28,8 @@ pub fn run(mut args: impl Iterator<Item = OsString>) -> Result<()> {
2728
let out_dir = PathBuf::from(args.next().ok_or("3rd argument must be output dir")?);
2829
let module = args.next().ok_or("4th argument must be module name")?;
2930
let module = module.to_str().ok_or("Not a valid module name")?;
30-
let version = get_version_from_headers(&opencv_header_dir)
31+
let version = opencv_header_dir
32+
.find_version()
3133
.ok_or("Can't find the version in the headers")?
3234
.to_string();
3335
let arg_additional_include_dirs = args.next();

‎build/header.rs

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
use std::fs::File;
2+
use std::io::{BufRead, BufReader};
3+
use std::path::{Path, PathBuf};
4+
use std::process::Command;
5+
6+
use semver::Version;
7+
8+
pub trait IncludePath {
9+
fn get_module_header_dir(&self) -> Option<PathBuf>;
10+
fn get_version_header(&self) -> Option<PathBuf>;
11+
fn get_config_header(&self) -> Option<PathBuf>;
12+
fn find_version(&self) -> Option<Version>;
13+
fn find_enabled_features(&self) -> Option<Vec<String>>;
14+
}
15+
16+
impl IncludePath for Path {
17+
fn get_module_header_dir(&self) -> Option<PathBuf> {
18+
let mut out = self.join("opencv2.framework/Headers");
19+
if out.is_dir() {
20+
return Some(out);
21+
}
22+
out = self.join("opencv2");
23+
if out.is_dir() {
24+
return Some(out);
25+
}
26+
None
27+
}
28+
29+
fn get_version_header(&self) -> Option<PathBuf> {
30+
self
31+
.get_module_header_dir()
32+
.map(|dir| dir.join("core/version.hpp"))
33+
.filter(|hdr| hdr.is_file())
34+
}
35+
36+
fn get_config_header(&self) -> Option<PathBuf> {
37+
self
38+
.get_module_header_dir()
39+
.map(|dir| dir.join("cvconfig.h"))
40+
.filter(|hdr| hdr.is_file())
41+
}
42+
43+
fn find_version(&self) -> Option<Version> {
44+
let version_hpp = self.get_version_header()?;
45+
let mut major = None;
46+
let mut minor = None;
47+
let mut revision = None;
48+
let mut line = String::with_capacity(256);
49+
let mut reader = BufReader::new(File::open(version_hpp).ok()?);
50+
while let Ok(bytes_read) = reader.read_line(&mut line) {
51+
if bytes_read == 0 {
52+
break;
53+
}
54+
if let Some(line) = line.strip_prefix("#define CV_VERSION_") {
55+
let mut parts = line.split_whitespace();
56+
if let (Some(ver_spec), Some(version)) = (parts.next(), parts.next()) {
57+
match ver_spec {
58+
"MAJOR" => {
59+
major = Some(version.parse().ok()?);
60+
}
61+
"MINOR" => {
62+
minor = Some(version.parse().ok()?);
63+
}
64+
"REVISION" => {
65+
revision = Some(version.parse().ok()?);
66+
}
67+
_ => {}
68+
}
69+
}
70+
if major.is_some() && minor.is_some() && revision.is_some() {
71+
break;
72+
}
73+
}
74+
line.clear();
75+
}
76+
if let (Some(major), Some(minor), Some(revision)) = (major, minor, revision) {
77+
Some(Version::new(major, minor, revision))
78+
} else {
79+
None
80+
}
81+
}
82+
83+
fn find_enabled_features(&self) -> Option<Vec<String>> {
84+
let config_h = self.get_config_header()?;
85+
let mut out = Vec::with_capacity(64);
86+
let mut line = String::with_capacity(256);
87+
let mut reader = BufReader::new(File::open(config_h).ok()?);
88+
while let Ok(bytes_read) = reader.read_line(&mut line) {
89+
if bytes_read == 0 {
90+
break;
91+
}
92+
if let Some(feature) = line.strip_prefix("#define HAVE_") {
93+
out.push(feature.trim().to_lowercase());
94+
}
95+
line.clear();
96+
}
97+
Some(out)
98+
}
99+
}
100+
101+
/// Something like `/usr/include/x86_64-linux-gnu/opencv4/` on newer Debian-derived distros
102+
///
103+
/// https://wiki.debian.org/Multiarch/Implementation
104+
pub fn get_multiarch_header_dir() -> Option<PathBuf> {
105+
let try_multiarch = Command::new("dpkg-architecture")
106+
.args(["--query", "DEB_TARGET_MULTIARCH"])
107+
.output()
108+
.inspect_err(|e| eprintln!("=== Failed to get DEB_TARGET_MULTIARCH: {e}"))
109+
.ok()
110+
.or_else(|| {
111+
Command::new("cc")
112+
.arg("-print-multiarch")
113+
.output()
114+
.inspect_err(|e| eprintln!("=== Failed to get -print-multiarch: {e}"))
115+
.ok()
116+
})
117+
.and_then(|output| String::from_utf8(output.stdout).ok())
118+
.map_or_else(
119+
|| {
120+
eprintln!("=== Failed to get DEB_TARGET_MULTIARCH, trying common multiarch paths");
121+
vec![
122+
"x86_64-linux-gnu".to_string(),
123+
"aarch64-linux-gnu".to_string(),
124+
"arm-linux-gnueabihf".to_string(),
125+
]
126+
},
127+
|multiarch| vec![multiarch.trim().to_string()],
128+
);
129+
130+
eprintln!("=== Trying multiarch paths: {try_multiarch:?}");
131+
132+
for multiarch in try_multiarch {
133+
let header_dir = PathBuf::from(format!("/usr/include/{multiarch}/opencv4"));
134+
if header_dir.is_dir() {
135+
return Some(header_dir);
136+
}
137+
}
138+
None
139+
}

‎build/library.rs

+40-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use dunce::canonicalize;
88
use semver::Version;
99

1010
use super::cmake_probe::{CmakeProbe, LinkLib, LinkSearch};
11-
use super::{get_version_from_headers, Result, MANIFEST_DIR, OUT_DIR, TARGET_VENDOR_APPLE};
11+
use super::header::IncludePath;
12+
use super::{header, Result, MANIFEST_DIR, OUT_DIR, TARGET_VENDOR_APPLE};
1213

1314
struct PackageName;
1415

@@ -149,12 +150,25 @@ impl Linkage {
149150
pub struct Library {
150151
pub include_paths: Vec<PathBuf>,
151152
pub version: Version,
153+
pub enabled_features: Vec<String>,
152154
pub cargo_metadata: Vec<String>,
153155
}
154156

155157
impl Library {
158+
fn add_multiarch_dir_if_needed(include_paths: &mut Vec<PathBuf>) {
159+
if include_paths.iter().all(|p| p.get_config_header().is_none()) {
160+
if let Some(multiarch_include_path) = header::get_multiarch_header_dir() {
161+
include_paths.push(multiarch_include_path);
162+
}
163+
}
164+
}
165+
156166
fn version_from_include_paths(include_paths: impl IntoIterator<Item = impl AsRef<Path>>) -> Option<Version> {
157-
include_paths.into_iter().find_map(|x| get_version_from_headers(x.as_ref()))
167+
include_paths.into_iter().find_map(|x| x.as_ref().find_version())
168+
}
169+
170+
fn enabled_features_from_include_paths(include_paths: impl IntoIterator<Item = impl AsRef<Path>>) -> Option<Vec<String>> {
171+
include_paths.into_iter().find_map(|x| x.as_ref().find_enabled_features())
158172
}
159173

160174
fn process_env_var_list<'a, T: From<&'a str>>(env_list: Option<EnvList<'a>>, sys_list: Vec<T>) -> Vec<T> {
@@ -226,16 +240,20 @@ impl Library {
226240
eprintln!("=== link_paths: {link_paths}");
227241
eprintln!("=== link_libs: {link_libs}");
228242
let mut cargo_metadata = Vec::with_capacity(64);
229-
let include_paths: Vec<_> = include_paths.iter().map(PathBuf::from).collect();
243+
let include_paths = include_paths.iter().map(PathBuf::from).collect::<Vec<_>>();
230244

231-
let version = Self::version_from_include_paths(&include_paths).ok_or("Could not OpenCV version from include_paths")?;
245+
let version =
246+
Self::version_from_include_paths(&include_paths).ok_or("Could not get OpenCV version from include_paths")?;
247+
let enabled_features =
248+
Self::enabled_features_from_include_paths(&include_paths).ok_or("Could not get OpenCV config from include_paths")?;
232249

233250
cargo_metadata.extend(Self::process_link_paths(Some(link_paths), vec![]));
234251
cargo_metadata.extend(Self::process_link_libs(Some(link_libs), vec![]));
235252

236253
Ok(Self {
237254
include_paths,
238255
version,
256+
enabled_features,
239257
cargo_metadata,
240258
})
241259
} else {
@@ -302,11 +320,15 @@ impl Library {
302320
));
303321
}
304322

305-
let include_paths = Self::process_env_var_list(include_paths, opencv.include_paths);
323+
let mut include_paths = Self::process_env_var_list(include_paths, opencv.include_paths);
324+
Self::add_multiarch_dir_if_needed(&mut include_paths);
325+
let enabled_features =
326+
Self::enabled_features_from_include_paths(&include_paths).ok_or("Could not get OpenCV config from include_paths")?;
306327

307328
Ok(Self {
308329
include_paths,
309330
version: Version::parse(&opencv.version)?,
331+
enabled_features,
310332
cargo_metadata,
311333
})
312334
}
@@ -355,9 +377,15 @@ impl Library {
355377
cargo_metadata.extend(Self::process_link_paths(link_paths, probe_result.link_paths));
356378
cargo_metadata.extend(Self::process_link_libs(link_libs, probe_result.link_libs));
357379

380+
let mut include_paths = Self::process_env_var_list(include_paths, probe_result.include_paths);
381+
Self::add_multiarch_dir_if_needed(&mut include_paths);
382+
let enabled_features =
383+
Self::enabled_features_from_include_paths(&include_paths).ok_or("Could not get OpenCV config from include_paths")?;
384+
358385
Ok(Self {
359-
include_paths: Self::process_env_var_list(include_paths, probe_result.include_paths),
386+
include_paths,
360387
version: probe_result.version.unwrap_or_else(|| Version::new(0, 0, 0)),
388+
enabled_features,
361389
cargo_metadata,
362390
})
363391
}
@@ -397,8 +425,6 @@ impl Library {
397425

398426
let version = Self::version_from_include_paths(&opencv_include_paths);
399427

400-
let include_paths = Self::process_env_var_list(include_paths, opencv_include_paths);
401-
402428
let mut cargo_metadata = opencv.cargo_metadata;
403429

404430
if link_paths.as_ref().is_some_and(|lp| !lp.is_extend()) {
@@ -411,9 +437,15 @@ impl Library {
411437
}
412438
cargo_metadata.extend(Self::process_link_libs(link_libs, vec![]));
413439

440+
let mut include_paths = Self::process_env_var_list(include_paths, opencv_include_paths);
441+
Self::add_multiarch_dir_if_needed(&mut include_paths);
442+
let enabled_features =
443+
Self::enabled_features_from_include_paths(&include_paths).ok_or("Could not get OpenCV config from include_paths")?;
444+
414445
Ok(Self {
415446
include_paths,
416447
version: version.unwrap_or_else(|| Version::new(0, 0, 0)),
448+
enabled_features,
417449
cargo_metadata,
418450
})
419451
}

‎ci/install-macos-vcpkg.sh

+4-36
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,8 @@
22

33
set -xeu
44

5-
if [[ "${VCPKG_VERSION:-}" == "" ]]; then
6-
echo "Must set VCPKG_VERSION environment var"
7-
exit 1
8-
fi
9-
10-
export VCPKG_ROOT="$HOME/build/vcpkg"
11-
if [[ -e "$VCPKG_ROOT" && ! -e "$VCPKG_ROOT/.git" ]]; then
12-
rm -rf "$VCPKG_ROOT"
13-
fi
14-
if [ ! -e "$VCPKG_ROOT" ]; then
15-
git clone https://github.com/Microsoft/vcpkg.git "$VCPKG_ROOT"
16-
fi
17-
pushd "$VCPKG_ROOT"
18-
git fetch --all --prune --tags
19-
git status
20-
git checkout .
21-
git checkout "$VCPKG_VERSION"
22-
./bootstrap-vcpkg.sh -disableMetrics
23-
#./vcpkg integrate install
24-
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/arm64-osx.cmake
25-
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x64-osx.cmake
265
export VCPKG_DEFAULT_TRIPLET=arm64-osx
27-
(
28-
set +e
29-
which cmake
30-
cmake --version
31-
if ! ./vcpkg install --clean-after-build --recurse "opencv[contrib,nonfree,ade,opencl]"; then
32-
for log in "$VCPKG_ROOT/buildtrees"/**/*out.log; do
33-
echo "=== $log"
34-
cat "$log"
35-
done
36-
exit 1
37-
fi
38-
)
39-
# remove build artifacts to save CI cache space
40-
rm -rf "$VCPKG_ROOT/downloads" "$VCPKG_ROOT/buildtrees" "$VCPKG_ROOT/packages"
41-
popd
6+
7+
script_dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
8+
9+
. "$script_dir/install-vcpkg.sh"

‎ci/install-ubuntu-vcpkg.sh

+4-37
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@
22

33
set -xeu
44

5-
if [[ "${VCPKG_VERSION:-}" == "" ]]; then
6-
echo "Must set VCPKG_VERSION environment var"
7-
exit 1
8-
fi
9-
105
sudo apt-get update
116
sudo apt-get install -y \
127
autoconf \
@@ -38,36 +33,8 @@ sudo apt-get install -y \
3833
unzip \
3934
zip
4035

41-
export VCPKG_ROOT="$HOME/build/vcpkg"
42-
export VCPKG_DISABLE_METRICS=1
43-
if [[ -e "$VCPKG_ROOT" && ! -e "$VCPKG_ROOT/.git" ]]; then
44-
rm -rf "$VCPKG_ROOT"
45-
fi
46-
if [ ! -e "$VCPKG_ROOT" ]; then
47-
git clone https://github.com/Microsoft/vcpkg.git "$VCPKG_ROOT"
48-
fi
49-
pushd "$VCPKG_ROOT"
50-
git fetch --all --prune --tags
51-
git status
52-
git checkout .
53-
git checkout "$VCPKG_VERSION"
54-
./bootstrap-vcpkg.sh -disableMetrics
55-
#./vcpkg integrate install
56-
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x64-linux.cmake
5736
export VCPKG_DEFAULT_TRIPLET=x64-linux
58-
#./vcpkg install llvm # takes very long time
59-
(
60-
set +e
61-
which cmake
62-
cmake --version
63-
if ! ./vcpkg install --clean-after-build --recurse "opencv[contrib,nonfree,ade,opencl]"; then
64-
for log in "$VCPKG_ROOT/buildtrees"/**/*-{out,err}.log; do
65-
echo "=== $log"
66-
cat "$log"
67-
done
68-
exit 1
69-
fi
70-
)
71-
# remove build artifacts to save CI cache space
72-
rm -rf "$VCPKG_ROOT/downloads" "$VCPKG_ROOT/buildtrees" "$VCPKG_ROOT/packages"
73-
popd
37+
38+
script_dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
39+
40+
. "$script_dir/install-vcpkg.sh"

‎ci/install-vcpkg.sh

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/bash
2+
3+
set -xeu
4+
5+
export VCPKG_ROOT="$HOME/build/vcpkg"
6+
export VCPKG_DISABLE_METRICS=1
7+
if [[ -e "$VCPKG_ROOT" && ! -e "$VCPKG_ROOT/.git" ]]; then
8+
rm -rf "$VCPKG_ROOT"
9+
fi
10+
if [ ! -e "$VCPKG_ROOT" ]; then
11+
git clone https://github.com/Microsoft/vcpkg.git "$VCPKG_ROOT"
12+
fi
13+
pushd "$VCPKG_ROOT"
14+
git fetch --all --prune --tags
15+
git status
16+
git checkout .
17+
git checkout "$VCPKG_VERSION"
18+
./bootstrap-vcpkg.sh -disableMetrics
19+
#./vcpkg integrate install
20+
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x64-linux.cmake
21+
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/arm64-osx.cmake
22+
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x64-osx.cmake
23+
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x64-windows.cmake
24+
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x64-windows-static.cmake
25+
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x86-windows.cmake
26+
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/community/x64-windows-static-md.cmake
27+
#./vcpkg install llvm # takes very long time
28+
(
29+
set +e
30+
which cmake
31+
cmake --version
32+
if ! ./vcpkg install --clean-after-build --recurse "opencv4[$VCPKG_FEATURES]"; then
33+
for log in "$VCPKG_ROOT/buildtrees"/**/*-{out,err}.log; do
34+
echo "=== $log"
35+
cat "$log"
36+
done
37+
exit 1
38+
fi
39+
)
40+
# remove build artifacts to save CI cache space
41+
rm -rf "$VCPKG_ROOT/downloads" "$VCPKG_ROOT/buildtrees" "$VCPKG_ROOT/packages"
42+
popd

‎ci/install-windows-vcpkg.sh

+4-38
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,11 @@
22

33
set -xeu
44

5-
# remove system vcpkg
6-
rm -rf "$VCPKG_INSTALLATION_ROOT"
7-
85
# install llvm from choco in place of vcpkg to speed things up
96
choco install -y llvm --version "$CHOCO_LLVM_VERSION"
107

11-
export VCPKG_ROOT="$HOME/build/vcpkg"
12-
export VCPKG_DISABLE_METRICS=1
13-
if [[ -e "$VCPKG_ROOT" && ! -e "$VCPKG_ROOT/.git" ]]; then
14-
rm -rf "$VCPKG_ROOT"
15-
fi
16-
if [ ! -e "$VCPKG_ROOT" ]; then
17-
git clone https://github.com/Microsoft/vcpkg.git "$VCPKG_ROOT"
18-
fi
19-
pushd "$VCPKG_ROOT"
20-
git fetch --all --prune --tags
21-
git status
22-
git checkout .
23-
git checkout "$VCPKG_VERSION"
24-
./bootstrap-vcpkg.sh -disableMetrics
25-
#./vcpkg integrate install
26-
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x64-windows.cmake
27-
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x64-windows-static.cmake
28-
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x86-windows.cmake
29-
echo "set(VCPKG_BUILD_TYPE release)" >> triplets/community/x64-windows-static-md.cmake
308
export VCPKG_DEFAULT_TRIPLET=x64-windows
31-
#./vcpkg install llvm # takes very long time
32-
(
33-
set +e
34-
which cmake
35-
cmake --version
36-
if ! ./vcpkg install --clean-after-build --recurse "opencv[contrib,nonfree,ade,opencl]"; then
37-
for log in "$VCPKG_ROOT/buildtrees"/**/*out.log; do
38-
echo "=== $log"
39-
cat "$log"
40-
done
41-
exit 1
42-
fi
43-
)
44-
# remove build artifacts to save CI cache space
45-
rm -rf "$VCPKG_ROOT/downloads" "$VCPKG_ROOT/buildtrees" "$VCPKG_ROOT/packages"
46-
popd
9+
10+
script_dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
11+
12+
. "$script_dir/install-vcpkg.sh"

‎examples/opencl.rs

+21-12
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
use std::{env, time};
1+
use opencv::Result;
22

3-
use opencv::core::{Device, Size, UMat, Vector};
4-
use opencv::prelude::*;
5-
use opencv::{core, imgcodecs, imgproc, Result};
3+
#[cfg(ocvrs_has_inherent_feature_opencl)]
4+
fn main() -> Result<()> {
5+
use std::{env, time};
66

7-
opencv::not_opencv_branch_34! {
8-
use opencv::core::AccessFlag::ACCESS_READ;
9-
}
10-
opencv::opencv_branch_34! {
11-
use opencv::core::ACCESS_READ;
12-
}
7+
use opencv::core::{Device, Size, UMat, Vector};
8+
use opencv::prelude::*;
9+
use opencv::{core, imgcodecs, imgproc};
1310

14-
const ITERATIONS: usize = 100;
11+
opencv::not_opencv_branch_34! {
12+
use opencv::core::AccessFlag::ACCESS_READ;
13+
}
14+
opencv::opencv_branch_34! {
15+
use opencv::core::ACCESS_READ;
16+
}
1517

16-
fn main() -> Result<()> {
18+
const ITERATIONS: usize = 100;
1719
let img_file = env::args().nth(1).expect("Please supply image file name");
1820
let opencl_have = core::have_opencl()?;
1921
if opencl_have {
@@ -74,3 +76,10 @@ fn main() -> Result<()> {
7476
}
7577
Ok(())
7678
}
79+
80+
#[cfg(not(ocvrs_has_inherent_feature_opencl))]
81+
fn main() -> Result<()> {
82+
eprintln!("This example requires that OpenCV is build with OpenCL support:");
83+
eprintln!("{}", opencv::core::get_build_information()?);
84+
Ok(())
85+
}

‎src_cpp/core.hpp

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
#include "ocvrs_common.hpp"
22
#include <opencv2/core/affine.hpp>
3-
#include <opencv2/core/directx.hpp>
4-
#include <opencv2/core/ocl.hpp>
5-
#include <opencv2/core/va_intel.hpp>
3+
#ifdef HAVE_OPENCL
4+
#include <opencv2/core/ocl.hpp>
5+
// opengl.hpp, va_intel.hpp and directx.hpp unconditionally include ocl.hpp thus it needs to be within ifdef HAVE_OPENCL
6+
#ifdef HAVE_OPENGL
7+
#include <opencv2/core/opengl.hpp>
8+
#endif
9+
#include <opencv2/core/va_intel.hpp>
10+
#include <opencv2/core/directx.hpp>
11+
#endif
612
#include <opencv2/core/cuda.hpp>
7-
#include <opencv2/core/opengl.hpp>
8-
#include <opencv2/core/directx.hpp>
913
#if (CV_VERSION_MAJOR == 3 && CV_VERSION_MINOR == 4 && CV_VERSION_REVISION >= 4) /* 3.4.4+ */ \
1014
|| (CV_VERSION_MAJOR == 4) /* 4.0+ */ \
1115
|| (CV_VERSION_MAJOR == 5) /* 5.0+ */

‎src_cpp/ocvrs_common.hpp

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#ifndef __OCVRS_COMMON_HPP__
22
#define __OCVRS_COMMON_HPP__
33

4-
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) \
5-
|| defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
6-
#define OCVRS_TARGET_OS_WINDOWS
7-
#endif
4+
#include <memory>
5+
#include <opencv2/cvconfig.h>
6+
// defining HAVE_VA starts to rely on <va/va.h> for VADisplay and VASurfaceID instead of OpenCV stubs, and we stop generating
7+
// bindings for the functions that use them
8+
#undef HAVE_VA
89

910
#define CV_COLLECT_IMPL_DATA
1011
#ifdef OCVRS_PARSING_HEADERS
@@ -15,9 +16,13 @@
1516
#define OCVRS_FFI_EXPORT_SUFFIX
1617
#endif
1718

18-
#include <memory>
1919
#include <opencv2/core.hpp>
2020

21+
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) \
22+
|| defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
23+
#define OCVRS_TARGET_OS_WINDOWS
24+
#endif
25+
2126
#define OCVRS_ONLY_DEPENDENT_TYPES
2227

2328
#define OCVRS_HANDLE(code, msg, return_name) Err(code, msg, return_name)

‎tests/opencl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use opencv::{core, Result};
22

33
#[test]
44
fn convert_type_str() -> Result<()> {
5+
#[cfg(ocvrs_has_inherent_feature_opencl)]
56
if core::have_opencl()? {
67
// this function writes to buf argument and returns it
78
let mut test = "test".to_string();

0 commit comments

Comments
 (0)
Please sign in to comment.