dinghy_build/
lib.rs

1//! Helpers for build.rs scripts.
2//!
3//! This library is meant to be used in build.rs scripts context.
4//!
5//! It contains a set of standalone functions that encodes some of the
6//! shared wisdom and conventions across build.rs scripts, cargo, dinghy,
7//! cc-rs, pkg-config-rs, bindgen, and others. It also helps providing
8//! cross-compilation arguments to autotools `./configure` scripts.
9
10mod bindgen_macros;
11pub mod build;
12pub mod build_env;
13pub mod utils;
14
15use crate::build::is_cross_compiling;
16use crate::build_env::sysroot_path;
17use crate::build_env::target_env;
18use crate::utils::path_between;
19use crate::utils::path_to_str;
20use std::env;
21use std::ffi::OsStr;
22use std::path::Path;
23use std::path::PathBuf;
24use std::process::Command;
25
26#[doc(hidden)]
27pub use anyhow::{Context, Result};
28
29/// Decorator for the std::process::Command adding a some chainable helpers.
30///
31/// Mostly useful for calling `./configure` scripts.
32pub trait CommandExt {
33    /// Add this argument to the commands, but only on macos.
34    fn arg_for_macos<S: AsRef<OsStr>>(&mut self, arg: S) -> Result<&mut Command>;
35
36    /// Add a `--prefix` to point to a toolchain sysroot or the /, depending on
37    /// dinghy environment.
38    fn configure_prefix<P: AsRef<Path>>(&mut self, path: P) -> Result<&mut Command>;
39
40    /// Adds pkgconfig environment variables to point to an eventual cross compiling sysroot.
41    ///
42    /// Usefull for compatibilty with pkg-config-rs up to 0.3.9 or to deal with
43    /// `./configure` scripts.
44    fn with_pkgconfig(&mut self) -> Result<&mut Command>;
45
46    /// Propagate TARGET, TARGET_CC, TARGET_AR and TARGET_SYSROOT to a
47    /// `./configure` script.
48    fn with_toolchain(&mut self) -> Result<&mut Command>;
49}
50
51impl CommandExt for Command {
52    fn arg_for_macos<S: AsRef<OsStr>>(&mut self, arg: S) -> Result<&mut Command> {
53        if env::var("TARGET")
54            .map(|target| target.contains("-apple-darwin"))
55            .unwrap_or(false)
56        {
57            self.arg(arg.as_ref());
58        }
59        Ok(self)
60    }
61
62    fn configure_prefix<P: AsRef<Path>>(&mut self, prefix_dir: P) -> Result<&mut Command> {
63        self.args(&[
64            "--prefix",
65            path_to_str(&path_between(
66                sysroot_path().unwrap_or(PathBuf::from("/")),
67                prefix_dir,
68            ))?,
69        ]);
70        Ok(self)
71    }
72
73    fn with_pkgconfig(&mut self) -> Result<&mut Command> {
74        if is_cross_compiling()? {
75            if let Ok(value) = target_env("PKG_CONFIG_PATH") {
76                log::info!("Running command with PKG_CONFIG_PATH:{:?}", value);
77                self.env("PKG_CONFIG_PATH", value);
78            }
79            if let Ok(value) = target_env("PKG_CONFIG_LIBDIR") {
80                log::info!("Running command with PKG_CONFIG_LIBDIR:{:?}", value);
81                self.env("PKG_CONFIG_LIBDIR", value);
82            }
83            if let Ok(value) = target_env("PKG_CONFIG_SYSROOT_DIR") {
84                log::info!("Running command with PKG_CONFIG_SYSROOT_DIR:{:?}", value);
85                self.env("PKG_CONFIG_SYSROOT_DIR", value);
86            }
87        }
88        Ok(self)
89    }
90
91    fn with_toolchain(&mut self) -> Result<&mut Command> {
92        if is_cross_compiling()? {
93            if let Ok(target) = env::var("TARGET") {
94                self.arg(format!("--host={}", target));
95            }
96            if let Ok(cc) = env::var("TARGET_CC") {
97                self.arg(format!("CC={}", cc));
98            }
99            if let Ok(ar) = env::var("TARGET_AR") {
100                self.arg(format!("AR={}", ar));
101            }
102            if let Ok(sysroot) = env::var("TARGET_SYSROOT") {
103                self.arg(format!("--with-sysroot={}", &sysroot));
104            }
105        }
106        Ok(self)
107    }
108}