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.