From 5511a12e57af7bead3d32bdc0618cf754e56a97e Mon Sep 17 00:00:00 2001 From: daladim Date: Fri, 28 May 2021 09:00:39 +0200 Subject: [PATCH] Use `env::var` instead of `cfg` in some cases in build.rs (#961) Co-authored-by: Thom Chiovoloni --- libsqlite3-sys/Cargo.toml | 2 - libsqlite3-sys/build.rs | 107 +++++++++++++++++++++++--------------- 2 files changed, 65 insertions(+), 44 deletions(-) diff --git a/libsqlite3-sys/Cargo.toml b/libsqlite3-sys/Cargo.toml index 5ea27ec..cb51944 100644 --- a/libsqlite3-sys/Cargo.toml +++ b/libsqlite3-sys/Cargo.toml @@ -40,6 +40,4 @@ winsqlite3 = ["min_sqlite_version_3_7_16"] bindgen = { version = "0.58", optional = true, default-features = false, features = ["runtime"] } pkg-config = { version = "0.3.19", optional = true } cc = { version = "1.0", optional = true } - -[target.'cfg(target_env = "msvc")'.build-dependencies] vcpkg = { version = "0.2", optional = true } diff --git a/libsqlite3-sys/build.rs b/libsqlite3-sys/build.rs index 103b142..593061c 100644 --- a/libsqlite3-sys/build.rs +++ b/libsqlite3-sys/build.rs @@ -1,6 +1,31 @@ use std::env; use std::path::Path; +/// Tells whether we're building for Windows. This is more suitable than a plain +/// `cfg!(windows)`, since the latter does not properly handle cross-compilation +/// +/// Note that there is no way to know at compile-time which system we'll be +/// targetting, and this test must be made at run-time (of the build script) See +/// https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts +fn win_target() -> bool { + std::env::var("CARGO_CFG_WINDOWS").is_ok() +} + +/// Tells whether we're building for Android. +/// See [`win_target`] +#[cfg(any(feature = "bundled", feature = "bundled-windows"))] +fn android_target() -> bool { + std::env::var("CARGO_CFG_TARGET_OS").map_or(false, |v| v == "android") +} + +/// Tells whether a given compiler will be used `compiler_name` is compared to +/// the content of `CARGO_CFG_TARGET_ENV` (and is always lowercase) +/// +/// See [`win_target`] +fn is_compiler(compiler_name: &str) -> bool { + std::env::var("CARGO_CFG_TARGET_ENV").map_or(false, |v| v == compiler_name) +} + fn main() { let out_dir = env::var("OUT_DIR").unwrap(); let out_path = Path::new(&out_dir).join("bindgen.rs"); @@ -12,40 +37,40 @@ fn main() { return; } if cfg!(feature = "sqlcipher") { - if cfg!(any( - feature = "bundled", - all(windows, feature = "bundled-windows") - )) { + if cfg!(feature = "bundled") || (win_target() && cfg!(feature = "bundled-windows")) { println!( "cargo:warning=Builds with bundled SQLCipher are not supported. Searching for SQLCipher to link against. \ This can lead to issues if your version of SQLCipher is not up to date!"); } build_linked::main(&out_dir, &out_path) + } else if cfg!(feature = "bundled") || (win_target() && cfg!(feature = "bundled-windows")) { + #[cfg(any(feature = "bundled", feature = "bundled-windows"))] + build_bundled::main(&out_dir, &out_path); + #[cfg(not(any(feature = "bundled", feature = "bundled-windows")))] + panic!("The runtime test should not run this branch, which has not compiled any logic.") } else { - // This can't be `cfg!` without always requiring our `mod build_bundled` (and - // thus `cc`) - #[cfg(any(feature = "bundled", all(windows, feature = "bundled-windows")))] - { - build_bundled::main(&out_dir, &out_path) - } - #[cfg(not(any(feature = "bundled", all(windows, feature = "bundled-windows"))))] - { - build_linked::main(&out_dir, &out_path) - } + build_linked::main(&out_dir, &out_path) } } -#[cfg(any(feature = "bundled", all(windows, feature = "bundled-windows")))] +#[cfg(any(feature = "bundled", feature = "bundled-windows"))] mod build_bundled { use std::env; use std::path::Path; + use super::{is_compiler, win_target}; + pub fn main(out_dir: &str, out_path: &Path) { if cfg!(feature = "sqlcipher") { // This is just a sanity check, the top level `main` should ensure this. panic!("Builds with bundled SQLCipher are not supported"); } + if cfg!(feature = "bundled-windows") && !cfg!(feature = "bundled") && !win_target() { + // This is just a sanity check, the top level `main` should ensure this. + panic!("This module should not be used: we're not on Windows and the bundled feature has not been enabled"); + } + #[cfg(feature = "buildtime_bindgen")] { use super::{bindings, HeaderLocation}; @@ -86,7 +111,7 @@ mod build_bundled { // on android sqlite can't figure out where to put the temp files. // the bundled sqlite on android also uses `SQLITE_TEMP_STORE=3`. // https://android.googlesource.com/platform/external/sqlite/+/2c8c9ae3b7e6f340a19a0001c2a889a211c9d8b2/dist/Android.mk - if cfg!(target_os = "android") { + if super::android_target() { cfg.flag("-DSQLITE_TEMP_STORE=3"); } @@ -101,7 +126,7 @@ mod build_bundled { // // There may be other platforms that don't support `isnan`, they should be // tested for here. - if cfg!(target_env = "msvc") { + if is_compiler("msvc") { use cc::windows_registry::{find_vs_version, VsVers}; let vs_has_nan = match find_vs_version() { Ok(ver) => ver != VsVers::Vs12, @@ -113,11 +138,11 @@ mod build_bundled { } else { cfg.flag("-DHAVE_ISNAN"); } - if cfg!(not(target_os = "windows")) { + if !win_target() { cfg.flag("-DHAVE_LOCALTIME_R"); } // Target wasm32-wasi can't compile the default VFS - if env::var("TARGET") == Ok("wasm32-wasi".to_string()) { + if is_compiler("wasm32-wasi") { cfg.flag("-DSQLITE_OS_OTHER") // https://github.com/rust-lang/rust/issues/74393 .flag("-DLONGDOUBLE_TYPE=double"); @@ -199,20 +224,18 @@ impl From for String { } mod build_linked { - #[cfg(all(feature = "vcpkg", target_env = "msvc"))] + #[cfg(feature = "vcpkg")] extern crate vcpkg; - use super::{bindings, env_prefix, HeaderLocation}; + use super::{bindings, env_prefix, is_compiler, win_target, HeaderLocation}; use std::env; use std::path::Path; pub fn main(_out_dir: &str, out_path: &Path) { let header = find_sqlite(); - if cfg!(any( - feature = "bundled_bindings", - feature = "bundled", - all(windows, feature = "bundled-windows") - )) && !cfg!(feature = "buildtime_bindgen") + if (cfg!(any(feature = "bundled_bindings", feature = "bundled")) + || (win_target() && cfg!(feature = "bundled-windows"))) + && !cfg!(feature = "buildtime_bindgen") { // Generally means the `bundled_bindings` feature is enabled // (there's also an edge case where we get here involving @@ -242,7 +265,7 @@ mod build_linked { println!("cargo:rerun-if-env-changed={}_INCLUDE_DIR", env_prefix()); println!("cargo:rerun-if-env-changed={}_LIB_DIR", env_prefix()); println!("cargo:rerun-if-env-changed={}_STATIC", env_prefix()); - if cfg!(all(feature = "vcpkg", target_env = "msvc")) { + if cfg!(feature = "vcpkg") && is_compiler("msvc") { println!("cargo:rerun-if-env-changed=VCPKGRS_DYNAMIC"); } @@ -252,7 +275,7 @@ mod build_linked { // on is available, for example. println!("cargo:link-target={}", link_lib); - if cfg!(all(windows, feature = "winsqlite3")) { + if win_target() && cfg!(feature = "winsqlite3") { println!("cargo:rustc-link-lib=dylib={}", link_lib); return HeaderLocation::Wrapper; } @@ -298,27 +321,25 @@ mod build_linked { } } - #[cfg(all(feature = "vcpkg", target_env = "msvc"))] fn try_vcpkg() -> Option { - // See if vcpkg can find it. - if let Ok(mut lib) = vcpkg::Config::new().probe(link_lib()) { - if let Some(mut header) = lib.include_paths.pop() { - header.push("sqlite3.h"); - return Some(HeaderLocation::FromPath(header.to_string_lossy().into())); + if cfg!(feature = "vcpkg") && is_compiler("msvc") { + // See if vcpkg can find it. + if let Ok(mut lib) = vcpkg::Config::new().probe(link_lib()) { + if let Some(mut header) = lib.include_paths.pop() { + header.push("sqlite3.h"); + return Some(HeaderLocation::FromPath(header.to_string_lossy().into())); + } } + None + } else { + None } - None - } - - #[cfg(not(all(feature = "vcpkg", target_env = "msvc")))] - fn try_vcpkg() -> Option { - None } fn link_lib() -> &'static str { if cfg!(feature = "sqlcipher") { "sqlcipher" - } else if cfg!(all(windows, feature = "winsqlite3")) { + } else if win_target() && cfg!(feature = "winsqlite3") { "winsqlite3" } else { "sqlite3" @@ -358,6 +379,8 @@ mod bindings { use std::io::Write; use std::path::Path; + use super::win_target; + #[derive(Debug)] struct SqliteTypeChooser; @@ -400,7 +423,7 @@ mod bindings { if cfg!(feature = "session") { bindings = bindings.clang_arg("-DSQLITE_ENABLE_SESSION"); } - if cfg!(all(windows, feature = "winsqlite3")) { + if win_target() && cfg!(feature = "winsqlite3") { bindings = bindings .clang_arg("-DBINDGEN_USE_WINSQLITE3") .blocklist_item("NTDDI_.+")