Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable raw-dylib for bin crates #98989

Merged
merged 1 commit into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions compiler/rustc_codegen_cranelift/src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,16 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
any_members
}

fn inject_dll_import_lib(
&mut self,
fn sess(&self) -> &Session {
self.sess
}

fn create_dll_import_lib(
_sess: &Session,
_lib_name: &str,
_dll_imports: &[rustc_session::cstore::DllImport],
_tmpdir: &rustc_data_structures::temp_dir::MaybeTempDir,
) {
bug!("injecting dll imports is not supported");
_tmpdir: &Path,
) -> PathBuf {
bug!("creating dll imports is not supported");
}
}
12 changes: 10 additions & 2 deletions compiler/rustc_codegen_gcc/src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::path::{Path, PathBuf};
use rustc_codegen_ssa::back::archive::ArchiveBuilder;
use rustc_session::Session;

use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_session::cstore::DllImport;

struct ArchiveConfig<'a> {
Expand Down Expand Up @@ -177,7 +176,16 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
any_members
}

fn inject_dll_import_lib(&mut self, _lib_name: &str, _dll_imports: &[DllImport], _tmpdir: &MaybeTempDir) {
fn sess(&self) -> &Session {
self.config.sess
}

fn create_dll_import_lib(
_sess: &Session,
_lib_name: &str,
_dll_imports: &[DllImport],
_tmpdir: &Path,
) -> PathBuf {
unimplemented!();
}
}
44 changes: 20 additions & 24 deletions compiler/rustc_codegen_llvm/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use std::str;
use crate::llvm::archive_ro::{ArchiveRO, Child};
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
use rustc_codegen_ssa::back::archive::ArchiveBuilder;
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_session::cstore::{DllCallingConvention, DllImport};
use rustc_session::Session;

Expand Down Expand Up @@ -96,19 +95,23 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
}
}

fn inject_dll_import_lib(
&mut self,
fn sess(&self) -> &Session {
self.sess
}

fn create_dll_import_lib(
sess: &Session,
lib_name: &str,
dll_imports: &[DllImport],
tmpdir: &MaybeTempDir,
) {
tmpdir: &Path,
) -> PathBuf {
let output_path = {
let mut output_path: PathBuf = tmpdir.as_ref().to_path_buf();
let mut output_path: PathBuf = tmpdir.to_path_buf();
output_path.push(format!("{}_imports", lib_name));
output_path.with_extension("lib")
};

let target = &self.sess.target;
let target = &sess.target;
let mingw_gnu_toolchain = target.vendor == "pc"
&& target.os == "windows"
&& target.env == "gnu"
Expand All @@ -117,7 +120,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = dll_imports
.iter()
.map(|import: &DllImport| {
if self.sess.target.arch == "x86" {
if sess.target.arch == "x86" {
(
LlvmArchiveBuilder::i686_decorated_name(import, mingw_gnu_toolchain),
import.ordinal,
Expand All @@ -134,8 +137,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
// 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");
let def_file_path = tmpdir.join(format!("{}_imports", lib_name)).with_extension("def");

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

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

match result {
Err(e) => {
self.sess.fatal(&format!("Error calling dlltool: {}", e));
sess.fatal(&format!("Error calling dlltool: {}", e));
}
Ok(output) if !output.status.success() => self.sess.fatal(&format!(
Ok(output) if !output.status.success() => sess.fatal(&format!(
"Dlltool could not create import library: {}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
Expand Down Expand Up @@ -220,27 +222,21 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
output_path_z.as_ptr(),
ffi_exports.as_ptr(),
ffi_exports.len(),
llvm_machine_type(&self.sess.target.arch) as u16,
!self.sess.target.is_like_msvc,
llvm_machine_type(&sess.target.arch) as u16,
!sess.target.is_like_msvc,
)
};

if result == crate::llvm::LLVMRustResult::Failure {
self.sess.fatal(&format!(
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.sess.fatal(&format!(
"failed to add native library {}: {}",
output_path.display(),
e
));
});
output_path
}
}

Expand Down
29 changes: 28 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,37 @@ pub trait ArchiveBuilder<'a> {

fn build(self) -> bool;

fn sess(&self) -> &Session;

/// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>.
/// and returns the path on disk to that import library.
/// This functions doesn't take `self` so that it can be called from
/// `linker_with_args`, which is specialized on `ArchiveBuilder` but
/// doesn't take or create an instance of that type.
fn create_dll_import_lib(
sess: &Session,
dpaoliello marked this conversation as resolved.
Show resolved Hide resolved
lib_name: &str,
dll_imports: &[DllImport],
tmpdir: &Path,
) -> PathBuf;

/// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>
/// and adds it to the current compilation's set of archives.
fn inject_dll_import_lib(
&mut self,
lib_name: &str,
dll_imports: &[DllImport],
tmpdir: &MaybeTempDir,
);
) {
let output_path =
Self::create_dll_import_lib(self.sess(), lib_name, dll_imports, tmpdir.as_ref());

self.add_archive(&output_path, |_| false).unwrap_or_else(|e| {
self.sess().fatal(&format!(
"failed to add native library {}: {}",
output_path.display(),
e
));
});
}
}
27 changes: 20 additions & 7 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
&out_filename,
codegen_results,
path.as_ref(),
);
)?;
}
}
if sess.opts.json_artifact_notifications {
Expand Down Expand Up @@ -650,7 +650,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
out_filename: &Path,
codegen_results: &CodegenResults,
tmpdir: &Path,
) {
) -> Result<(), ErrorGuaranteed> {
info!("preparing {:?} to {:?}", crate_type, out_filename);
let (linker_path, flavor) = linker_and_flavor(sess);
let mut cmd = linker_with_args::<B>(
Expand All @@ -661,7 +661,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
tmpdir,
out_filename,
codegen_results,
);
)?;

linker::disable_localization(&mut cmd);

Expand Down Expand Up @@ -1000,6 +1000,8 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
(Strip::None, _) => {}
}
}

Ok(())
}

// Temporarily support both -Z strip and -C strip
Expand Down Expand Up @@ -1848,7 +1850,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
tmpdir: &Path,
out_filename: &Path,
codegen_results: &CodegenResults,
) -> Command {
) -> Result<Command, ErrorGuaranteed> {
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
let cmd = &mut *super::linker::get_linker(
sess,
Expand Down Expand Up @@ -1955,6 +1957,18 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
add_upstream_native_libraries(cmd, sess, codegen_results);
}

// Link with the import library generated for any raw-dylib functions.
for (raw_dylib_name, raw_dylib_imports) in
collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)?
{
cmd.add_object(&B::create_dll_import_lib(
sess,
&raw_dylib_name,
&raw_dylib_imports,
tmpdir,
));
}

// Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
// command line shorter, reset it to default here before adding more libraries.
cmd.reset_per_library_state();
Expand Down Expand Up @@ -1998,7 +2012,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
// to it and remove the option.
add_post_link_args(cmd, sess, flavor);

cmd.take_cmd()
Ok(cmd.take_cmd())
}

fn add_order_independent_options(
Expand Down Expand Up @@ -2222,8 +2236,7 @@ fn add_local_native_libraries(
}
}
NativeLibKind::RawDylib => {
// FIXME(#58713): Proper handling for raw dylibs.
bug!("raw_dylib feature not yet implemented");
// Ignore RawDylib here, they are handled separately in linker_with_args().
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/run-make-fulldeps/tools.mk
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ NATIVE_STATICLIB = $(TMPDIR)/$(call NATIVE_STATICLIB_FILE,$(1))
OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
-Fo:`cygpath -w $(TMPDIR)/$(1).obj`
else
COMPILE_OBJ = $(CC) -c -o $(1) $(2)
COMPILE_OBJ = $(CC) -v -c -o $(1) $(2)
COMPILE_OBJ_CXX = $(CXX) -c -o $(1) $(2)
NATIVE_STATICLIB_FILE = lib$(1).a
NATIVE_STATICLIB = $(call STATICLIB,$(1))
Expand Down
6 changes: 3 additions & 3 deletions src/test/run-make/raw-dylib-alt-calling-convention/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
-include ../../run-make-fulldeps/tools.mk

all:
$(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
$(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
ifdef IS_MSVC
$(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll
$(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll -noimplib
else
$(CC) "$(TMPDIR)"/extern.obj -shared -o "$(TMPDIR)"/extern.dll
endif
$(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt

ifdef RUSTC_BLESS_TEST
Expand Down
11 changes: 7 additions & 4 deletions src/test/run-make/raw-dylib-c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@
-include ../../run-make-fulldeps/tools.mk

all:
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
$(RUSTC) --crate-type bin --crate-name raw_dylib_test_bin lib.rs
$(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
$(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll -noimplib
$(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll -noimplib
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
"$(TMPDIR)"/raw_dylib_test_bin > "$(TMPDIR)"/output_bin.txt

ifdef RUSTC_BLESS_TEST
cp "$(TMPDIR)"/output.txt output.txt
else
$(DIFF) output.txt "$(TMPDIR)"/output.txt
$(DIFF) output.txt "$(TMPDIR)"/output_bin.txt
endif
4 changes: 4 additions & 0 deletions src/test/run-make/raw-dylib-c/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ pub fn library_function() {
extern_fn_3();
}
}

fn main() {
library_function();
}
6 changes: 3 additions & 3 deletions src/test/run-make/raw-dylib-link-ordinal/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
-include ../../run-make-fulldeps/tools.mk

all:
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
ifdef IS_MSVC
$(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll
$(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
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

ifdef RUSTC_BLESS_TEST
Expand Down
6 changes: 3 additions & 3 deletions src/test/run-make/raw-dylib-stdcall-ordinal/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
-include ../../run-make-fulldeps/tools.mk

all:
$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
ifdef IS_MSVC
$(CC) "$(TMPDIR)"/exporter.obj exporter-msvc.def -link -dll -out:"$(TMPDIR)"/exporter.dll
$(CC) "$(TMPDIR)"/exporter.obj exporter-msvc.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
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
Expand Down