Skip to content

Commit

Permalink
Auto merge of #68448 - maurer:dyn-cdylib, r=alexcrichton
Browse files Browse the repository at this point in the history
rustc: Allow cdylibs to link against dylibs

Previously, rustc mandated that cdylibs could only link against rlibs as dependencies (not dylibs).
This commit disables that restriction and tests that it works in a simple case.

I don't have a windows rustc dev environment, so I guessed at the MSVC test code, I'm hoping the CI can run that for me.

Additionally, we might want to consider emitting (through cargo or rustc) some metadata to help C users of a cdylib figure out where all the dylibs they need are. I don't think that should be needed to land this change, as it will still be usable by homogeneous build systems without it.

My new test was templated off the `tests/run-make-fulldeps/cdylib` test. It seemed more appropriate to have it as a separate test, since both foo.rs and bar.rs would need to be replicated to make that test cover both cases, but I can do that if it would be preferred.

If I'm doing anything out of order/process, please let me know; this is only my second change to rustc and the prior one was trivial.

r? alexcrichton
  • Loading branch information
bors committed Jan 25, 2020
2 parents 8bf1758 + 72aaa3a commit 80a65bc
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 24 deletions.
20 changes: 11 additions & 9 deletions src/librustc_metadata/dependency_format.rs
Expand Up @@ -83,14 +83,17 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList {
}

let preferred_linkage = match ty {
// cdylibs must have all static dependencies.
config::CrateType::Cdylib => Linkage::Static,

// Generating a dylib without `-C prefer-dynamic` means that we're going
// to try to eagerly statically link all dependencies. This is normally
// done for end-product dylibs, not intermediate products.
config::CrateType::Dylib if !sess.opts.cg.prefer_dynamic => Linkage::Static,
config::CrateType::Dylib => Linkage::Dynamic,
//
// Treat cdylibs similarly. If `-C prefer-dynamic` is set, the caller may
// be code-size conscious, but without it, it makes sense to statically
// link a cdylib.
config::CrateType::Dylib | config::CrateType::Cdylib if !sess.opts.cg.prefer_dynamic => {
Linkage::Static
}
config::CrateType::Dylib | config::CrateType::Cdylib => Linkage::Dynamic,

// If the global prefer_dynamic switch is turned off, or the final
// executable will be statically linked, prefer static crate linkage.
Expand Down Expand Up @@ -122,10 +125,9 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList {
return v;
}

// Staticlibs, cdylibs, and static executables must have all static
// dependencies. If any are not found, generate some nice pretty errors.
if ty == config::CrateType::Cdylib
|| ty == config::CrateType::Staticlib
// Staticlibs and static executables must have all static dependencies.
// If any are not found, generate some nice pretty errors.
if ty == config::CrateType::Staticlib
|| (ty == config::CrateType::Executable
&& sess.crt_static()
&& !sess.target.target.options.crt_static_allows_dylibs)
Expand Down
27 changes: 27 additions & 0 deletions src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile
@@ -0,0 +1,27 @@
include ../tools.mk

TARGET_SYSROOT := $(shell $(RUSTC) --print sysroot)/lib/rustlib/$(TARGET)/lib

ifdef IS_MSVC
LIBSTD := $(wildcard $(TARGET_SYSROOT)/libstd-*.dll.lib)
else
LIBSTD := $(wildcard $(TARGET_SYSROOT)/$(call DYLIB_GLOB,std))
STD := $(basename $(patsubst lib%,%, $(notdir $(LIBSTD))))
endif

all: $(call RUN_BINFILE,foo)
$(call RUN,foo)

ifdef IS_MSVC
CLIBS := $(TMPDIR)/foo.dll.lib $(TMPDIR)/bar.dll.lib $(LIBSTD)
$(call RUN_BINFILE,foo): $(call DYLIB,foo)
$(CC) $(CFLAGS) foo.c $(CLIBS) $(call OUT_EXE,foo)
else
CLIBS := -lfoo -lbar -l$(STD) -L $(TMPDIR) -L $(TARGET_SYSROOT)
$(call RUN_BINFILE,foo): $(call DYLIB,foo)
$(CC) $(CFLAGS) foo.c $(CLIBS) -o $(call RUN_BINFILE,foo)
endif

$(call DYLIB,foo):
$(RUSTC) -C prefer-dynamic bar.rs
$(RUSTC) foo.rs
5 changes: 5 additions & 0 deletions src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs
@@ -0,0 +1,5 @@
#![crate_type = "dylib"]

pub fn bar() {
println!("hello!");
}
10 changes: 10 additions & 0 deletions src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c
@@ -0,0 +1,10 @@
#include <assert.h>

extern void foo();
extern unsigned bar(unsigned a, unsigned b);

int main() {
foo();
assert(bar(1, 2) == 3);
return 0;
}
13 changes: 13 additions & 0 deletions src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs
@@ -0,0 +1,13 @@
#![crate_type = "cdylib"]

extern crate bar;

#[no_mangle]
pub extern fn foo() {
bar::bar();
}

#[no_mangle]
pub extern fn bar(a: u32, b: u32) -> u32 {
a + b
}
1 change: 0 additions & 1 deletion src/test/ui/auxiliary/cdylib-dep.rs

This file was deleted.

10 changes: 0 additions & 10 deletions src/test/ui/cdylib-deps-must-be-static.rs

This file was deleted.

4 changes: 0 additions & 4 deletions src/test/ui/cdylib-deps-must-be-static.stderr

This file was deleted.

0 comments on commit 80a65bc

Please sign in to comment.