Support linking to rust dylibs from a staticlib

This commit is contained in:
bjorn3 2022-12-28 17:10:21 +00:00
parent 3a5c8e91f0
commit 09e1fae118
5 changed files with 65 additions and 13 deletions

View File

@ -89,11 +89,12 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
// to try to eagerly statically link all dependencies. This is normally // to try to eagerly statically link all dependencies. This is normally
// done for end-product dylibs, not intermediate products. // done for end-product dylibs, not intermediate products.
// //
// Treat cdylibs similarly. If `-C prefer-dynamic` is set, the caller may // Treat cdylibs and staticlibs similarly. If `-C prefer-dynamic` is set,
// be code-size conscious, but without it, it makes sense to statically // the caller may be code-size conscious, but without it, it makes sense
// link a cdylib. // to statically link a cdylib or staticlib.
CrateType::Dylib | CrateType::Cdylib if !sess.opts.cg.prefer_dynamic => Linkage::Static, CrateType::Dylib | CrateType::Cdylib | CrateType::Staticlib => {
CrateType::Dylib | CrateType::Cdylib => Linkage::Dynamic, if sess.opts.cg.prefer_dynamic { Linkage::Dynamic } else { Linkage::Static }
}
// If the global prefer_dynamic switch is turned off, or the final // If the global prefer_dynamic switch is turned off, or the final
// executable will be statically linked, prefer static crate linkage. // executable will be statically linked, prefer static crate linkage.
@ -108,9 +109,6 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
// No linkage happens with rlibs, we just needed the metadata (which we // No linkage happens with rlibs, we just needed the metadata (which we
// got long ago), so don't bother with anything. // got long ago), so don't bother with anything.
CrateType::Rlib => Linkage::NotLinked, CrateType::Rlib => Linkage::NotLinked,
// staticlibs must have all static dependencies.
CrateType::Staticlib => Linkage::Static,
}; };
match preferred_linkage { match preferred_linkage {
@ -123,12 +121,11 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
return v; return v;
} }
// Staticlibs and static executables must have all static dependencies. // Static executables must have all static dependencies.
// If any are not found, generate some nice pretty errors. // If any are not found, generate some nice pretty errors.
if ty == CrateType::Staticlib if ty == CrateType::Executable
|| (ty == CrateType::Executable && sess.crt_static(Some(ty))
&& sess.crt_static(Some(ty)) && !sess.target.crt_static_allows_dylibs
&& !sess.target.crt_static_allows_dylibs)
{ {
for &cnum in tcx.crates(()).iter() { for &cnum in tcx.crates(()).iter() {
if tcx.dep_kind(cnum).macros_only() { if tcx.dep_kind(cnum).macros_only() {

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.lib $(TMPDIR)/bar.dll.lib $(LIBSTD)
$(call RUN_BINFILE,foo): $(call STATICLIB,foo)
$(CC) $(CFLAGS) foo.c $(CLIBS) $(call OUT_EXE,foo)
else
CLIBS := $(TMPDIR)/libfoo.a -lbar -l$(STD) -L $(TMPDIR) -L $(TARGET_SYSROOT)
$(call RUN_BINFILE,foo): $(call STATICLIB,foo)
$(CC) $(CFLAGS) foo.c $(CLIBS) -o $(call RUN_BINFILE,foo)
endif
$(call STATICLIB,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 = "staticlib"]
extern crate bar;
#[no_mangle]
pub extern "C" fn foo() {
bar::bar();
}
#[no_mangle]
pub extern "C" fn bar(a: u32, b: u32) -> u32 {
a + b
}