Skip to content

Commit 1f33785

Browse files
committed
Enable raw-dylib for binaries
1 parent 144227d commit 1f33785

File tree

11 files changed

+108
-53
lines changed

11 files changed

+108
-53
lines changed

Diff for: compiler/rustc_codegen_cranelift/src/archive.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,16 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
204204
any_members
205205
}
206206

207-
fn inject_dll_import_lib(
208-
&mut self,
207+
fn sess(&self) -> &Session {
208+
self.sess
209+
}
210+
211+
fn create_dll_import_lib(
212+
_sess: &Session,
209213
_lib_name: &str,
210214
_dll_imports: &[rustc_session::cstore::DllImport],
211-
_tmpdir: &rustc_data_structures::temp_dir::MaybeTempDir,
212-
) {
213-
bug!("injecting dll imports is not supported");
215+
_tmpdir: &Path,
216+
) -> PathBuf {
217+
bug!("creating dll imports is not supported");
214218
}
215219
}

Diff for: compiler/rustc_codegen_gcc/src/archive.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::path::{Path, PathBuf};
44
use rustc_codegen_ssa::back::archive::ArchiveBuilder;
55
use rustc_session::Session;
66

7-
use rustc_data_structures::temp_dir::MaybeTempDir;
87
use rustc_session::cstore::DllImport;
98

109
struct ArchiveConfig<'a> {
@@ -177,7 +176,16 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
177176
any_members
178177
}
179178

180-
fn inject_dll_import_lib(&mut self, _lib_name: &str, _dll_imports: &[DllImport], _tmpdir: &MaybeTempDir) {
179+
fn sess(&self) -> &Session {
180+
self.config.sess
181+
}
182+
183+
fn create_dll_import_lib(
184+
_sess: &Session,
185+
_lib_name: &str,
186+
_dll_imports: &[DllImport],
187+
_tmpdir: &Path,
188+
) -> PathBuf {
181189
unimplemented!();
182190
}
183191
}

Diff for: compiler/rustc_codegen_llvm/src/back/archive.rs

+20-24
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use std::str;
1111
use crate::llvm::archive_ro::{ArchiveRO, Child};
1212
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
1313
use rustc_codegen_ssa::back::archive::ArchiveBuilder;
14-
use rustc_data_structures::temp_dir::MaybeTempDir;
1514
use rustc_session::cstore::{DllCallingConvention, DllImport};
1615
use rustc_session::Session;
1716

@@ -96,19 +95,23 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
9695
}
9796
}
9897

