diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7007bce33..32ba56f3b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -99,8 +99,10 @@ jobs: run: | rustup target add aarch64-unknown-linux-gnu rustup target add aarch64-unknown-linux-musl + rustup target add aarch64-apple-darwin cargo run -- build --no-sdist -i python -m test-crates/pyo3-pure/Cargo.toml --target aarch64-unknown-linux-gnu --zig cargo run -- build --no-sdist -i python -m test-crates/pyo3-pure/Cargo.toml --target aarch64-unknown-linux-musl --zig + cargo run -- build --no-sdist -i python -m test-crates/pyo3-pure/Cargo.toml --target aarch64-apple-darwin --zig test-alpine: name: Test Alpine Linux diff --git a/Cargo.lock b/Cargo.lock index 1ad1fe35f..409f75d59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "cargo-zigbuild" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713fc3be70832f404d4538b8100306cc579bdb47ae8269c38245af67a553bc9c" +checksum = "e147af71d647d7d7705be89ae6786085d8de813888b07ae0537c89da4a2ec217" dependencies = [ "anyhow", "clap", @@ -244,6 +244,8 @@ dependencies = [ "fs-err", "rustc_version", "semver", + "serde", + "serde_json", "target-lexicon", ] @@ -323,9 +325,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d76c22c9b9b215eeb8d016ad3a90417bd13cb24cf8142756e6472445876cab7" +checksum = "5177fac1ab67102d8989464efd043c6ff44191b1557ec1ddd489b4f7e1447e77" dependencies = [ "atty", "bitflags", @@ -360,9 +362,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.1.0" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd1122e63869df2cb309f449da1ad54a7c6dfeb7c7e6ccd8e0825d9eb93bb72" +checksum = "01d42c94ce7c2252681b5fed4d3627cc807b13dfc033246bd05d5b252399000e" dependencies = [ "heck 0.4.0", "proc-macro-error", @@ -1408,9 +1410,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dada8c9981fcf32929c3c0f0cd796a9284aca335565227ed88c83babb1d43dc" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ "thiserror", "toml", @@ -2349,7 +2351,7 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4ca5e22593eb4212382d60d26350065bf2a02c34b85bc850474a74b589a3de9" dependencies = [ - "proc-macro-crate 1.1.2", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", diff --git a/Cargo.toml b/Cargo.toml index 63036c096..3ac01ebde 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ base64 = "0.13.0" bytesize = "1.0.1" glob = "0.3.0" cargo_metadata = "0.14.0" -cargo-zigbuild = "0.5.3" +cargo-zigbuild = "0.5.4" cbindgen = { version = "0.20.0", default-features = false } flate2 = "1.0.18" goblin = "0.5.1" diff --git a/src/build_context.rs b/src/build_context.rs index 8596b998b..84ceae3b3 100644 --- a/src/build_context.rs +++ b/src/build_context.rs @@ -151,6 +151,8 @@ pub struct BuildContext { pub module_name: String, /// The path to the Cargo.toml. Required for the cargo invocations pub manifest_path: PathBuf, + /// Directory for all generated artifacts + pub target_dir: PathBuf, /// The directory to store the built wheels in. Defaults to a new "wheels" /// directory in the project's target directory pub out: PathBuf, diff --git a/src/build_options.rs b/src/build_options.rs index c5e0b2fdd..f4eeb8381 100644 --- a/src/build_options.rs +++ b/src/build_options.rs @@ -334,6 +334,13 @@ impl BuildOptions { ); } + let target_dir = cargo_extra_args + .iter() + .position(|x| x == "--target-dir") + .and_then(|i| cargo_extra_args.get(i + 1)) + .map(PathBuf::from) + .unwrap_or_else(|| cargo_metadata.target_directory.clone().into_std_path_buf()); + Ok(BuildContext { target, bridge, @@ -342,6 +349,7 @@ impl BuildOptions { crate_name: crate_name.to_string(), module_name, manifest_path: manifest_file, + target_dir, out: wheel_dir, release, strip, diff --git a/src/compile.rs b/src/compile.rs index f568e1fda..094182b68 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -105,7 +105,18 @@ fn compile_target( python_interpreter: Option<&PythonInterpreter>, bindings_crate: &BridgeModel, ) -> Result> { - let (zig_cc, zig_cxx) = if context.zig && context.target.is_linux() { + let target = &context.target; + let target_triple = target.target_triple(); + let zig_triple = if target.is_linux() { + match context.platform_tag { + Some(PlatformTag::Manylinux { x, y }) => format!("{}.{}.{}", target_triple, x, y), + _ => target_triple.to_string(), + } + } else { + target_triple.to_string() + }; + let (zig_cc, zig_cxx) = if context.zig && !target.is_msvc() && target.host_triple != zig_triple + { let (cc, cxx) = prepare_zig_linker(context).context("Failed to create zig linker wrapper")?; (Some(cc), Some(cxx)) @@ -163,7 +174,7 @@ fn compile_target( let macos_dylib_install_name = format!("link-args=-Wl,-install_name,@rpath/{}", so_filename); // https://github.com/PyO3/pyo3/issues/88#issuecomment-337744403 - if context.target.is_macos() { + if target.is_macos() { if let BridgeModel::Bindings(_) | BridgeModel::BindingsAbi3(_, _) = bindings_crate { let mac_args = &[ "-C", @@ -190,7 +201,7 @@ fn compile_target( // however, we get an exit code 0xc0000005 if we try the same with // `/FORCE:UNDEFINED`, so we still look up the python interpreter // and pass the location of the lib with the definitions. - if context.target.is_windows() { + if target.is_windows() { let python_interpreter = python_interpreter .expect("Must have a python interpreter for building abi3 on windows"); pythonxy_lib_folder = format!("native={}", python_interpreter.libs_dir.display()); @@ -222,11 +233,7 @@ fn compile_target( // Also set TARGET_CC and TARGET_CXX for cc-rs and cmake-rs if let Some(zig_cc) = zig_cc { - let env_target = context - .target - .target_triple() - .to_uppercase() - .replace('-', "_"); + let env_target = target_triple.to_uppercase().replace('-', "_"); build_command.env("TARGET_CC", &zig_cc); build_command.env(format!("CARGO_TARGET_{}_LINKER", env_target), &zig_cc); } @@ -324,6 +331,8 @@ fn compile_target( } fn prepare_zig_linker(context: &BuildContext) -> Result<(PathBuf, PathBuf)> { + use cargo_zigbuild::macos::LIBICONV_TBD; + let target = &context.target; let triple = target.target_triple(); let triple = if target.is_linux() { @@ -339,6 +348,18 @@ fn prepare_zig_linker(context: &BuildContext) -> Result<(PathBuf, PathBuf)> { triple.to_string() }; let (cc, cxx) = cargo_zigbuild::zig::prepare_zig_linker(&triple)?; + + if target.is_macos() { + let target_dir = if target.user_specified { + context.target_dir.join(triple) + } else { + context.target_dir.clone() + }; + let profile = if context.release { "release" } else { "debug" }; + let deps_dir = target_dir.join(profile).join("deps"); + fs::create_dir_all(&deps_dir)?; + fs::write(deps_dir.join("libiconv.tbd"), LIBICONV_TBD)?; + } Ok((cc, cxx)) } diff --git a/src/target.rs b/src/target.rs index b0bb88fed..cff7b5806 100644 --- a/src/target.rs +++ b/src/target.rs @@ -102,6 +102,10 @@ pub struct Target { env: Environment, triple: String, cross_compiling: bool, + /// Host machine target triple + pub(crate) host_triple: String, + /// Is user specified `--target` + pub(crate) user_specified: bool, } impl Target { @@ -110,17 +114,17 @@ impl Target { /// /// Fails if the target triple isn't supported pub fn from_target_triple(target_triple: Option) -> Result { + let host_triple = get_host_target()?; let (platform, triple) = if let Some(ref target_triple) = target_triple { let platform: Triple = target_triple .parse() .map_err(|_| format_err!("Unknown target triple {}", target_triple))?; (platform, target_triple.to_string()) } else { - let target_triple = get_host_target()?; - let platform: Triple = target_triple + let platform: Triple = host_triple .parse() - .map_err(|_| format_err!("Unknown target triple {}", target_triple))?; - (platform, target_triple) + .map_err(|_| format_err!("Unknown target triple {}", host_triple))?; + (platform, host_triple.clone()) }; let os = match platform.operating_system { @@ -157,6 +161,8 @@ impl Target { arch, env: platform.environment, triple, + host_triple, + user_specified: target_triple.is_some(), cross_compiling: false, }; target.cross_compiling = is_cross_compiling(&target)?; @@ -367,6 +373,11 @@ impl Target { self.os == Os::Windows } + /// Returns true if the current environment is msvc + pub fn is_msvc(&self) -> bool { + self.env == Environment::Msvc + } + /// Returns true if the current platform is illumos pub fn is_illumos(&self) -> bool { self.os == Os::Illumos