#![allow(
clippy::expect_used,
clippy::panic,
clippy::manual_assert,
clippy::too_many_lines
)]
use std::env;
use std::path::PathBuf;
fn main() {
let manifest_dir = PathBuf::from(
env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR must be set by Cargo"),
);
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
if env::var("CARGO_FEATURE_HIGHS").is_ok() {
println!("cargo:rerun-if-changed=csrc/highs_wrapper.c");
println!("cargo:rerun-if-changed=csrc/highs_wrapper.h");
println!("cargo:rerun-if-changed=csrc/highs_wrapper_cpp.cpp");
let highs_src = manifest_dir.join("vendor/HiGHS");
if !highs_src.join("CMakeLists.txt").exists() {
panic!(
"HiGHS source not found at crates/cobre-solver/vendor/HiGHS/. \
Run: git submodule update --init --recursive"
);
}
eprintln!("cobre-solver: building HiGHS from {}", highs_src.display());
let mut cmake_config = cmake::Config::new(&highs_src);
cmake_config
.define("CMAKE_BUILD_TYPE", "Release")
.define("BUILD_SHARED_LIBS", "OFF")
.define("HIGHS_NO_DEFAULT_THREADS", "ON")
.define("BUILD_TESTING", "OFF")
.define("BUILD_EXAMPLES", "OFF")
.define("HIGHSINT64", "OFF")
.define("CMAKE_DISABLE_FIND_PACKAGE_ZLIB", "ON");
if target_env == "msvc" {
cmake_config.define("CMAKE_MSVC_RUNTIME_LIBRARY", "MultiThreaded");
cmake_config.cflag("/MT");
cmake_config.cxxflag("/MT");
}
let highs_dst = cmake_config.build();
eprintln!(
"cobre-solver: HiGHS cmake output at {}",
highs_dst.display()
);
println!(
"cargo:rustc-link-search=native={}",
highs_dst.join("lib").display()
);
println!(
"cargo:rustc-link-search=native={}",
highs_dst.join("lib64").display()
);
if target_env == "msvc" {
println!(
"cargo:rustc-link-search=native={}",
highs_dst.join("lib/Release").display()
);
}
println!("cargo:rustc-link-lib=static=highs");
if target_env != "msvc" {
if target_os == "macos" {
println!("cargo:rustc-link-lib=c++");
} else {
println!("cargo:rustc-link-lib=stdc++");
}
}
let highs_include = highs_dst.join("include");
let highs_include_highs = highs_dst.join("include/highs");
eprintln!(
"cobre-solver: compiling C wrapper with include paths: {}, {}",
highs_include.display(),
highs_include_highs.display()
);
let mut build = cc::Build::new();
build
.file("csrc/highs_wrapper.c")
.include("csrc")
.warnings(true)
.extra_warnings(true);
add_system_or_include(&mut build, target_env == "msvc", &highs_include);
add_system_or_include(&mut build, target_env == "msvc", &highs_include_highs);
if target_env == "msvc" {
build.static_crt(true);
}
if target_env != "msvc" {
build.flag("-Wno-unused-function");
}
build.compile("highs_wrapper");
let mut build_cpp = cc::Build::new();
build_cpp
.file("csrc/highs_wrapper_cpp.cpp")
.cpp(true)
.include("csrc")
.warnings(true)
.extra_warnings(true);
add_system_or_include(&mut build_cpp, target_env == "msvc", &highs_include);
add_system_or_include(&mut build_cpp, target_env == "msvc", &highs_include_highs);
build_cpp.flag_if_supported("-std=c++17");
if target_env == "msvc" {
build_cpp.flag("/std:c++17");
build_cpp.static_crt(true);
} else {
build_cpp.flag("-Wno-unused-function");
}
build_cpp.compile("highs_wrapper_cpp");
}
if env::var("CARGO_FEATURE_CLP").is_ok() {
println!("cargo:rerun-if-changed=csrc/clp_wrapper.c");
println!("cargo:rerun-if-changed=csrc/clp_wrapper.h");
println!("cargo:rerun-if-changed=csrc/clp_wrapper_cpp.cpp");
println!("cargo:rerun-if-changed=vendor/coin-build/CMakeLists.txt");
println!("cargo:rerun-if-changed=vendor/coin-build/include/ClpConfig.h");
println!("cargo:rerun-if-changed=vendor/coin-build/include/CoinUtilsConfig.h");
println!("cargo:rerun-if-changed=vendor/coin-build/include/config_clp.h");
println!("cargo:rerun-if-changed=vendor/coin-build/include/config_coinutils.h");
let clp_header = manifest_dir.join("vendor/Clp/Clp/src/Clp_C_Interface.h");
let coinutils_header =
manifest_dir.join("vendor/CoinUtils/CoinUtils/src/CoinFactorization.hpp");
if !clp_header.exists() || !coinutils_header.exists() {
panic!(
"CLP/CoinUtils source not found under crates/cobre-solver/vendor/Clp/ and \
crates/cobre-solver/vendor/CoinUtils/. \
Run: git submodule update --init --recursive"
);
}
let coin_build_src = manifest_dir.join("vendor/coin-build");
eprintln!(
"cobre-solver: building CLP superbuild from {}",
coin_build_src.display()
);
let mut clp_config = cmake::Config::new(&coin_build_src);
clp_config
.define("CMAKE_BUILD_TYPE", "Release")
.define("BUILD_SHARED_LIBS", "OFF");
if target_env == "msvc" {
clp_config.define("CMAKE_MSVC_RUNTIME_LIBRARY", "MultiThreaded");
clp_config.cflag("/MT");
clp_config.cxxflag("/MT");
}
let clp_dst = clp_config.build();
eprintln!("cobre-solver: CLP cmake output at {}", clp_dst.display());
println!(
"cargo:rustc-link-search=native={}",
clp_dst.join("lib").display()
);
println!(
"cargo:rustc-link-search=native={}",
clp_dst.join("lib64").display()
);
if target_env == "msvc" {
println!(
"cargo:rustc-link-search=native={}",
clp_dst.join("lib/Release").display()
);
}
println!("cargo:rustc-link-lib=static=Clp");
println!("cargo:rustc-link-lib=static=CoinUtils");
if target_env != "msvc" {
if target_os == "macos" {
println!("cargo:rustc-link-lib=c++");
} else {
println!("cargo:rustc-link-lib=stdc++");
}
}
let clp_include = clp_dst.join("include");
let clp_src_include = manifest_dir.join("vendor/Clp/Clp/src");
let coinutils_src_include = manifest_dir.join("vendor/CoinUtils/CoinUtils/src");
eprintln!(
"cobre-solver: compiling CLP wrapper with include paths: {}, {}, {}",
clp_src_include.display(),
coinutils_src_include.display(),
clp_include.display()
);
let mut clp_build = cc::Build::new();
clp_build
.file("csrc/clp_wrapper.c")
.include("csrc")
.warnings(true)
.extra_warnings(true);
add_system_or_include(&mut clp_build, target_env == "msvc", &clp_src_include);
add_system_or_include(&mut clp_build, target_env == "msvc", &coinutils_src_include);
add_system_or_include(&mut clp_build, target_env == "msvc", &clp_include);
if target_env == "msvc" {
clp_build.static_crt(true);
}
clp_build.compile("clp_wrapper");
let mut clp_build_cpp = cc::Build::new();
clp_build_cpp
.file("csrc/clp_wrapper_cpp.cpp")
.cpp(true)
.include("csrc")
.warnings(true)
.extra_warnings(true);
add_system_or_include(&mut clp_build_cpp, target_env == "msvc", &clp_src_include);
add_system_or_include(
&mut clp_build_cpp,
target_env == "msvc",
&coinutils_src_include,
);
add_system_or_include(&mut clp_build_cpp, target_env == "msvc", &clp_include);
clp_build_cpp.flag_if_supported("-std=c++17");
if target_env == "msvc" {
clp_build_cpp.flag("/std:c++17");
clp_build_cpp.static_crt(true);
}
clp_build_cpp.compile("clp_wrapper_cpp");
}
}
fn add_system_or_include(build: &mut cc::Build, is_msvc: bool, path: &std::path::Path) {
if is_msvc {
build.include(path);
} else {
build.flag("-isystem");
build.flag(path.to_str().expect("HiGHS include path must be UTF-8"));
}
}