about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs39
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile1
-rw-r--r--src/tools/compiletest/src/header.rs15
-rw-r--r--tests/run-make/raw-dylib-cross-compilation/Makefile22
-rw-r--r--tests/run-make/raw-dylib-cross-compilation/lib.rs20
9 files changed, 87 insertions, 14 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index dd3268d7780..a570f2af0f0 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -189,6 +189,15 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
                 path.push(lib_name);
                 path
             };
+            // dlltool target architecture args from:
+            // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
+            let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch.as_ref() {
+                "x86_64" => ("i386:x86-64", "--64"),
+                "x86" => ("i386", "--32"),
+                "aarch64" => ("arm64", "--64"),
+                "arm" => ("arm", "--32"),
+                _ => panic!("unsupported arch {}", sess.target.arch),
+            };
             let result = std::process::Command::new(dlltool)
                 .args([
                     "-d",
@@ -197,6 +206,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
                     lib_name,
                     "-l",
                     output_path.to_str().unwrap(),
+                    "-m",
+                    dlltool_target_arch,
+                    "-f",
+                    dlltool_target_bitness,
                     "--no-leading-underscore",
                     "--temp-prefix",
                     temp_prefix.to_str().unwrap(),
@@ -422,24 +435,22 @@ fn find_binutils_dlltool(sess: &Session) -> OsString {
         return dlltool_path.clone().into_os_string();
     }
 
-    let mut tool_name: OsString = if sess.host.arch != sess.target.arch {
-        // We are cross-compiling, so we need the tool with the prefix matching our target
-        if sess.target.arch == "x86" {
-            "i686-w64-mingw32-dlltool"
-        } else {
-            "x86_64-w64-mingw32-dlltool"
-        }
+    let tool_name: OsString = if sess.host.options.is_like_windows {
+        // If we're compiling on Windows, always use "dlltool.exe".
+        "dlltool.exe"
     } else {
-        // We are not cross-compiling, so we just want `dlltool`
-        "dlltool"
+        // On other platforms, use the architecture-specific name.
+        match sess.target.arch.as_ref() {
+            "x86_64" => "x86_64-w64-mingw32-dlltool",
+            "x86" => "i686-w64-mingw32-dlltool",
+            "aarch64" => "aarch64-w64-mingw32-dlltool",
+
+            // For non-standard architectures (e.g., aarch32) fallback to "dlltool".
+            _ => "dlltool",
+        }
     }
     .into();
 
-    if sess.host.options.is_like_windows {
-        // If we're compiling on Windows, add the .exe suffix
-        tool_name.push(".exe");
-    }
-
     // NOTE: it's not clear how useful it is to explicitly search PATH.
     for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
         let full_path = dir.join(&tool_name);
diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
index d9e58386256..b5abf6564a6 100644
--- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
@@ -16,6 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   zlib1g-dev \
   lib32z1-dev \
   xz-utils \
+  mingw-w64 \
   && rm -rf /var/lib/apt/lists/*
 
 
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile
index b99a0886b4d..21dcf29b4a9 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile
@@ -22,6 +22,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   zlib1g-dev \
   xz-utils \
   nodejs \
+  mingw-w64 \
   && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile
index dc8a4aac768..cfb638e8b07 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile
@@ -23,6 +23,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   zlib1g-dev \
   xz-utils \
   nodejs \
+  mingw-w64 \
   && rm -rf /var/lib/apt/lists/*
 
 # Install powershell (universal package) so we can test x.ps1 on Linux
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
index 5219247cc6f..fb5037e3b97 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
@@ -25,6 +25,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   zlib1g-dev \
   xz-utils \
   nodejs \
+  mingw-w64 \
   && rm -rf /var/lib/apt/lists/*
 
 # Install powershell (universal package) so we can test x.ps1 on Linux
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
index 5b9581f72a6..fbec368c9ee 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
@@ -16,6 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config \
   xz-utils \
+  mingw-w64 \
   && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 22a0b1d13be..5bc9d9afcb9 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -964,6 +964,19 @@ pub fn make_test_description<R: Read>(
         .join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" })
         .exists();
 
+    fn is_on_path(file: &'static str) -> impl Fn() -> bool {
+        move || env::split_paths(&env::var_os("PATH").unwrap()).any(|dir| dir.join(file).is_file())
+    }
+
+    // On Windows, dlltool.exe is used for all architectures.
+    #[cfg(windows)]
+    let (has_i686_dlltool, has_x86_64_dlltool) =
+        (is_on_path("dlltool.exe"), is_on_path("dlltool.exe"));
+    // For non-Windows, there are architecture specific dlltool binaries.
+    #[cfg(not(windows))]
+    let (has_i686_dlltool, has_x86_64_dlltool) =
+        (is_on_path("i686-w64-mingw32-dlltool"), is_on_path("x86_64-w64-mingw32-dlltool"));
+
     iter_header(path, src, &mut |revision, ln| {
         if revision.is_some() && revision != cfg {
             return;
@@ -1031,6 +1044,8 @@ pub fn make_test_description<R: Read>(
         reason!(config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln));
         reason!(config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln));
         reason!(!has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld"));
+        reason!(config.parse_name_directive(ln, "needs-i686-dlltool") && !has_i686_dlltool());
+        reason!(config.parse_name_directive(ln, "needs-x86_64-dlltool") && !has_x86_64_dlltool());
         should_fail |= config.parse_name_directive(ln, "should-fail");
     });
 
diff --git a/tests/run-make/raw-dylib-cross-compilation/Makefile b/tests/run-make/raw-dylib-cross-compilation/Makefile
new file mode 100644
index 00000000000..2a714f3a11f
--- /dev/null
+++ b/tests/run-make/raw-dylib-cross-compilation/Makefile
@@ -0,0 +1,22 @@
+# Tests that raw-dylib cross compilation works correctly
+
+# only-gnu
+# needs-i686-dlltool
+# needs-x86_64-dlltool
+
+# i686 dlltool.exe can't product x64 binaries.
+# ignore-i686-pc-windows-gnu
+
+include ../../run-make-fulldeps/tools.mk
+
+all:
+	# Build as x86 and make sure that we have x86 objects only.
+	$(RUSTC) --crate-type lib --crate-name i686_raw_dylib_test --target i686-pc-windows-gnu lib.rs
+	"$(LLVM_BIN_DIR)"/llvm-objdump -a $(TMPDIR)/libi686_raw_dylib_test.rlib > $(TMPDIR)/i686.objdump.txt
+	$(CGREP) "file format coff-i386" < $(TMPDIR)/i686.objdump.txt
+	$(CGREP) -v "file format coff-x86-64" < $(TMPDIR)/i686.objdump.txt
+	# Build as x64 and make sure that we have x64 objects only.
+	$(RUSTC) --crate-type lib --crate-name x64_raw_dylib_test --target x86_64-pc-windows-gnu lib.rs
+	"$(LLVM_BIN_DIR)"/llvm-objdump -a $(TMPDIR)/libx64_raw_dylib_test.rlib > $(TMPDIR)/x64.objdump.txt
+	$(CGREP) "file format coff-x86-64" < $(TMPDIR)/x64.objdump.txt
+	$(CGREP) -v "file format coff-i386" < $(TMPDIR)/x64.objdump.txt
diff --git a/tests/run-make/raw-dylib-cross-compilation/lib.rs b/tests/run-make/raw-dylib-cross-compilation/lib.rs
new file mode 100644
index 00000000000..51bf2ec6b6e
--- /dev/null
+++ b/tests/run-make/raw-dylib-cross-compilation/lib.rs
@@ -0,0 +1,20 @@
+#![feature(raw_dylib)]
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+// This is needed because of #![no_core]:
+#[lang = "sized"]
+trait Sized {}
+
+#[link(name = "extern_1", kind = "raw-dylib")]
+extern {
+    fn extern_fn();
+}
+
+pub fn extern_fn_caller() {
+    unsafe {
+        extern_fn();
+    }
+}