Use env::var instead of cfg in some cases in build.rs (#961)

Co-authored-by: Thom Chiovoloni <chiovolonit@gmail.com>
This commit is contained in:
daladim 2021-05-28 09:00:39 +02:00 committed by GitHub
parent df02910660
commit 5511a12e57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 44 deletions

View File

@ -40,6 +40,4 @@ winsqlite3 = ["min_sqlite_version_3_7_16"]
bindgen = { version = "0.58", optional = true, default-features = false, features = ["runtime"] } bindgen = { version = "0.58", optional = true, default-features = false, features = ["runtime"] }
pkg-config = { version = "0.3.19", optional = true } pkg-config = { version = "0.3.19", optional = true }
cc = { version = "1.0", optional = true } cc = { version = "1.0", optional = true }
[target.'cfg(target_env = "msvc")'.build-dependencies]
vcpkg = { version = "0.2", optional = true } vcpkg = { version = "0.2", optional = true }

View File

@ -1,6 +1,31 @@
use std::env; use std::env;
use std::path::Path; 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() { fn main() {
let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap();
let out_path = Path::new(&out_dir).join("bindgen.rs"); let out_path = Path::new(&out_dir).join("bindgen.rs");
@ -12,40 +37,40 @@ fn main() {
return; return;
} }
if cfg!(feature = "sqlcipher") { if cfg!(feature = "sqlcipher") {
if cfg!(any( if cfg!(feature = "bundled") || (win_target() && cfg!(feature = "bundled-windows")) {
feature = "bundled",
all(windows, feature = "bundled-windows")
)) {
println!( println!(
"cargo:warning=Builds with bundled SQLCipher are not supported. Searching for SQLCipher to link against. \ "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!"); This can lead to issues if your version of SQLCipher is not up to date!");
} }
build_linked::main(&out_dir, &out_path) 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 { } else {
// This can't be `cfg!` without always requiring our `mod build_bundled` (and build_linked::main(&out_dir, &out_path)
// 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)
}
} }
} }
#[cfg(any(feature = "bundled", all(windows, feature = "bundled-windows")))] #[cfg(any(feature = "bundled", feature = "bundled-windows"))]
mod build_bundled { mod build_bundled {
use std::env; use std::env;
use std::path::Path; use std::path::Path;
use super::{is_compiler, win_target};
pub fn main(out_dir: &str, out_path: &Path) { pub fn main(out_dir: &str, out_path: &Path) {
if cfg!(feature = "sqlcipher") { if cfg!(feature = "sqlcipher") {
// This is just a sanity check, the top level `main` should ensure this. // This is just a sanity check, the top level `main` should ensure this.
panic!("Builds with bundled SQLCipher are not supported"); 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")] #[cfg(feature = "buildtime_bindgen")]
{ {
use super::{bindings, HeaderLocation}; use super::{bindings, HeaderLocation};
@ -86,7 +111,7 @@ mod build_bundled {
// on android sqlite can't figure out where to put the temp files. // on android sqlite can't figure out where to put the temp files.
// the bundled sqlite on android also uses `SQLITE_TEMP_STORE=3`. // the bundled sqlite on android also uses `SQLITE_TEMP_STORE=3`.
// https://android.googlesource.com/platform/external/sqlite/+/2c8c9ae3b7e6f340a19a0001c2a889a211c9d8b2/dist/Android.mk // 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"); 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 // There may be other platforms that don't support `isnan`, they should be
// tested for here. // tested for here.
if cfg!(target_env = "msvc") { if is_compiler("msvc") {
use cc::windows_registry::{find_vs_version, VsVers}; use cc::windows_registry::{find_vs_version, VsVers};
let vs_has_nan = match find_vs_version() { let vs_has_nan = match find_vs_version() {
Ok(ver) => ver != VsVers::Vs12, Ok(ver) => ver != VsVers::Vs12,
@ -113,11 +138,11 @@ mod build_bundled {
} else { } else {
cfg.flag("-DHAVE_ISNAN"); cfg.flag("-DHAVE_ISNAN");
} }
if cfg!(not(target_os = "windows")) { if !win_target() {
cfg.flag("-DHAVE_LOCALTIME_R"); cfg.flag("-DHAVE_LOCALTIME_R");
} }
// Target wasm32-wasi can't compile the default VFS // 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") cfg.flag("-DSQLITE_OS_OTHER")
// https://github.com/rust-lang/rust/issues/74393 // https://github.com/rust-lang/rust/issues/74393
.flag("-DLONGDOUBLE_TYPE=double"); .flag("-DLONGDOUBLE_TYPE=double");
@ -199,20 +224,18 @@ impl From<HeaderLocation> for String {
} }
mod build_linked { mod build_linked {
#[cfg(all(feature = "vcpkg", target_env = "msvc"))] #[cfg(feature = "vcpkg")]
extern crate 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::env;
use std::path::Path; use std::path::Path;
pub fn main(_out_dir: &str, out_path: &Path) { pub fn main(_out_dir: &str, out_path: &Path) {
let header = find_sqlite(); let header = find_sqlite();
if cfg!(any( if (cfg!(any(feature = "bundled_bindings", feature = "bundled"))
feature = "bundled_bindings", || (win_target() && cfg!(feature = "bundled-windows")))
feature = "bundled", && !cfg!(feature = "buildtime_bindgen")
all(windows, feature = "bundled-windows")
)) && !cfg!(feature = "buildtime_bindgen")
{ {
// Generally means the `bundled_bindings` feature is enabled // Generally means the `bundled_bindings` feature is enabled
// (there's also an edge case where we get here involving // (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={}_INCLUDE_DIR", env_prefix());
println!("cargo:rerun-if-env-changed={}_LIB_DIR", env_prefix()); println!("cargo:rerun-if-env-changed={}_LIB_DIR", env_prefix());
println!("cargo:rerun-if-env-changed={}_STATIC", 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"); println!("cargo:rerun-if-env-changed=VCPKGRS_DYNAMIC");
} }
@ -252,7 +275,7 @@ mod build_linked {
// on is available, for example. // on is available, for example.
println!("cargo:link-target={}", link_lib); 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); println!("cargo:rustc-link-lib=dylib={}", link_lib);
return HeaderLocation::Wrapper; return HeaderLocation::Wrapper;
} }
@ -298,27 +321,25 @@ mod build_linked {
} }
} }
#[cfg(all(feature = "vcpkg", target_env = "msvc"))]
fn try_vcpkg() -> Option<HeaderLocation> { fn try_vcpkg() -> Option<HeaderLocation> {
// See if vcpkg can find it. if cfg!(feature = "vcpkg") && is_compiler("msvc") {
if let Ok(mut lib) = vcpkg::Config::new().probe(link_lib()) { // See if vcpkg can find it.
if let Some(mut header) = lib.include_paths.pop() { if let Ok(mut lib) = vcpkg::Config::new().probe(link_lib()) {
header.push("sqlite3.h"); if let Some(mut header) = lib.include_paths.pop() {
return Some(HeaderLocation::FromPath(header.to_string_lossy().into())); 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<HeaderLocation> {
None
} }
fn link_lib() -> &'static str { fn link_lib() -> &'static str {
if cfg!(feature = "sqlcipher") { if cfg!(feature = "sqlcipher") {
"sqlcipher" "sqlcipher"
} else if cfg!(all(windows, feature = "winsqlite3")) { } else if win_target() && cfg!(feature = "winsqlite3") {
"winsqlite3" "winsqlite3"
} else { } else {
"sqlite3" "sqlite3"
@ -358,6 +379,8 @@ mod bindings {
use std::io::Write; use std::io::Write;
use std::path::Path; use std::path::Path;
use super::win_target;
#[derive(Debug)] #[derive(Debug)]
struct SqliteTypeChooser; struct SqliteTypeChooser;
@ -400,7 +423,7 @@ mod bindings {
if cfg!(feature = "session") { if cfg!(feature = "session") {
bindings = bindings.clang_arg("-DSQLITE_ENABLE_SESSION"); bindings = bindings.clang_arg("-DSQLITE_ENABLE_SESSION");
} }
if cfg!(all(windows, feature = "winsqlite3")) { if win_target() && cfg!(feature = "winsqlite3") {
bindings = bindings bindings = bindings
.clang_arg("-DBINDGEN_USE_WINSQLITE3") .clang_arg("-DBINDGEN_USE_WINSQLITE3")
.blocklist_item("NTDDI_.+") .blocklist_item("NTDDI_.+")