build.rs

changeset 1
a4137aedcb3a
child 3
c3a4f4bb87f7
equal deleted inserted replaced
0:7ec1cfe19a24 1:a4137aedcb3a
1 /*!
2 Build script for `pointsource_pde`
3 */
4
5 //use pyo3::{prepare_freethreaded_python, types::PyModule, PyErr, Python};
6 use conda_build::python_config;
7 use std::env::split_paths;
8 use std::fs::File;
9 use std::io::Write;
10 use std::path::PathBuf;
11 use std::process::Command;
12
13 const REQUIRED_PYTHON_MODULES: [&str; 7] = [
14 "dolfinx", "ufl", "numpy", "time", "petsc4py", "mpi4py", "json",
15 ];
16
17 const DOLFINX_ACCESS_CXX_SOURCES: [&str; 3] =
18 ["nanobind_helpers.cc", "minmax_p2.cc", "function.cc"];
19
20 const PY_SRC: [&str; 7] = [
21 "src/dolfinx_extras.py",
22 "src/compose.py",
23 "src/measure.py",
24 "src/quadratic_dataterm.py",
25 "src/convection_diffusion.py",
26 "src/laser_sampling.py",
27 "src/full_sampling.py",
28 ];
29
30 fn main() -> Result<(), std::io::Error> {
31 // Check Python module availability.
32 // This doesn't necessarily work in a Conda setup.
33 // prepare_freethreaded_python();
34 // Python::with_gil(|py| {
35 // for m in REQUIRED_PYTHON_MODULES {
36 // PyModule::import(py, m)?;
37 // }
38 // Ok::<_, PyErr>(())
39 // })?;
40
41 let (pyc_e, py_is_conda) = python_config();
42 let py_path = pyc_e.and_then(|pyc| pyc.exec_prefix_path())?;
43 let py_exec = py_path.join("bin").join("python3");
44 let import_check_code = REQUIRED_PYTHON_MODULES
45 .map(|m| format!("import {}\n", m))
46 .concat();
47 let res = Command::new(&py_exec)
48 .args(["-c", import_check_code.as_ref()])
49 .status()?;
50 if !res.success() {
51 return Err(std::io::Error::other(format!(
52 "Failed to load required Python modules (python execuitable {}{})",
53 py_exec.display(),
54 if py_is_conda { " from Conda" } else { "" }
55 )));
56 }
57
58 // Set up local-to-crate paths
59 let cc_mod_name = "dolfinx_access";
60 let crate_name = "pointsource_pde";
61 let src = PathBuf::from("src");
62 let cc_mod_root = src.join(cc_mod_name);
63 let bridge = src.join(format!("{cc_mod_name}.rs"));
64 let cc_sources = DOLFINX_ACCESS_CXX_SOURCES.map(|f| cc_mod_root.join(f));
65 let mut include_dirs = Vec::from([PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("include")]);
66
67 // Add (an estimate of) dolfinx ldflags. This shouldn't really be our problem to deal with,
68 // but everything that is not piss, is shit.
69 add_dep_ldflags("DEP_DOLFINX_LDFLAGS");
70
71 // Add external include paths
72 add_dep_includes(&mut include_dirs, "DEP_DOLFINX_INCLUDE");
73 add_dep_includes(&mut include_dirs, "DEP_NANOBIND_INCLUDE");
74
75 // This may be useful to enable sometimes, when there's
76 // trouble location GSL.
77 // pkg_config::Config::new().probe("gsl").unwrap();
78
79 // Build the bridge
80 cxx_build::bridge(&bridge)
81 .std("c++20")
82 .files(&cc_sources)
83 .includes(&include_dirs)
84 .compile(crate_name);
85
86 for dep in PY_SRC {
87 println!("cargo::rerun-if-changed={}", dep);
88 }
89
90 let header_prefix = PathBuf::from("include").join(cc_mod_name);
91 let headers = DOLFINX_ACCESS_CXX_SOURCES
92 .into_iter()
93 .map(|s| header_prefix.join(s.replace(".cc", ".h")));
94
95 for dep in cc_sources
96 .into_iter()
97 .chain(headers)
98 .chain(std::iter::once(bridge))
99 {
100 println!("cargo:rerun-if-changed={}", dep.display());
101 }
102
103 // Generate .clangd
104 let mut dot_clangd = File::create(".clangd")?;
105 write!(
106 dot_clangd,
107 "\
108 # Automatically generated by build.rs
109 CompileFlags:
110 Add:
111 "
112 )?;
113 for i in include_dirs {
114 writeln!(dot_clangd, " - --include-directory={}", i.display())?;
115 }
116
117 Ok(())
118 }
119
120 /// Add list of include directions in the environment variable `dep` to
121 /// `include_dirs`.
122 fn add_dep_includes(include_dirs: &mut Vec<PathBuf>, dep: &str) {
123 if let Some(include) = std::env::var_os(&dep) {
124 include_dirs.extend(split_paths(&include).collect::<Vec<_>>());
125 } else {
126 panic!("{dep} unset.");
127 }
128 }
129
130 fn add_dep_ldflags(dep: &str) {
131 if let Some(ldflags) = std::env::var_os(&dep) {
132 for lp in split_paths(&ldflags) {
133 println!("cargo:rustc-link-arg=-Wl,{}", lp.display());
134 }
135 } else {
136 panic!("{dep} unset.");
137 }
138 }

mercurial