From e297b8fe1d35dd0cdd3d9ebd7a8263ddf22e1a6e Mon Sep 17 00:00:00 2001 From: Dominick Schroer Date: Sun, 28 May 2023 12:31:01 -0600 Subject: [PATCH] Add support use of installed OpenCASCADE This commit uses cmake to find installed OpenCASCADE libraries in system. If it found it will be used if it version fits to requirements. Otherwise the builtin one will be used. The `builtin` feature may be enabled to force use builtin OpenCASCADE. --- crates/opencascade-sys/Cargo.toml | 7 +- .../opencascade-sys/OCCT_PKG/CMakeLists.txt | 12 ++ crates/opencascade-sys/build.rs | 126 ++++++++++++++---- crates/opencascade/Cargo.toml | 3 + 4 files changed, 119 insertions(+), 29 deletions(-) create mode 100644 crates/opencascade-sys/OCCT_PKG/CMakeLists.txt diff --git a/crates/opencascade-sys/Cargo.toml b/crates/opencascade-sys/Cargo.toml index c3bdc0b6..738a2557 100644 --- a/crates/opencascade-sys/Cargo.toml +++ b/crates/opencascade-sys/Cargo.toml @@ -11,6 +11,9 @@ repository = "https://github.com/bschwind/opencascade-rs" cxx = "1" [build-dependencies] -cmake = "0.1" cxx-build = "1" -occt-sys = { path = "../occt-sys" } +cmake = "0.1" +occt-sys = { path = "../occt-sys", optional = true } + +[features] +builtin = ["occt-sys"] diff --git a/crates/opencascade-sys/OCCT_PKG/CMakeLists.txt b/crates/opencascade-sys/OCCT_PKG/CMakeLists.txt new file mode 100644 index 00000000..a8fb52b8 --- /dev/null +++ b/crates/opencascade-sys/OCCT_PKG/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required (VERSION 3.1 FATAL_ERROR) +project (OpenCASCADEPackageConfig) +find_package (OpenCASCADE REQUIRED) + +file (WRITE ${CMAKE_BINARY_DIR}/occ_info.txt + "VERSION_MAJOR=${OpenCASCADE_MAJOR_VERSION}\n" + "VERSION_MINOR=${OpenCASCADE_MINOR_VERSION}\n" + "INCLUDE_DIR=${OpenCASCADE_INCLUDE_DIR}\n" + "LIBRARY_DIR=${OpenCASCADE_LIBRARY_DIR}\n" + "BUILD_SHARED_LIBS=${OpenCASCADE_BUILD_SHARED_LIBS}\n") + +install (FILES ${CMAKE_BINARY_DIR}/occ_info.txt TYPE DATA) diff --git a/crates/opencascade-sys/build.rs b/crates/opencascade-sys/build.rs index b3b6c82b..6dce4177 100644 --- a/crates/opencascade-sys/build.rs +++ b/crates/opencascade-sys/build.rs @@ -1,35 +1,45 @@ -use occt_sys::{occt_include_path, occt_lib_path}; +const OCCT_VERSION: (u8, u8) = (7, 2); + +const OCCT_LIBS: &[&str] = &[ + "TKMath", + "TKernel", + "TKFeat", + "TKGeomBase", + "TKG2d", + "TKG3d", + "TKTopAlgo", + "TKGeomAlgo", + "TKGeomBase", + "TKBRep", + "TKPrim", + "TKSTEP", + "TKSTEPAttr", + "TKSTEPBase", + "TKSTEP209", + "TKSTL", + "TKMesh", + "TKShHealing", + "TKFillet", + "TKBool", + "TKBO", + "TKOffset", + "TKV3d", + "TKXSBase", +]; fn main() { let target = std::env::var("TARGET").expect("No TARGET environment variable defined"); let is_windows = target.to_lowercase().contains("windows"); let is_windows_gnu = target.to_lowercase().contains("windows-gnu"); - println!("cargo:rustc-link-search=native={}", occt_lib_path().to_str().unwrap()); - println!("cargo:rustc-link-lib=static=TKMath"); - println!("cargo:rustc-link-lib=static=TKernel"); - println!("cargo:rustc-link-lib=static=TKFeat"); - println!("cargo:rustc-link-lib=static=TKGeomBase"); - println!("cargo:rustc-link-lib=static=TKG2d"); - println!("cargo:rustc-link-lib=static=TKG3d"); - println!("cargo:rustc-link-lib=static=TKTopAlgo"); - println!("cargo:rustc-link-lib=static=TKGeomAlgo"); - println!("cargo:rustc-link-lib=static=TKGeomBase"); - println!("cargo:rustc-link-lib=static=TKBRep"); - println!("cargo:rustc-link-lib=static=TKPrim"); - println!("cargo:rustc-link-lib=static=TKSTEP"); - println!("cargo:rustc-link-lib=static=TKSTEPAttr"); - println!("cargo:rustc-link-lib=static=TKSTEPBase"); - println!("cargo:rustc-link-lib=static=TKSTEP209"); - println!("cargo:rustc-link-lib=static=TKSTL"); - println!("cargo:rustc-link-lib=static=TKMesh"); - println!("cargo:rustc-link-lib=static=TKShHealing"); - println!("cargo:rustc-link-lib=static=TKFillet"); - println!("cargo:rustc-link-lib=static=TKBool"); - println!("cargo:rustc-link-lib=static=TKBO"); - println!("cargo:rustc-link-lib=static=TKOffset"); - println!("cargo:rustc-link-lib=static=TKV3d"); - println!("cargo:rustc-link-lib=static=TKXSBase"); + let occt_config = OcctConfig::default(); + + println!("cargo:rustc-link-search=native={}", occt_config.library_dir.to_str().unwrap()); + + let lib_type = if occt_config.is_dynamic { "dylib" } else { "static" }; + for lib in OCCT_LIBS { + println!("cargo:rustc-link-lib={lib_type}={lib}"); + } if is_windows { println!("cargo:rustc-link-lib=dylib=user32"); @@ -45,7 +55,7 @@ fn main() { .cpp(true) .flag_if_supported("-std=c++11") .define("_USE_MATH_DEFINES", "TRUE") - .include(occt_include_path()) + .include(occt_config.include_dir) .include("include") .compile("wrapper"); @@ -54,3 +64,65 @@ fn main() { println!("cargo:rerun-if-changed=src/lib.rs"); println!("cargo:rerun-if-changed=include/wrapper.hxx"); } + +struct OcctConfig { + include_dir: std::path::PathBuf, + library_dir: std::path::PathBuf, + is_dynamic: bool, +} + +impl Default for OcctConfig { + #[cfg(feature = "builtin")] + fn default() -> Self { + let include_dir = occt_sys::occt_include_path(); + let library_dir = occt_sys::occt_lib_path(); + + Self { include_dir, library_dir, is_dynamic: false } + } + + #[cfg(not(feature = "builtin"))] + fn default() -> Self { + let dst = std::panic::catch_unwind(|| cmake::Config::new("OCCT_PKG").build()) + .expect("Pre-installed OpenCASCADE library not found! You can use `builtin` feature if you do not want install OCCT libraries system-wide."); + let cfg = std::fs::read_to_string(dst.join("share").join("occ_info.txt")) + .expect("Something went wrong when detecting pre-installed OpenCASCADE library!"); + + let mut version_major: Option = None; + let mut version_minor: Option = None; + let mut include_dir: Option = None; + let mut library_dir: Option = None; + let mut is_dynamic: bool = false; + + for line in cfg.lines() { + if let Some((var, val)) = line.split_once("=") { + match var { + "VERSION_MAJOR" => version_major = val.parse().ok(), + "VERSION_MINOR" => version_minor = val.parse().ok(), + "INCLUDE_DIR" => include_dir = val.parse().ok(), + "LIBRARY_DIR" => library_dir = val.parse().ok(), + "BUILD_SHARED_LIBS" => is_dynamic = val == "ON", + _ => (), + } + } + } + + if let (Some(version_major), Some(version_minor), Some(include_dir), Some(library_dir)) = + (version_major, version_minor, include_dir, library_dir) + { + if version_major != OCCT_VERSION.0 { + panic!("Pre-installed OpenCASCADE library found but major version is not the same (found {}.x but {}.x required)! Please provide required version or use `builtin` feature.", version_major, OCCT_VERSION.0); + } + + if version_minor < OCCT_VERSION.1 { + panic!( + "Pre-installed OpenCASCADE library found but minor version is lower than required ({}.{} < {}.{})! Please provide required version or use `builtin` feature.", + version_major, version_minor, OCCT_VERSION.0, OCCT_VERSION.1 + ); + } + + Self { include_dir, library_dir, is_dynamic } + } else { + panic!("Pre-installed OpenCASCADE library found but something went wrong!"); + } + } +} diff --git a/crates/opencascade/Cargo.toml b/crates/opencascade/Cargo.toml index 2f9e040f..cf26eb61 100644 --- a/crates/opencascade/Cargo.toml +++ b/crates/opencascade/Cargo.toml @@ -12,3 +12,6 @@ cxx = "1" opencascade-sys = { version = "0.1", path = "../opencascade-sys" } glam = { version = "0.23", features = ["bytemuck"] } thiserror = "1" + +[features] +builtin = ["opencascade-sys/builtin"]