Skip to content

Commit a2f3413

Browse files
authored
Merge pull request #1524 from dpaoliello/rawdylib
Add support for raw-dylib
2 parents fdc6a55 + 2756bd6 commit a2f3413

8 files changed

+120
-91
lines changed

Diff for: Cargo.lock

+12-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ cranelift-object = { version = "0.110.1" }
1717
target-lexicon = "0.12.0"
1818
gimli = { version = "0.28", default-features = false, features = ["write"]}
1919
object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
20+
ar_archive_writer = "0.3"
2021

2122
indexmap = "2.0.0"
2223
libloading = { version = "0.8.0", optional = true }

Diff for: build_system/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
106106
]);
107107
runner.run_out_command("gen_block_iterate", &[]);
108108
}),
109+
TestCase::build_bin_and_run("aot.raw-dylib", "example/raw-dylib.rs", &[]),
109110
];
110111

111112
pub(crate) static RAND_REPO: GitRepo = GitRepo::github(

Diff for: config.txt

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ aot.issue-59326
4545
aot.polymorphize_coroutine
4646
aot.neon
4747
aot.gen_block_iterate
48+
aot.raw-dylib
4849

4950
testsuite.extended_sysroot
5051
test.rust-random/rand

Diff for: example/raw-dylib.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Tests the raw-dylib feature for Windows.
2+
// https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute
3+
4+
fn main() {
5+
#[cfg(windows)]
6+
{
7+
#[link(name = "kernel32", kind = "raw-dylib")]
8+
extern "C" {
9+
fn GetModuleFileNameA(
10+
module: *mut std::ffi::c_void,
11+
filename: *mut u8,
12+
size: u32,
13+
) -> u32;
14+
}
15+
16+
// Get the filename of the current executable....
17+
let mut buffer = [0u8; 1024];
18+
let size = unsafe {
19+
GetModuleFileNameA(core::ptr::null_mut(), buffer.as_mut_ptr(), buffer.len() as u32)
20+
};
21+
if size == 0 {
22+
eprintln!("failed to get module file name: {}", std::io::Error::last_os_error());
23+
return;
24+
} else {
25+
// ...and make sure that it matches the test name.
26+
let filename =
27+
std::ffi::CStr::from_bytes_with_nul(&buffer[..size as usize + 1]).unwrap();
28+
assert!(filename.to_str().unwrap().ends_with("raw-dylib.exe"));
29+
}
30+
}
31+
}

Diff for: patches/0029-stdlib-rawdylib-processprng.patch

-47
This file was deleted.

Diff for: patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch

-37
This file was deleted.

Diff for: src/archive.rs

+74-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
use std::borrow::Borrow;
2+
use std::fs;
13
use std::path::Path;
24

5+
use ar_archive_writer::{COFFShortExport, MachineTypes};
36
use rustc_codegen_ssa::back::archive::{
4-
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
7+
create_mingw_dll_import_lib, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder,
8+
DEFAULT_OBJECT_READER,
59
};
10+
use rustc_codegen_ssa::common::is_mingw_gnu_toolchain;
611
use rustc_session::Session;
712

813
pub(crate) struct ArArchiveBuilderBuilder;
@@ -15,10 +20,74 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
1520
fn create_dll_import_lib(
1621
&self,
1722
sess: &Session,
18-
_lib_name: &str,
19-
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
20-
_output_path: &Path,
23+
lib_name: &str,
24+
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
25+
output_path: &Path,
2126
) {
22-
sess.dcx().fatal("raw-dylib is not yet supported by rustc_codegen_cranelift");
27+
if is_mingw_gnu_toolchain(&sess.target) {
28+
// The binutils linker used on -windows-gnu targets cannot read the import
29+
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
30+
// that loaded but crashed with an AV upon calling one of the imported
31+
// functions. Therefore, use binutils to create the import library instead,
32+
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
33+
create_mingw_dll_import_lib(
34+
sess,
35+
lib_name,
36+
import_name_and_ordinal_vector,
37+
output_path,
38+
);
39+
} else {
40+
let mut file =
41+
match fs::OpenOptions::new().write(true).create_new(true).open(&output_path) {
42+
Ok(file) => file,
43+
Err(error) => {
44+
sess.dcx().fatal(format!(
45+
"failed to create import library file `{path}`: {error}",
46+
path = output_path.display(),
47+
));
48+
}
49+
};
50+
51+
let machine = match sess.target.arch.borrow() {
52+
"x86" => MachineTypes::I386,
53+
"x86_64" => MachineTypes::AMD64,
54+
"arm" => MachineTypes::ARMNT,
55+
"aarch64" => MachineTypes::ARM64,
56+
_ => {
57+
sess.dcx().fatal(format!(
58+
"unsupported target architecture `{arch}`",
59+
arch = sess.target.arch,
60+
));
61+
}
62+
};
63+
64+
let exports = import_name_and_ordinal_vector
65+
.iter()
66+
.map(|(name, ordinal)| COFFShortExport {
67+
name: name.to_string(),
68+
ext_name: None,
69+
symbol_name: None,
70+
alias_target: None,
71+
ordinal: ordinal.unwrap_or(0),
72+
noname: ordinal.is_some(),
73+
data: false,
74+
private: false,
75+
constant: false,
76+
})
77+
.collect::<Vec<_>>();
78+
79+
if let Err(error) = ar_archive_writer::write_import_library(
80+
&mut file,
81+
lib_name,
82+
&exports,
83+
machine,
84+
!sess.target.is_like_msvc,
85+
) {
86+
sess.dcx().fatal(format!(
87+
"failed to create import library `{path}`: `{error}`",
88+
path = output_path.display(),
89+
));
90+
}
91+
}
2392
}
2493
}

0 commit comments

Comments
 (0)