mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-27 07:03:45 +00:00
Call out to binutils' dlltool for raw-dylib on windows-gnu platforms.
This commit is contained in:
parent
4961b107f2
commit
0cf7fd1208
@ -1,6 +1,7 @@
|
||||
//! A helper class for dealing with static archives
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::env;
|
||||
use std::ffi::{CStr, CString, OsString};
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -158,55 +159,128 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
|
||||
output_path.with_extension("lib")
|
||||
};
|
||||
|
||||
// we've checked for \0 characters in the library name already
|
||||
let dll_name_z = CString::new(lib_name).unwrap();
|
||||
// All import names are Rust identifiers and therefore cannot contain \0 characters.
|
||||
// FIXME: when support for #[link_name] implemented, ensure that import.name values don't
|
||||
// have any \0 characters
|
||||
let import_name_and_ordinal_vector: Vec<(CString, Option<u16>)> = dll_imports
|
||||
let mingw_gnu_toolchain = self.config.sess.target.llvm_target.ends_with("pc-windows-gnu");
|
||||
|
||||
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = dll_imports
|
||||
.iter()
|
||||
.map(|import: &DllImport| {
|
||||
if self.config.sess.target.arch == "x86" {
|
||||
(LlvmArchiveBuilder::i686_decorated_name(import), import.ordinal)
|
||||
(
|
||||
LlvmArchiveBuilder::i686_decorated_name(import, mingw_gnu_toolchain),
|
||||
import.ordinal,
|
||||
)
|
||||
} else {
|
||||
(CString::new(import.name.to_string()).unwrap(), import.ordinal)
|
||||
(import.name.to_string(), import.ordinal)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let output_path_z = rustc_fs_util::path_to_c_string(&output_path);
|
||||
if mingw_gnu_toolchain {
|
||||
// The binutils linker used on -windows-gnu targets cannot read the import
|
||||
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
|
||||
// that loaded but crashed with an AV upon calling one of the imported
|
||||
// functions. Therefore, use binutils to create the import library instead,
|
||||
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
|
||||
let def_file_path =
|
||||
tmpdir.as_ref().join(format!("{}_imports", lib_name)).with_extension("def");
|
||||
|
||||
tracing::trace!("invoking LLVMRustWriteImportLibrary");
|
||||
tracing::trace!(" dll_name {:#?}", dll_name_z);
|
||||
tracing::trace!(" output_path {}", output_path.display());
|
||||
tracing::trace!(
|
||||
" import names: {}",
|
||||
dll_imports.iter().map(|import| import.name.to_string()).collect::<Vec<_>>().join(", "),
|
||||
);
|
||||
let def_file_content = format!(
|
||||
"EXPORTS\n{}",
|
||||
import_name_and_ordinal_vector
|
||||
.into_iter()
|
||||
.map(|(name, ordinal)| {
|
||||
match ordinal {
|
||||
Some(n) => format!("{} @{} NONAME", name, n),
|
||||
None => name,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
);
|
||||
|
||||
let ffi_exports: Vec<LLVMRustCOFFShortExport> = import_name_and_ordinal_vector
|
||||
.iter()
|
||||
.map(|(name_z, ordinal)| LLVMRustCOFFShortExport::new(name_z.as_ptr(), *ordinal))
|
||||
.collect();
|
||||
let result = unsafe {
|
||||
crate::llvm::LLVMRustWriteImportLibrary(
|
||||
dll_name_z.as_ptr(),
|
||||
output_path_z.as_ptr(),
|
||||
ffi_exports.as_ptr(),
|
||||
ffi_exports.len(),
|
||||
llvm_machine_type(&self.config.sess.target.arch) as u16,
|
||||
!self.config.sess.target.is_like_msvc,
|
||||
)
|
||||
match std::fs::write(&def_file_path, def_file_content) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
self.config.sess.fatal(&format!("Error writing .DEF file: {}", e));
|
||||
}
|
||||
};
|
||||
|
||||
let dlltool = find_binutils_dlltool(self.config.sess);
|
||||
let result = std::process::Command::new(dlltool)
|
||||
.args([
|
||||
"-d",
|
||||
def_file_path.to_str().unwrap(),
|
||||
"-D",
|
||||
lib_name,
|
||||
"-l",
|
||||
output_path.to_str().unwrap(),
|
||||
])
|
||||
.output();
|
||||
|
||||
match result {
|
||||
Err(e) => {
|
||||
self.config.sess.fatal(&format!("Error calling dlltool: {}", e.to_string()));
|
||||
}
|
||||
Ok(output) if !output.status.success() => self.config.sess.fatal(&format!(
|
||||
"Dlltool could not create import library: {}\n{}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
)),
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
// we've checked for \0 characters in the library name already
|
||||
let dll_name_z = CString::new(lib_name).unwrap();
|
||||
|
||||
let output_path_z = rustc_fs_util::path_to_c_string(&output_path);
|
||||
|
||||
tracing::trace!("invoking LLVMRustWriteImportLibrary");
|
||||
tracing::trace!(" dll_name {:#?}", dll_name_z);
|
||||
tracing::trace!(" output_path {}", output_path.display());
|
||||
tracing::trace!(
|
||||
" import names: {}",
|
||||
dll_imports
|
||||
.iter()
|
||||
.map(|import| import.name.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
);
|
||||
|
||||
// All import names are Rust identifiers and therefore cannot contain \0 characters.
|
||||
// FIXME: when support for #[link_name] is implemented, ensure that the import names
|
||||
// still don't contain any \0 characters. Also need to check that the names don't
|
||||
// contain substrings like " @" or "NONAME" that are keywords or otherwise reserved
|
||||
// in definition files.
|
||||
let cstring_import_name_and_ordinal_vector: Vec<(CString, Option<u16>)> =
|
||||
import_name_and_ordinal_vector
|
||||
.into_iter()
|
||||
.map(|(name, ordinal)| (CString::new(name).unwrap(), ordinal))
|
||||
.collect();
|
||||
|
||||
let ffi_exports: Vec<LLVMRustCOFFShortExport> = cstring_import_name_and_ordinal_vector
|
||||
.iter()
|
||||
.map(|(name_z, ordinal)| LLVMRustCOFFShortExport::new(name_z.as_ptr(), *ordinal))
|
||||
.collect();
|
||||
let result = unsafe {
|
||||
crate::llvm::LLVMRustWriteImportLibrary(
|
||||
dll_name_z.as_ptr(),
|
||||
output_path_z.as_ptr(),
|
||||
ffi_exports.as_ptr(),
|
||||
ffi_exports.len(),
|
||||
llvm_machine_type(&self.config.sess.target.arch) as u16,
|
||||
!self.config.sess.target.is_like_msvc,
|
||||
)
|
||||
};
|
||||
|
||||
if result == crate::llvm::LLVMRustResult::Failure {
|
||||
self.config.sess.fatal(&format!(
|
||||
"Error creating import library for {}: {}",
|
||||
lib_name,
|
||||
llvm::last_error().unwrap_or("unknown LLVM error".to_string())
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
if result == crate::llvm::LLVMRustResult::Failure {
|
||||
self.config.sess.fatal(&format!(
|
||||
"Error creating import library for {}: {}",
|
||||
lib_name,
|
||||
llvm::last_error().unwrap_or("unknown LLVM error".to_string())
|
||||
));
|
||||
}
|
||||
|
||||
self.add_archive(&output_path, |_| false).unwrap_or_else(|e| {
|
||||
self.config.sess.fatal(&format!(
|
||||
"failed to add native library {}: {}",
|
||||
@ -332,22 +406,61 @@ impl<'a> LlvmArchiveBuilder<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn i686_decorated_name(import: &DllImport) -> CString {
|
||||
fn i686_decorated_name(import: &DllImport, mingw: bool) -> String {
|
||||
let name = import.name;
|
||||
// We verified during construction that `name` does not contain any NULL characters, so the
|
||||
// conversion to CString is guaranteed to succeed.
|
||||
CString::new(match import.calling_convention {
|
||||
DllCallingConvention::C => format!("_{}", name),
|
||||
DllCallingConvention::Stdcall(arg_list_size) => format!("_{}@{}", name, arg_list_size),
|
||||
let prefix = if mingw { "" } else { "_" };
|
||||
|
||||
match import.calling_convention {
|
||||
DllCallingConvention::C => format!("{}{}", prefix, name),
|
||||
DllCallingConvention::Stdcall(arg_list_size) => {
|
||||
format!("{}{}@{}", prefix, name, arg_list_size)
|
||||
}
|
||||
DllCallingConvention::Fastcall(arg_list_size) => format!("@{}@{}", name, arg_list_size),
|
||||
DllCallingConvention::Vectorcall(arg_list_size) => {
|
||||
format!("{}@@{}", name, arg_list_size)
|
||||
}
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn string_to_io_error(s: String) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, format!("bad archive: {}", s))
|
||||
}
|
||||
|
||||
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.debugging_opts.dlltool {
|
||||
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"
|
||||
}
|
||||
} else {
|
||||
// We are not cross-compiling, so we just want `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);
|
||||
if full_path.is_file() {
|
||||
return full_path.into_os_string();
|
||||
}
|
||||
}
|
||||
|
||||
// The user didn't specify the location of the dlltool binary, and we weren't able
|
||||
// to find the appropriate one on the PATH. Just return the name of the tool
|
||||
// and let the invocation fail with a hopefully useful error message.
|
||||
tool_name
|
||||
}
|
||||
|
@ -640,6 +640,7 @@ fn test_debugging_options_tracking_hash() {
|
||||
untracked!(borrowck, String::from("other"));
|
||||
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_mir, Some(String::from("abc")));
|
||||
|
@ -274,11 +274,6 @@ impl Collector<'tcx> {
|
||||
span,
|
||||
"`#[link(...)]` with `kind = \"raw-dylib\"` only supported on Windows",
|
||||
);
|
||||
} else if !self.tcx.sess.target.options.is_like_msvc {
|
||||
self.tcx.sess.span_warn(
|
||||
span,
|
||||
"`#[link(...)]` with `kind = \"raw-dylib\"` not supported on windows-gnu",
|
||||
);
|
||||
}
|
||||
|
||||
if lib_name.as_str().contains('\0') {
|
||||
|
@ -1073,6 +1073,8 @@ options! {
|
||||
dep_tasks: bool = (false, parse_bool, [UNTRACKED],
|
||||
"print tasks that execute and the color their dep node gets (requires debug build) \
|
||||
(default: no)"),
|
||||
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)"),
|
||||
|
@ -1,14 +1,19 @@
|
||||
# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
|
||||
|
||||
# only-windows-msvc
|
||||
# only-windows
|
||||
|
||||
-include ../../run-make-fulldeps/tools.mk
|
||||
|
||||
all:
|
||||
$(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
|
||||
$(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
|
||||
ifdef IS_MSVC
|
||||
$(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
|
||||
$(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
|
||||
else
|
||||
$(CC) "$(TMPDIR)"/extern_1.obj -shared -o "$(TMPDIR)"/extern_1.dll
|
||||
$(CC) "$(TMPDIR)"/extern_2.obj -shared -o "$(TMPDIR)"/extern_2.dll
|
||||
endif
|
||||
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
|
||||
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
|
||||
"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
|
||||
|
@ -1,12 +1,16 @@
|
||||
# Test the behavior of #[link(.., kind = "raw-dylib")] and #[link_ordinal] on windows-msvc
|
||||
|
||||
# only-windows-msvc
|
||||
# only-windows
|
||||
|
||||
-include ../../run-make-fulldeps/tools.mk
|
||||
|
||||
all:
|
||||
$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
|
||||
ifdef IS_MSVC
|
||||
$(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll
|
||||
else
|
||||
$(CC) "$(TMPDIR)"/exporter.obj exporter.def -shared -o "$(TMPDIR)"/exporter.dll
|
||||
endif
|
||||
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
|
||||
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
|
||||
"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
|
||||
|
23
src/test/run-make/raw-dylib-stdcall-ordinal/Makefile
Normal file
23
src/test/run-make/raw-dylib-stdcall-ordinal/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
# Test the behavior of #[link(.., kind = "raw-dylib")], #[link_ordinal], and alternative calling conventions on i686 windows.
|
||||
|
||||
# only-x86
|
||||
# only-windows
|
||||
|
||||
-include ../../run-make-fulldeps/tools.mk
|
||||
|
||||
all:
|
||||
$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
|
||||
ifdef IS_MSVC
|
||||
$(CC) "$(TMPDIR)"/exporter.obj exporter-msvc.def -link -dll -out:"$(TMPDIR)"/exporter.dll
|
||||
else
|
||||
$(CC) "$(TMPDIR)"/exporter.obj exporter-gnu.def -shared -o "$(TMPDIR)"/exporter.dll
|
||||
endif
|
||||
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
|
||||
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
|
||||
"$(TMPDIR)"/driver > "$(TMPDIR)"/actual_output.txt
|
||||
|
||||
ifdef RUSTC_BLESS_TEST
|
||||
cp "$(TMPDIR)"/actual_output.txt expected_output.txt
|
||||
else
|
||||
$(DIFF) expected_output.txt "$(TMPDIR)"/actual_output.txt
|
||||
endif
|
5
src/test/run-make/raw-dylib-stdcall-ordinal/driver.rs
Normal file
5
src/test/run-make/raw-dylib-stdcall-ordinal/driver.rs
Normal file
@ -0,0 +1,5 @@
|
||||
extern crate raw_dylib_test;
|
||||
|
||||
fn main() {
|
||||
raw_dylib_test::library_function();
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
exported_function_stdcall(6)
|
||||
exported_function_fastcall(125)
|
@ -0,0 +1,4 @@
|
||||
LIBRARY exporter
|
||||
EXPORTS
|
||||
exported_function_stdcall@4 @15 NONAME
|
||||
@exported_function_fastcall@4 @18 NONAME
|
@ -0,0 +1,4 @@
|
||||
LIBRARY exporter
|
||||
EXPORTS
|
||||
_exported_function_stdcall@4 @15 NONAME
|
||||
@exported_function_fastcall@4 @18 NONAME
|
11
src/test/run-make/raw-dylib-stdcall-ordinal/exporter.c
Normal file
11
src/test/run-make/raw-dylib-stdcall-ordinal/exporter.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void __stdcall exported_function_stdcall(int i) {
|
||||
printf("exported_function_stdcall(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void __fastcall exported_function_fastcall(int i) {
|
||||
printf("exported_function_fastcall(%d)\n", i);
|
||||
fflush(stdout);
|
||||
}
|
20
src/test/run-make/raw-dylib-stdcall-ordinal/lib.rs
Normal file
20
src/test/run-make/raw-dylib-stdcall-ordinal/lib.rs
Normal file
@ -0,0 +1,20 @@
|
||||
#![feature(raw_dylib)]
|
||||
|
||||
#[link(name = "exporter", kind = "raw-dylib")]
|
||||
extern "stdcall" {
|
||||
#[link_ordinal(15)]
|
||||
fn imported_function_stdcall(i: i32);
|
||||
}
|
||||
|
||||
#[link(name = "exporter", kind = "raw-dylib")]
|
||||
extern "fastcall" {
|
||||
#[link_ordinal(18)]
|
||||
fn imported_function_fastcall(i: i32);
|
||||
}
|
||||
|
||||
pub fn library_function() {
|
||||
unsafe {
|
||||
imported_function_stdcall(6);
|
||||
imported_function_fastcall(125);
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
// gate-test-raw_dylib
|
||||
// only-windows-gnu
|
||||
#[link(name = "foo", kind = "raw-dylib")]
|
||||
//~^ ERROR: kind="raw-dylib" is unstable
|
||||
//~| WARNING: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
|
||||
extern "C" {}
|
||||
|
||||
fn main() {}
|
@ -1,18 +0,0 @@
|
||||
warning: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
|
||||
--> $DIR/feature-gate-raw-dylib-windows-gnu.rs:3:1
|
||||
|
|
||||
LL | #[link(name = "foo", kind = "raw-dylib")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0658]: kind="raw-dylib" is unstable
|
||||
--> $DIR/feature-gate-raw-dylib-windows-gnu.rs:3:1
|
||||
|
|
||||
LL | #[link(name = "foo", kind = "raw-dylib")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
|
||||
= help: add `#![feature(raw_dylib)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -1,5 +1,4 @@
|
||||
// gate-test-raw_dylib
|
||||
// only-windows-msvc
|
||||
// only-windows
|
||||
#[link(name = "foo", kind = "raw-dylib")]
|
||||
//~^ ERROR: kind="raw-dylib" is unstable
|
||||
extern "C" {}
|
@ -1,5 +1,5 @@
|
||||
error[E0658]: kind="raw-dylib" is unstable
|
||||
--> $DIR/feature-gate-raw-dylib-windows-msvc.rs:3:1
|
||||
--> $DIR/feature-gate-raw-dylib.rs:2:1
|
||||
|
|
||||
LL | #[link(name = "foo", kind = "raw-dylib")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
@ -1,4 +1,4 @@
|
||||
// only-windows-msvc
|
||||
// only-windows
|
||||
#![feature(raw_dylib)]
|
||||
//~^ WARN the feature `raw_dylib` is incomplete
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// only-i686-pc-windows-msvc
|
||||
// only-x86
|
||||
// only-windows
|
||||
// compile-flags: --crate-type lib --emit link
|
||||
#![allow(clashing_extern_declarations)]
|
||||
#![feature(raw_dylib)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/multiple-declarations.rs:4:12
|
||||
--> $DIR/multiple-declarations.rs:5:12
|
||||
|
|
||||
LL | #![feature(raw_dylib)]
|
||||
| ^^^^^^^^^
|
||||
@ -8,7 +8,7 @@ LL | #![feature(raw_dylib)]
|
||||
= note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
|
||||
|
||||
error: multiple declarations of external function `f` from library `foo.dll` have different calling conventions
|
||||
--> $DIR/multiple-declarations.rs:14:9
|
||||
--> $DIR/multiple-declarations.rs:15:9
|
||||
|
|
||||
LL | fn f(x: i32);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -1,8 +0,0 @@
|
||||
// only-windows-gnu
|
||||
// check-pass
|
||||
// compile-flags: --crate-type lib
|
||||
#![feature(raw_dylib)]
|
||||
//~^ WARNING: the feature `raw_dylib` is incomplete
|
||||
#[link(name = "foo", kind = "raw-dylib")]
|
||||
//~^ WARNING: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
|
||||
extern "C" {}
|
@ -1,17 +0,0 @@
|
||||
warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/raw-dylib-msvc-only.rs:4:12
|
||||
|
|
||||
LL | #![feature(raw_dylib)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
|
||||
|
||||
warning: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
|
||||
--> $DIR/raw-dylib-msvc-only.rs:6:1
|
||||
|
|
||||
LL | #[link(name = "foo", kind = "raw-dylib")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
@ -1,4 +1,5 @@
|
||||
// only-x86_64-pc-windows-msvc
|
||||
// only-x86_64
|
||||
// only-windows
|
||||
// compile-flags: --crate-type lib --emit link
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(raw_dylib)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
|
||||
--> $DIR/unsupported-abi.rs:7:5
|
||||
--> $DIR/unsupported-abi.rs:8:5
|
||||
|
|
||||
LL | fn f(x: i32);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
Loading…
Reference in New Issue
Block a user