about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-01-25 07:49:40 +0000
committerbors <bors@rust-lang.org>2020-01-25 07:49:40 +0000
commit80a65bcaf2f2b8a5c659b21b32b42bc300338a0e (patch)
tree52525b3dfbde41746b2b9b3c9122393574fd3b56
parent8bf17584e01d85c631bcb19b7cd0f95e84c9a9b1 (diff)
parent72aaa3a414d17aa0c4f19feafa5bab5f84b60e63 (diff)
downloadrust-80a65bcaf2f2b8a5c659b21b32b42bc300338a0e.tar.gz
rust-80a65bcaf2f2b8a5c659b21b32b42bc300338a0e.zip
Auto merge of #68448 - maurer:dyn-cdylib, r=alexcrichton
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
-rw-r--r--src/librustc_metadata/dependency_format.rs20
-rw-r--r--src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile27
-rw-r--r--src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs5
-rw-r--r--src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c10
-rw-r--r--src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs13
-rw-r--r--src/test/ui/auxiliary/cdylib-dep.rs1
-rw-r--r--src/test/ui/cdylib-deps-must-be-static.rs10
-rw-r--r--src/test/ui/cdylib-deps-must-be-static.stderr4
8 files changed, 66 insertions, 24 deletions
diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs
index 3427de19daa..375f372005f 100644
--- a/src/librustc_metadata/dependency_format.rs
+++ b/src/librustc_metadata/dependency_format.rs
@@ -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)
diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile b/src/test/run-make-fulldeps/cdylib-dylib-linkage/Makefile
new file mode 100644
index 00000000000..5c9b2d1bb2f
--- /dev/null
+++ b/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
diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs b/src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs
new file mode 100644
index 00000000000..b3a7539abae
--- /dev/null
+++ b/src/test/run-make-fulldeps/cdylib-dylib-linkage/bar.rs
@@ -0,0 +1,5 @@
+#![crate_type = "dylib"]
+
+pub fn bar() {
+    println!("hello!");
+}
diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.c
new file mode 100644
index 00000000000..154f9682ef8
--- /dev/null
+++ b/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;
+}
diff --git a/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs b/src/test/run-make-fulldeps/cdylib-dylib-linkage/foo.rs
new file mode 100644
index 00000000000..c2cc3afcc13
--- /dev/null
+++ b/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
+}
diff --git a/src/test/ui/auxiliary/cdylib-dep.rs b/src/test/ui/auxiliary/cdylib-dep.rs
deleted file mode 100644
index 8bd2b3353b8..00000000000
--- a/src/test/ui/auxiliary/cdylib-dep.rs
+++ /dev/null
@@ -1 +0,0 @@
-#![crate_type = "dylib"]
diff --git a/src/test/ui/cdylib-deps-must-be-static.rs b/src/test/ui/cdylib-deps-must-be-static.rs
deleted file mode 100644
index abf954d8fb2..00000000000
--- a/src/test/ui/cdylib-deps-must-be-static.rs
+++ /dev/null
@@ -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;
diff --git a/src/test/ui/cdylib-deps-must-be-static.stderr b/src/test/ui/cdylib-deps-must-be-static.stderr
deleted file mode 100644
index a1dc8e985da..00000000000
--- a/src/test/ui/cdylib-deps-must-be-static.stderr
+++ /dev/null
@@ -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
-