diff --git a/pq-src/build.rs b/pq-src/build.rs index 2c0b7e2..a2a1556 100644 --- a/pq-src/build.rs +++ b/pq-src/build.rs @@ -1,8 +1,7 @@ use std::path::PathBuf; +use std::{env, fs}; -const LIBPORTS: &'static [&'static str] = &[ - #[cfg(any(target_os = "linux", target_os = "windows"))] - "getpeereid.c", +const LIBPORTS_BASE: &[&str] = &[ "strlcat.c", "strlcpy.c", "snprintf.c", @@ -23,47 +22,35 @@ const LIBPORTS: &'static [&'static str] = &[ "quotes.c", "strerror.c", "tar.c", - #[cfg(not(target_os = "windows"))] - "thread.c", - #[cfg(any(target_os = "macos", target_os = "windows"))] +]; + +const LIBPORTS_LINUX: &[&str] = &["getpeereid.c", "thread.c"]; + +const LIBPORTS_MACOS: &[&str] = &["explicit_bzero.c", "thread.c"]; + +const LIBPORTS_WINDOWS: &[&str] = &[ + "getpeereid.c", "explicit_bzero.c", - #[cfg(target_os = "windows")] "win32common.c", - #[cfg(target_os = "windows")] "win32dlopen.c", - #[cfg(target_os = "windows")] "win32env.c", - #[cfg(target_os = "windows")] "win32error.c", - #[cfg(target_os = "windows")] "win32fdatasync.c", - #[cfg(target_os = "windows")] "win32fseek.c", - #[cfg(target_os = "windows")] "win32getrusage.c", - #[cfg(target_os = "windows")] "win32gettimeofday.c", - #[cfg(target_os = "windows")] "win32link.c", - #[cfg(target_os = "windows")] "win32ntdll.c", - #[cfg(target_os = "windows")] "win32pread.c", - #[cfg(target_os = "windows")] "win32pwrite.c", - #[cfg(target_os = "windows")] "win32security.c", - #[cfg(target_os = "windows")] "win32setlocale.c", - #[cfg(target_os = "windows")] "win32stat.c", - #[cfg(target_os = "windows")] "open.c", - #[cfg(target_os = "windows")] "dirmod.c", ]; -const LIBCOMMON: &'static [&'static str] = &[ +const LIBCOMMON_BASE: &[&str] = &[ "file_perm.c", "encnames.c", "base64.c", @@ -87,31 +74,28 @@ const LIBCOMMON: &'static [&'static str] = &[ "username.c", "wait_error.c", "wchar.c", - #[cfg(not(target_os = "windows"))] - "cryptohash_openssl.c", - #[cfg(target_os = "windows")] - "cryptohash.c", - #[cfg(not(target_os = "windows"))] - "hmac_openssl.c", - #[cfg(target_os = "windows")] - "hmac.c", - #[cfg(not(target_os = "windows"))] - "protocol_openssl.c", "fe_memutils.c", "restricted_token.c", "sprompt.c", "logging.c", - #[cfg(target_os = "windows")] +]; + +const LIBCOMMON_NOT_WINDOWS: &[&str] = &[ + "cryptohash_openssl.c", + "hmac_openssl.c", + "protocol_openssl.c", +]; + +const LIBCOMMON_WINDOWS: &[&str] = &[ + "cryptohash.c", + "hmac.c", "md5.c", - #[cfg(target_os = "windows")] "sha1.c", - #[cfg(target_os = "windows")] "sha2.c", - #[cfg(target_os = "windows")] "wchar.c", ]; -const LIBPQ: &'static [&'static str] = &[ +const LIBPQ_BASE: &[&str] = &[ "fe-auth-scram.c", "fe-auth.c", "fe-connect.c", @@ -125,128 +109,144 @@ const LIBPQ: &'static [&'static str] = &[ "legacy-pqsignal.c", "libpq-events.c", "pqexpbuffer.c", - #[cfg(not(target_os = "windows"))] - "fe-secure-common.c", - #[cfg(not(target_os = "windows"))] - "fe-secure-openssl.c", - #[cfg(target_os = "windows")] - "fe-secure.c", - #[cfg(target_os = "windows")] - "pthread-win32.c", - #[cfg(target_os = "windows")] - "win32.c", ]; +const LIBPQ_NOT_WINDOWS: &[&str] = &["fe-secure-common.c", "fe-secure-openssl.c"]; + +const LIBPQ_WINDOWS: &[&str] = &["fe-secure.c", "pthread-win32.c", "win32.c"]; + +fn unimplemented() -> ! { + unimplemented!( + "Building a bundled version of libpq is currently not supported for this OS\n\ + If you are interested in support for using a bundled libpq we are happy to accept patches \ + at https://github.com/sgrif/pq-sys/" + ); +} + fn main() { + let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); + println!("cargo:rerun-if-changed=additional_include"); let crate_dir = env!("CARGO_MANIFEST_DIR"); - let temp_include = format!("{}/more_include/", std::env::var("OUT_DIR").unwrap()); + let temp_include = format!("{}/more_include/", env::var("OUT_DIR").unwrap()); let path = format!("{crate_dir}/source/"); let port_path = "src/port/"; let common_path = "src/common/"; let pq_path = "src/interfaces/libpq/"; if !PathBuf::from(&temp_include).exists() { - std::fs::create_dir(&temp_include).unwrap(); + fs::create_dir(&temp_include).unwrap(); } if !PathBuf::from(format!("{temp_include}pg_config_os.h")).exists() { - if cfg!(target_os = "linux") { - std::fs::copy( - format!("{path}src/include/port/linux.h"), - format!("{temp_include}pg_config_os.h"), - ) - .unwrap(); - } else if cfg!(target_os = "macos") { - std::fs::copy( - format!("{path}src/include/port/darwin.h"), - format!("{temp_include}pg_config_os.h"), - ) - .unwrap(); - } else if cfg!(target_os = "windows") { - std::fs::copy( - format!("{path}src/include/port/win32.h"), - format!("{temp_include}pg_config_os.h"), - ) - .unwrap(); - println!("cargo:rustc-link-lib=Secur32"); - println!("cargo:rustc-link-lib=Shell32"); - } else { - unimplemented!( - "Building a bundled version of libpq is currently not supported for this OS\n\ - If you are interested in support for using a bundled libpq we are happy to accept patches \n - at https://github.com/sgrif/pq-sys/" - ); + match target_os.as_str() { + "linux" => { + fs::copy( + format!("{path}src/include/port/linux.h"), + format!("{temp_include}pg_config_os.h"), + ) + .unwrap(); + } + "macos" => { + fs::copy( + format!("{path}src/include/port/darwin.h"), + format!("{temp_include}pg_config_os.h"), + ) + .unwrap(); + } + "windows" => { + fs::copy( + format!("{path}src/include/port/win32.h"), + format!("{temp_include}pg_config_os.h"), + ) + .unwrap(); + println!("cargo:rustc-link-lib=Secur32"); + println!("cargo:rustc-link-lib=Shell32"); + } + _ => unimplemented(), } } - #[cfg(not(target_os = "windows"))] - let openssl = std::env::var("DEP_OPENSSL_INCLUDE").unwrap(); let mut basic_build = cc::Build::new(); + let base_includes = &[ + format!("{path}{port_path}"), + format!("{path}src/include"), + format!("{crate_dir}/additional_include"), + temp_include.clone(), + ][..]; + + let includes = if target_os == "windows" { + let includes_windows = &[ + format!("{path}/src/include/port/win32/"), + format!("{path}/src/include/port/win32_msvc/"), + ]; + [base_includes, includes_windows].concat() + } else { + let includes_not_windows = &[env::var("DEP_OPENSSL_INCLUDE").unwrap().clone()]; + [base_includes, includes_not_windows].concat() + }; + basic_build .define("FRONTEND", None) .warnings(false) - .includes([ - format!("{path}{port_path}"), - format!("{path}src/include"), - format!("{crate_dir}/additional_include"), - temp_include.clone(), - #[cfg(not(target_os = "windows"))] - openssl.clone(), - #[cfg(target_os = "windows")] - format!("{path}/src/include/port/win32/"), - #[cfg(target_os = "windows")] - format!("{path}/src/include/port/win32_msvc/"), - ]); + .includes(includes); - if cfg!(feature = "with-asan") { + if env::var("CARGO_FEATURE_WITH_ASAN").is_ok() { basic_build.flag("-fsanitize=address"); } - if cfg!(target_os = "linux") { - basic_build.define("_GNU_SOURCE", None); - } - if cfg!(target_os = "macos") { - // something is broken in homebrew - // https://github.com/Homebrew/legacy-homebrew/pull/23620 - basic_build.define("_FORTIFY_SOURCE", Some("0")); - } - if cfg!(target_os = "windows") { - basic_build.define("WIN32", None); - basic_build.define("_WINDOWS", None); - basic_build.define("__WIN32__", None); - basic_build.define("__WINDOWS__", None); - } + let (libports_os, libcommon_os, libpq_os) = match target_os.as_str() { + "linux" => { + basic_build.define("_GNU_SOURCE", None); + (LIBPORTS_LINUX, LIBCOMMON_NOT_WINDOWS, LIBPQ_NOT_WINDOWS) + } + "macos" => { + // something is broken in homebrew + // https://github.com/Homebrew/legacy-homebrew/pull/23620 + basic_build.define("_FORTIFY_SOURCE", Some("0")); + (LIBPORTS_MACOS, LIBCOMMON_NOT_WINDOWS, LIBPQ_NOT_WINDOWS) + } + "windows" => { + basic_build.define("WIN32", None); + basic_build.define("_WINDOWS", None); + basic_build.define("__WIN32__", None); + basic_build.define("__WINDOWS__", None); + basic_build.define("HAVE_SOCKLEN_T", Some("1")); + (LIBPORTS_WINDOWS, LIBCOMMON_WINDOWS, LIBPQ_WINDOWS) + } + _ => unimplemented(), + }; + + let libports = LIBPORTS_BASE.iter().chain(libports_os); + let libcommon = LIBCOMMON_BASE.iter().chain(libcommon_os); + let libpq = LIBPQ_BASE.iter().chain(libpq_os); basic_build - .clone() .files( - LIBPORTS - .iter() - .map(|p| format!("{path}{port_path}{p}")) - .chain(LIBCOMMON.iter().map(|p| format!("{path}{common_path}{p}"))) - .chain(LIBPQ.iter().map(|p| format!("{path}{pq_path}{p}"))), + (libports.map(|p| format!("{path}{port_path}{p}"))) + .chain(libcommon.map(|p| format!("{path}{common_path}{p}"))) + .chain(libpq.map(|p| format!("{path}{pq_path}{p}"))), ) .compile("pq"); - let out = std::env::var("OUT_DIR").expect("Set by cargo"); + let out = env::var("OUT_DIR").expect("Set by cargo"); let include_path = PathBuf::from(&out).join("include"); let lib_pq_path = PathBuf::from(format!("{path}/{pq_path}")); - std::fs::create_dir_all(&include_path).expect("Failed to create include directory"); - std::fs::create_dir_all(include_path.join("postgres").join("internal")) + fs::create_dir_all(&include_path).expect("Failed to create include directory"); + fs::create_dir_all(include_path.join("postgres").join("internal")) .expect("Failed to create include directory"); - std::fs::copy( + fs::copy( lib_pq_path.join("libpq-fe.h"), include_path.join("libpq-fe.h"), ) .expect("Copying headers failed"); - std::fs::copy( + fs::copy( lib_pq_path.join("libpq-events.h"), include_path.join("libpq-events.h"), ) .expect("Copying headers failed"); - std::fs::copy( + fs::copy( lib_pq_path.join("libpq-int.h"), include_path .join("postgres") @@ -254,7 +254,7 @@ fn main() { .join("libpq-int.h"), ) .expect("Copying headers failed"); - std::fs::copy( + fs::copy( lib_pq_path.join("fe-auth-sasl.h"), include_path .join("postgres") @@ -262,7 +262,7 @@ fn main() { .join("fe-auth-sasl.h"), ) .expect("Copying headers failed"); - std::fs::copy( + fs::copy( lib_pq_path.join("pqexpbuffer.h"), include_path .join("postgres")