Move version detection into binding-generator binary
MODIFY
binding-generator/src/bin/binding-generator.rs
binding-generator/src/bin/binding-generator.rs
use std::{
env,
- path::PathBuf,
+ fs::File,
+ io::{BufRead, BufReader},
+ path::{Path, PathBuf},
};
use clang::Clang;
@@ -10,6 +12,60 @@ use opencv_binding_generator::{
writer::RustNativeBindingWriter,
};
+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_version_from_headers(header_dir: &Path) -> Option<String> {
+ let version_hpp = get_version_header(header_dir)?;
+ let mut major = None;
+ let mut minor = None;
+ let mut revision = None;
+ let mut line = String::with_capacity(256);
+ let mut reader = BufReader::new(File::open(version_hpp).ok()?);
+ while let Ok(bytes_read) = reader.read_line(&mut line) {
+ if bytes_read == 0 {
+ break;
+ }
+ if let Some(line) = line.strip_prefix("#define CV_VERSION_") {
+ let mut parts = line.split_whitespace();
+ if let (Some(ver_spec), Some(version)) = (parts.next(), parts.next()) {
+ match ver_spec {
+ "MAJOR" => {
+ major = Some(version.to_string());
+ }
+ "MINOR" => {
+ minor = Some(version.to_string());
+ }
+ "REVISION" => {
+ revision = Some(version.to_string());
+ }
+ _ => {}
+ }
+ }
+ if major.is_some() && minor.is_some() && revision.is_some() {
+ break;
+ }
+ }
+ line.clear();
+ }
+ if let (Some(major), Some(minor), Some(revision)) = (major, minor, revision) {
+ Some(format!("{}.{}.{}", major, minor, revision))
+ } else {
+ Some("0.0.0".to_string())
+ }
+}
+
fn main() {
let mut args = env::args_os().skip(1);
let opencv_header_dir = PathBuf::from(args.next().expect("1st argument must be OpenCV header dir"));
@@ -17,8 +73,7 @@ fn main() {
let out_dir = PathBuf::from(args.next().expect("3rd argument must be output dir"));
let module = args.next().expect("4th argument must be module name");
let module = module.to_str().expect("Not a valid module name");
- let version = args.next().expect("5th argument must be OpenCV version");
- let version = version.to_str().expect("Not a valid version");
+ let version = get_version_from_headers(&opencv_header_dir).expect("Can't find the version in the headers");
let additional_include_dirs = if let Some(additional_include_dirs) = args.next() {
additional_include_dirs.to_str()
.map(|s| s.split(','))
@@ -32,7 +87,7 @@ fn main() {
};
let debug = args.next().map_or(false, |x| x == "1");
let clang = Clang::new().expect("Cannot initialize clang");
- let bindings_writer = RustNativeBindingWriter::new(&src_cpp_dir, &out_dir, module, version, debug);
+ let bindings_writer = RustNativeBindingWriter::new(&src_cpp_dir, &out_dir, module, &version, debug);
Generator::new(&opencv_header_dir, &additional_include_dirs, &src_cpp_dir, clang)
.process_opencv_module(&module, bindings_writer);
}

MODIFY
build/generator.rs
build/generator.rs
@@ -98,7 +98,6 @@ pub fn gen_wrapper(opencv_header_dir: &Path, opencv: &Library, generator_build:
start = Instant::now();
modules.iter().for_each(|module| {
let token = job_server.acquire().expect("Can't acquire token from job server");
- let opencv_version = opencv.version.to_string();
let join_handle = thread::spawn({
let additional_include_dirs = Arc::clone(&additional_include_dirs);
let opencv_header_dir = Arc::clone(&opencv_header_dir);
@@ -111,7 +110,6 @@ pub fn gen_wrapper(opencv_header_dir: &Path, opencv: &Library, generator_build:
.arg(&*SRC_CPP_DIR)
.arg(&*OUT_DIR)
.arg(&module)
- .arg(&opencv_version)
.arg(additional_include_dirs.join(","));
eprintln!("=== Running binding generator binary: {:#?}", bin_generator);
let res = bin_generator.status().expect("Can't run bindings generator");

Move version detection into binding-generator binary