@@ -115,6 +115,40 @@ pub fn find_target(build: &Build, target: TargetSelection) {
115115 }
116116
117117 let compiler = cfg. get_compiler ( ) ;
118+
119+ // When the cc crate cannot find the appropriate C compiler for the requested target, rather
120+ // than erroring out it returns the default C compiler. In most cases, this is wrong.
121+ //
122+ // For example, let's say that you're cross-compiling for aarch64-unknown-none from an x86_64
123+ // host, and that target is not recognized by the cc crate. In that case, the detected cc will
124+ // be an x86_64 compiler, even though we're compiling for aarch64-unknown-none. If a crate then
125+ // compiles some C code in its build script, the resulting rlib will have mixed AArch64 and
126+ // x86_64 objects in it, and the linker will show rather unhelpful messages.
127+ //
128+ // To avoid the confusing error messages, we detect whether the configuration is likely broken,
129+ // and if so we replace the detected C compiler with a stub binary that prints a useful error
130+ // message, telling the user to manually configure their C compiler.
131+ //
132+ // We use a custom binary rather than erroring out directly here because some build steps might
133+ // not need a C compiler at all, and it would be annoying to prevent the build in those cases.
134+ let default_cc = new_cc_build ( build, build. build ) . get_compiler ( ) ;
135+ if target != build. build && !compiler. is_like_clang ( ) && compiler. path ( ) == default_cc. path ( ) {
136+ let mut broken_cc = new_cc_build ( build, target) ;
137+ broken_cc. compiler (
138+ std:: env:: current_exe ( )
139+ . expect ( "failed to retrieve path to the bootstrap executable" )
140+ . parent ( )
141+ . unwrap ( )
142+ . join ( format ! ( "broken-cc{}" , std:: env:: consts:: EXE_SUFFIX ) ) ,
143+ ) ;
144+ broken_cc. flag ( & format ! ( "--broken-cc-target={target}" ) ) ;
145+ broken_cc. flag ( & format ! ( "--broken-cc-detected={}" , default_cc. path( ) . display( ) ) ) ;
146+
147+ build. cc . borrow_mut ( ) . insert ( target, broken_cc. get_compiler ( ) ) ;
148+ build. cxx . borrow_mut ( ) . insert ( target, broken_cc. get_compiler ( ) ) ;
149+ return ;
150+ }
151+
118152 let ar = if let ar @ Some ( ..) = config. and_then ( |c| c. ar . clone ( ) ) {
119153 ar
120154 } else {
0 commit comments