99-
fn inject_dll_import_lib(
100-
&mut self,
98+
fn sess(&self) -> &Session {
99+
self.sess
100+
}
101+
102+
fn create_dll_import_lib(
103+
sess: &Session,
101104
lib_name: &str,
102105
dll_imports: &[DllImport],
103-
tmpdir: &MaybeTempDir,
104-
) {
106+
tmpdir: &Path,
107+
) -> PathBuf {
105108
let output_path = {
106-
let mut output_path: PathBuf = tmpdir.as_ref().to_path_buf();
109+
let mut output_path: PathBuf = tmpdir.to_path_buf();
107110
output_path.push(format!("{}_imports", lib_name));
108111
output_path.with_extension("lib")
109112
};
110113

111-
let target = &self.sess.target;
114+
let target = &sess.target;
112115
let mingw_gnu_toolchain = target.vendor == "pc"
113116
&& target.os == "windows"
114117
&& target.env == "gnu"
@@ -117,7 +120,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
117120
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = dll_imports
118121
.iter()
119122
.map(|import: &DllImport| {
120-
if self.sess.target.arch == "x86" {
123+
if sess.target.arch == "x86" {
121124
(
122125
LlvmArchiveBuilder::i686_decorated_name(import, mingw_gnu_toolchain),
123126
import.ordinal,
@@ -134,8 +137,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
134137
// that loaded but crashed with an AV upon calling one of the imported
135138
// functions. Therefore, use binutils to create the import library instead,
136139
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
137-
let def_file_path =
138-
tmpdir.as_ref().join(format!("{}_imports", lib_name)).with_extension("def");
140+
let def_file_path = tmpdir.join(format!("{}_imports", lib_name)).with_extension("def");
139141

140142
let def_file_content = format!(
141143
"EXPORTS\n{}",
@@ -154,11 +156,11 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
154156
match std::fs::write(&def_file_path, def_file_content) {
155157
Ok(_) => {}
156158
Err(e) => {
157-
self.sess.fatal(&format!("Error writing .DEF file: {}", e));
159+
sess.fatal(&format!("Error writing .DEF file: {}", e));
158160
}
159161
};
160162

161-
let dlltool = find_binutils_dlltool(self.sess);
163+
let dlltool = find_binutils_dlltool(sess);
162164
let result = std::process::Command::new(dlltool)
163165
.args([
164166
"-d",
@@ -172,9 +174,9 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
172174

173175
match result {
174176
Err(e) => {
175-
self.sess.fatal(&format!("Error calling dlltool: {}", e));
177+
sess.fatal(&format!("Error calling dlltool: {}", e));
176178
}
177-
Ok(output) if !output.status.success() => self.sess.fatal(&format!(
179+
Ok(output) if !output.status.success() => sess.fatal(&format!(
178180
"Dlltool could not create import library: {}\n{}",
179181
String::from_utf8_lossy(&output.stdout),
180182
String::from_utf8_lossy(&output.stderr)
@@ -220,27 +222,21 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
220222
output_path_z.as_ptr(),
221223
ffi_exports.as_ptr(),
222224
ffi_exports.len(),
223-
llvm_machine_type(&self.sess.target.arch) as u16,
224-
!self.sess.target.is_like_msvc,
225+
llvm_machine_type(&sess.target.arch) as u16,
226+
!sess.target.is_like_msvc,
225227
)
226228
};
227229

228230
if result == crate::llvm::LLVMRustResult::Failure {
229-
self.sess.fatal(&format!(
231+
sess.fatal(&format!(
230232
"Error creating import library for {}: {}",
231233
lib_name,
232234
llvm::last_error().unwrap_or("unknown LLVM error".to_string())
233235
));
234236
}
235237
};
236238

237-
self.add_archive(&output_path, |_| false).unwrap_or_else(|e| {
238-
self.sess.fatal(&format!(
239-
"failed to add native library {}: {}",
240-
output_path.display(),
241-
e
242-
));
243-
});
239+
output_path
244240
}
245241
}
246242

Diff for: compiler/rustc_codegen_ssa/src/back/archive.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,37 @@ pub trait ArchiveBuilder<'a> {
5151

5252
fn build(self) -> bool;
5353

54+
fn sess(&self) -> &Session;
55+
56+
/// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>.
57+
/// and returns the path on disk to that import library.
58+
/// This functions doesn't take `self` so that it can be called from
59+
/// `linker_with_args`, which is specialized on `ArchiveBuilder` but
60+
/// doesn't take or create an instance of that type.
61+
fn create_dll_import_lib(
62+
sess: &Session,
63+
lib_name: &str,
64+
dll_imports: &[DllImport],
65+
tmpdir: &Path,
66+
) -> PathBuf;
67+
68+
/// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>
69+
/// and adds it to the current compilation's set of archives.
5470
fn inject_dll_import_lib(
5571
&mut self,
5672
lib_name: &str,
5773
dll_imports: &[DllImport],
5874
tmpdir: &MaybeTempDir,
59-
);
75+
) {
76+
let output_path =
77+
Self::create_dll_import_lib(self.sess(), lib_name, dll_imports, tmpdir.as_ref());
78+
79+
self.add_archive(&output_path, |_| false).unwrap_or_else(|e| {
80+
self.sess().fatal(&format!(
81+
"failed to add native library {}: {}",
82+
output_path.display(),
83+
e
84+
));
85+
});
86+
}
6087
}

Diff for: compiler/rustc_codegen_ssa/src/back/link.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
120120
&out_filename,
121121
codegen_results,
122122
path.as_ref(),
123-
);
123+
)?;
124124
}
125125
}
126126
if sess.opts.json_artifact_notifications {
@@ -650,7 +650,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
650650
out_filename: &Path,
651651
codegen_results: &CodegenResults,
652652
tmpdir: &Path,
653-
) {
653+
) -> Result<(), ErrorGuaranteed> {
654654
info!("preparing {:?} to {:?}", crate_type, out_filename);
655655
let (linker_path, flavor) = linker_and_flavor(sess);
656656
let mut cmd = linker_with_args::<B>(
@@ -661,7 +661,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
661661
tmpdir,
662662
out_filename,
663663
codegen_results,
664-
);
664+
)?;
665665

666666
linker::disable_localization(&mut cmd);
667667

@@ -1000,6 +1000,8 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
10001000
(Strip::None, _) => {}
10011001
}
10021002
}
1003+
1004+
Ok(())
10031005
}
10041006

10051007
// Temporarily support both -Z strip and -C strip
@@ -1848,7 +1850,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
18481850
tmpdir: &Path,
18491851
out_filename: &Path,
18501852
codegen_results: &CodegenResults,
1851-
) -> Command {
1853+
) -> Result<Command, ErrorGuaranteed> {
18521854
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
18531855
let cmd = &mut *super::linker::get_linker(
18541856
sess,
@@ -1955,6 +1957,18 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
19551957
add_upstream_native_libraries(cmd, sess, codegen_results);
19561958
}
19571959

1960+
// Link with the import library generated for any raw-dylib functions.
1961+
for (raw_dylib_name, raw_dylib_imports) in
1962+
collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
1963+
{
1964+
cmd.add_object(&B::create_dll_import_lib(
1965+
sess,
1966+
&raw_dylib_name,
1967+
&raw_dylib_imports,
1968+
tmpdir,
1969+
));
1970+
}
1971+
19581972
// Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
19591973
// command line shorter, reset it to default here before adding more libraries.
19601974
cmd.reset_per_library_state();
@@ -1998,7 +2012,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
19982012
// to it and remove the option.
19992013
add_post_link_args(cmd, sess, flavor);
20002014

2001-
cmd.take_cmd()
2015+
Ok(cmd.take_cmd())
20022016
}
20032017

20042018
fn add_order_independent_options(
@@ -2222,8 +2236,7 @@ fn add_local_native_libraries(
22222236
}
22232237
}
22242238
NativeLibKind::RawDylib => {
2225-
// FIXME(#58713): Proper handling for raw dylibs.
2226-
bug!("raw_dylib feature not yet implemented");
2239+
// Ignore RawDylib here, they are handled separately in linker_with_args().
22272240
}
22282241
}
22292242
}

