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