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.
This commit is contained in:
Matthew Maurer 2020-01-21 22:47:03 -08:00 committed by Matthew Maurer
parent c0e02ad724
commit 72aaa3a414
8 changed files with 66 additions and 24 deletions

View File

@ -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.
@ -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)

View File

@ -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

View File

@ -0,0 +1,5 @@
#![crate_type = "dylib"]
pub fn bar() {
println!("hello!");
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -1 +0,0 @@
#![crate_type = "dylib"]

View File

@ -1,10 +0,0 @@
// build-fail
// error-pattern: crate `cdylib_dep` required to be available in rlib format, but was not found
// aux-build:cdylib-dep.rs
// ignore-musl
// ignore-cloudabi
// ignore-emscripten
// ignore-sgx no dynamic libraries
#![crate_type = "cdylib"]
extern crate cdylib_dep;

View File

@ -1,4 +0,0 @@
error: crate `cdylib_dep` required to be available in rlib format, but was not found in this form
error: aborting due to previous error