Skip to content

Commit 7e2f6c1

Browse files
committed
Support --print native-static-libs with rust dylibs
1 parent 0f371ca commit 7e2f6c1

File tree

2 files changed

+76
-24
lines changed
  • compiler/rustc_codegen_ssa/src/back
  • tests/run-make-fulldeps/staticlib-dylib-linkage

2 files changed

+76
-24
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+70-5
Original file line numberDiff line numberDiff line change
@@ -544,12 +544,38 @@ fn link_staticlib<'a>(
544544

545545
ab.build(out_filename);
546546

547-
if !all_native_libs.is_empty() {
548-
if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) {
549-
print_native_static_libs(sess, &all_native_libs);
547+
let crates = codegen_results.crate_info.used_crates.iter();
548+
549+
let fmts = codegen_results
550+
.crate_info
551+
.dependency_formats
552+
.iter()
553+
.find_map(|&(ty, ref list)| if ty == CrateType::Staticlib { Some(list) } else { None })
554+
.expect("no dependency formats for staticlib");
555+
556+
let mut all_rust_dylibs = vec![];
557+
for &cnum in crates {
558+
match fmts.get(cnum.as_usize() - 1) {
559+
Some(&Linkage::Dynamic) => {}
560+
_ => continue,
561+
}
562+
let crate_name = codegen_results.crate_info.crate_name[&cnum];
563+
let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum];
564+
if let Some((path, _)) = &used_crate_source.dylib {
565+
all_rust_dylibs.push(&**path);
566+
} else {
567+
if used_crate_source.rmeta.is_some() {
568+
sess.emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name });
569+
} else {
570+
sess.emit_fatal(errors::LinkRlibError::NotFound { crate_name });
571+
}
550572
}
551573
}
552574

575+
if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) {
576+
print_native_static_libs(sess, &all_native_libs, &all_rust_dylibs);
577+
}
578+
553579
Ok(())
554580
}
555581

@@ -1289,8 +1315,12 @@ enum RlibFlavor {
12891315
StaticlibBase,
12901316
}
12911317

1292-
fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
1293-
let lib_args: Vec<_> = all_native_libs
1318+
fn print_native_static_libs(
1319+
sess: &Session,
1320+
all_native_libs: &[NativeLib],
1321+
all_rust_dylibs: &[&Path],
1322+
) {
1323+
let mut lib_args: Vec<_> = all_native_libs
12941324
.iter()
12951325
.filter(|l| relevant_lib(sess, l))
12961326
.filter_map(|lib| {
@@ -1319,6 +1349,41 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
13191349
}
13201350
})
13211351
.collect();
1352+
for path in all_rust_dylibs {
1353+
// FIXME deduplicate with add_dynamic_crate
1354+
1355+
// Just need to tell the linker about where the library lives and
1356+
// what its name is
1357+
let parent = path.parent();
1358+
if let Some(dir) = parent {
1359+
let dir = fix_windows_verbatim_for_gcc(dir);
1360+
if sess.target.is_like_msvc {
1361+
let mut arg = String::from("/LIBPATH:");
1362+
arg.push_str(&dir.display().to_string());
1363+
lib_args.push(arg);
1364+
} else {
1365+
lib_args.push("-L".to_owned());
1366+
lib_args.push(dir.display().to_string());
1367+
}
1368+
}
1369+
let stem = path.file_stem().unwrap().to_str().unwrap();
1370+
// Convert library file-stem into a cc -l argument.
1371+
let prefix = if stem.starts_with("lib") && !sess.target.is_like_windows { 3 } else { 0 };
1372+
let lib = &stem[prefix..];
1373+
let path = parent.unwrap_or_else(|| Path::new(""));
1374+
if sess.target.is_like_msvc {
1375+
// When producing a dll, the MSVC linker may not actually emit a
1376+
// `foo.lib` file if the dll doesn't actually export any symbols, so we
1377+
// check to see if the file is there and just omit linking to it if it's
1378+
// not present.
1379+
let name = format!("{}.dll.lib", lib);
1380+
if path.join(&name).exists() {
1381+
lib_args.push(name);
1382+
}
1383+
} else {
1384+
lib_args.push(format!("-l{}", lib));
1385+
}
1386+
}
13221387
if !lib_args.is_empty() {
13231388
sess.emit_note(errors::StaticLibraryNativeArtifacts);
13241389
// Prefix for greppability
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,14 @@
11
include ../tools.mk
22

3-
TARGET_SYSROOT := $(shell $(RUSTC) --print sysroot)/lib/rustlib/$(TARGET)/lib
3+
all:
4+
$(RUSTC) -C prefer-dynamic bar.rs
5+
$(RUSTC) foo.rs --crate-type staticlib --print native-static-libs 2>&1 | grep 'note: native-static-libs: ' | sed 's/note: native-static-libs: \(.*\)/\1/' > $(TMPDIR)/libs.txt
6+
cat $(TMPDIR)/libs.txt
47

58
ifdef IS_MSVC
6-
LIBSTD := $(wildcard $(TARGET_SYSROOT)/libstd-*.dll.lib)
9+
$(CC) $(CFLAGS) foo.c $(TMPDIR)/foo.lib $$(cat $(TMPDIR)/libs.txt) $(call OUT_EXE,foo)
710
else
8-
LIBSTD := $(wildcard $(TARGET_SYSROOT)/$(call DYLIB_GLOB,std))
9-
STD := $(basename $(patsubst lib%,%, $(notdir $(LIBSTD))))
11+
$(CC) $(CFLAGS) foo.c -L $(TMPDIR) -lfoo $$(cat $(TMPDIR)/libs.txt) -o $(call RUN_BINFILE,foo)
1012
endif
1113

12-
all: $(call RUN_BINFILE,foo)
1314
$(call RUN,foo)
14-
15-
ifdef IS_MSVC
16-
CLIBS := $(TMPDIR)/foo.lib $(TMPDIR)/bar.dll.lib $(LIBSTD)
17-
$(call RUN_BINFILE,foo): $(call STATICLIB,foo)
18-
$(CC) $(CFLAGS) foo.c $(CLIBS) $(call OUT_EXE,foo)
19-
else
20-
CLIBS := $(TMPDIR)/libfoo.a -lbar -l$(STD) -L $(TMPDIR) -L $(TARGET_SYSROOT)
21-
$(call RUN_BINFILE,foo): $(call STATICLIB,foo)
22-
$(CC) $(CFLAGS) foo.c $(CLIBS) -o $(call RUN_BINFILE,foo)
23-
endif
24-
25-
$(call STATICLIB,foo):
26-
$(RUSTC) -C prefer-dynamic bar.rs
27-
$(RUSTC) foo.rs

0 commit comments

Comments
 (0)