1 // Copyright 2024, Linaro Limited
2 // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
3 // SPDX-License-Identifier: GPL-2.0-or-later
4 
5 #[cfg(unix)]
6 use std::os::unix::fs::symlink as symlink_file;
7 #[cfg(windows)]
8 use std::os::windows::fs::symlink_file;
9 use std::{env, fs::remove_file, io::Result, path::Path};
10 
11 fn main() -> Result<()> {
12     let manifest_dir = env!("CARGO_MANIFEST_DIR");
13     let file = if let Ok(root) = env::var("MESON_BUILD_ROOT") {
14         let sub = get_rust_subdir(manifest_dir).unwrap();
15         format!("{root}/{sub}/bindings.inc.rs")
16     } else {
17         // Placing bindings.inc.rs in the source directory is supported
18         // but not documented or encouraged.
19         format!("{manifest_dir}/src/bindings.inc.rs")
20     };
21 
22     let file = Path::new(&file);
23     if !Path::new(&file).exists() {
24         panic!(concat!(
25             "\n",
26             "    No generated C bindings found! Maybe you wanted one of\n",
27             "    `make clippy`, `make rustfmt`, `make rustdoc`?\n",
28             "\n",
29             "    For other uses of `cargo`, start a subshell with\n",
30             "    `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n",
31             "    the top of the build tree."
32         ));
33     }
34 
35     let out_dir = env::var("OUT_DIR").unwrap();
36     let dest_path = format!("{out_dir}/bindings.inc.rs");
37     let dest_path = Path::new(&dest_path);
38     if dest_path.symlink_metadata().is_ok() {
39         remove_file(dest_path)?;
40     }
41     symlink_file(file, dest_path)?;
42 
43     println!("cargo:rerun-if-changed=build.rs");
44     Ok(())
45 }
46 
47 fn get_rust_subdir(path: &str) -> Option<&str> {
48     path.find("/rust").map(|index| &path[index + 1..])
49 }
50