@@ -3433,29 +3433,51 @@ impl<'test> TestCx<'test> {
3433
3433
3434
3434
fn run_rmake_v2_test ( & self ) {
3435
3435
// For `run-make` V2, we need to perform 2 steps to build and run a `run-make` V2 recipe
3436
- // (`rmake.rs`) to run the actual tests. The support library is already built as a tool
3437
- // dylib and is available under `build/$TARGET/stageN-tools-bin/librun_make_support.rlib`.
3436
+ // (`rmake.rs`) to run the actual tests. The support library is already built as a tool rust
3437
+ // library and is available under `build/$TARGET/stageN-tools-bin/librun_make_support.rlib`.
3438
3438
//
3439
- // 1. We need to build the recipe `rmake.rs` and link in the support library.
3440
- // 2. We need to run the recipe to build and run the tests.
3441
- let cwd = env:: current_dir ( ) . unwrap ( ) ;
3442
- let src_root = self . config . src_base . parent ( ) . unwrap ( ) . parent ( ) . unwrap ( ) ;
3443
- let src_root = cwd. join ( & src_root) ;
3444
- let build_root = self . config . build_base . parent ( ) . unwrap ( ) . parent ( ) . unwrap ( ) ;
3445
- let build_root = cwd. join ( & build_root) ;
3439
+ // 1. We need to build the recipe `rmake.rs` as a binary and link in the `run_make_support`
3440
+ // library.
3441
+ // 2. We need to run the recipe binary.
3442
+
3443
+ // So we assume the rust-lang/rust project setup looks like the following (our `.` is the
3444
+ // top-level directory, irrelevant entries to our purposes omitted):
3445
+ //
3446
+ // ```
3447
+ // . // <- `source_root`
3448
+ // ├── build/ // <- `build_root`
3449
+ // ├── compiler/
3450
+ // ├── library/
3451
+ // ├── src/
3452
+ // │ └── tools/
3453
+ // │ └── run_make_support/
3454
+ // └── tests
3455
+ // └── run-make/
3456
+ // ```
3457
+
3458
+ // `source_root` is the top-level directory containing the rust-lang/rust checkout.
3459
+ let source_root =
3460
+ self . config . find_rust_src_root ( ) . expect ( "could not determine rust source root" ) ;
3461
+ // `self.config.build_base` is actually the build base folder + "test" + test suite name, it
3462
+ // looks like `build/<host_triple>/test/run-make`. But we want `build/<host_triple>/`. Note
3463
+ // that the `build` directory does not need to be called `build`, nor does it need to be
3464
+ // under `source_root`, so we must compute it based off of `self.config.build_base`.
3465
+ let build_root =
3466
+ self . config . build_base . parent ( ) . and_then ( Path :: parent) . unwrap ( ) . to_path_buf ( ) ;
3446
3467
3447
3468
// We construct the following directory tree for each rmake.rs test:
3448
3469
// ```
3449
- // base_dir/
3470
+ // < base_dir> /
3450
3471
// rmake.exe
3451
3472
// rmake_out/
3452
3473
// ```
3453
- // having the executable separate from the output artifacts directory allows the recipes to
3454
- // `remove_dir_all($TMPDIR)` without running into permission denied issues because
3455
- // the executable is not under the `rmake_out/` directory.
3474
+ // having the recipe executable separate from the output artifacts directory allows the
3475
+ // recipes to `remove_dir_all($TMPDIR)` without running into issues related trying to remove
3476
+ // a currently running executable because the recipe executable is not under the
3477
+ // `rmake_out/` directory.
3456
3478
//
3457
3479
// This setup intentionally diverges from legacy Makefile run-make tests.
3458
- let base_dir = cwd . join ( self . output_base_name ( ) ) ;
3480
+ let base_dir = self . output_base_name ( ) ;
3459
3481
if base_dir. exists ( ) {
3460
3482
self . aggressive_rm_rf ( & base_dir) . unwrap ( ) ;
3461
3483
}
@@ -3477,120 +3499,186 @@ impl<'test> TestCx<'test> {
3477
3499
}
3478
3500
}
3479
3501
3480
- // HACK: assume stageN-target, we only want stageN.
3502
+ // `self.config.stage_id` looks like `stage1-<target_triple>`, but we only want
3503
+ // the `stage1` part as that is what the output directories of bootstrap are prefixed with.
3504
+ // Note that this *assumes* build layout from bootstrap is produced as:
3505
+ //
3506
+ // ```
3507
+ // build/<target_triple>/ // <- this is `build_root`
3508
+ // ├── stage0
3509
+ // ├── stage0-bootstrap-tools
3510
+ // ├── stage0-codegen
3511
+ // ├── stage0-rustc
3512
+ // ├── stage0-std
3513
+ // ├── stage0-sysroot
3514
+ // ├── stage0-tools
3515
+ // ├── stage0-tools-bin
3516
+ // ├── stage1
3517
+ // ├── stage1-std
3518
+ // ├── stage1-tools
3519
+ // ├── stage1-tools-bin
3520
+ // └── test
3521
+ // ```
3522
+ // FIXME(jieyouxu): improve the communication between bootstrap and compiletest here so
3523
+ // we don't have to hack out a `stageN`.
3481
3524
let stage = self . config . stage_id . split ( '-' ) . next ( ) . unwrap ( ) ;
3482
3525
3483
- // First, we construct the path to the built support library.
3484
- let mut support_lib_path = PathBuf :: new ( ) ;
3485
- support_lib_path. push ( & build_root) ;
3486
- support_lib_path. push ( format ! ( "{}-tools-bin" , stage) ) ;
3487
- support_lib_path. push ( "librun_make_support.rlib" ) ;
3526
+ // In order to link in the support library as a rlib when compiling recipes, we need three
3527
+ // paths:
3528
+ // 1. Path of the built support library rlib itself.
3529
+ // 2. Path of the built support library's dependencies directory.
3530
+ // 3. Path of the built support library's dependencies' dependencies directory.
3531
+ //
3532
+ // The paths look like
3533
+ //
3534
+ // ```
3535
+ // build/<target_triple>/
3536
+ // ├── stageN-tools-bin/
3537
+ // │ └── librun_make_support.rlib // <- support rlib itself
3538
+ // ├── stageN-tools/
3539
+ // │ ├── release/deps/ // <- deps of deps
3540
+ // │ └── <host_triple>/release/deps/ // <- deps
3541
+ // ```
3542
+ //
3543
+ // FIXME(jieyouxu): there almost certainly is a better way to do this (specifically how the
3544
+ // support lib and its deps are organized, can't we copy them to the tools-bin dir as
3545
+ // well?), but this seems to work for now.
3488
3546
3489
- let mut stage_std_path = PathBuf :: new ( ) ;
3490
- stage_std_path. push ( & build_root) ;
3491
- stage_std_path. push ( & stage) ;
3492
- stage_std_path. push ( "lib" ) ;
3547
+ let stage_tools_bin = build_root. join ( format ! ( "{stage}-tools-bin" ) ) ;
3548
+ let support_lib_path = stage_tools_bin. join ( "librun_make_support.rlib" ) ;
3493
3549
3494
- // Then, we need to build the recipe `rmake.rs` and link in the support library.
3495
- let recipe_bin = base_dir. join ( if self . config . target . contains ( "windows" ) {
3496
- "rmake.exe"
3497
- } else {
3498
- "rmake"
3499
- } ) ;
3500
-
3501
- let mut support_lib_deps = PathBuf :: new ( ) ;
3502
- support_lib_deps. push ( & build_root) ;
3503
- support_lib_deps. push ( format ! ( "{}-tools" , stage) ) ;
3504
- support_lib_deps. push ( & self . config . host ) ;
3505
- support_lib_deps. push ( "release" ) ;
3506
- support_lib_deps. push ( "deps" ) ;
3507
-
3508
- let mut support_lib_deps_deps = PathBuf :: new ( ) ;
3509
- support_lib_deps_deps. push ( & build_root) ;
3510
- support_lib_deps_deps. push ( format ! ( "{}-tools" , stage) ) ;
3511
- support_lib_deps_deps. push ( "release" ) ;
3512
- support_lib_deps_deps. push ( "deps" ) ;
3513
-
3514
- debug ! ( ?support_lib_deps) ;
3515
- debug ! ( ?support_lib_deps_deps) ;
3516
-
3517
- let orig_dylib_env_paths =
3550
+ let stage_tools = build_root. join ( format ! ( "{stage}-tools" ) ) ;
3551
+ let support_lib_deps = stage_tools. join ( & self . config . host ) . join ( "release" ) . join ( "deps" ) ;
3552
+ let support_lib_deps_deps = stage_tools. join ( "release" ) . join ( "deps" ) ;
3553
+
3554
+ // To compile the recipe with rustc, we need to provide suitable dynamic library search
3555
+ // paths to rustc. This includes both:
3556
+ // 1. The "base" dylib search paths that was provided to compiletest, e.g. `LD_LIBRARY_PATH`
3557
+ // on some linux distros.
3558
+ // 2. Specific library paths in `self.config.compile_lib_path` needed for running rustc.
3559
+
3560
+ let base_dylib_search_paths =
3518
3561
Vec :: from_iter ( env:: split_paths ( & env:: var ( dylib_env_var ( ) ) . unwrap ( ) ) ) ;
3519
3562
3520
- let mut host_dylib_env_paths = Vec :: new ( ) ;
3521
- host_dylib_env_paths. push ( cwd. join ( & self . config . compile_lib_path ) ) ;
3522
- host_dylib_env_paths. extend ( orig_dylib_env_paths. iter ( ) . cloned ( ) ) ;
3523
- let host_dylib_env_paths = env:: join_paths ( host_dylib_env_paths) . unwrap ( ) ;
3563
+ let host_dylib_search_paths = {
3564
+ let mut paths = vec ! [ self . config. compile_lib_path. clone( ) ] ;
3565
+ paths. extend ( base_dylib_search_paths. iter ( ) . cloned ( ) ) ;
3566
+ paths
3567
+ } ;
3568
+
3569
+ // Calculate the paths of the recipe binary. As previously discussed, this is placed at
3570
+ // `<base_dir>/<bin_name>` with `bin_name` being `rmake` or `rmake.exe` depending on
3571
+ // platform.
3572
+ let recipe_bin = {
3573
+ let mut p = base_dir. join ( "rmake" ) ;
3574
+ p. set_extension ( env:: consts:: EXE_EXTENSION ) ;
3575
+ p
3576
+ } ;
3524
3577
3525
- let mut cmd = Command :: new ( & self . config . rustc_path ) ;
3526
- cmd. arg ( "-o" )
3578
+ let mut rustc = Command :: new ( & self . config . rustc_path ) ;
3579
+ rustc
3580
+ . arg ( "-o" )
3527
3581
. arg ( & recipe_bin)
3582
+ // Specify library search paths for `run_make_support`.
3528
3583
. arg ( format ! ( "-Ldependency={}" , & support_lib_path. parent( ) . unwrap( ) . to_string_lossy( ) ) )
3529
3584
. arg ( format ! ( "-Ldependency={}" , & support_lib_deps. to_string_lossy( ) ) )
3530
3585
. arg ( format ! ( "-Ldependency={}" , & support_lib_deps_deps. to_string_lossy( ) ) )
3586
+ // Provide `run_make_support` as extern prelude, so test writers don't need to write
3587
+ // `extern run_make_support;`.
3531
3588
. arg ( "--extern" )
3532
3589
. arg ( format ! ( "run_make_support={}" , & support_lib_path. to_string_lossy( ) ) )
3533
3590
. arg ( "--edition=2021" )
3534
3591
. arg ( & self . testpaths . file . join ( "rmake.rs" ) )
3535
- . env ( "TARGET" , & self . config . target )
3536
- . env ( "PYTHON" , & self . config . python )
3537
- . env ( "RUST_BUILD_STAGE" , & self . config . stage_id )
3538
- . env ( "RUSTC" , cwd. join ( & self . config . rustc_path ) )
3539
- . env ( "LD_LIB_PATH_ENVVAR" , dylib_env_var ( ) )
3540
- . env ( dylib_env_var ( ) , & host_dylib_env_paths)
3541
- . env ( "HOST_RPATH_DIR" , cwd. join ( & self . config . compile_lib_path ) )
3542
- . env ( "TARGET_RPATH_DIR" , cwd. join ( & self . config . run_lib_path ) )
3543
- . env ( "LLVM_COMPONENTS" , & self . config . llvm_components ) ;
3592
+ // Provide necessary library search paths for rustc.
3593
+ . env ( dylib_env_var ( ) , & env:: join_paths ( host_dylib_search_paths) . unwrap ( ) ) ;
3544
3594
3545
3595
// In test code we want to be very pedantic about values being silently discarded that are
3546
3596
// annotated with `#[must_use]`.
3547
- cmd. arg ( "-Dunused_must_use" ) ;
3548
-
3597
+ rustc. arg ( "-Dunused_must_use" ) ;
3598
+
3599
+ // > `cg_clif` uses `COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0` for running the rustc
3600
+ // > test suite. With the introduction of rmake.rs this broke. `librun_make_support.rlib` is
3601
+ // > compiled using the bootstrap rustc wrapper which sets `--sysroot
3602
+ // > build/aarch64-unknown-linux-gnu/stage0-sysroot`, but then compiletest will compile
3603
+ // > `rmake.rs` using the sysroot of the bootstrap compiler causing it to not find the
3604
+ // > `libstd.rlib` against which `librun_make_support.rlib` is compiled.
3605
+ //
3606
+ // The gist here is that we have to pass the proper stage0 sysroot if we want
3607
+ //
3608
+ // ```
3609
+ // $ COMPILETEST_FORCE_STAGE0=1 ./x test run-make --stage 0
3610
+ // ```
3611
+ //
3612
+ // to work correctly.
3613
+ //
3614
+ // See <https://github.com/rust-lang/rust/pull/122248> for more background.
3549
3615
if std:: env:: var_os ( "COMPILETEST_FORCE_STAGE0" ) . is_some ( ) {
3550
- let mut stage0_sysroot = build_root. clone ( ) ;
3551
- stage0_sysroot. push ( "stage0-sysroot" ) ;
3552
- debug ! ( ?stage0_sysroot) ;
3553
- debug ! ( exists = stage0_sysroot. exists( ) ) ;
3554
-
3555
- cmd. arg ( "--sysroot" ) . arg ( & stage0_sysroot) ;
3616
+ let stage0_sysroot = build_root. join ( "stage0-sysroot" ) ;
3617
+ rustc. arg ( "--sysroot" ) . arg ( & stage0_sysroot) ;
3556
3618
}
3557
3619
3558
- let res = self . run_command_to_procres ( & mut cmd) ;
3620
+ // Now run rustc to build the recipe.
3621
+ let res = self . run_command_to_procres ( & mut rustc) ;
3559
3622
if !res. status . success ( ) {
3560
3623
self . fatal_proc_rec ( "run-make test failed: could not build `rmake.rs` recipe" , & res) ;
3561
3624
}
3562
3625
3563
- // Finally, we need to run the recipe binary to build and run the actual tests.
3564
- debug ! ( ?recipe_bin) ;
3626
+ // To actually run the recipe, we have to provide the recipe with a bunch of information
3627
+ // provided through env vars.
3628
+
3629
+ // Compute stage-specific standard library paths.
3630
+ let stage_std_path = build_root. join ( & stage) . join ( "lib" ) ;
3565
3631
3566
- let mut dylib_env_paths = orig_dylib_env_paths. clone ( ) ;
3567
- dylib_env_paths. push ( support_lib_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ) ;
3568
- dylib_env_paths. push ( stage_std_path. join ( "rustlib" ) . join ( & self . config . host ) . join ( "lib" ) ) ;
3569
- let dylib_env_paths = env:: join_paths ( dylib_env_paths) . unwrap ( ) ;
3632
+ // Compute dynamic library search paths for recipes.
3633
+ let recipe_dylib_search_paths = {
3634
+ let mut paths = base_dylib_search_paths. clone ( ) ;
3635
+ paths. push ( support_lib_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ) ;
3636
+ paths. push ( stage_std_path. join ( "rustlib" ) . join ( & self . config . host ) . join ( "lib" ) ) ;
3637
+ paths
3638
+ } ;
3570
3639
3571
- let mut target_rpath_env_path = Vec :: new ( ) ;
3572
- target_rpath_env_path. push ( & rmake_out_dir) ;
3573
- target_rpath_env_path. extend ( & orig_dylib_env_paths) ;
3574
- let target_rpath_env_path = env:: join_paths ( target_rpath_env_path) . unwrap ( ) ;
3640
+ // Compute runtime library search paths for recipes. This is target-specific.
3641
+ let target_runtime_dylib_search_paths = {
3642
+ let mut paths = vec ! [ rmake_out_dir. clone( ) ] ;
3643
+ paths. extend ( base_dylib_search_paths. iter ( ) . cloned ( ) ) ;
3644
+ paths
3645
+ } ;
3575
3646
3647
+ // FIXME(jieyouxu): please rename `TARGET_RPATH_ENV`, `HOST_RPATH_DIR` and
3648
+ // `TARGET_RPATH_DIR`, it is **extremely** confusing!
3576
3649
let mut cmd = Command :: new ( & recipe_bin) ;
3577
3650
cmd. current_dir ( & rmake_out_dir)
3578
3651
. stdout ( Stdio :: piped ( ) )
3579
3652
. stderr ( Stdio :: piped ( ) )
3653
+ // Provide the target-specific env var that is used to record dylib search paths. For
3654
+ // example, this could be `LD_LIBRARY_PATH` on some linux distros but `PATH` on Windows.
3580
3655
. env ( "LD_LIB_PATH_ENVVAR" , dylib_env_var ( ) )
3581
- . env ( "TARGET_RPATH_ENV" , & target_rpath_env_path)
3582
- . env ( dylib_env_var ( ) , & dylib_env_paths)
3656
+ // Provide the dylib search paths.
3657
+ . env ( dylib_env_var ( ) , & env:: join_paths ( recipe_dylib_search_paths) . unwrap ( ) )
3658
+ // Provide runtime dylib search paths.
3659
+ . env ( "TARGET_RPATH_ENV" , & env:: join_paths ( target_runtime_dylib_search_paths) . unwrap ( ) )
3660
+ // Provide the target.
3583
3661
. env ( "TARGET" , & self . config . target )
3662
+ // Some tests unfortunately still need Python, so provide path to a Python interpreter.
3584
3663
. env ( "PYTHON" , & self . config . python )
3585
- . env ( "SOURCE_ROOT" , & src_root)
3586
- . env ( "RUST_BUILD_STAGE" , & self . config . stage_id )
3587
- . env ( "RUSTC" , cwd. join ( & self . config . rustc_path ) )
3588
- . env ( "HOST_RPATH_DIR" , cwd. join ( & self . config . compile_lib_path ) )
3589
- . env ( "TARGET_RPATH_DIR" , cwd. join ( & self . config . run_lib_path ) )
3664
+ // Provide path to checkout root. This is the top-level directory containing
3665
+ // rust-lang/rust checkout.
3666
+ . env ( "SOURCE_ROOT" , & source_root)
3667
+ // Provide path to stage-corresponding rustc.
3668
+ . env ( "RUSTC" , & self . config . rustc_path )
3669
+ // Provide the directory to libraries that are needed to run the *compiler*. This is not
3670
+ // to be confused with `TARGET_RPATH_ENV` or `TARGET_RPATH_DIR`. This is needed if the
3671
+ // recipe wants to invoke rustc.
3672
+ . env ( "HOST_RPATH_DIR" , & self . config . compile_lib_path )
3673
+ // Provide the directory to libraries that might be needed to run compiled binaries
3674
+ // (further compiled by the recipe!).
3675
+ . env ( "TARGET_RPATH_DIR" , & self . config . run_lib_path )
3676
+ // Provide which LLVM components are available (e.g. which LLVM components are provided
3677
+ // through a specific CI runner).
3590
3678
. env ( "LLVM_COMPONENTS" , & self . config . llvm_components ) ;
3591
3679
3592
3680
if let Some ( ref rustdoc) = self . config . rustdoc_path {
3593
- cmd. env ( "RUSTDOC" , cwd . join ( rustdoc) ) ;
3681
+ cmd. env ( "RUSTDOC" , source_root . join ( rustdoc) ) ;
3594
3682
}
3595
3683
3596
3684
if let Some ( ref node) = self . config . nodejs {
0 commit comments