Skip to content

Commit

Permalink
Add C++ support for --zig
Browse files Browse the repository at this point in the history
Set `TARGET_CC` and `TARGET_CXX` to support both cc-rs and cmake-rs
  • Loading branch information
messense committed Dec 29, 2021
1 parent 3015c7b commit e900a62
Showing 1 changed file with 46 additions and 21 deletions.
67 changes: 46 additions & 21 deletions src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn compile_universal2(
///
/// We create different files for different args because otherwise cargo might skip recompiling even
/// if the linker target changed
fn prepare_zig_linker(context: &BuildContext) -> Result<PathBuf> {
fn prepare_zig_linker(context: &BuildContext) -> Result<(PathBuf, PathBuf)> {
let target = &context.target;
let arch = if target.cross_compiling() {
if matches!(target.target_arch(), Arch::Armv7L) {
Expand All @@ -122,20 +122,24 @@ fn prepare_zig_linker(context: &BuildContext) -> Result<PathBuf> {
} else {
"native".to_string()
};
let (zig_linker, cc_args) = match context.platform_tag {
let (zig_cc, zig_cxx, cc_args) = match context.platform_tag {
// Not sure branch even has any use case, but it doesn't hurt to support it
None | Some(PlatformTag::Linux) => {
("./zigcc-gnu.sh".to_string(), format!("{}-linux-gnu", arch))
}
None | Some(PlatformTag::Linux) => (
"./zigcc-gnu.sh".to_string(),
"./zigcxx-gnu.sh".to_string(),
format!("{}-linux-gnu", arch),
),
Some(PlatformTag::Musllinux { x, y }) => {
println!("⚠️ Warning: zig with musl is unstable");
(
format!("./zigcc-musl-{}-{}.sh", x, y),
format!("./zigcxx-musl-{}-{}.sh", x, y),
format!("{}-linux-musl", arch),
)
}
Some(PlatformTag::Manylinux { x, y }) => (
format!("./zigcc-gnu-{}-{}.sh", x, y),
format!("./zigcxx-gnu-{}-{}.sh", x, y),
// https://github.com/ziglang/zig/issues/10050#issuecomment-956204098
format!(
"${{@/-lgcc_s/-lunwind}} -target {}-linux-gnu.{}.{}",
Expand All @@ -150,32 +154,49 @@ fn prepare_zig_linker(context: &BuildContext) -> Result<PathBuf> {
.join(env!("CARGO_PKG_NAME"))
.join(env!("CARGO_PKG_VERSION"));
fs::create_dir_all(&zig_linker_dir)?;
let zig_linker = zig_linker_dir.join(zig_linker);
let zig_cc = zig_linker_dir.join(zig_cc);
let zig_cxx = zig_linker_dir.join(zig_cxx);

let mut zig_cc_file = create_linker_script(&zig_cc)?;
writeln!(&mut zig_cc_file, "#!/bin/bash")?;
writeln!(&mut zig_cc_file, "python -m ziglang cc {}", cc_args)?;
drop(zig_cc_file);

let mut zig_cxx_file = create_linker_script(&zig_cxx)?;
writeln!(&mut zig_cxx_file, "#!/bin/bash")?;
writeln!(&mut zig_cxx_file, "python -m ziglang c++ {}", cc_args)?;
drop(zig_cxx_file);

Ok((zig_cc, zig_cxx))
}

#[cfg(target_family = "unix")]
let mut custom_linker_file = OpenOptions::new()
#[cfg(target_family = "unix")]
fn create_linker_script(path: &Path) -> Result<std::fs::File> {
let custom_linker_file = OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.mode(0o700)
.open(&zig_linker)?;
#[cfg(not(target_family = "unix"))]
let mut custom_linker_file = File::create(&zig_linker)?;
writeln!(&mut custom_linker_file, "#!/bin/bash")?;
writeln!(&mut custom_linker_file, "python -m ziglang cc {}", cc_args)?;
drop(custom_linker_file);
Ok(zig_linker)
.open(path)?;
Ok(custom_linker_file)
}

#[cfg(not(target_family = "unix"))]
fn create_linker_script(path: &Path) -> Result<File> {
File::create(path)
}

fn compile_target(
context: &BuildContext,
python_interpreter: Option<&PythonInterpreter>,
bindings_crate: &BridgeModel,
) -> Result<HashMap<String, PathBuf>> {
let zig_linker = if context.zig && context.target.is_linux() {
Some(prepare_zig_linker(context).context("Failed to create zig linker wrapper")?)
let (zig_cc, zig_cxx) = if context.zig && context.target.is_linux() {
let (cc, cxx) =
prepare_zig_linker(context).context("Failed to create zig linker wrapper")?;
(Some(cc), Some(cxx))
} else {
None
(None, None)
};

let mut shared_args = vec!["--manifest-path", context.manifest_path.to_str().unwrap()];
Expand Down Expand Up @@ -279,14 +300,18 @@ fn compile_target(
// but forwarding stderr is still useful in case there some non-json error
.stderr(Stdio::inherit());

if let Some(zig_linker) = zig_linker {
// 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("-", "_");
build_command.env(format!("{}_CC", env_target), &zig_linker);
build_command.env(format!("CARGO_TARGET_{}_LINKER", env_target), &zig_linker);
build_command.env("TARGET_CC", &zig_cc);
build_command.env(format!("CARGO_TARGET_{}_LINKER", env_target), &zig_cc);
}
if let Some(zig_cxx) = zig_cxx {
build_command.env("TARGET_CXX", &zig_cxx);
}

if let BridgeModel::BindingsAbi3(_, _) = bindings_crate {
Expand Down

0 comments on commit e900a62

Please sign in to comment.