nanobind-sys/build.rs

changeset 1
a4137aedcb3a
child 3
c3a4f4bb87f7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nanobind-sys/build.rs	Thu Feb 26 09:32:12 2026 -0500
@@ -0,0 +1,83 @@
+use anyhow::bail;
+use build_print::info;
+use cc;
+use conda_build::python_config;
+use std::env;
+use std::path::PathBuf;
+
+const NANOBIND_SOURCES: [&str; 7] = [
+    "common.cpp",
+    "trampoline.cpp",
+    "nb_func.cpp",
+    "nb_type.cpp",
+    "nb_internals.cpp",
+    "error.cpp",
+    "implicit.cpp",
+];
+
+fn main() -> Result<(), anyhow::Error> {
+    // Need to build it
+    let (pyc_e, py_conda) = python_config();
+
+    // This is very clumsy due to PythonConfig::Error not supporting
+    // conversion into std::error::Error, just std::io::Error.
+    let (pyc, mut includes, _py_ldflags) = pyc_e
+        .and_then(|pyc| {
+            pyc.include_paths()
+                .and_then(|ip| pyc.ldflags().map(|ld| (pyc, ip, ld)))
+        })
+        .map_err(|e| anyhow::Error::from(std::io::Error::from(e)))?;
+
+    let nanobind_root = pyc
+        .prefix_path().ok()
+        .zip(pyc.semantic_version().ok())
+        .and_then(|(prefix, version)| {
+            info!("{}Python {} found at prefix {}", if py_conda { "Conda " } else { ""}, version, prefix.display());
+            let nanobind_root = prefix
+                .join("lib")
+                .join(format!("python{}.{}", version.major, version.minor))
+                .join("site-packages")
+                .join("nanobind");
+            if !nanobind_root.exists() {
+                info!("… but no nanobind installed there");
+                None
+            } else {
+                Some(nanobind_root)
+            }
+        })
+        .map_or_else(|| {
+            let last_ditch = "/usr/share/nanobind";
+            let nanobind_root = PathBuf::from(last_ditch);
+            if !nanobind_root.exists() {
+                bail!("Could not find nanobind in known locations. The recommended installation method is with pip at system Python location, or with Conda into the active environment. Also /usr/share/nanobind was attempted.");
+            } else {
+                info!("Found in {last_ditch}.");
+                Ok(nanobind_root)
+            }
+        }, Ok)?;
+
+    let nanobind_src = nanobind_root.join("src");
+
+    println!("cargo:rerun-if-changed=build.rs");
+
+    //println!("cargo:rustc-link-arg={}", py_ldflags);
+
+    includes.extend([
+        nanobind_root.join("include"),
+        nanobind_root.join("ext/robin_map/include"),
+    ]);
+
+    println!(
+        "cargo:include={}",
+        env::join_paths(&includes)?.into_string().unwrap()
+    );
+
+    cc::Build::new()
+        .std("c++20")
+        .files(NANOBIND_SOURCES.map(|f| nanobind_src.join(f)))
+        .includes(includes)
+        //.flags(pyc.cflags()?)
+        .compile("nanobind-sys");
+
+    Ok(())
+}

mercurial