enable building on windows and osx
MODIFY
.travis.yml
.travis.yml
-language: rust
-rust:
- - stable
- - beta
- - nightly
+os:
+ - linux
+ - windows
+ - osx
+
+sudo: true
+dist: bionic
+osx_image: xcode11.2
cache:
timeout: 600
- cargo: true
- ccache: true
+ cargo: false
directories:
- $HOME/build/opencv
-sudo: true
-dist: bionic
+language: rust
+rust:
+ - stable
+ - beta
+# - nightly
+
+matrix:
+ allow_failures:
+ - rust: nightly
+ fast_finish: true
+ include:
+ - os: linux
+ env: OPENCV_VERSION=3.2.0 OPENCV_PKGCONFIG=opencv CARGO_FEATURES=opencv-32
+ rust: stable
+
+env:
+ global:
+ - Atlas_ROOT_DIR=/usr/include/ # for cmake to find lapacke.h
+ - LC_CTYPE=C.UTF-8 # makes python3 locale.getpreferredencoding() return utf8 encoding instead of ansi
+ matrix:
+ - OPENCV_VERSION=3.4.7 OPENCV_PKGCONFIG=opencv CARGO_FEATURES=opencv-34
+ - OPENCV_VERSION=4.1.1 OPENCV_PKGCONFIG=opencv4 CARGO_FEATURES=opencv-41
addons:
apt:
@@ -50,24 +72,8 @@ addons:
- qtbase5-dev
- tree
-env:
- global:
- - Atlas_ROOT_DIR=/usr/include/ # for cmake to find lapacke.h
- - LC_CTYPE=C.UTF-8 # makes python3 locale.getpreferredencoding() return utf8 encoding instead of ansi
- matrix:
- - OPENCV_VERSION=3.2.0 OPENCV_PKGCONFIG=opencv CARGO_FEATURES=opencv-32
- - OPENCV_VERSION=3.4.7 OPENCV_PKGCONFIG=opencv CARGO_FEATURES=opencv-34
- - OPENCV_VERSION=4.1.1 OPENCV_PKGCONFIG=opencv4 CARGO_FEATURES=opencv-41
-
-before_script:
- - ci/bionic-install-opencv.sh
- - pkg-config --cflags $OPENCV_PKGCONFIG
- - pkg-config --libs $OPENCV_PKGCONFIG
+install:
+ - ci/install.sh
script:
- - cargo test --verbose --no-default-features --features $CARGO_FEATURES
-
-matrix:
- allow_failures:
- - rust: nightly
- fast_finish: true
+ - ci/script.sh

MODIFY
Cargo.toml
Cargo.toml
@@ -31,6 +31,7 @@ glob_crate = {package = "glob", version = "0.3"}
once_cell = "1.0"
pkg-config = "0.3"
rayon = "1.0"
+regex = "1.0"
semver = "0.9"
which_crate = {package = "which", version = "3.0", default-features = false}

