Skip to content

Commit

Permalink
Stabilize -Cdlltool
Browse files Browse the repository at this point in the history
  • Loading branch information
dpaoliello committed Mar 24, 2023
1 parent df7fd99 commit 13d3b75
Show file tree
Hide file tree
Showing 17 changed files with 104 additions and 15 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/messages.ftl
Expand Up @@ -24,10 +24,10 @@ codegen_llvm_error_writing_def_file =
Error writing .DEF file: {$error}
codegen_llvm_error_calling_dlltool =
Error calling dlltool: {$error}
Error calling dlltool '{$dlltool_path}': {$error}
codegen_llvm_dlltool_fail_import_library =
Dlltool could not create import library: {$stdout}\n{$stderr}
Dlltool could not create import library: {$error}
codegen_llvm_target_feature_disable_or_enable =
the target features {$features} must all be either enabled or disabled together
Expand Down
15 changes: 9 additions & 6 deletions compiler/rustc_codegen_llvm/src/back/archive.rs
Expand Up @@ -198,7 +198,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
"arm" => ("arm", "--32"),
_ => panic!("unsupported arch {}", sess.target.arch),
};
let result = std::process::Command::new(dlltool)
let result = std::process::Command::new(&dlltool)
.args([
"-d",
def_file_path.to_str().unwrap(),
Expand All @@ -218,12 +218,15 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {

match result {
Err(e) => {
sess.emit_fatal(ErrorCallingDllTool { error: e });
sess.emit_fatal(ErrorCallingDllTool {
dlltool_path: dlltool.to_string_lossy(),
error: e,
});
}
Ok(output) if !output.status.success() => {
// dlltool returns '0' on failure, so check for error output instead.
Ok(output) if !output.stderr.is_empty() => {
sess.emit_fatal(DlltoolFailImportLibrary {
stdout: String::from_utf8_lossy(&output.stdout),
stderr: String::from_utf8_lossy(&output.stderr),
error: String::from_utf8_lossy(&output.stderr),
})
}
_ => {}
Expand Down Expand Up @@ -431,7 +434,7 @@ fn string_to_io_error(s: String) -> io::Error {

fn find_binutils_dlltool(sess: &Session) -> OsString {
assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
if let Some(dlltool_path) = &sess.opts.unstable_opts.dlltool {
if let Some(dlltool_path) = &sess.opts.cg.dlltool {
return dlltool_path.clone().into_os_string();
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_llvm/src/errors.rs
Expand Up @@ -67,15 +67,15 @@ pub(crate) struct ErrorWritingDEFFile {

#[derive(Diagnostic)]
#[diag(codegen_llvm_error_calling_dlltool)]
pub(crate) struct ErrorCallingDllTool {
pub(crate) struct ErrorCallingDllTool<'a> {
pub dlltool_path: Cow<'a, str>,
pub error: std::io::Error,
}

#[derive(Diagnostic)]
#[diag(codegen_llvm_dlltool_fail_import_library)]
pub(crate) struct DlltoolFailImportLibrary<'a> {
pub stdout: Cow<'a, str>,
pub stderr: Cow<'a, str>,
pub error: Cow<'a, str>,
}

#[derive(Diagnostic)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/tests.rs
Expand Up @@ -545,6 +545,7 @@ fn test_codegen_options_tracking_hash() {
untracked!(ar, String::from("abc"));
untracked!(codegen_units, Some(42));
untracked!(default_linker_libraries, true);
untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe")));
untracked!(extra_filename, String::from("extra-filename"));
untracked!(incremental, Some(String::from("abc")));
// `link_arg` is omitted because it just forwards to `link_args`.
Expand Down Expand Up @@ -649,7 +650,6 @@ fn test_unstable_options_tracking_hash() {
untracked!(assert_incr_state, Some(String::from("loaded")));
untracked!(deduplicate_diagnostics, false);
untracked!(dep_tasks, true);
untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe")));
untracked!(dont_buffer_diagnostics, true);
untracked!(dump_dep_graph, true);
untracked!(dump_drop_tracking_cfg, Some("cfg.dot".to_string()));
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_session/src/options.rs
Expand Up @@ -1205,6 +1205,8 @@ options! {
2 = full debug info with variable and type information; default: 0)"),
default_linker_libraries: bool = (false, parse_bool, [UNTRACKED],
"allow the linker to link its default libraries (default: no)"),
dlltool: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"import library generation tool (windows-gnu only)"),
embed_bitcode: bool = (true, parse_bool, [TRACKED],
"emit bitcode in rlibs (default: yes)"),
extra_filename: String = (String::new(), parse_string, [UNTRACKED],
Expand Down Expand Up @@ -1361,8 +1363,6 @@ options! {
(default: no)"),
diagnostic_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
"set the current output width for diagnostic truncation"),
dlltool: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"import library generation tool (windows-gnu only)"),
dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED],
"emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) \
(default: no)"),
Expand Down
8 changes: 8 additions & 0 deletions src/doc/rustc/src/codegen-options/index.md
Expand Up @@ -88,6 +88,14 @@ It takes one of the following values:
For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to
the linker.

## dlltool

On `windows-gnu` targets, this flag controls which dlltool `rustc` invokes to
generate import libraries when using the [`raw-dylib` link kind](../../reference/items/external-blocks.md#the-link-attribute).
It takes a path to [the dlltool executable](https://sourceware.org/binutils/docs/binutils/dlltool.html).
If this flag is not specified, a dlltool executable will be inferred based on
the host environment and target.

## embed-bitcode

This flag controls whether or not the compiler embeds LLVM bitcode into object
Expand Down
10 changes: 10 additions & 0 deletions src/tools/compiletest/src/header.rs
Expand Up @@ -976,6 +976,15 @@ pub fn make_test_description<R: Read>(
#[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"));
let has_dlltool = || {
if config.matches_arch("x86") {
has_i686_dlltool()
} else if config.matches_arch("x86_64") {
has_x86_64_dlltool()
} else {
false
}
};

iter_header(path, src, &mut |revision, ln| {
if revision.is_some() && revision != cfg {
Expand Down Expand Up @@ -1046,6 +1055,7 @@ pub fn make_test_description<R: Read>(
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());
reason!(config.parse_name_directive(ln, "needs-dlltool") && !has_dlltool());
should_fail |= config.parse_name_directive(ln, "should-fail");
});

Expand Down
11 changes: 11 additions & 0 deletions tests/run-make/raw-dylib-custom-dlltool/Makefile
@@ -0,0 +1,11 @@
# Test using -Cdlltool to change where raw-dylib looks for the dlltool binary.

# only-windows
# only-gnu
# needs-dlltool

include ../../run-make-fulldeps/tools.mk

all:
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs -Cdlltool=$(CURDIR)/script.cmd
$(DIFF) output.txt "$(TMPDIR)"/output.txt
12 changes: 12 additions & 0 deletions tests/run-make/raw-dylib-custom-dlltool/lib.rs
@@ -0,0 +1,12 @@
#![feature(raw_dylib)]

#[link(name = "extern_1", kind = "raw-dylib")]
extern {
fn extern_fn_1();
}

pub fn library_function() {
unsafe {
extern_fn_1();
}
}
1 change: 1 addition & 0 deletions tests/run-make/raw-dylib-custom-dlltool/output.txt
@@ -0,0 +1 @@
Called dlltool via script.cmd
2 changes: 2 additions & 0 deletions tests/run-make/raw-dylib-custom-dlltool/script.cmd
@@ -0,0 +1,2 @@
echo Called dlltool via script.cmd> %TMPDIR%\output.txt
dlltool.exe %*
1 change: 1 addition & 0 deletions tests/rustdoc-ui/c-help.stdout
Expand Up @@ -5,6 +5,7 @@
-C debug-assertions=val -- explicitly enable the `cfg(debug_assertions)` directive
-C debuginfo=val -- debug info emission level (0 = no debug info, 1 = line tables only, 2 = full debug info with variable and type information; default: 0)
-C default-linker-libraries=val -- allow the linker to link its default libraries (default: no)
-C dlltool=val -- import library generation tool (windows-gnu only)
-C embed-bitcode=val -- emit bitcode in rlibs (default: yes)
-C extra-filename=val -- extra data to put in each output filename
-C force-frame-pointers=val -- force use of the frame pointers
Expand Down
1 change: 0 additions & 1 deletion tests/rustdoc-ui/z-help.stdout
Expand Up @@ -17,7 +17,6 @@
-Z dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no)
-Z dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no)
-Z diagnostic-width=val -- set the current output width for diagnostic truncation
-Z dlltool=val -- import library generation tool (windows-gnu only)
-Z dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no)
-Z drop-tracking=val -- enables drop tracking in generators (default: no)
-Z drop-tracking-mir=val -- enables drop tracking on MIR in generators (default: no)
Expand Down
20 changes: 20 additions & 0 deletions tests/ui/rfc-2627-raw-dylib/dlltool-failed.rs
@@ -0,0 +1,20 @@
// Tests that dlltool failing to generate an import library will raise an error.

// only-gnu
// only-windows
// needs-dlltool
// compile-flags: --crate-type lib --emit link
// normalize-stderr-test: "[^ ']*/dlltool.exe" -> "$$DLLTOOL"
// normalize-stderr-test: "[^ ]*/foo.def" -> "$$DEF_FILE"
#![feature(raw_dylib)]
#[link(name = "foo", kind = "raw-dylib")]
extern "C" {
// `@1` is an invalid name to export, as it usually indicates that something
// is being exported via ordinal.
#[link_name = "@1"]
fn f(x: i32);
}

pub fn lib_main() {
unsafe { f(42); }
}
4 changes: 4 additions & 0 deletions tests/ui/rfc-2627-raw-dylib/dlltool-failed.stderr
@@ -0,0 +1,4 @@
error: Dlltool could not create import library: $DLLTOOL: Syntax error in def file $DEF_FILE:1

error: aborting due to previous error

14 changes: 14 additions & 0 deletions tests/ui/rfc-2627-raw-dylib/invalid-dlltool.rs
@@ -0,0 +1,14 @@
// Tests that failing to run dlltool will raise an error.

// only-gnu
// only-windows
// compile-flags: --crate-type lib --emit link -Cdlltool=does_not_exit.exe
#![feature(raw_dylib)]
#[link(name = "foo", kind = "raw-dylib")]
extern "C" {
fn f(x: i32);
}

pub fn lib_main() {
unsafe { f(42); }
}
4 changes: 4 additions & 0 deletions tests/ui/rfc-2627-raw-dylib/invalid-dlltool.stderr
@@ -0,0 +1,4 @@
error: Error calling dlltool 'does_not_exit.exe': program not found

error: aborting due to previous error

0 comments on commit 13d3b75

Please sign in to comment.