Diff for: src/test/run-make-fulldeps/tools.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ NATIVE_STATICLIB = $(TMPDIR)/$(call NATIVE_STATICLIB_FILE,$(1))
9090
OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
9191
-Fo:`cygpath -w $(TMPDIR)/$(1).obj`
9292
else
93-
COMPILE_OBJ = $(CC) -c -o $(1) $(2)
93+
COMPILE_OBJ = $(CC) -v -c -o $(1) $(2)
9494
COMPILE_OBJ_CXX = $(CXX) -c -o $(1) $(2)
9595
NATIVE_STATICLIB_FILE = lib$(1).a
9696
NATIVE_STATICLIB = $(call STATICLIB,$(1))

Diff for: src/test/run-make/raw-dylib-alt-calling-convention/Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
-include ../../run-make-fulldeps/tools.mk
77

88
all:
9+
$(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs
10+
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
911
$(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
1012
ifdef IS_MSVC
11-
$(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll
13+
$(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll -noimplib
1214
else
1315
$(CC) "$(TMPDIR)"/extern.obj -shared -o "$(TMPDIR)"/extern.dll
1416
endif
15-
$(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs
16-
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
1717
"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
1818

1919
ifdef RUSTC_BLESS_TEST

Diff for: src/test/run-make/raw-dylib-c/Makefile

+7-4
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,24 @@
55
-include ../../run-make-fulldeps/tools.mk
66

77
all:
8+
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
9+
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
10+
$(RUSTC) --crate-type bin --crate-name raw_dylib_test_bin lib.rs
811
$(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
912
$(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
1013
ifdef IS_MSVC
11-
$(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
12-
$(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
14+
$(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll -noimplib
15+
$(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll -noimplib
1316
else
1417
$(CC) "$(TMPDIR)"/extern_1.obj -shared -o "$(TMPDIR)"/extern_1.dll
1518
$(CC) "$(TMPDIR)"/extern_2.obj -shared -o "$(TMPDIR)"/extern_2.dll
1619
endif
17-
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
18-
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
1920
"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
21+
"$(TMPDIR)"/raw_dylib_test_bin > "$(TMPDIR)"/output_bin.txt
2022

2123
ifdef RUSTC_BLESS_TEST
2224
cp "$(TMPDIR)"/output.txt output.txt
2325
else
2426
$(DIFF) output.txt "$(TMPDIR)"/output.txt
27+
$(DIFF) output.txt "$(TMPDIR)"/output_bin.txt
2528
endif

Diff for: src/test/run-make/raw-dylib-c/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,7 @@ pub fn library_function() {
2020
extern_fn_3();
2121
}
2222
}
23+
24+
fn main() {
25+
library_function();
26+
}

Diff for: src/test/run-make/raw-dylib-link-ordinal/Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
-include ../../run-make-fulldeps/tools.mk
66

77
all:
8+
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
9+
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
810
$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
911
ifdef IS_MSVC
10-
$(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll
12+
$(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
1113
else
1214
$(CC) "$(TMPDIR)"/exporter.obj exporter.def -shared -o "$(TMPDIR)"/exporter.dll
1315
endif
14-
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
15-
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
1616
"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
1717

1818
ifdef RUSTC_BLESS_TEST

Diff for: src/test/run-make/raw-dylib-stdcall-ordinal/Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
-include ../../run-make-fulldeps/tools.mk
77

88
all:
9+
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
10+
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
911
$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
1012
ifdef IS_MSVC
11-
$(CC) "$(TMPDIR)"/exporter.obj exporter-msvc.def -link -dll -out:"$(TMPDIR)"/exporter.dll
13+
$(CC) "$(TMPDIR)"/exporter.obj exporter-msvc.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
1214
else
1315
$(CC) "$(TMPDIR)"/exporter.obj exporter-gnu.def -shared -o "$(TMPDIR)"/exporter.dll
1416
endif
15-
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
16-
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
1717
"$(TMPDIR)"/driver > "$(TMPDIR)"/actual_output.txt
1818

1919
ifdef RUSTC_BLESS_TEST

0 commit comments

Comments
 (0)