Skip to content

Commit b430952

Browse files
committed
Correctly fix C++ cross-compilation w/ clang++ on FreeBSD
When cross compiling, we are forced to emit the `--target=<triple>` compiler flag, but this can break clang++ C++ builds on FreeBSD if the triple isn't set to a value that causes clang++ to infer the use of libc++ instead of libstdc++ (the latter of which does not support C++11 and beyond on FreeBSD). By manually specifying the usage of `-std=libc++` we avoid the need to know which version of FreeBSD we are targeting (as we do not have that information from the rust target triple and cannot infer it from the host as we are cross-compiling). Note that we were already specifying a default stdlib value libc++ for `cpp_link_stdlib` under FreeBSD but that is not sufficient. This fix supersedes #788. See relevant discussions in #785 and #788.
1 parent 7fd191b commit b430952

File tree

1 file changed

+21
-19
lines changed

1 file changed

+21
-19
lines changed

src/lib.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,26 +1724,28 @@ impl Build {
17241724
} else if target.contains("aarch64") {
17251725
cmd.args.push("--target=aarch64-unknown-windows-gnu".into())
17261726
}
1727-
} else if target.ends_with("-freebsd") && self.get_host()?.ends_with("-freebsd")
1728-
{
1729-
// clang <= 13 on FreeBSD doesn't support a target triple without at least
1730-
// the major os version number appended; e.g. use x86_64-unknown-freebsd13
1731-
// or x86_64-unknown-freebsd13.0 instead of x86_64-unknown-freebsd.
1732-
// The current version is appended. If it doesn't align with your goals, pass
1733-
// .flag("--target=...") in the build script or adjust CXXFLAGS accordingly.
1734-
let stdout = std::process::Command::new("freebsd-version")
1735-
.output()
1736-
.map_err(|e| {
1737-
Error::new(
1738-
ErrorKind::ToolNotFound,
1739-
&format!("Error executing freebsd-version: {}", e),
1740-
)
1741-
})?
1742-
.stdout;
1743-
let stdout = String::from_utf8_lossy(&stdout);
1744-
let os_ver = stdout.split('-').next().unwrap();
1727+
} else if target.ends_with("-freebsd") {
1728+
// FreeBSD only supports C++11 and above when compiling against libc++
1729+
// (available from FreeBSD 10 onwards). Under FreeBSD, clang uses libc++ by
1730+
// default on FreeBSD 10 and newer unless `--target` is manually passed to
1731+
// the compiler, in which case its default behavior differs:
1732+
// * If --target=xxx-unknown-freebsdX(.Y) is specified and X is higher than
1733+
// 10, clang++ uses libc++
1734+
// * If --target=xxx-unknown-freebsd is specified (without a version),
1735+
// clang++ cannot assume libc++ is available and reverts to a default of
1736+
// libstdc++ (this behavior was changed in llvm 14).
1737+
//
1738+
// This breaks C++11 (or greater) builds if targeting FreeBSD with the
1739+
// generic xxx-unknown-freebsd triple on clang 13 or below *without*
1740+
// explicitly specifying that libc++ should be used.
1741+
// When cross-compiling, we can't infer from the rust/cargo target triple
1742+
// which major version of FreeBSD we are targeting, so we need to make sure
1743+
// that libc++ is used (unless the user has explicitly specified otherwise).
1744+
if self.cpp && self.cpp_set_stdlib.is_none() {
1745+
cmd.push_cc_arg("-stdlib=libc++".into());
1746+
}
17451747

1746-
cmd.push_cc_arg(format!("--target={}{}", target, os_ver).into());
1748+
cmd.push_cc_arg(format!("--target={}", target).into());
17471749
} else {
17481750
cmd.push_cc_arg(format!("--target={}", target).into());
17491751
}

0 commit comments

Comments
 (0)