diff --git a/src/tools/run-make-support/src/artifact_names.rs b/src/tools/run-make-support/src/artifact_names.rs index bc6ec7566e555..0d7b5cb98388e 100644 --- a/src/tools/run-make-support/src/artifact_names.rs +++ b/src/tools/run-make-support/src/artifact_names.rs @@ -38,6 +38,17 @@ pub fn dynamic_lib_name(name: &str) -> String { format!("{}{name}.{}", std::env::consts::DLL_PREFIX, std::env::consts::DLL_EXTENSION) } +/// Construct the name of the import library for the dynamic library, exclusive to MSVC and +/// accepted by link.exe. +#[track_caller] +#[must_use] +pub fn msvc_import_dynamic_lib_name(name: &str) -> String { + assert!(is_msvc(), "this function is exclusive to MSVC"); + assert!(!name.contains(char::is_whitespace), "import library name cannot contain whitespace"); + + format!("{name}.dll.lib") +} + /// Construct the dynamic library extension based on the target. #[must_use] pub fn dynamic_lib_extension() -> &'static str { diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 63c4c4d88638a..fc7e5ceae4006 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -72,13 +72,14 @@ pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, targe /// Helpers for building names of output artifacts that are potentially target-specific. pub use artifact_names::{ - bin_name, dynamic_lib_extension, dynamic_lib_name, rust_lib_name, static_lib_name, + bin_name, dynamic_lib_extension, dynamic_lib_name, msvc_import_dynamic_lib_name, rust_lib_name, + static_lib_name, }; /// Path-related helpers. pub use path_helpers::{ - cwd, filename_not_in_denylist, has_extension, has_prefix, has_suffix, not_contains, path, - shallow_find_files, source_root, + cwd, filename_contains, filename_not_in_denylist, has_extension, has_prefix, has_suffix, + not_contains, path, shallow_find_files, source_root, }; /// Helpers for scoped test execution where certain properties are attempted to be maintained. diff --git a/src/tools/run-make-support/src/path_helpers.rs b/src/tools/run-make-support/src/path_helpers.rs index f37ea8dfef8c6..b788bc6ef302c 100644 --- a/src/tools/run-make-support/src/path_helpers.rs +++ b/src/tools/run-make-support/src/path_helpers.rs @@ -3,6 +3,7 @@ use std::path::{Path, PathBuf}; use crate::env::env_var; +use crate::rfs; /// Return the current working directory. /// @@ -40,7 +41,7 @@ pub fn shallow_find_files, F: Fn(&PathBuf) -> bool>( filter: F, ) -> Vec { let mut matching_files = Vec::new(); - for entry in std::fs::read_dir(path).unwrap() { + for entry in rfs::read_dir(path) { let entry = entry.expect("failed to read directory entry."); let path = entry.path(); @@ -78,3 +79,8 @@ pub fn has_extension>(path: P, extension: &str) -> bool { pub fn has_suffix>(path: P, suffix: &str) -> bool { path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().ends_with(suffix)) } + +/// Returns true if the filename at `path` contains `needle`. +pub fn filename_contains>(path: P, needle: &str) -> bool { + path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(needle)) +} diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 38880e5e95fcf..a2cfdea712e7c 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,6 +1,5 @@ run-make/branch-protection-check-IBT/Makefile run-make/cat-and-grep-sanity-check/Makefile -run-make/cdylib-dylib-linkage/Makefile run-make/cross-lang-lto-upstream-rlibs/Makefile run-make/dep-info-doesnt-run-much/Makefile run-make/dep-info-spaces/Makefile diff --git a/tests/run-make/cdylib-dylib-linkage/Makefile b/tests/run-make/cdylib-dylib-linkage/Makefile deleted file mode 100644 index db8393d3c05a7..0000000000000 --- a/tests/run-make/cdylib-dylib-linkage/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# This test checks that cdylibs can link against dylibs as dependencies, after this restriction was disabled. -# See https://github.com/rust-lang/rust/commit/72aaa3a414d17aa0c4f19feafa5bab5f84b60e63 - -# ignore-cross-compile -include ../tools.mk - -TARGET_SYSROOT := $(shell $(RUSTC) --print sysroot)/lib/rustlib/$(TARGET)/lib - -ifdef IS_MSVC -LIBSTD := $(wildcard $(TARGET_SYSROOT)/libstd-*.dll.lib) -else -LIBSTD := $(wildcard $(TARGET_SYSROOT)/$(call DYLIB_GLOB,std)) -STD := $(basename $(patsubst lib%,%, $(notdir $(LIBSTD)))) -endif - -all: $(call RUN_BINFILE,foo) - $(call RUN,foo) - -ifdef IS_MSVC -CLIBS := $(TMPDIR)/foo.dll.lib $(TMPDIR)/bar.dll.lib $(LIBSTD) -$(call RUN_BINFILE,foo): $(call DYLIB,foo) - $(CC) $(CFLAGS) foo.c $(CLIBS) $(call OUT_EXE,foo) -else -CLIBS := -lfoo -lbar -l$(STD) -L $(TMPDIR) -L $(TARGET_SYSROOT) -$(call RUN_BINFILE,foo): $(call DYLIB,foo) - $(CC) $(CFLAGS) foo.c $(CLIBS) -o $(call RUN_BINFILE,foo) -endif - -$(call DYLIB,foo): - $(RUSTC) -C prefer-dynamic bar.rs - $(RUSTC) foo.rs diff --git a/tests/run-make/cdylib-dylib-linkage/rmake.rs b/tests/run-make/cdylib-dylib-linkage/rmake.rs new file mode 100644 index 0000000000000..a8fd8e2d16848 --- /dev/null +++ b/tests/run-make/cdylib-dylib-linkage/rmake.rs @@ -0,0 +1,41 @@ +// Previously, rustc mandated that cdylibs could only link against rlibs as dependencies, +// making linkage between cdylibs and dylibs impossible. After this was changed in #68448, +// this test attempts to link both `foo` (a cdylib) and `bar` (a dylib) and checks that +// both compilation and execution are successful. +// See https://github.com/rust-lang/rust/pull/68448 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{ + bin_name, cc, dynamic_lib_extension, dynamic_lib_name, filename_contains, has_extension, + has_prefix, has_suffix, is_msvc, msvc_import_dynamic_lib_name, path, run, rustc, + shallow_find_files, target, +}; + +fn main() { + rustc().arg("-Cprefer-dynamic").input("bar.rs").run(); + rustc().input("foo.rs").run(); + let sysroot = rustc().print("sysroot").run().stdout_utf8(); + let sysroot = sysroot.trim(); + let target_sysroot = path(sysroot).join("lib/rustlib").join(target()).join("lib"); + if is_msvc() { + let mut libs = shallow_find_files(&target_sysroot, |path| { + has_prefix(path, "libstd-") && has_suffix(path, ".dll.lib") + }); + libs.push(path(msvc_import_dynamic_lib_name("foo"))); + libs.push(path(msvc_import_dynamic_lib_name("bar"))); + cc().input("foo.c").args(&libs).out_exe("foo").run(); + } else { + let stdlibs = shallow_find_files(&target_sysroot, |path| { + has_extension(path, dynamic_lib_extension()) && filename_contains(path, "std") + }); + cc().input("foo.c") + .args(&[dynamic_lib_name("foo"), dynamic_lib_name("bar")]) + .arg(stdlibs.get(0).unwrap()) + .library_search_path(&target_sysroot) + .output(bin_name("foo")) + .run(); + } + run("foo"); +}