MODIFY
README.md
README.md
@@ -59,8 +59,18 @@ Generally you should use the latest stable rustc to compile this crate.
### Platform support
-Currently development and testing of the crate is only performed on Linux, please feel
-free to submit support for other platforms.
+Currently the main development and testing of the crate is performed on Linux, but other
+major platforms are also supported: Mac OS X and Windows.
+
+Support for Windows is a bit tricky at the moment: you will need to set up `OPENCV_LINK_LIBS`,
+`OPENCV_LINK_PATHS`, `OPENCV_INCLUDE_PATHS` and potentially `OPENCV_PYTHON3_BIN` environment
+variables. Then build the crate with `buildtime-bindgen` feature enabled. If you get linking
+errors try also building with `--release` flag.
+
+Mac OS X build currently also requires `buildtime-bindgen` feature enabled.
+
+Also refer to the corresponding [issue](https://github.com/twistedfall/opencv-rust/issues/6)
+and Travis [build script] (https://github.com/twistedfall/opencv-rust/blob/master/ci/script.sh).
### Features
* `opencv-32` - build against OpenCV 3.2.0, this feature is aimed primarily on stable Debian and
@@ -143,8 +153,7 @@ Path specified by `LD_LIBRARY_PATH` must contain `libopencv_*.so` files.
During crate build it uses opencv headers supplied inside the crate for binding generation.
If you want to use your own (system) headers supply `OPENCV_HEADER_DIR` environment variable.
The directory in that environment variable should contain `opencv2` dir, e.g. `/usr/include` for
- OpenCV-3.4.x or `/usr/include/opencv4` for OpenCV-4.x. Please be sure to match the supplied
- header version with the crate version features (opencv-34, opencv-41, etc.).
+ OpenCV-3.4.x or `/usr/include/opencv4` for OpenCV-4.x.
* `OPENCV_PKGCONFIG_NAME`
In some cases you might want to override the pkgconfig package name, you can use `OPENCV_PKGCONFIG_NAME`
@@ -156,6 +165,23 @@ Path specified by `LD_LIBRARY_PATH` must contain `libopencv_*.so` files.
autodiscovered, but you can use `OPENCV_PYTHON3_BIN` to specify the full path to the binary to
invoke. E.g. "/usr/bin/python3" or "C:\Python37\python.exe"
+The following variables must be set when building without `pkg_config` (e.g. on Windows msvc target):
+
+* `OPENCV_LINK_LIBS`
+ Comma separated list of library names to link to. `.lib`, `.so` or `.dylib` extension is optional.
+ E.g. "opencv_world411".
+
+* `OPENCV_LINK_PATHS`
+ Comma separated list of paths to search for libraries to link. E.g. "C:\tools\opencv\build\x64\vc14\lib".
+
+* `OPENCV_INCLUDE_PATHS`
+ Comma separated list of paths to search for system include files during compilation. E.g.
+ "C:\tools\opencv\build\include". One of the directories specified therein must contain
+ "opencv2/core/version.hpp" file, it's used to detect the version of the headers.
+
+You can also set them on other platforms, then `pkg_config` usage will be disabled and the set values will
+be used.
+
### Compiling OpenCV
See the [upstream

MODIFY
build.rs
build.rs
@@ -12,6 +12,7 @@ use std::{
use once_cell::sync::OnceCell;
use rayon::prelude::*;
+use regex::Regex;
use semver::{Version, VersionReq};
use glob_crate::glob;
@@ -22,6 +23,136 @@ type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
static CORE_MODULES: OnceCell<HashSet<&'static str>> = OnceCell::new();
static MODULES: OnceCell<Vec<(String, Vec<PathBuf>)>> = OnceCell::new();
+#[derive(Debug)]
+struct Library {
+ pub pkg_name: String,
+ pub libs: Vec<String>,
+ pub link_paths: Vec<PathBuf>,
+ pub framework_paths: Vec<PathBuf>,
+ pub include_paths: Vec<PathBuf>,
+ pub version: String,
+ pub prefix: PathBuf,
+ pub libdir: PathBuf,
+}
+
+impl Library {
+ fn probe_from_paths(pkg_name: &str, link_libs: &str, link_paths: &str, include_paths: &str) -> Result<Self> {
+ let libs: Vec<_> = link_libs.split(',')
+ .map(|x| {
+ let mut path = PathBuf::from(x.trim());
+ if path.extension().map(|e| e == "lib" || e == "so" || e == "dylib").unwrap_or(false) {
+ path.set_extension("");
+ }
+ let out = path.file_name().and_then(|f| f.to_str()).expect("Invalid library name").to_owned();
+ if cfg!(target_env = "msvc") {
+ println!("cargo:rustc-link-lib=static={}", out);
+ } else {
+ println!("cargo:rustc-link-lib={}", out);
+ }
+ out
+ })
+ .collect();
+
+ let link_paths: Vec<_> = link_paths
+ .split(',')
+ .map(|x| {
+ let out = PathBuf::from(x.trim());
+ println!("cargo:rustc-link-search=native={}", out.to_str().expect("Invalid link path"));
+ out
+ })
+ .collect();
+
+ let libdir = link_paths
+ .first()
+ .map(|x| x.clone())
+ .unwrap_or_else(|| PathBuf::from(""));
+
+ let include_paths: Vec<_> = include_paths
+ .split(',')
+ .map(|x| PathBuf::from(x.trim()))
+ .collect();
+
+ let version = include_paths.iter()
+ .filter_map(get_version_from_headers)
+ .next();
+ let out = Self {
+ pkg_name: pkg_name.to_owned(),
+ libs,
+ link_paths,
+ framework_paths: vec![],
+ include_paths,
+ version: version.unwrap_or("0.0.0".to_owned()),
+ prefix: PathBuf::from(""),
+ libdir
+ };
+ Ok(out)
+ }
+
+ fn probe_pkg_config(pkg_name: &str) -> Result<Self> {
+ let opencv = pkg_config::probe_library(pkg_name)?;
+ Ok(Self {
+ pkg_name: pkg_name.to_owned(),
+ libs: opencv.libs,
+ link_paths: opencv.link_paths,
+ framework_paths: opencv.framework_paths,
+ include_paths: opencv.include_paths,
+ version: opencv.version,
+ prefix: PathBuf::from(pkg_config::get_variable(pkg_name, "prefix")?),
+ libdir: PathBuf::from(pkg_config::get_variable(pkg_name, "libdir")?),
+ })
+ }
+
+
+ pub fn probe(pkg_name: &str) -> Result<Self> {
+ if let (Ok(link_libs), Ok(link_paths), Ok(include_paths)) = (env::var("OPENCV_LINK_LIBS"), env::var("OPENCV_LINK_PATHS"), env::var("OPENCV_INCLUDE_PATHS")) {
+ Self::probe_from_paths(pkg_name, &link_libs, &link_paths, &include_paths)
+ } else {
+ Self::probe_pkg_config(pkg_name)
+ }
+ }
+
+ pub fn update_compiler(&self, cc: &mut cc::Build) -> Result<Vec<OsString>> {
+ for p in &self.include_paths {
+ cc.include(p);
+ }
+ let mut extra_args: Vec<OsString> = Vec::with_capacity(60);
+ let third_party_dirs = if cfg!(feature = "force-3rd-party-libs-discovery") {
+ // add 3rdparty lib dir. pkgconfig forgets it somehow.
+ self.get_3rdparty_lib_dirs()
+ } else {
+ vec![]
+ };
+ let link_paths = self.link_paths.iter().chain(third_party_dirs.iter());
+ if cfg!(target_env = "msvc") {
+ for l in &self.libs {
+ extra_args.push(format!("{}.lib", l).into());
+ }
+ extra_args.push("-link".into());
+ for p in link_paths {
+ extra_args.push(format!("-LIBPATH:{}", p.to_string_lossy()).into());
+ }
+ } else {
+ for p in link_paths {
+ extra_args.push("-L".into());
+ extra_args.push(p.into());
+ }
+ for f in &self.framework_paths {
+ extra_args.push("-F".into());
+ extra_args.push(f.into());
+ }
+ for l in &self.libs {
+ extra_args.push("-l".into());
+ extra_args.push(l.into());
+ }
+ }
+ Ok(extra_args)
+ }
+
+ pub fn get_3rdparty_lib_dirs(&self) -> Vec<PathBuf> {
+ vec![self.prefix.join("share/OpenCV/3rdparty/lib"), self.libdir.join(&format!("{}/3rdparty", self.pkg_name))]
+ }
+}
+
trait CompilerFlagSetter {
fn flag_if_supported(&mut self, flag: &str) -> &mut Self;
}
@@ -45,6 +176,43 @@ fn set_compiler_flags<T: CompilerFlagSetter>(cc: &mut T) {
.flag_if_supported("-Wno-class-memaccess")
.flag_if_supported("-Wno-deprecated-declarations")
.flag_if_supported("-Wno-ignored-qualifiers");
+ if cfg!(target_env = "msvc") {
+ cc.flag_if_supported("-wd4996")
+ .flag_if_supported("-EHsc");
+ }
+}
+
+fn get_version_from_headers(header_dir: &PathBuf) -> Option<String> {
+ let version_hpp = header_dir.join("opencv2/core/version.hpp");
+ if !version_hpp.is_file() {
+ return None;
+ }
+ let version_header = fs::read_to_string(version_hpp).ok()?;
+ let get_version_part = |def| {
+ Regex::new(&format!(r"#define\s+CV_VERSION_{}\s+(\d+)", def)).ok()
+ .map(|r| {
+ r.captures(&version_header)
+ .and_then(|c| c.get(1))
+ .map(|m| m.as_str())
+ .unwrap_or("0")
+ })
+ };
+ let major = get_version_part("MAJOR")?;
+ let minor = get_version_part("MINOR")?;
+ let revision = get_version_part("REVISION")?;
+ Some(format!("{}.{}.{}", major, minor, revision))
+}
+
+fn check_matching_version(version: &str) -> Result<()> {
+ if cfg!(feature = "opencv-32") && !VersionReq::parse("~3.2")?.matches(&Version::parse(version)?) {
+ Err(format!("OpenCV version: {} must be from 3.2 branch because of the feature: opencv-32", version).into())
+ } else if cfg!(feature = "opencv-34") && !VersionReq::parse("~3.4")?.matches(&Version::parse(version)?) {
+ Err(format!("OpenCV version: {} must be from 3.4 branch because of the feature: opencv-34", version).into())
+ } else if cfg!(feature = "opencv-41") && !VersionReq::parse("~4.1")?.matches(&Version::parse(version)?) {
+ Err(format!("OpenCV version: {} must be from 4.1 branch because of the feature: opencv-41", version).into())
+ } else {
+ Ok(())
+ }
}
fn get_versioned_hub_dir() -> PathBuf {
@@ -215,78 +383,58 @@ fn copy_indent(mut read: impl BufRead, mut write: impl Write, level: usize, inde
Ok(())
}
-fn build_pkg_config_args((opencv, pkg_name): (&pkg_config::Library, &str)) -> Vec<String> {
- let mut out = Vec::with_capacity(60);
- out.extend(opencv.link_paths.iter().map(|x| format!("-L{}", x.to_string_lossy())));
- if let Ok(prefix) = pkg_config::get_variable(pkg_name, "prefix") {
- out.push(format!("-L{}/share/OpenCV/3rdparty/lib", prefix))
- }
- if let Ok(libdir) = pkg_config::get_variable(pkg_name, "libdir") {
- out.push(format!("-L{}/{}/3rdparty", libdir, pkg_name));
- }
- out.extend(opencv.framework_paths.iter().map(|x| format!("-F{}", x.to_string_lossy())));
- out.extend(opencv.include_paths.iter().map(|x| format!("-I{}", x.to_string_lossy())));
- out.extend(opencv.libs.iter().map(|x| format!("-l{}", x)));
- out
-}
-
fn build_compiler(opencv_header_dir: &PathBuf) -> cc::Build {
let out_dir = PathBuf::from(env::var_os("OUT_DIR").expect("Can't read OUT_DIR env var"));
let mut out = cc::Build::new();
set_compiler_flags(&mut out);
out.cpp(true)
- .flag("-std=c++11")
.include(opencv_header_dir)
.include(&out_dir)
.include(".");
+ if !cfg!(target_env = "msvc") {
+ out.flag("-std=c++11");
+ }
out
}
-fn link_wrapper() -> Result<(pkg_config::Library, String)> {
- let (opencv, pkg_name) = if cfg!(feature = "opencv-32") || cfg!(feature = "opencv-34") {
- let pkg_name = env::var("OPENCV_PKGCONFIG_NAME").map(|x| Cow::Owned(x)).unwrap_or_else(|_| Cow::Borrowed("opencv"));
- let opencv = pkg_config::probe_library(&pkg_name).expect(&format!("package {} is not found by pkg-config", pkg_name));
- if cfg!(feature = "opencv-32") && !VersionReq::parse("~3.2")?.matches(&Version::parse(&opencv.version)?) {
- panic!("OpenCV version from pkg-config: {} must be from 3.2 branch because of the feature: opencv-32", opencv.version);
- }
- if cfg!(feature = "opencv-34") && !VersionReq::parse("~3.4")?.matches(&Version::parse(&opencv.version)?) {
- panic!("OpenCV version from pkg-config: {} must be from 3.4 branch because of the feature: opencv-34", opencv.version);
- }
- (opencv, pkg_name)
+fn link_wrapper() -> Result<Library> {
+ let pkg_name = if cfg!(feature = "opencv-32") || cfg!(feature = "opencv-34") {
+ env::var("OPENCV_PKGCONFIG_NAME").map(|x| Cow::Owned(x)).unwrap_or_else(|_| Cow::Borrowed("opencv"))
} else if cfg!(feature = "opencv-41") {
- let pkg_name = env::var("OPENCV_PKGCONFIG_NAME").map(|x| Cow::Owned(x)).unwrap_or_else(|_| Cow::Borrowed("opencv4"));
- let opencv = pkg_config::probe_library(&pkg_name).expect(&format!("package {} is not found by pkg-config", pkg_name));
- if !VersionReq::parse("~4.1")?.matches(&Version::parse(&opencv.version)?) {
- panic!("OpenCV version from pkg-config: {} must be from 4.1 branch because of the feature: opencv-41", opencv.version);
- }
- (opencv, pkg_name)
+ env::var("OPENCV_PKGCONFIG_NAME").map(|x| Cow::Owned(x)).unwrap_or_else(|_| Cow::Borrowed("opencv4"))
} else {
unreachable!("Feature flags should have been checked in main()");
};
+ let opencv = Library::probe(&pkg_name).expect(&format!("Package {} is not found", pkg_name));
+ check_matching_version(&opencv.version).map_err(|e| format!("{}, (version coming from pkg_config for package: {})", e, opencv.pkg_name))?;
- eprintln!("=== Using OpenCV library version: {} from: {}", opencv.version, pkg_config::get_variable(&pkg_name, "libdir")?);
+ eprintln!("=== Using OpenCV library version: {} from: {}", opencv.version, opencv.libdir.display());
// fixme: I wonder whether that kind of forced discovery is needed at all now
// It sure messes with cross-building when a lib is present in host, but not in target platform
// So for now let's hide it behind a non-default feature and check the breakage reports
if cfg!(feature = "force-3rd-party-libs-discovery") {
+ let mut third_party_dirs = opencv.get_3rdparty_lib_dirs();
// add 3rdparty lib dir. pkgconfig forgets it somehow.
- let third_party_dir1 = format!("{}/share/OpenCV/3rdparty/lib", pkg_config::get_variable(&pkg_name, "prefix")?);
- println!("cargo:rustc-link-search=native={}", third_party_dir1);
- let third_party_dir2 = format!("{}/{}/3rdparty", pkg_config::get_variable(&pkg_name, "libdir")?, pkg_name);
- println!("cargo:rustc-link-search=native={}", third_party_dir2);
- let third_party_dirs: [&str; 2] = [&third_party_dir1, &third_party_dir2];
+ third_party_dirs.iter().for_each(|p| println!("cargo:rustc-link-search=native={}", p.to_string_lossy()));
+ third_party_dirs.extend(vec![
+ PathBuf::from("/usr/lib"),
+ PathBuf::from("/usr/lib64"),
+ PathBuf::from("/usr/local/lib"),
+ PathBuf::from("/usr/local/lib64"),
+ PathBuf::from("/usr/lib/x86_64-linux-gnu/"),
+ ]);
// now, this is a nightmare.
// opencv will embark these as .a when they are not available, or
// use the one from the system
// and some may appear in one or more variant (-llibtiff or -ltiff, depending on the system)
- fn lookup_lib(third_party_dirs: &[&str], search: &str) {
+ fn lookup_lib(third_party_dirs: &[PathBuf], search: &str) {
for &prefix in &["lib", "liblib"] {
- for &path in third_party_dirs.iter().chain(&["/usr/lib", "/usr/lib64", "/usr/local/lib", "/usr/local/lib64", "/usr/lib/x86_64-linux-gnu/"]) {
+ for path in third_party_dirs.iter() {
for &ext in &[".a", ".dylib", ".so"] {
let name = format!("{}{}", prefix, search);
- let filename = PathBuf::from(format!("{}/{}{}", path, name, ext));
+ let filename = path.join(format!("{}{}", name, ext));
if filename.exists() {
println!("cargo:rustc-link-lib={}", &name[3..]);
return;
@@ -314,14 +462,17 @@ fn link_wrapper() -> Result<(pkg_config::Library, String)> {
third_party_deps.iter().for_each(|&x| lookup_lib(&third_party_dirs, x));
}
- Ok((opencv, pkg_name.into_owned()))
+ Ok(opencv)
}
fn build_wrapper(opencv_header_dir: &PathBuf) -> Result<()> {
println!("cargo:rerun-if-changed=hdr_parser.py");
println!("cargo:rerun-if-changed=gen_rust.py");
- println!("cargo:rerun-if-env-changed=OPENCV_PKGCONFIG_NAME");
println!("cargo:rerun-if-env-changed=OPENCV_HEADER_DIR");
+ println!("cargo:rerun-if-env-changed=OPENCV_PKGCONFIG_NAME");
+ println!("cargo:rerun-if-env-changed=OPENCV_LINK_LIBS");
+ println!("cargo:rerun-if-env-changed=OPENCV_LINK_PATHS");
+ println!("cargo:rerun-if-env-changed=OPENCV_INCLUDE_PATHS");
let out_dir = PathBuf::from(env::var_os("OUT_DIR").ok_or_else(|| "Can't read OUT_DIR env var")?);
let out_dir_as_str = out_dir.to_str().unwrap();
@@ -456,7 +607,7 @@ fn install_wrapper() -> Result<()> {
Ok(())
}
-fn gen_wrapper((opencv, pkg_name): (&pkg_config::Library, &str), opencv_header_dir: &PathBuf) -> Result<()> {
+fn gen_wrapper(opencv: &Library, opencv_header_dir: &PathBuf) -> Result<()> {
let out_dir = PathBuf::from(env::var_os("OUT_DIR").ok_or_else(|| "Can't read OUT_DIR env var")?);
let out_dir_as_str = out_dir.to_str().unwrap();
let src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").ok_or_else(|| "Can't read CARGO_MANIFEST_DIR env var")?).join("src");
@@ -467,25 +618,25 @@ fn gen_wrapper((opencv, pkg_name): (&pkg_config::Library, &str), opencv_header_d
eprintln!("=== Placing generated bindings into: {}", hub_dir.display());
- let compiler = build_compiler(opencv_header_dir).get_compiler();
- let pkg_config_args = build_pkg_config_args((opencv, pkg_name));
+ let mut compiler = build_compiler(opencv_header_dir);
+ let extra_args = opencv.update_compiler(&mut compiler)?;
let modules = get_modules(&opencv_dir.to_string_lossy())?;
modules.par_iter().for_each(|(module, ..)| {
let consts_cpp = out_dir.join(format!("{}.consts.cpp", module));
if consts_cpp.is_file() {
- let e = compiler.to_command()
+ let consts_bin = out_dir.join(format!("{}.consts{}", module, if cfg!(target_env = "msvc") { ".exe" } else { "" }));
+ let mut command = compiler.get_compiler().to_command();
+ command
.current_dir(&out_dir)
- .args(&[
- format!("{}.consts.cpp", module),
- "-o".into(),
- format!("{}.consts", module)
- ])
- .args(&pkg_config_args)
+ .arg(consts_cpp)
+ .args(&extra_args)
+ .arg(format!("{}{}", if cfg!(target_env = "msvc") { "-OUT:" } else { "-o" }, consts_bin.to_string_lossy()));
+ println!("running: {:?}", &command);
+ let e = command
.status()
.unwrap();
assert!(e.success());
- let output = Command::new(format!("./{}.consts", module))
- .current_dir(&out_dir)
+ let output = Command::new(consts_bin)
.output()
.unwrap();
assert!(output.status.success());
@@ -540,7 +691,11 @@ fn gen_wrapper((opencv, pkg_name): (&pkg_config::Library, &str), opencv_header_d
writeln!(&mut hub, "pub mod {};", module)?;
let module_filename = format!("{}.rs", module);
let target_file = module_dir.join(&module_filename);
- fs::rename(out_dir.join(&module_filename), &target_file)?;
+ let src_file = out_dir.join(&module_filename);
+ if fs::rename(&src_file, &target_file).is_err() {
+ fs::copy(&src_file, &target_file)?;
+ fs::remove_file(src_file)?;
+ }
let mut f = OpenOptions::new().append(true).open(&target_file)?;
add_manual(&mut f, module)?;
@@ -596,7 +751,11 @@ fn cleanup(opencv_dir: &PathBuf) -> Result<()> {
let out_dir = PathBuf::from(env::var_os("OUT_DIR").ok_or_else(|| "Can't read OUT_DIR env var")?);
let modules = get_modules(&opencv_dir.to_string_lossy())?;
modules.par_iter().for_each(|(module, ..)| {
+ if cfg!(target_env = "msvc") {
+ let _ = fs::remove_file(out_dir.join(format!("{}.consts.exe", module)));
+ } else {
let _ = fs::remove_file(out_dir.join(format!("{}.consts", module)));
+ }
let _ = fs::remove_file(out_dir.join(format!("{}.consts.cpp", module)));
});
for entry in glob(&format!("{}/*.rs", out_dir.to_string_lossy()))? {
@@ -623,12 +782,17 @@ fn main() -> Result<()> {
panic!("Please select one OpenCV major version using one of the opencv-* features or specify OpenCV header path manually via OPENCV_HEADER_DIR environment var");
}
});
+ if let Some(version) = get_version_from_headers(&opencv_header_dir) {
+ check_matching_version(&version).map_err(|e| format!("{}, (version coming from headers at: {})", e, opencv_header_dir.display()))?;
+ } else {
+ panic!("Unable to find header version in: {}", opencv_header_dir.display())
+ }
build_wrapper(&opencv_header_dir)?;
if !cfg!(feature = "docs-only") {
let opencv = link_wrapper()?;
if cfg!(feature = "buildtime-bindgen") {
- gen_wrapper((&opencv.0, &opencv.1), &opencv_header_dir)?;
+ gen_wrapper(&opencv, &opencv_header_dir)?;
}
}
install_wrapper()?;

RENAME
ci/bionic-install-opencv.sh
ci/install-bionic.sh
#!/bin/bash
-set -ex
+set -vex
BUILD_FLAGS="
-D BUILD_CUDA_STUBS=OFF
@@ -113,6 +113,5 @@ else
-D OPENCV_EXTRA_MODULES_PATH=~/"build/opencv/opencv_contrib-$OPENCV_VERSION/modules" \
~/"build/opencv/opencv-$OPENCV_VERSION"
sudo make -j"$(nproc)" install
- tree .
popd > /dev/null
fi

ADD
ci/install-osx.sh
+#!/bin/bash
+
+set -vex
+
+if [[ "$OPENCV_VERSION" == 4* ]]; then
+ BREW_OPENCV_VERSION=""
+elif [[ "$OPENCV_VERSION" == 3.4* ]]; then
+ BREW_OPENCV_VERSION="@3"
+else
+ BREW_OPENCV_VERSION=""
+fi
+brew install opencv"$BREW_OPENCV_VERSION"

ADD
ci/install-windows.sh
+#!/bin/bash
+
+set -vex
+
+choco install -y python3 --version "3.7.4"
+choco install -y opencv --version "$OPENCV_VERSION"

ADD
ci/install.sh
+#!/bin/bash
+
+set -vex
+
+ci_dir="$(dirname "$0")"
+
+if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
+ "$ci_dir/install-bionic.sh"
+elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ "$ci_dir/install-osx.sh"
+elif [[ "$TRAVIS_OS_NAME" == "windows" ]]; then
+ "$ci_dir/install-windows.sh"
+fi

ADD
ci/script.sh
+#!/bin/bash
+
+set -vex
+
+if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then
+ export PATH="C:\\Python37\\:$PATH:C:\\tools\\opencv\\build\\x64\\vc14\\bin"
+ export OPENCV_LINK_PATHS="C:\\tools\\opencv\\build\\x64\\vc14\\lib"
+ export OPENCV_LINK_LIBS="opencv_world${OPENCV_VERSION//./}"
+ export OPENCV_INCLUDE_PATHS="C:\\tools\\opencv\\build\\include"
+ export OPENCV_HEADER_DIR="C:\\tools\\opencv\\build\\include"
+ CARGO_FEATURES="$CARGO_FEATURES,buildtime-bindgen"
+elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ if [[ "$OPENCV_VERSION" == 3.4* ]]; then
+ export PKG_CONFIG_PATH="/usr/local/opt/opencv@3/lib/pkgconfig"
+ export OPENCV_HEADER_DIR="/usr/local/opt/opencv@3/include"
+ elif [[ "$OPENCV_VERSION" == 4.1* ]]; then
+ export OPENCV_HEADER_DIR="/usr/local/include/opencv4"
+ fi
+ CARGO_FEATURES="$CARGO_FEATURES,buildtime-bindgen"
+fi
+
+# when building both debug and release we're getting above 50min travis if not using cached build of OpenCV
+# so build stable rust only in --release, and beta only in debug
+CARGO_EXTRA_FLAGS=""
+if [[ "$TRAVIS_RUST_VERSION" == "stable" ]]; then
+ CARGO_EXTRA_FLAGS="--release"
+fi
+cargo build -vv --no-default-features --features "$CARGO_FEATURES" $CARGO_EXTRA_FLAGS
+
+# windows (gui?) binaries can't be run in travis:
+# C:/Users/travis/.cargo/bin/cargo.exe: error while loading shared libraries: ?: cannot open shared object file: No such file or directory
+# probably because of:
+# https://travis-ci.community/t/python-and-opencv-dll-load-fails-every-time/4431
+# https://travis-ci.community/t/make-running-gui-apps-available-in-windows/1557
+# that's why we don't run test
+if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then
+ cargo test -vv --no-default-features --features "$CARGO_FEATURES" $CARGO_EXTRA_FLAGS
+fi

MODIFY
gen_rust.py
gen_rust.py
@@ -327,7 +327,8 @@ func_rename = {
"cv_MatConstIterator_MatConstIterator_const_Mat": "over",
"cv_MatConstIterator_MatConstIterator_const_Mat_int_int": "with_rows_cols",
"cv_MatConstIterator_MatConstIterator_const_Mat_Point": "with_start",
- "cv_MatConstIterator_MatConstIterator_const_Mat_const_int_X": "with_idx",
+ # "cv_MatConstIterator_MatConstIterator_const_Mat_const_int_X": "with_idx",
+ "cv_MatConstIterator_MatConstIterator_const_Mat_const_int_X": "-",
"cv_MatConstIterator_pos_const_int_X": "+_to",
"cv_MatConstIterator_seek_const_int_X_bool": "+_idx",
"cv_AsyncArray_get_const__OutputArray_int64": "+_with_timeout",

MODIFY
tests/callback.rs
tests/callback.rs
@@ -4,10 +4,8 @@ use opencv::{highgui, Result};
#[test]
fn callback() -> Result<()> {
- // only run under X11 if on linux
- if cfg!(target_os = "linux") && option_env!("DISPLAY").is_none() {
- return Ok(());
- }
+ // only run under X11 on linux
+ if cfg!(target_os = "linux") && option_env!("DISPLAY").is_some() {
highgui::named_window("test", 0)?;
let mut value = 50;
let cb_value = Arc::new(Mutex::new(0));
@@ -20,6 +18,6 @@ fn callback() -> Result<()> {
highgui::set_trackbar_pos("test_track", "test", 10)?;
assert_eq!(value, 10);
assert_eq!(*cb_value.lock().unwrap(), 10);
+ }
Ok(())
}
-

MODIFY
tests/vector.rs
tests/vector.rs
@@ -143,7 +143,7 @@ fn capacity() {
vec.push(true);
assert_eq!(1, vec.len());
assert!(!vec.is_empty());
- assert_eq!(64, vec.capacity());
+ assert!(vec.capacity() > 0);
}
}

enable building on windows and osx