Fix building with macOS framework OpenCV
MODIFY
binding-generator/src/bin/binding-generator.rs
binding-generator/src/bin/binding-generator.rs
@@ -17,7 +17,7 @@ fn get_version_header(header_dir: &Path) -> Option<PathBuf> {
if out.is_file() {
Some(out)
} else {
- let out = header_dir.join("Headers/core/version.hpp");
+ let out = header_dir.join("opencv2.framework/Headers/core/version.hpp");
if out.is_file() {
Some(out)
} else {

MODIFY
binding-generator/src/element.rs
binding-generator/src/element.rs
@@ -257,7 +257,7 @@ pub fn is_opencv_path(path: &Path) -> bool {
path.components()
.rfind(|c| {
if let Component::Normal(c) = c {
- if *c == "opencv2" {
+ if *c == "opencv2" || *c == "Headers" {
return true;
}
}
@@ -276,7 +276,7 @@ fn opencv_module_component(path: &Path) -> Option<&OsStr> {
let mut module = None;
while let Some(cur) = module_comp.next() {
if let Some(&parent) = module_comp.peek() {
- if parent == "opencv2" || parent == "src_cpp" {
+ if parent == "opencv2" || parent == "src_cpp" || parent == "Headers" {
module = Some(cur);
break;
}

MODIFY
binding-generator/src/generator.rs
binding-generator/src/generator.rs
@@ -203,12 +203,13 @@ impl EntityWalkerVisitor<'_> for &mut EphemeralGenerator<'_> {
pub struct Generator {
clang_include_dirs: Vec<PathBuf>,
opencv_include_dir: PathBuf,
+ opencv_module_header_dir: PathBuf,
src_cpp_dir: PathBuf,
clang: Clang,
}
struct OpenCvWalker<'tu, 'r, V: GeneratorVisitor> {
- opencv_include_dir: &'r Path,
+ opencv_module_header_dir: &'r Path,
module: &'r str,
visitor: V,
gen_env: GeneratorEnv<'tu>,
@@ -298,8 +299,8 @@ impl<'tu, V: GeneratorVisitor> EntityWalkerVisitor<'tu> for OpenCvWalker<'tu, '_
}
impl<'tu, 'r, V: GeneratorVisitor> OpenCvWalker<'tu, 'r, V> {
- pub fn new(opencv_include_dir: &'r Path, module: &'r str, visitor: V, gen_env: GeneratorEnv<'tu>) -> Self {
- Self { opencv_include_dir, module, visitor, gen_env, comment_found: false }
+ pub fn new(opencv_module_header_dir: &'r Path, module: &'r str, visitor: V, gen_env: GeneratorEnv<'tu>) -> Self {
+ Self { opencv_module_header_dir, module, visitor, gen_env, comment_found: false }
}
fn process_const(&mut self, const_decl: Entity) {
@@ -443,10 +444,8 @@ impl<V: GeneratorVisitor> Drop for OpenCvWalker<'_, '_, V> {
if !self.comment_found {
// some module level comments like "bioinspired" are not attached to anything and libclang
// doesn't seem to offer a way to extract them, do it the hard way then
- let mut module_path = self.opencv_include_dir.join("opencv2");
- module_path.push(self.gen_env.module());
- module_path.set_extension("hpp");
let mut comment = String::with_capacity(2048);
+ let module_path = self.opencv_module_header_dir.join(format!("{}.hpp", self.gen_env.module()));
let f = BufReader::new(File::open(module_path).expect("Can't open main module file"));
let mut found_module_comment = false;
let mut defgroup_found = false;
@@ -496,9 +495,14 @@ impl Generator {
}
};
}
+ let mut opencv_module_header_dir = opencv_include_dir.join("opencv2.framework/Headers");
+ if !opencv_module_header_dir.exists() {
+ opencv_module_header_dir = opencv_include_dir.join("opencv2");
+ }
Self {
clang_include_dirs,
opencv_include_dir: canonicalize(opencv_include_dir).expect("Can't canonicalize opencv_include_dir"),
+ opencv_module_header_dir: canonicalize(opencv_module_header_dir).expect("Can't canonicalize opencv_module_header_dir"),
src_cpp_dir: canonicalize(src_cpp_dir).expect("Can't canonicalize src_cpp_dir"),
clang,
}
@@ -528,7 +532,13 @@ impl Generator {
let mut args = self.clang_include_dirs.iter()
.map(|d| format!("-isystem{}", d.to_str().expect("Incorrect system include path")).into())
.chain([&self.opencv_include_dir, &self.src_cpp_dir].iter()
- .map(|d| format!("-I{}", d.to_str().expect("Incorrect include path")).into())
+ .flat_map(|d| {
+ let include_path = d.to_str().expect("Incorrect include path");
+ [
+ format!("-I{}", include_path).into(),
+ format!("-F{}", include_path).into(),
+ ]
+ })
)
.collect::<Vec<_>>();
args.push("-DOCVRS_PARSING_HEADERS".into());
@@ -542,7 +552,7 @@ impl Generator {
let index = Index::new(&self.clang, true, false);
let mut module_file = self.src_cpp_dir.join(format!("{}.hpp", module));
if !module_file.exists() {
- module_file = self.opencv_include_dir.join(format!("opencv2/{}.hpp", module));
+ module_file = self.opencv_module_header_dir.join(format!("{}.hpp", module));
}
let mut root_tu: TranslationUnit = index.parser(module_file)
.unsaved(&[self.make_ephemeral_header("")])
@@ -565,7 +575,7 @@ impl Generator {
visitor.visit_ephemeral_header(&ephemeral_header);
let gen_env = GeneratorEnv::new(root_entity, module);
let opencv_walker = OpenCvWalker::new(
- &self.opencv_include_dir,
+ &self.opencv_module_header_dir,
module,
visitor,
gen_env,

MODIFY
build.rs
build.rs
@@ -83,18 +83,22 @@ fn cleanup_lib_filename(filename: &OsStr) -> Option<&OsStr> {
}
}
-fn get_version_header(header_dir: &Path) -> Option<PathBuf> {
- let out = header_dir.join("opencv2/core/version.hpp");
- if out.is_file() {
- Some(out)
- } else {
- let out = header_dir.join("Headers/core/version.hpp");
- if out.is_file() {
- Some(out)
- } else {
- None
+fn get_module_header_dir(header_dir: &Path) -> Option<PathBuf> {
+ let mut out = header_dir.join("opencv2.framework/Headers");
+ if out.exists() {
+ return Some(out);
+ }
+ out = header_dir.join("opencv2");
+ if out.exists() {
+ return Some(out);
}
+ None
}
+
+fn get_version_header(header_dir: &Path) -> Option<PathBuf> {
+ get_module_header_dir(header_dir)
+ .map(|dir| dir.join("core/version.hpp"))
+ .filter(|dir| dir.is_file())
}
fn get_version_from_headers(header_dir: &Path) -> Option<Version> {
@@ -188,7 +192,12 @@ fn build_compiler(opencv: &Library) -> cc::Build {
.flag_if_supported("-Wno-ignored-qualifiers") // type qualifiers ignored on function return type in const size_t cv_MatStep_operator___const_int(const cv::MatStep* instance, int i)
.flag_if_supported("-Wno-return-type-c-linkage") // warning: 'cv_aruco_CharucoBoard_getChessboardSize_const' has C-linkage specified, but returns user-defined type 'Result<cv::Size>' (aka 'Result<Size_<int> >') which is incompatible with C
;
- opencv.include_paths.iter().for_each(|p| { out.include(p); });
+ opencv.include_paths.iter().for_each(|p| {
+ out.include(p);
+ if cfg!(target_vendor = "apple") {
+ out.flag_if_supported(&format!("-F{}", p.to_str().expect("Can't convert path to str")));
+ }
+ });
if cfg!(target_env = "msvc") {
out.flag("-std:c++latest")
.flag("-EHsc")
@@ -310,7 +319,9 @@ fn main() -> Result<()> {
.find(|p| get_version_header(p).is_some())
.expect("Discovered OpenCV include paths is empty or contains non-existent paths");
- make_modules(&opencv_header_dir.join("opencv2"))?;
+ let opencv_module_header_dir = get_module_header_dir(&opencv_header_dir).expect("Can't find OpenCV module header dir");
+ eprintln!("=== Detected OpenCV module header dir at: {}", opencv_module_header_dir.display());
+ make_modules(&opencv_module_header_dir)?;
if let Some(header_version) = get_version_from_headers(opencv_header_dir) {
if header_version != opencv.version {

MODIFY
build/generator.rs
build/generator.rs
@@ -56,11 +56,10 @@ pub fn gen_wrapper(opencv_header_dir: &Path, opencv: &Library, generator_build:
let target_hub_dir = SRC_DIR.join("opencv");
let target_module_dir = target_hub_dir.join("hub");
let manual_dir = SRC_DIR.join("manual");
- let opencv_dir = opencv_header_dir.join("opencv2");
eprintln!("=== Generating code in: {}", out_dir_as_str);
eprintln!("=== Placing generated bindings into: {}", target_hub_dir.display());
- eprintln!("=== Using OpenCV headers from: {}", opencv_dir.display());
+ eprintln!("=== Using OpenCV headers from: {}", opencv_header_dir.display());
let modules = MODULES.get().expect("MODULES not initialized");

MODIFY
build/library.rs
build/library.rs
@@ -168,12 +168,12 @@ impl Library {
Self::process_env_var_list(link_paths, sys_link_paths).into_iter()
.map(move |path| {
let out = iter::once(Self::emit_link_search(&path, typ));
- #[cfg(target_os = "macos")] {
+ #[cfg(target_vendor = "apple")] {
out.chain(
iter::once(Self::emit_link_search(&path, Some("framework")))
)
}
- #[cfg(not(target_os = "macos"))] {
+ #[cfg(not(target_vendor = "apple"))] {
out
}
})

MODIFY
ci/script.sh
ci/script.sh
@@ -29,8 +29,7 @@ elif [[ "$OS_FAMILY" == "osx" ]]; then
clang_dir="$(clang --print-search-dirs | awk -F= '/^libraries: =/ { print $2 }')"
export OPENCV_LINK_PATHS="$HOME/build/opencv/opencv-$OPENCV_VERSION-build,$clang_dir/lib/darwin"
export OPENCV_LINK_LIBS="opencv2.framework,OpenCL.framework,Cocoa.framework,Accelerate.framework,AVFoundation.framework,CoreGraphics.framework,CoreMedia.framework,CoreVideo.framework,QuartzCore.framework,clang_rt.osx"
-# export OPENCV_INCLUDE_PATHS="$HOME/build/opencv/opencv-$OPENCV_VERSION-build/opencv2.framework"
- export OPENCV_INCLUDE_PATHS="$HOME/build/opencv/opencv-$OPENCV_VERSION-build/build/build-x86_64-macosx/install/include"
+ export OPENCV_INCLUDE_PATHS="$HOME/build/opencv/opencv-$OPENCV_VERSION-build"
fi
echo "=== Installed brew packages:"
brew list --versions

Fix building with macOS framework OpenCV