From 034a4c55e34b10d812159b42cde4efbc42f18b5f Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 16 Jul 2024 14:59:56 -0400 Subject: [PATCH 1/3] rewrite macos-fat-archive to rmake --- src/tools/run-make-support/src/lib.rs | 4 +- src/tools/run-make-support/src/llvm.rs | 37 +++++++++++++++++++ .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/macos-fat-archive/Makefile | 10 ----- tests/run-make/macos-fat-archive/rmake.rs | 20 ++++++++++ 5 files changed, 59 insertions(+), 13 deletions(-) delete mode 100644 tests/run-make/macos-fat-archive/Makefile create mode 100644 tests/run-make/macos-fat-archive/rmake.rs diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index e5f1ce1bf345e..8d30a8dc7b32c 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}; diff --git a/src/tools/run-make-support/src/llvm.rs b/src/tools/run-make-support/src/llvm.rs index 4c9e9a5323025..064dc62a4afa2 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, input: impl AsRef) -> &mut Self { + self.cmd.arg(out.as_ref()); + self.cmd.arg(input.as_ref()); + self + } +} diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index f7ec7d0b3f6b9..aa56f4c30678a 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -76,7 +76,6 @@ run-make/lto-linkage-used-attr/Makefile run-make/lto-no-link-whole-rlib/Makefile run-make/lto-smoke-c/Makefile run-make/macos-deployment-target/Makefile -run-make/macos-fat-archive/Makefile run-make/manual-link/Makefile run-make/min-global-align/Makefile run-make/missing-crate-dependency/Makefile diff --git a/tests/run-make/macos-fat-archive/Makefile b/tests/run-make/macos-fat-archive/Makefile deleted file mode 100644 index 0feb39a23cb54..0000000000000 --- a/tests/run-make/macos-fat-archive/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# only-apple - -include ../tools.mk - -"$(TMPDIR)"/libnative-library.a: native-library.c - $(CC) -arch arm64 -arch x86_64 native-library.c -c -o "$(TMPDIR)"/native-library.o - $(AR) crs "$(TMPDIR)"/libnative-library.a "$(TMPDIR)"/native-library.o - -all: "$(TMPDIR)"/libnative-library.a - $(RUSTC) lib.rs --crate-type=lib -L "native=$(TMPDIR)" -l static=native-library diff --git a/tests/run-make/macos-fat-archive/rmake.rs b/tests/run-make/macos-fat-archive/rmake.rs new file mode 100644 index 0000000000000..c9f0fa0769306 --- /dev/null +++ b/tests/run-make/macos-fat-archive/rmake.rs @@ -0,0 +1,20 @@ +// macOS (and iOS) has a concept of universal (fat) binaries which contain code for multiple CPU +// architectures in the same file. Apple is migrating from x86_64 to aarch64 CPUs, +// so for the next few years it will be important for macOS developers to +// build "fat" binaries (executables and cdylibs). + +// Rustc used to be unable to handle these special libraries, which was fixed in #98736. If +// compilation in this test is successful, the native fat library was successfully linked to. +// See https://github.com/rust-lang/rust/issues/55235 + +//@ only-apple + +use run_make_support::{cc, llvm_ar, rustc}; + +fn main() { + cc().args(&["-arch", "arm64", "-arch", "x86_64", "native-library.c", "-c"]) + .out_exe("native-library.o") + .run(); + llvm_ar().obj_to_ar().output_input("libnative-library.a", "native-library.o").run(); + rustc().input("lib.rs").crate_type("lib").arg("-lstatic=native-library").run(); +} From bfa10ac479c9a827933257ef7765edb414348189 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 16 Jul 2024 15:07:10 -0400 Subject: [PATCH 2/3] rewrite manual-link to rmake --- src/tools/run-make-support/src/lib.rs | 20 +++++++++++++++++++ .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/manual-link/Makefile | 7 ------- tests/run-make/manual-link/rmake.rs | 16 +++++++++++++++ 4 files changed, 36 insertions(+), 8 deletions(-) delete mode 100644 tests/run-make/manual-link/Makefile create mode 100644 tests/run-make/manual-link/rmake.rs diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 8d30a8dc7b32c..27c8919f42dfb 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -321,6 +321,26 @@ pub fn count_regex_matches_in_files_with_extension(re: ®ex::Regex, ext: &str) count } +/// 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 mut obj_file = PathBuf::from(format!("{lib_name}.o")); + if is_msvc() { + obj_file.set_extension(""); + obj_file.set_extension("obj"); + } + llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run(); + path(lib_path) +} + /// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is /// available on the platform! #[track_caller] diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index aa56f4c30678a..59d33381146c9 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -76,7 +76,6 @@ run-make/lto-linkage-used-attr/Makefile run-make/lto-no-link-whole-rlib/Makefile run-make/lto-smoke-c/Makefile run-make/macos-deployment-target/Makefile -run-make/manual-link/Makefile run-make/min-global-align/Makefile run-make/missing-crate-dependency/Makefile run-make/mixing-libs/Makefile diff --git a/tests/run-make/manual-link/Makefile b/tests/run-make/manual-link/Makefile deleted file mode 100644 index 8dbf0460fff50..0000000000000 --- a/tests/run-make/manual-link/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: $(TMPDIR)/libbar.a - $(RUSTC) foo.rs -lstatic=bar - $(RUSTC) main.rs - $(call RUN,main) diff --git a/tests/run-make/manual-link/rmake.rs b/tests/run-make/manual-link/rmake.rs new file mode 100644 index 0000000000000..1d3621722630a --- /dev/null +++ b/tests/run-make/manual-link/rmake.rs @@ -0,0 +1,16 @@ +// A smoke test for the `-l` command line rustc flag, which manually links to the selected +// library. Useful for native libraries, this is roughly equivalent to `#[link]` in Rust code. +// If compilation succeeds, the flag successfully linked the native library. +// See https://github.com/rust-lang/rust/pull/18470 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{build_native_static_lib, run, rustc}; + +fn main() { + build_native_static_lib("bar"); + rustc().input("foo.rs").arg("-lstatic=bar").run(); + rustc().input("main.rs").run(); + run("main"); +} From 3a14ef08b80e9482b172ca50f9cf15f0f25eef4b Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 16 Jul 2024 15:30:41 -0400 Subject: [PATCH 3/3] rewrite archive-duplicate-names to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../run-make/archive-duplicate-names/Makefile | 16 -------- .../run-make/archive-duplicate-names/rmake.rs | 37 +++++++++++++++++++ 3 files changed, 37 insertions(+), 17 deletions(-) delete mode 100644 tests/run-make/archive-duplicate-names/Makefile create mode 100644 tests/run-make/archive-duplicate-names/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 59d33381146c9..0dd6ff80031d9 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,4 +1,3 @@ -run-make/archive-duplicate-names/Makefile run-make/atomic-lock-free/Makefile run-make/branch-protection-check-IBT/Makefile run-make/c-dynamic-dylib/Makefile diff --git a/tests/run-make/archive-duplicate-names/Makefile b/tests/run-make/archive-duplicate-names/Makefile deleted file mode 100644 index 207eee392993b..0000000000000 --- a/tests/run-make/archive-duplicate-names/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# When two object archives with the same filename are present, an iterator is supposed to inspect each object, recognize the duplication and extract each one to a different directory. -# This test checks that this duplicate handling behaviour has not been broken. -# See https://github.com/rust-lang/rust/pull/24439 - -# ignore-cross-compile -include ../tools.mk - -all: - mkdir $(TMPDIR)/a - mkdir $(TMPDIR)/b - $(call COMPILE_OBJ,$(TMPDIR)/a/foo.o,foo.c) - $(call COMPILE_OBJ,$(TMPDIR)/b/foo.o,bar.c) - $(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o - $(RUSTC) foo.rs - $(RUSTC) bar.rs - $(call RUN,bar) diff --git a/tests/run-make/archive-duplicate-names/rmake.rs b/tests/run-make/archive-duplicate-names/rmake.rs new file mode 100644 index 0000000000000..151970aec4b10 --- /dev/null +++ b/tests/run-make/archive-duplicate-names/rmake.rs @@ -0,0 +1,37 @@ +// When two object archives with the same filename are present, an iterator is supposed to +// inspect each object, recognize the duplication and extract each one to a different directory. +// This test checks that this duplicate handling behaviour has not been broken. +// See https://github.com/rust-lang/rust/pull/24439 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{cc, fs_wrapper, is_msvc, llvm_ar, run, rustc}; + +fn main() { + fs_wrapper::create_dir("a"); + fs_wrapper::create_dir("b"); + compile_obj_force_foo("a", "foo"); + compile_obj_force_foo("b", "bar"); + let mut ar = llvm_ar(); + ar.obj_to_ar().arg("libfoo.a"); + if is_msvc() { + ar.arg("a/foo.obj").arg("b/foo.obj").run(); + } else { + ar.arg("a/foo.o").arg("b/foo.o").run(); + } + rustc().input("foo.rs").run(); + rustc().input("bar.rs").run(); + run("bar"); +} + +#[track_caller] +pub fn compile_obj_force_foo(dir: &str, lib_name: &str) { + let obj_file = if is_msvc() { format!("{dir}/foo") } else { format!("{dir}/foo.o") }; + let src = format!("{lib_name}.c"); + 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(); + }; +}