about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock7
-rw-r--r--src/tools/run-make-support/Cargo.toml2
-rw-r--r--src/tools/run-make-support/src/cc.rs11
-rw-r--r--src/tools/run-make-support/src/lib.rs37
-rw-r--r--src/tools/run-make-support/src/llvm.rs37
-rw-r--r--src/tools/run-make-support/src/rustc.rs13
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt3
-rw-r--r--tests/run-make/compiler-lookup-paths/Makefile44
-rw-r--r--tests/run-make/compiler-lookup-paths/rmake.rs84
-rw-r--r--tests/run-make/dump-mono-stats/Makefile5
-rw-r--r--tests/run-make/dump-mono-stats/rmake.rs17
-rw-r--r--tests/run-make/invalid-library/rmake.rs10
-rw-r--r--tests/run-make/prune-link-args/Makefile10
-rw-r--r--tests/run-make/prune-link-args/rmake.rs17
14 files changed, 206 insertions, 91 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ff755e5bec6..2d3bc59dddb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -229,12 +229,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "ar"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69"
-
-[[package]]
 name = "ar_archive_writer"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3451,7 +3445,6 @@ dependencies = [
 name = "run_make_support"
 version = "0.2.0"
 dependencies = [
- "ar",
  "bstr",
  "build_helper",
  "gimli 0.31.0",
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index 681284b1a48..b3913732839 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -10,6 +10,4 @@ similar = "2.5.0"
 wasmparser = "0.118.2"
 regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
 gimli = "0.31.0"
-ar = "0.9.0"
-
 build_helper = { path = "../build_helper" }
diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs
index 31b9e8a23b8..75a20a21a31 100644
--- a/src/tools/run-make-support/src/cc.rs
+++ b/src/tools/run-make-support/src/cc.rs
@@ -1,7 +1,7 @@
 use std::path::Path;
 
 use crate::command::Command;
-use crate::{bin_name, cygpath_windows, env_var, is_msvc, is_windows, uname};
+use crate::{cygpath_windows, env_var, is_msvc, is_windows, uname};
 
 /// Construct a new platform-specific C compiler invocation.
 ///
@@ -68,9 +68,14 @@ impl Cc {
         // endif
         // ```
 
+        let mut path = std::path::PathBuf::from(name);
+
         if is_msvc() {
-            let fe_path = cygpath_windows(bin_name(name));
-            let fo_path = cygpath_windows(format!("{name}.obj"));
+            path.set_extension("exe");
+            let fe_path = cygpath_windows(&path);
+            path.set_extension("");
+            path.set_extension("obj");
+            let fo_path = cygpath_windows(path);
             self.cmd.arg(format!("-Fe:{fe_path}"));
             self.cmd.arg(format!("-Fo:{fo_path}"));
         } else {
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index e5f1ce1bf34..cec2cedd15c 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -30,8 +30,8 @@ pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
 pub use clang::{clang, Clang};
 pub use diff::{diff, Diff};
 pub use llvm::{
-    llvm_filecheck, llvm_objdump, llvm_profdata, llvm_readobj, LlvmFilecheck, LlvmObjdump,
-    LlvmProfdata, LlvmReadobj,
+    llvm_ar, llvm_filecheck, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, LlvmFilecheck,
+    LlvmObjdump, LlvmProfdata, LlvmReadobj,
 };
 pub use run::{cmd, run, run_fail, run_with_args};
 pub use rustc::{aux_build, bare_rustc, rustc, Rustc};
@@ -61,19 +61,6 @@ pub fn target() -> String {
     env_var("TARGET")
 }
 
-/// `AR`
-#[track_caller]
-pub fn ar(inputs: &[impl AsRef<Path>], output_path: impl AsRef<Path>) {
-    let output = fs::File::create(&output_path).expect(&format!(
-        "the file in path \"{}\" could not be created",
-        output_path.as_ref().display()
-    ));
-    let mut builder = ar::Builder::new(output);
-    for input in inputs {
-        builder.append_path(input).unwrap();
-    }
-}
-
 /// Check if target is windows-like.
 #[must_use]
 pub fn is_windows() -> bool {
@@ -294,6 +281,26 @@ pub fn not_contains<P: AsRef<Path>>(path: P, expected: &str) -> bool {
     !path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(expected))
 }
 
+/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
+#[track_caller]
+pub fn build_native_static_lib(lib_name: &str) -> PathBuf {
+    let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") };
+    let src = format!("{lib_name}.c");
+    let lib_path = static_lib_name(lib_name);
+    if is_msvc() {
+        cc().arg("-c").out_exe(&obj_file).input(src).run();
+    } else {
+        cc().arg("-v").arg("-c").out_exe(&obj_file).input(src).run();
+    };
+    let obj_file = if is_msvc() {
+        PathBuf::from(format!("{lib_name}.obj"))
+    } else {
+        PathBuf::from(format!("{lib_name}.o"))
+    };
+    llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run();
+    path(lib_path)
+}
+
 /// Returns true if the filename at `path` is not in `expected`.
 pub fn filename_not_in_denylist<P: AsRef<Path>, V: AsRef<[String]>>(path: P, expected: V) -> bool {
     let expected = expected.as_ref();
diff --git a/src/tools/run-make-support/src/llvm.rs b/src/tools/run-make-support/src/llvm.rs
index 4c9e9a53230..064dc62a4af 100644
--- a/src/tools/run-make-support/src/llvm.rs
+++ b/src/tools/run-make-support/src/llvm.rs
@@ -29,6 +29,12 @@ pub fn llvm_objdump() -> LlvmObjdump {
     LlvmObjdump::new()
 }
 
+/// Construct a new `llvm-ar` invocation. This assumes that `llvm-ar` is available
+/// at `$LLVM_BIN_DIR/llvm-ar`.
+pub fn llvm_ar() -> LlvmAr {
+    LlvmAr::new()
+}
+
 /// A `llvm-readobj` invocation builder.
 #[derive(Debug)]
 #[must_use]
@@ -57,10 +63,18 @@ pub struct LlvmObjdump {
     cmd: Command,
 }
 
+/// A `llvm-ar` invocation builder.
+#[derive(Debug)]
+#[must_use]
+pub struct LlvmAr {
+    cmd: Command,
+}
+
 crate::impl_common_helpers!(LlvmReadobj);
 crate::impl_common_helpers!(LlvmProfdata);
 crate::impl_common_helpers!(LlvmFilecheck);
 crate::impl_common_helpers!(LlvmObjdump);
+crate::impl_common_helpers!(LlvmAr);
 
 /// Generate the path to the bin directory of LLVM.
 #[must_use]
@@ -204,3 +218,26 @@ impl LlvmObjdump {
         self
     }
 }
+
+impl LlvmAr {
+    /// Construct a new `llvm-ar` invocation. This assumes that `llvm-ar` is available
+    /// at `$LLVM_BIN_DIR/llvm-ar`.
+    pub fn new() -> Self {
+        let llvm_ar = llvm_bin_dir().join("llvm-ar");
+        let cmd = Command::new(llvm_ar);
+        Self { cmd }
+    }
+
+    pub fn obj_to_ar(&mut self) -> &mut Self {
+        self.cmd.arg("rcus");
+        self
+    }
+
+    /// Provide an output, then an input file. Bundled in one function, as llvm-ar has
+    /// no "--output"-style flag.
+    pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -> &mut Self {
+        self.cmd.arg(out.as_ref());
+        self.cmd.arg(input.as_ref());
+        self
+    }
+}
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
index ae200d51431..6b08608cc62 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -242,6 +242,19 @@ impl Rustc {
         self
     }
 
+    /// Add a directory to the library search path with a restriction, where `kind` is a dependency
+    /// type. Equivalent to `-L KIND=PATH` in rustc.
+    pub fn specific_library_search_path<P: AsRef<Path>>(
+        &mut self,
+        kind: &str,
+        path: P,
+    ) -> &mut Self {
+        assert!(["dependency", "native", "all", "framework", "crate"].contains(&kind));
+        let path = path.as_ref().to_string_lossy();
+        self.cmd.arg(format!("-L{kind}={path}"));
+        self
+    }
+
     /// Override the system root. Equivalent to `--sysroot` in rustc.
     pub fn sysroot<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         self.cmd.arg("--sysroot");
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index e6376a8df0f..2e26f9344b8 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -10,7 +10,6 @@ run-make/c-unwind-abi-catch-panic/Makefile
 run-make/cat-and-grep-sanity-check/Makefile
 run-make/cdylib-dylib-linkage/Makefile
 run-make/compiler-lookup-paths-2/Makefile
-run-make/compiler-lookup-paths/Makefile
 run-make/compiler-rt-works-on-mingw/Makefile
 run-make/crate-hash-rustc-version/Makefile
 run-make/cross-lang-lto-clang/Makefile
@@ -21,7 +20,6 @@ run-make/dep-info-doesnt-run-much/Makefile
 run-make/dep-info-spaces/Makefile
 run-make/dep-info/Makefile
 run-make/dump-ice-to-disk/Makefile
-run-make/dump-mono-stats/Makefile
 run-make/emit-to-stdout/Makefile
 run-make/export-executable-symbols/Makefile
 run-make/extern-diff-internal-name/Makefile
@@ -93,7 +91,6 @@ run-make/pgo-indirect-call-promotion/Makefile
 run-make/pointer-auth-link-with-c/Makefile
 run-make/print-calling-conventions/Makefile
 run-make/print-target-list/Makefile
-run-make/prune-link-args/Makefile
 run-make/raw-dylib-alt-calling-convention/Makefile
 run-make/raw-dylib-c/Makefile
 run-make/raw-dylib-import-name-type/Makefile
diff --git a/tests/run-make/compiler-lookup-paths/Makefile b/tests/run-make/compiler-lookup-paths/Makefile
deleted file mode 100644
index fc0cbde4c35..00000000000
--- a/tests/run-make/compiler-lookup-paths/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-# rustc supports different types of lookup paths, such as dependency, native or crate. This test checks that these lookup paths are functional and result in functional compilation.
-# See https://github.com/rust-lang/rust/pull/19941
-
-include ../tools.mk
-
-# ignore-wasm32 (need a C compiler)
-# ignore-wasm64 (need a C compiler)
-
-all: $(TMPDIR)/libnative.a
-	mkdir -p $(TMPDIR)/crate
-	mkdir -p $(TMPDIR)/native
-	mv $(TMPDIR)/libnative.a $(TMPDIR)/native
-	$(RUSTC) a.rs
-	mv $(TMPDIR)/liba.rlib $(TMPDIR)/crate
-	$(RUSTC) b.rs -L native=$(TMPDIR)/crate && exit 1 || exit 0
-	$(RUSTC) b.rs -L dependency=$(TMPDIR)/crate && exit 1 || exit 0
-	$(RUSTC) b.rs -L crate=$(TMPDIR)/crate
-	$(RUSTC) b.rs -L all=$(TMPDIR)/crate
-	$(RUSTC) c.rs -L native=$(TMPDIR)/crate && exit 1 || exit 0
-	$(RUSTC) c.rs -L crate=$(TMPDIR)/crate && exit 1 || exit 0
-	$(RUSTC) c.rs -L dependency=$(TMPDIR)/crate
-	$(RUSTC) c.rs -L all=$(TMPDIR)/crate
-	$(RUSTC) d.rs -L dependency=$(TMPDIR)/native && exit 1 || exit 0
-	$(RUSTC) d.rs -L crate=$(TMPDIR)/native && exit 1 || exit 0
-	$(RUSTC) d.rs -L native=$(TMPDIR)/native
-	$(RUSTC) d.rs -L all=$(TMPDIR)/native
-	# Deduplication tests:
-	#   Same hash, no errors.
-	mkdir -p $(TMPDIR)/e1
-	mkdir -p $(TMPDIR)/e2
-	$(RUSTC) e.rs -o $(TMPDIR)/e1/libe.rlib
-	$(RUSTC) e.rs -o $(TMPDIR)/e2/libe.rlib
-	$(RUSTC) f.rs -L $(TMPDIR)/e1 -L $(TMPDIR)/e2
-	$(RUSTC) f.rs -L crate=$(TMPDIR)/e1 -L $(TMPDIR)/e2
-	$(RUSTC) f.rs -L crate=$(TMPDIR)/e1 -L crate=$(TMPDIR)/e2
-	#   Different hash, errors.
-	$(RUSTC) e2.rs -o $(TMPDIR)/e2/libe.rlib
-	$(RUSTC) f.rs -L $(TMPDIR)/e1 -L $(TMPDIR)/e2 && exit 1 || exit 0
-	$(RUSTC) f.rs -L crate=$(TMPDIR)/e1 -L $(TMPDIR)/e2 && exit 1 || exit 0
-	$(RUSTC) f.rs -L crate=$(TMPDIR)/e1 -L crate=$(TMPDIR)/e2 && exit 1 || exit 0
-	#   Native/dependency paths don't cause errors.
-	$(RUSTC) f.rs -L native=$(TMPDIR)/e1 -L $(TMPDIR)/e2
-	$(RUSTC) f.rs -L dependency=$(TMPDIR)/e1 -L $(TMPDIR)/e2
-	$(RUSTC) f.rs -L dependency=$(TMPDIR)/e1 -L crate=$(TMPDIR)/e2
diff --git a/tests/run-make/compiler-lookup-paths/rmake.rs b/tests/run-make/compiler-lookup-paths/rmake.rs
new file mode 100644
index 00000000000..0f791852821
--- /dev/null
+++ b/tests/run-make/compiler-lookup-paths/rmake.rs
@@ -0,0 +1,84 @@
+// Since #19941, rustc can accept specifications on its library search paths.
+// This test runs Rust programs with varied library dependencies, expecting them
+// to succeed or fail depending on the situation.
+// The second part of the tests also checks that libraries with an incorrect hash
+// fail to be used by the compiler.
+// See https://github.com/rust-lang/rust/pull/19941
+
+//@ ignore-wasm32
+//@ ignore-wasm64
+// Reason: a C compiler is required for build_native_static_lib
+
+use run_make_support::{build_native_static_lib, fs_wrapper, rustc, static_lib_name};
+
+fn main() {
+    build_native_static_lib("native");
+    let lib_native = static_lib_name("native");
+    fs_wrapper::create_dir_all("crate");
+    fs_wrapper::create_dir_all("native");
+    fs_wrapper::rename(&lib_native, format!("native/{}", &lib_native));
+    rustc().input("a.rs").run();
+    fs_wrapper::rename("liba.rlib", "crate/liba.rlib");
+    rustc().input("b.rs").specific_library_search_path("native", "crate").run_fail();
+    rustc().input("b.rs").specific_library_search_path("dependency", "crate").run_fail();
+    rustc().input("b.rs").specific_library_search_path("crate", "crate").run();
+    rustc().input("b.rs").specific_library_search_path("all", "crate").run();
+
+    rustc().input("c.rs").specific_library_search_path("native", "crate").run_fail();
+    rustc().input("c.rs").specific_library_search_path("crate", "crate").run_fail();
+    rustc().input("c.rs").specific_library_search_path("dependency", "crate").run();
+    rustc().input("c.rs").specific_library_search_path("all", "crate").run();
+
+    rustc().input("d.rs").specific_library_search_path("dependency", "native").run_fail();
+    rustc().input("d.rs").specific_library_search_path("crate", "native").run_fail();
+    rustc().input("d.rs").specific_library_search_path("native", "native").run();
+    rustc().input("d.rs").specific_library_search_path("all", "native").run();
+
+    // Deduplication tests.
+    fs_wrapper::create_dir_all("e1");
+    fs_wrapper::create_dir_all("e2");
+
+    rustc().input("e.rs").output("e1/libe.rlib").run();
+    rustc().input("e.rs").output("e2/libe.rlib").run();
+    // If the library hash is correct, compilation should succeed.
+    rustc().input("f.rs").library_search_path("e1").library_search_path("e2").run();
+    rustc()
+        .input("f.rs")
+        .specific_library_search_path("crate", "e1")
+        .library_search_path("e2")
+        .run();
+    rustc()
+        .input("f.rs")
+        .specific_library_search_path("crate", "e1")
+        .specific_library_search_path("crate", "e2")
+        .run();
+    // If the library has a different hash, errors should occur.
+    rustc().input("e2.rs").output("e2/libe.rlib").run();
+    rustc().input("f.rs").library_search_path("e1").library_search_path("e2").run_fail();
+    rustc()
+        .input("f.rs")
+        .specific_library_search_path("crate", "e1")
+        .library_search_path("e2")
+        .run_fail();
+    rustc()
+        .input("f.rs")
+        .specific_library_search_path("crate", "e1")
+        .specific_library_search_path("crate", "e2")
+        .run_fail();
+    // Native and dependency paths do not cause errors.
+    rustc()
+        .input("f.rs")
+        .specific_library_search_path("native", "e1")
+        .library_search_path("e2")
+        .run();
+    rustc()
+        .input("f.rs")
+        .specific_library_search_path("dependency", "e1")
+        .library_search_path("e2")
+        .run();
+    rustc()
+        .input("f.rs")
+        .specific_library_search_path("dependency", "e1")
+        .specific_library_search_path("crate", "e2")
+        .run();
+}
diff --git a/tests/run-make/dump-mono-stats/Makefile b/tests/run-make/dump-mono-stats/Makefile
deleted file mode 100644
index 196f84be6ec..00000000000
--- a/tests/run-make/dump-mono-stats/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTC) --crate-type lib foo.rs -Z dump-mono-stats=$(TMPDIR) -Zdump-mono-stats-format=json
-	cat $(TMPDIR)/foo.mono_items.json | $(CGREP) '"name":"bar"'
diff --git a/tests/run-make/dump-mono-stats/rmake.rs b/tests/run-make/dump-mono-stats/rmake.rs
new file mode 100644
index 00000000000..05ba2e6b8ff
--- /dev/null
+++ b/tests/run-make/dump-mono-stats/rmake.rs
@@ -0,0 +1,17 @@
+// A flag named dump-mono-stats was added to the compiler in 2022, which
+// collects stats on instantiation of items and their associated costs.
+// This test checks that the output stat file exists, and that it contains
+// a specific expected string.
+// See https://github.com/rust-lang/rust/pull/105481
+
+use run_make_support::{cwd, fs_wrapper, rustc};
+
+fn main() {
+    rustc()
+        .crate_type("lib")
+        .input("foo.rs")
+        .arg(format!("-Zdump-mono-stats={}", cwd().display()))
+        .arg("-Zdump-mono-stats-format=json")
+        .run();
+    assert!(fs_wrapper::read_to_string("foo.mono_items.json").contains(r#""name":"bar""#));
+}
diff --git a/tests/run-make/invalid-library/rmake.rs b/tests/run-make/invalid-library/rmake.rs
index 750fcd05c8a..9ebab1c8b0f 100644
--- a/tests/run-make/invalid-library/rmake.rs
+++ b/tests/run-make/invalid-library/rmake.rs
@@ -1,8 +1,14 @@
+// When the metadata format changes, old libraries used to cause librustc to abort
+// when reading their metadata. The error message for this scenario was unhelpful at best.
+// A better error message was implemented in #12645, and this test checks that it is the
+// one appearing in stderr in this scenario.
+// See https://github.com/rust-lang/rust/pull/12645
+
 use run_make_support::fs_wrapper::create_file;
-use run_make_support::{ar, rustc};
+use run_make_support::{llvm_ar, rustc};
 
 fn main() {
     create_file("lib.rmeta");
-    ar(&["lib.rmeta"], "libfoo-ffffffff-1.0.rlib");
+    llvm_ar().obj_to_ar().output_input("libfoo-ffffffff-1.0.rlib", "lib.rmeta").run();
     rustc().input("foo.rs").run_fail().assert_stderr_contains("found invalid metadata");
 }
diff --git a/tests/run-make/prune-link-args/Makefile b/tests/run-make/prune-link-args/Makefile
deleted file mode 100644
index c21ba6ace38..00000000000
--- a/tests/run-make/prune-link-args/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# ignore-windows
-
-# Notice the space in the end, this emulates the output of pkg-config
-RUSTC_FLAGS = -C link-args="-lc "
-
-all:
-	$(RUSTC) $(RUSTC_FLAGS) empty.rs
diff --git a/tests/run-make/prune-link-args/rmake.rs b/tests/run-make/prune-link-args/rmake.rs
new file mode 100644
index 00000000000..ea4ffa732bf
--- /dev/null
+++ b/tests/run-make/prune-link-args/rmake.rs
@@ -0,0 +1,17 @@
+// Passing link-args with an unexpected space
+// could result in the flag being parsed and receiving
+// an unexpected, empty linker argument. This test
+// ensures successful compilation even when a space is
+// present.
+// See https://github.com/rust-lang/rust/pull/10749
+
+//@ ignore-cross-compile
+//@ ignore-windows-gnu
+// Reason: The space is parsed as an empty linker argument on windows-gnu.
+
+use run_make_support::rustc;
+
+fn main() {
+    // Notice the space at the end of -lc, which emulates the output of pkg-config.
+    rustc().arg("-Clink-args=-lc ").input("empty.rs").run();
+}