简体   繁体   中英

Is there a way to use Rust-Cargo to link SOME OF THE dependency crates dynamically?

I have a rust project, it has the following structure:

├─engine
│  │  Cargo.lock
│  │  Cargo.toml
│  │
│  └─src
│          lib.rs
│
├─sandbox
│  │  build.rs
│  │  Cargo.toml
│  │
│  └─src
│          main.rs
│
└─test_static
    │  Cargo.toml
    │
    └─src
            lib.rs

The crate sandbox is a bin crate, engine is designed to be a dylib, and test_static is a rlib.

In sandbox/cargo.toml :

[package]
name = "sandbox"
version = "0.1.0"
edition = "2021"
build = "build.rs"

[dependencies]
prefer-dynamic = "0"
engine = { path = "../engine" }
test_static = { path = "../test_static" }

I want to build crate engine as a dylib, test_static as an rlib, and build sandbox , with test_static statically linked and engine dynamically linked.

To achieve my goal, I used the following rustc commands:

rustc --crate-name engine engine\src\lib.rs --crate-type dylib -C prefer-dynamic
rustc --crate-name test_static test_static\src\lib.rs --crate-type rlib
rustc sandbox\src\main.rs --crate-type bin --extern engine='engine.dll' --extern test_static='libtest_static.rlib'

Those commands worked just fine, but I wonder if there is a way to achieve this by Cargo... When using command 'cargo build' in project root directory, I always get a binary that links 2 dependencies statically.

I searched for official docs, RFCs, but I got nothing, seems that the dependencies must be either all-static (by default) or auto-dynamic (using RUSTFLAGS='-C prefer-dynamic', which will cause the rust to build everything dynamically if possible).

Is there any Cargo.toml settings syntax to specify how to link the dependency crate? For example, the build-in libstd, when using RUSTFLAGS='-C prefer-dynamic' , the libstd will also be linked dynamically, which is not what I expected.

-C prefer-dynamic doesn't actually affect how crates are built, only how they're searched for. What you need to do is add this to the Cargo.toml of the dependency which you want to link dynamically (in your case, engine ):

[lib]
crate-type = ["dylib"]

This will tell Cargo that the crate can only be a Rust DLL (those have an unstable ABI, so you can't use them with code built by a different compiler version or with different compilation settings – the special ugly name prevents you from doing that).

If you want the engine crate to be able to exist in both incarnations, you can do what Bevy does with its dynamic feature flag that turns the engine into a Rust DLL for fast incremental compiles. Thoroughly explaining its behavior is outside the scope of this answer, but you can check out Bevy's Cargo.toml on the top-level crate, it's not a very complicated mechanism.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM