Skip to content

Commit 77187c9

Browse files
committed
Auto merge of rust-lang#136463 - matthiaskrgr:rollup-rrf7r18, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#134777 (Enable more tests on Windows) - rust-lang#134807 (fix(rustdoc): always use a channel when linking to doc.rust-lang.org) - rust-lang#135621 (Move some std tests to integration tests) - rust-lang#135695 (Support raw-dylib link kind on ELF) - rust-lang#135836 (bootstrap: only build `crt{begin,end}.o` when compiling to MUSL) - rust-lang#136235 (Pretty print pattern type values with transmute if they don't satisfy their pattern) - rust-lang#136392 (bootstrap: add wrapper macros for `feature = "tracing"`-gated `tracing` macros) - rust-lang#136462 (mir_build: Simplify `lower_pattern_range_endpoint`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 613bdd4 + 72bb960 commit 77187c9

File tree

197 files changed

+1724
-1061
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

197 files changed

+1724
-1061
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+78-134
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
mod raw_dylib;
2+
13
use std::collections::BTreeSet;
24
use std::ffi::OsString;
35
use std::fs::{File, OpenOptions, read};
@@ -12,7 +14,7 @@ use itertools::Itertools;
1214
use regex::Regex;
1315
use rustc_arena::TypedArena;
1416
use rustc_ast::CRATE_NODE_ID;
15-
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
17+
use rustc_data_structures::fx::FxIndexSet;
1618
use rustc_data_structures::memmap::Mmap;
1719
use rustc_data_structures::temp_dir::MaybeTempDir;
1820
use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
@@ -30,7 +32,6 @@ use rustc_session::config::{
3032
self, CFGuard, CrateType, DebugInfo, LinkerFeaturesCli, OutFileName, OutputFilenames,
3133
OutputType, PrintKind, SplitDwarfKind, Strip,
3234
};
33-
use rustc_session::cstore::DllImport;
3435
use rustc_session::lint::builtin::LINKER_MESSAGES;
3536
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
3637
use rustc_session::search_paths::PathKind;
@@ -48,15 +49,14 @@ use rustc_target::spec::{
4849
use tempfile::Builder as TempFileBuilder;
4950
use tracing::{debug, info, warn};
5051

51-
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem};
52+
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
5253
use super::command::Command;
5354
use super::linker::{self, Linker};
5455
use super::metadata::{MetadataPosition, create_wrapper_file};
5556
use super::rpath::{self, RPathConfig};
5657
use super::{apple, versioned_llvm_target};
5758
use crate::{
58-
CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors,
59-
looks_like_rust_object_file,
59+
CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file,
6060
};
6161

6262
pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
@@ -381,16 +381,22 @@ fn link_rlib<'a>(
381381
}
382382
}
383383

384-
for output_path in create_dll_import_libs(
385-
sess,
386-
archive_builder_builder,
387-
codegen_results.crate_info.used_libraries.iter(),
388-
tmpdir.as_ref(),
389-
true,
390-
) {
391-
ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
392-
sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
393-
});
384+
// On Windows, we add the raw-dylib import libraries to the rlibs already.
385+
// But on ELF, this is not possible, as a shared object cannot be a member of a static library.
386+
// Instead, we add all raw-dylibs to the final link on ELF.
387+
if sess.target.is_like_windows {
388+
for output_path in raw_dylib::create_raw_dylib_dll_import_libs(
389+
sess,
390+
archive_builder_builder,
391+
codegen_results.crate_info.used_libraries.iter(),
392+
tmpdir.as_ref(),
393+
true,
394+
) {
395+
ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
396+
sess.dcx()
397+
.emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
398+
});
399+
}
394400
}
395401

396402
if let Some(trailing_metadata) = trailing_metadata {
@@ -431,108 +437,6 @@ fn link_rlib<'a>(
431437
ab
432438
}
433439

434-
/// Extract all symbols defined in raw-dylib libraries, collated by library name.
435-
///
436-
/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library,
437-
/// then the CodegenResults value contains one NativeLib instance for each block. However, the
438-
/// linker appears to expect only a single import library for each library used, so we need to
439-
/// collate the symbols together by library name before generating the import libraries.
440-
fn collate_raw_dylibs<'a>(
441-
sess: &Session,
442-
used_libraries: impl IntoIterator<Item = &'a NativeLib>,
443-
) -> Vec<(String, Vec<DllImport>)> {
444-
// Use index maps to preserve original order of imports and libraries.
445-
let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
446-
447-
for lib in used_libraries {
448-
if lib.kind == NativeLibKind::RawDylib {
449-
let ext = if lib.verbatim { "" } else { ".dll" };
450-
let name = format!("{}{}", lib.name, ext);
451-
let imports = dylib_table.entry(name.clone()).or_default();
452-
for import in &lib.dll_imports {
453-
if let Some(old_import) = imports.insert(import.name, import) {
454-
// FIXME: when we add support for ordinals, figure out if we need to do anything
455-
// if we have two DllImport values with the same name but different ordinals.
456-
if import.calling_convention != old_import.calling_convention {
457-
sess.dcx().emit_err(errors::MultipleExternalFuncDecl {
458-
span: import.span,
459-
function: import.name,
460-
library_name: &name,
461-
});
462-
}
463-
}
464-
}
465-
}
466-
}
467-
sess.dcx().abort_if_errors();
468-
dylib_table
469-
.into_iter()
470-
.map(|(name, imports)| {
471-
(name, imports.into_iter().map(|(_, import)| import.clone()).collect())
472-
})
473-
.collect()
474-
}
475-
476-
fn create_dll_import_libs<'a>(
477-
sess: &Session,
478-
archive_builder_builder: &dyn ArchiveBuilderBuilder,
479-
used_libraries: impl IntoIterator<Item = &'a NativeLib>,
480-
tmpdir: &Path,
481-
is_direct_dependency: bool,
482-
) -> Vec<PathBuf> {
483-
collate_raw_dylibs(sess, used_libraries)
484-
.into_iter()
485-
.map(|(raw_dylib_name, raw_dylib_imports)| {
486-
let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
487-
let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib"));
488-
489-
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
490-
491-
let items: Vec<ImportLibraryItem> = raw_dylib_imports
492-
.iter()
493-
.map(|import: &DllImport| {
494-
if sess.target.arch == "x86" {
495-
ImportLibraryItem {
496-
name: common::i686_decorated_name(
497-
import,
498-
mingw_gnu_toolchain,
499-
false,
500-
false,
501-
),
502-
ordinal: import.ordinal(),
503-
symbol_name: import.is_missing_decorations().then(|| {
504-
common::i686_decorated_name(
505-
import,
506-
mingw_gnu_toolchain,
507-
false,
508-
true,
509-
)
510-
}),
511-
is_data: !import.is_fn,
512-
}
513-
} else {
514-
ImportLibraryItem {
515-
name: import.name.to_string(),
516-
ordinal: import.ordinal(),
517-
symbol_name: None,
518-
is_data: !import.is_fn,
519-
}
520-
}
521-
})
522-
.collect();
523-
524-
archive_builder_builder.create_dll_import_lib(
525-
sess,
526-
&raw_dylib_name,
527-
items,
528-
&output_path,
529-
);
530-
531-
output_path
532-
})
533-
.collect()
534-
}
535-
536440
/// Create a static archive.
537441
///
538442
/// This is essentially the same thing as an rlib, but it also involves adding all of the upstream
@@ -2370,15 +2274,39 @@ fn linker_with_args(
23702274
link_output_kind,
23712275
);
23722276

2277+
// Raw-dylibs from all crates.
2278+
let raw_dylib_dir = tmpdir.join("raw-dylibs");
2279+
if sess.target.binary_format() == object::BinaryFormat::Elf {
2280+
// On ELF we can't pass the raw-dylibs stubs to the linker as a path,
2281+
// instead we need to pass them via -l. To find the stub, we need to add
2282+
// the directory of the stub to the linker search path.
2283+
// We make an extra directory for this to avoid polluting the search path.
2284+
if let Err(error) = fs::create_dir(&raw_dylib_dir) {
2285+
sess.dcx().emit_fatal(errors::CreateTempDir { error })
2286+
}
2287+
cmd.include_path(&raw_dylib_dir);
2288+
}
2289+
23732290
// Link with the import library generated for any raw-dylib functions.
2374-
for output_path in create_dll_import_libs(
2375-
sess,
2376-
archive_builder_builder,
2377-
codegen_results.crate_info.used_libraries.iter(),
2378-
tmpdir,
2379-
true,
2380-
) {
2381-
cmd.add_object(&output_path);
2291+
if sess.target.is_like_windows {
2292+
for output_path in raw_dylib::create_raw_dylib_dll_import_libs(
2293+
sess,
2294+
archive_builder_builder,
2295+
codegen_results.crate_info.used_libraries.iter(),
2296+
tmpdir,
2297+
true,
2298+
) {
2299+
cmd.add_object(&output_path);
2300+
}
2301+
} else {
2302+
for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
2303+
sess,
2304+
codegen_results.crate_info.used_libraries.iter(),
2305+
&raw_dylib_dir,
2306+
) {
2307+
// Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
2308+
cmd.link_dylib_by_name(&link_path, true, false);
2309+
}
23822310
}
23832311
// As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
23842312
// they are used within inlined functions or instantiated generic functions. We do this *after*
@@ -2397,19 +2325,35 @@ fn linker_with_args(
23972325
.native_libraries
23982326
.iter()
23992327
.filter_map(|(&cnum, libraries)| {
2400-
(dependency_linkage[cnum] != Linkage::Static).then_some(libraries)
2328+
if sess.target.is_like_windows {
2329+
(dependency_linkage[cnum] != Linkage::Static).then_some(libraries)
2330+
} else {
2331+
Some(libraries)
2332+
}
24012333
})
24022334
.flatten()
24032335
.collect::<Vec<_>>();
24042336
native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
2405-
for output_path in create_dll_import_libs(
2406-
sess,
2407-
archive_builder_builder,
2408-
native_libraries_from_nonstatics,
2409-
tmpdir,
2410-
false,
2411-
) {
2412-
cmd.add_object(&output_path);
2337+
2338+
if sess.target.is_like_windows {
2339+
for output_path in raw_dylib::create_raw_dylib_dll_import_libs(
2340+
sess,
2341+
archive_builder_builder,
2342+
native_libraries_from_nonstatics,
2343+
tmpdir,
2344+
false,
2345+
) {
2346+
cmd.add_object(&output_path);
2347+
}
2348+
} else {
2349+
for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
2350+
sess,
2351+
native_libraries_from_nonstatics,
2352+
&raw_dylib_dir,
2353+
) {
2354+
// Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
2355+
cmd.link_dylib_by_name(&link_path, true, false);
2356+
}
24132357
}
24142358

24152359
// Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make

0 commit comments

Comments
 (0)