@@ -94,7 +94,7 @@ impl Step for Std {
9494 target_deps. extend ( copy_third_party_objects ( builder, & compiler, target) . into_iter ( ) ) ;
9595
9696 let mut cargo = builder. cargo ( compiler, Mode :: Std , target, "build" ) ;
97- std_cargo ( builder, & compiler , target, & mut cargo) ;
97+ std_cargo ( builder, target, & mut cargo) ;
9898
9999 builder. info ( & format ! ( "Building stage{} std artifacts ({} -> {})" , compiler. stage,
100100 & compiler. host, target) ) ;
@@ -163,7 +163,6 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target:
163163/// Configure cargo to compile the standard library, adding appropriate env vars
164164/// and such.
165165pub fn std_cargo ( builder : & Builder < ' _ > ,
166- compiler : & Compiler ,
167166 target : Interned < String > ,
168167 cargo : & mut Cargo ) {
169168 if let Some ( target) = env:: var_os ( "MACOSX_STD_DEPLOYMENT_TARGET" ) {
@@ -208,21 +207,6 @@ pub fn std_cargo(builder: &Builder<'_>,
208207 let mut features = builder. std_features ( ) ;
209208 features. push_str ( & compiler_builtins_c_feature) ;
210209
211- if compiler. stage != 0 && builder. config . sanitizers {
212- // This variable is used by the sanitizer runtime crates, e.g.
213- // rustc_lsan, to build the sanitizer runtime from C code
214- // When this variable is missing, those crates won't compile the C code,
215- // so we don't set this variable during stage0 where llvm-config is
216- // missing
217- // We also only build the runtimes when --enable-sanitizers (or its
218- // config.toml equivalent) is used
219- let llvm_config = builder. ensure ( native:: Llvm {
220- target : builder. config . build ,
221- } ) ;
222- cargo. env ( "LLVM_CONFIG" , llvm_config) ;
223- cargo. env ( "RUSTC_BUILD_SANITIZERS" , "1" ) ;
224- }
225-
226210 cargo. arg ( "--features" ) . arg ( features)
227211 . arg ( "--manifest-path" )
228212 . arg ( builder. src . join ( "src/libtest/Cargo.toml" ) ) ;
@@ -281,30 +265,105 @@ impl Step for StdLink {
281265 let hostdir = builder. sysroot_libdir ( target_compiler, compiler. host ) ;
282266 add_to_sysroot ( builder, & libdir, & hostdir, & libstd_stamp ( builder, compiler, target) ) ;
283267
284- if builder. config . sanitizers && compiler. stage != 0 && target == "x86_64-apple-darwin" {
285- // The sanitizers are only built in stage1 or above, so the dylibs will
286- // be missing in stage0 and causes panic. See the `std()` function above
287- // for reason why the sanitizers are not built in stage0.
288- copy_apple_sanitizer_dylibs ( builder, & builder. native_dir ( target) , "osx" , & libdir) ;
268+ if builder. config . sanitizers && compiler. stage != 0 {
269+ // The sanitizers are only copied in stage1 or above,
270+ // to avoid creating dependency on LLVM.
271+ copy_sanitizers ( builder, & target_compiler, target) ;
289272 }
290273 }
291274}
292275
293- fn copy_apple_sanitizer_dylibs (
294- builder : & Builder < ' _ > ,
295- native_dir : & Path ,
296- platform : & str ,
297- into : & Path ,
298- ) {
299- for & sanitizer in & [ "asan" , "tsan" ] {
300- let filename = format ! ( "lib__rustc__clang_rt.{}_{}_dynamic.dylib" , sanitizer, platform) ;
301- let mut src_path = native_dir. join ( sanitizer) ;
302- src_path. push ( "build" ) ;
303- src_path. push ( "lib" ) ;
304- src_path. push ( "darwin" ) ;
305- src_path. push ( & filename) ;
306- builder. copy ( & src_path, & into. join ( filename) ) ;
276+ /// Copies sanitizer runtime libraries into target libdir.
277+ fn copy_sanitizers ( builder : & Builder < ' _ > , target_compiler : & Compiler , target : Interned < String > ) {
278+ let sanitizers = supported_sanitizers ( target) ;
279+ if sanitizers. is_empty ( ) {
280+ return ;
281+ }
282+
283+ let llvm_config: PathBuf = builder. ensure ( native:: Llvm {
284+ target : target_compiler. host ,
285+ } ) ;
286+ if builder. config . dry_run {
287+ return ;
288+ }
289+
290+ // The compiler-rt installs sanitizer runtimes into clang resource directory.
291+ let clang_resourcedir = clang_resourcedir ( & llvm_config) ;
292+ let libdir = builder. sysroot_libdir ( * target_compiler, target) ;
293+
294+ for ( path, name) in & sanitizers {
295+ let src = clang_resourcedir. join ( path) ;
296+ let dst = libdir. join ( name) ;
297+ if !src. exists ( ) {
298+ println ! ( "Ignoring missing runtime: {}" , src. display( ) ) ;
299+ continue ;
300+ }
301+ builder. copy ( & src, & dst) ;
302+
303+ if target == "x86_64-apple-darwin" {
304+ // Update the library install name reflect the fact it has been renamed.
305+ let status = Command :: new ( "install_name_tool" )
306+ . arg ( "-id" )
307+ . arg ( format ! ( "@rpath/{}" , name) )
308+ . arg ( & dst)
309+ . status ( )
310+ . expect ( "failed to execute `install_name_tool`" ) ;
311+ assert ! ( status. success( ) ) ;
312+ }
313+ }
314+ }
315+
316+ /// Returns path to clang's resource directory.
317+ fn clang_resourcedir ( llvm_config : & Path ) -> PathBuf {
318+ let llvm_version = output ( Command :: new ( & llvm_config) . arg ( "--version" ) ) ;
319+ let llvm_version = llvm_version. trim ( ) ;
320+ let llvm_libdir = output ( Command :: new ( & llvm_config) . arg ( "--libdir" ) ) ;
321+ let llvm_libdir = PathBuf :: from ( llvm_libdir. trim ( ) ) ;
322+
323+ // Determine CLANG_VERSION by stripping LLVM_VERSION_SUFFIX from LLVM_VERSION.
324+ let mut non_digits = 0 ;
325+ let mut third_non_digit = llvm_version. len ( ) ;
326+ for ( i, c) in llvm_version. char_indices ( ) {
327+ if !c. is_digit ( 10 ) {
328+ non_digits += 1 ;
329+ if non_digits == 3 {
330+ third_non_digit = i;
331+ break ;
332+ }
333+ }
334+ }
335+ let clang_version = & llvm_version[ ..third_non_digit] ;
336+ llvm_libdir. join ( "clang" ) . join ( & clang_version)
337+ }
338+
339+ /// Returns a list of paths to sanitizer libraries supported on given target,
340+ /// and corresponding names we plan to give them when placed in target libdir.
341+ ///
342+ /// Returned paths are relative to clang's resource directory.
343+ fn supported_sanitizers ( target : Interned < String > ) -> Vec < ( PathBuf , String ) > {
344+ let sanitizers = & [ "asan" , "lsan" , "msan" , "tsan" ] ;
345+ let mut result = Vec :: new ( ) ;
346+ match & * target {
347+ "x86_64-apple-darwin" => {
348+ let srcdir = Path :: new ( "lib/darwin" ) ;
349+ for s in sanitizers {
350+ let src = format ! ( "libclang_rt.{}_osx_dynamic.dylib" , s) ;
351+ let dst = format ! ( "librustc_rt.{}.dylib" , s) ;
352+ result. push ( ( srcdir. join ( src) , dst) ) ;
353+ }
354+
355+ }
356+ "x86_64-unknown-linux-gnu" => {
357+ let srcdir = Path :: new ( "lib/linux" ) ;
358+ for s in sanitizers {
359+ let src = format ! ( "libclang_rt.{}-x86_64.a" , s) ;
360+ let dst = format ! ( "librustc_rt.{}.a" , s) ;
361+ result. push ( ( srcdir. join ( src) , dst) ) ;
362+ }
363+ }
364+ _ => { }
307365 }
366+ result
308367}
309368
310369#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
0 commit comments