@@ -1011,6 +1011,7 @@ ArgData! {
10111011 PassThrough ( OsString ) ,
10121012 Target ( ArgTarget ) ,
10131013 Unstable ( ArgUnstable ) ,
1014+ RemapPathPrefix ( String ) ,
10141015}
10151016
10161017use self :: ArgData :: * ;
@@ -1156,7 +1157,7 @@ fn parse_arguments(arguments: &[OsString], cwd: &Path) -> CompilerArguments<Pars
11561157 Some ( Json ( _) ) => {
11571158 has_json = true ;
11581159 }
1159- Some ( PassThrough ( _) ) => ( ) ,
1160+ Some ( PassThrough ( _) | RemapPathPrefix ( _ ) ) => ( ) ,
11601161 Some ( Target ( target) ) => match target {
11611162 ArgTarget :: Path ( _) | ArgTarget :: Unsure ( _) => cannot_cache ! ( "target" ) ,
11621163 ArgTarget :: Name ( _) => ( ) ,
@@ -1447,8 +1448,28 @@ where
14471448 val. hash ( & mut HashToDigest { digest : & mut m } ) ;
14481449 }
14491450 }
1451+ let mut arguments = arguments;
14501452 // 8. The cwd of the compile. This will wind up in the rlib.
1451- cwd. hash ( & mut HashToDigest { digest : & mut m } ) ;
1453+ // This will end up in the rlib only in the case no basedir path
1454+ // rewriting is done and the build is operating with the absolute paths.
1455+ if let Ok ( _idx) = env_vars
1456+ . binary_search_by ( |( ref k, _) | k. cmp ( & OsString :: from ( "CACHEPOT_REMAP_RELATIVE" ) ) )
1457+ {
1458+ if let Ok ( cargo_manifest_dir) =
1459+ env_vars. binary_search_by ( |( ref k, _) | k. cmp ( & OsString :: from ( "CARGO_MANIFEST_DIR" ) ) )
1460+ {
1461+ let ( _, ref cargo_home) = env_vars[ cargo_manifest_dir] ;
1462+ if let Some ( cargo_home) = cargo_home. as_os_str ( ) . to_str ( ) {
1463+ arguments. push ( Argument :: WithValue (
1464+ "--remap-path-prefix" ,
1465+ ArgData :: RemapPathPrefix ( format ! ( "{}={}" , cargo_home, "./" ) ) ,
1466+ ArgDisposition :: CanBeSeparated ( Some ( '=' as u8 ) ) ,
1467+ ) ) ;
1468+ }
1469+ }
1470+ } else {
1471+ cwd. hash ( & mut HashToDigest { digest : & mut m } ) ;
1472+ }
14521473 // Turn arguments into a simple Vec<OsString> to calculate outputs.
14531474 let flat_os_string_arguments: Vec < OsString > = os_string_arguments
14541475 . into_iter ( )
@@ -3109,6 +3130,208 @@ proc_macro false
31093130 assert_eq ! ( out, vec![ "foo.a" , "foo.rlib" , "foo.rmeta" ] ) ;
31103131 }
31113132
3133+ // Verify that the same code located at two different
3134+ // locations with the properly set `CACHEPOT_REMAP_RELATIVE`
3135+ // ends up with equal hashes.
3136+ #[ test]
3137+ fn test_hashes_equal_with_basedir ( ) {
3138+ let _ = env_logger:: Builder :: new ( ) . is_test ( true ) . try_init ( ) ;
3139+ let project1 = TestFixture :: new ( ) ;
3140+ let project2 = TestFixture :: new ( ) ;
3141+
3142+ const FAKE_DIGEST : & str = "abcd1234" ;
3143+
3144+ // We'll just use empty files for each of these.
3145+ for s in [ "foo.rs" , "bar.rs" , "bar.rlib" , "libbaz.a" ] . iter ( ) {
3146+ project1. touch ( s) . unwrap ( ) ;
3147+ project2. touch ( s) . unwrap ( ) ;
3148+ }
3149+
3150+ let mut emit = HashSet :: new ( ) ;
3151+ emit. insert ( "link" . to_string ( ) ) ;
3152+ emit. insert ( "metadata" . to_string ( ) ) ;
3153+
3154+ let hasher_project1 = Box :: new ( RustHasher {
3155+ executable : "rustc" . into ( ) ,
3156+ host : "x86-64-unknown-unknown-unknown" . to_owned ( ) ,
3157+ sysroot : project1. tempdir . path ( ) . join ( "sysroot" ) ,
3158+ compiler_shlibs_digests : vec ! [ FAKE_DIGEST . to_owned( ) ] ,
3159+ #[ cfg( feature = "dist-client" ) ]
3160+ rlib_dep_reader : None ,
3161+ parsed_args : ParsedArguments {
3162+ arguments : vec ! [
3163+ Argument :: Raw ( "a" . into( ) ) ,
3164+ Argument :: WithValue (
3165+ "--cfg" ,
3166+ ArgData :: PassThrough ( "xyz" . into( ) ) ,
3167+ ArgDisposition :: Separated ,
3168+ ) ,
3169+ Argument :: Raw ( "b" . into( ) ) ,
3170+ Argument :: WithValue (
3171+ "--cfg" ,
3172+ ArgData :: PassThrough ( "abc" . into( ) ) ,
3173+ ArgDisposition :: Separated ,
3174+ ) ,
3175+ ] ,
3176+ gcno : None ,
3177+ output_dir : "foo/" . into ( ) ,
3178+ externs : vec ! [ "bar.rlib" . into( ) ] ,
3179+ crate_link_paths : vec ! [ ] ,
3180+ staticlibs : vec ! [ project1. tempdir. path( ) . join( "libbaz.a" ) ] ,
3181+ crate_name : "foo" . into ( ) ,
3182+ crate_types : CrateTypes {
3183+ rlib : true ,
3184+ staticlib : false ,
3185+ } ,
3186+ dep_info : None ,
3187+ emit,
3188+ color_mode : ColorMode :: Auto ,
3189+ has_json : false ,
3190+ } ,
3191+ } ) ;
3192+
3193+ let mut emit = HashSet :: new ( ) ;
3194+ emit. insert ( "link" . to_string ( ) ) ;
3195+ emit. insert ( "metadata" . to_string ( ) ) ;
3196+
3197+ let hasher_project2 = Box :: new ( RustHasher {
3198+ executable : "rustc" . into ( ) ,
3199+ host : "x86-64-unknown-unknown-unknown" . to_owned ( ) ,
3200+ sysroot : project2. tempdir . path ( ) . join ( "sysroot" ) ,
3201+ compiler_shlibs_digests : vec ! [ FAKE_DIGEST . to_owned( ) ] ,
3202+ #[ cfg( feature = "dist-client" ) ]
3203+ rlib_dep_reader : None ,
3204+ parsed_args : ParsedArguments {
3205+ arguments : vec ! [
3206+ Argument :: Raw ( "a" . into( ) ) ,
3207+ Argument :: WithValue (
3208+ "--cfg" ,
3209+ ArgData :: PassThrough ( "xyz" . into( ) ) ,
3210+ ArgDisposition :: Separated ,
3211+ ) ,
3212+ Argument :: Raw ( "b" . into( ) ) ,
3213+ Argument :: WithValue (
3214+ "--cfg" ,
3215+ ArgData :: PassThrough ( "abc" . into( ) ) ,
3216+ ArgDisposition :: Separated ,
3217+ ) ,
3218+ ] ,
3219+ output_dir : "foo/" . into ( ) ,
3220+ externs : vec ! [ "bar.rlib" . into( ) ] ,
3221+ crate_link_paths : vec ! [ ] ,
3222+ staticlibs : vec ! [ project2. tempdir. path( ) . join( "libbaz.a" ) ] ,
3223+ crate_name : "foo" . into ( ) ,
3224+ gcno : None ,
3225+ crate_types : CrateTypes {
3226+ rlib : true ,
3227+ staticlib : false ,
3228+ } ,
3229+ dep_info : None ,
3230+ emit,
3231+ color_mode : ColorMode :: Auto ,
3232+ has_json : false ,
3233+ } ,
3234+ } ) ;
3235+
3236+ let creator = new_creator ( ) ;
3237+ mock_dep_info ( & creator, & [ "foo.rs" , "bar.rs" ] ) ;
3238+ mock_file_names ( & creator, & [ "foo.rlib" , "foo.a" ] ) ;
3239+ let runtime = single_threaded_runtime ( ) ;
3240+ let pool = runtime. handle ( ) . clone ( ) ;
3241+ let res_project1 = hasher_project1
3242+ . clone ( )
3243+ . generate_hash_key (
3244+ & creator,
3245+ project1. tempdir . path ( ) . to_owned ( ) ,
3246+ [
3247+ ( OsString :: from ( "CARGO_PKG_NAME" ) , OsString :: from ( "foo" ) ) ,
3248+ ( OsString :: from ( "FOO" ) , OsString :: from ( "bar" ) ) ,
3249+ ( OsString :: from ( "CARGO_BLAH" ) , OsString :: from ( "abc" ) ) ,
3250+ (
3251+ OsString :: from ( "CACHEPOT_REMAP_RELATIVE" ) ,
3252+ OsString :: from ( "" ) ,
3253+ ) ,
3254+ ]
3255+ . to_vec ( ) ,
3256+ false ,
3257+ & pool,
3258+ false ,
3259+ )
3260+ . wait ( )
3261+ . unwrap ( ) ;
3262+
3263+ let creator_project2 = new_creator ( ) ;
3264+ mock_dep_info ( & creator_project2, & [ "foo.rs" , "bar.rs" ] ) ;
3265+ mock_file_names ( & creator_project2, & [ "foo.rlib" , "foo.a" ] ) ;
3266+ let res_project2 = hasher_project2
3267+ . clone ( )
3268+ . generate_hash_key (
3269+ & creator_project2,
3270+ project2. tempdir . path ( ) . to_owned ( ) ,
3271+ [
3272+ ( OsString :: from ( "CARGO_PKG_NAME" ) , OsString :: from ( "foo" ) ) ,
3273+ ( OsString :: from ( "FOO" ) , OsString :: from ( "bar" ) ) ,
3274+ ( OsString :: from ( "CARGO_BLAH" ) , OsString :: from ( "abc" ) ) ,
3275+ (
3276+ OsString :: from ( "CACHEPOT_REMAP_RELATIVE" ) ,
3277+ OsString :: from ( "" ) ,
3278+ ) ,
3279+ ]
3280+ . to_vec ( ) ,
3281+ false ,
3282+ & pool,
3283+ false ,
3284+ )
3285+ . wait ( )
3286+ . unwrap ( ) ;
3287+
3288+ let creator = new_creator ( ) ;
3289+ mock_dep_info ( & creator, & [ "foo.rs" , "bar.rs" ] ) ;
3290+ mock_file_names ( & creator, & [ "foo.rlib" , "foo.a" ] ) ;
3291+ let res_project1_no_basedir = hasher_project1
3292+ . generate_hash_key (
3293+ & creator,
3294+ project1. tempdir . path ( ) . to_owned ( ) ,
3295+ [
3296+ ( OsString :: from ( "CARGO_PKG_NAME" ) , OsString :: from ( "foo" ) ) ,
3297+ ( OsString :: from ( "FOO" ) , OsString :: from ( "bar" ) ) ,
3298+ ( OsString :: from ( "CARGO_BLAH" ) , OsString :: from ( "abc" ) ) ,
3299+ ]
3300+ . to_vec ( ) ,
3301+ false ,
3302+ & pool,
3303+ false ,
3304+ )
3305+ . wait ( )
3306+ . unwrap ( ) ;
3307+
3308+ let creator_project2 = new_creator ( ) ;
3309+ mock_dep_info ( & creator_project2, & [ "foo.rs" , "bar.rs" ] ) ;
3310+ mock_file_names ( & creator_project2, & [ "foo.rlib" , "foo.a" ] ) ;
3311+ let res_project2_no_basedir = hasher_project2
3312+ . generate_hash_key (
3313+ & creator_project2,
3314+ project2. tempdir . path ( ) . to_owned ( ) ,
3315+ [
3316+ ( OsString :: from ( "CARGO_PKG_NAME" ) , OsString :: from ( "foo" ) ) ,
3317+ ( OsString :: from ( "FOO" ) , OsString :: from ( "bar" ) ) ,
3318+ ( OsString :: from ( "CARGO_BLAH" ) , OsString :: from ( "abc" ) ) ,
3319+ ]
3320+ . to_vec ( ) ,
3321+ false ,
3322+ & pool,
3323+ false ,
3324+ )
3325+ . wait ( )
3326+ . unwrap ( ) ;
3327+
3328+ // This hashes equally
3329+ assert_eq ! ( res_project1. key, res_project2. key) ;
3330+
3331+ // But this does not
3332+ assert_neq ! ( res_project1_no_basedir. key, res_project2_no_basedir. key) ;
3333+ }
3334+
31123335 fn hash_key < F > (
31133336 f : & TestFixture ,
31143337 args : & [ & ' static str ] ,
0 commit comments