From 13d3b75580354ee6bb01a8378a9d5779a995a7c7 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 24 Mar 2023 10:13:25 -0700 Subject: [PATCH] Stabilize -Cdlltool --- compiler/rustc_codegen_llvm/messages.ftl | 4 ++-- .../rustc_codegen_llvm/src/back/archive.rs | 15 ++++++++------ compiler/rustc_codegen_llvm/src/errors.rs | 6 +++--- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/src/options.rs | 4 ++-- src/doc/rustc/src/codegen-options/index.md | 8 ++++++++ src/tools/compiletest/src/header.rs | 10 ++++++++++ .../raw-dylib-custom-dlltool/Makefile | 11 ++++++++++ .../run-make/raw-dylib-custom-dlltool/lib.rs | 12 +++++++++++ .../raw-dylib-custom-dlltool/output.txt | 1 + .../raw-dylib-custom-dlltool/script.cmd | 2 ++ tests/rustdoc-ui/c-help.stdout | 1 + tests/rustdoc-ui/z-help.stdout | 1 - tests/ui/rfc-2627-raw-dylib/dlltool-failed.rs | 20 +++++++++++++++++++ .../rfc-2627-raw-dylib/dlltool-failed.stderr | 4 ++++ .../ui/rfc-2627-raw-dylib/invalid-dlltool.rs | 14 +++++++++++++ .../rfc-2627-raw-dylib/invalid-dlltool.stderr | 4 ++++ 17 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 tests/run-make/raw-dylib-custom-dlltool/Makefile create mode 100644 tests/run-make/raw-dylib-custom-dlltool/lib.rs create mode 100644 tests/run-make/raw-dylib-custom-dlltool/output.txt create mode 100644 tests/run-make/raw-dylib-custom-dlltool/script.cmd create mode 100644 tests/ui/rfc-2627-raw-dylib/dlltool-failed.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/dlltool-failed.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/invalid-dlltool.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/invalid-dlltool.stderr diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index e5df417370bb9..864d82cf9ba72 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -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 diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index a570f2af0f0e5..b15a8b34b3049 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -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(), @@ -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), }) } _ => {} @@ -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(); } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index bae88d942934c..0bba6ed0f2ca7 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -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)] diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 014810dba9cce..7a4b690018aff 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -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`. @@ -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())); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 0548379dc2fc1..ae7082c875840 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -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 = (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], @@ -1361,8 +1363,6 @@ options! { (default: no)"), diagnostic_width: Option = (None, parse_opt_number, [UNTRACKED], "set the current output width for diagnostic truncation"), - dlltool: Option = (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)"), diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index c7f120dafeafd..bc106f63efc37 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -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 diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 5bc9d9afcb9d1..5753de1f37b24 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -976,6 +976,15 @@ pub fn make_test_description( #[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 { @@ -1046,6 +1055,7 @@ pub fn make_test_description( 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"); }); diff --git a/tests/run-make/raw-dylib-custom-dlltool/Makefile b/tests/run-make/raw-dylib-custom-dlltool/Makefile new file mode 100644 index 0000000000000..ce0091dceb837 --- /dev/null +++ b/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 diff --git a/tests/run-make/raw-dylib-custom-dlltool/lib.rs b/tests/run-make/raw-dylib-custom-dlltool/lib.rs new file mode 100644 index 0000000000000..473c765966caf --- /dev/null +++ b/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(); + } +} diff --git a/tests/run-make/raw-dylib-custom-dlltool/output.txt b/tests/run-make/raw-dylib-custom-dlltool/output.txt new file mode 100644 index 0000000000000..6dd9466d26ddc --- /dev/null +++ b/tests/run-make/raw-dylib-custom-dlltool/output.txt @@ -0,0 +1 @@ +Called dlltool via script.cmd diff --git a/tests/run-make/raw-dylib-custom-dlltool/script.cmd b/tests/run-make/raw-dylib-custom-dlltool/script.cmd new file mode 100644 index 0000000000000..95f85c61c67d2 --- /dev/null +++ b/tests/run-make/raw-dylib-custom-dlltool/script.cmd @@ -0,0 +1,2 @@ +echo Called dlltool via script.cmd> %TMPDIR%\output.txt +dlltool.exe %* diff --git a/tests/rustdoc-ui/c-help.stdout b/tests/rustdoc-ui/c-help.stdout index 75b2e2a2a43f4..d05a6b8406b01 100644 --- a/tests/rustdoc-ui/c-help.stdout +++ b/tests/rustdoc-ui/c-help.stdout @@ -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 diff --git a/tests/rustdoc-ui/z-help.stdout b/tests/rustdoc-ui/z-help.stdout index 5ad38e4fd9821..6a9303f9a577e 100644 --- a/tests/rustdoc-ui/z-help.stdout +++ b/tests/rustdoc-ui/z-help.stdout @@ -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) diff --git a/tests/ui/rfc-2627-raw-dylib/dlltool-failed.rs b/tests/ui/rfc-2627-raw-dylib/dlltool-failed.rs new file mode 100644 index 0000000000000..9378bd473c582 --- /dev/null +++ b/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); } +} diff --git a/tests/ui/rfc-2627-raw-dylib/dlltool-failed.stderr b/tests/ui/rfc-2627-raw-dylib/dlltool-failed.stderr new file mode 100644 index 0000000000000..68e7cc11f6a72 --- /dev/null +++ b/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 + diff --git a/tests/ui/rfc-2627-raw-dylib/invalid-dlltool.rs b/tests/ui/rfc-2627-raw-dylib/invalid-dlltool.rs new file mode 100644 index 0000000000000..2b2ce5da3d0f6 --- /dev/null +++ b/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); } +} diff --git a/tests/ui/rfc-2627-raw-dylib/invalid-dlltool.stderr b/tests/ui/rfc-2627-raw-dylib/invalid-dlltool.stderr new file mode 100644 index 0000000000000..3ae901e0dbc94 --- /dev/null +++ b/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 +