Closed fschutt closed 10 months ago
How about adding an example for wasm in Cargo.toml?
...
[[example]]
name = "wasm"
path = "src/lib.rs"
crate-type = ["cdylib"]
And build by
cargo +nightly build --example wasm --target wasm32-unknown-unknown --release
@fschutt I currently have the same issue, my workaround is basically this for WASM and rlib releases:
Cargo.toml
[lib]
crate-type = ["rlib"]
[[bin]]
name = "test_wasm"
path = "src/lib.rs"
src/lib.rs
#[cfg(target_arch = "wasm32")]
fn main() {}
So
cargo build --lib
will build the rlib, and
cargo build --bin test_wasm
builds the WASM.
Seems to work well for all lib types.
Noob here, but I came here with the same (I think) problem. and solved it by trying
[lib]
crate-type = ["cdylib", "lib"]
Both cargo +nightly build --target wasm32-unknown-unknown
and cargo run
from a crate including the wasm-compilable crate work, and I am able to use the functionality from wasm_or_lib as wasm and as a rust lib.
"rlib" instead of "lib" works too
Is it possible to specify create type by target in the .cargo/config file?
Android targets need cdylib iOS need staticlib
I've tried but it does not seem to accept.
@prographo no, unfortunately that's not supported by Cargo right now
@alvitawa Specified crate-type = ["cdylib", "lib"]
, but the generated wasm file size goes from 166KB to 2MB in my case.
Is it possible to specify create type by target in the .cargo/config file?
setting it from the env like CARGO_TARGET_{triple}_CRATE_TYPE
would also be nice for tooling.
Android targets need cdylib iOS need staticlib
any updates?
Why is is so hard to build a library for both regular Rust use and WASM? Right now I can only choose either-or.
Is there any progress on this?
Proposal: in analogy to:
[target.'cfg(target_arch = "wasm32")'.dependencies]
rand = { version = "0.7.3", features = ["getrandom"] }
This should be allowed:
[target.'cfg(target_arch = "wasm32")'.lib]
crate-type = ["cdylib", "rlib"]
Unfortunately, at the moment I still get:
$ wasm-pack build --target web --out-name wasm
Error: crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your Cargo.toml file:
[lib]
crate-type = ["cdylib", "rlib"]
People have also run into this issue when targeting iOS and Android: https://github.com/rust-lang/rust/pull/77716
This issue becomes critical after merging https://github.com/rust-lang/rust/pull/73516/ that added support of cdylib on iOS.
This new feature in Rust 1.46 added a lot of headache for iOS builds with cdylib
targets. cdylib
target is near impossible to build if you are using any crate with native dependencies (ex. openssl, libsodium, zmq). You can't just find .so files for all architectures to perform correct linking. Usual workflow is the following:
staticlib
and rely that native dependencies will be linked as frameworks laterAs cargo doesn't support platform-dependent crate types https://github.com/rust-lang/cargo/issues/4881 as a result a lot of projects now broken on Rust 1.46
So what's the best practice here? Lot of workarounds above but I don't see a clear answer.
I have the same issue, I need to build on Android, iOS and Wasm but:
crate-type= ["dylib", "cdylib", "staticlib"]
) makes build failcargo build
argument (--crate-type "dylib")FWIW, I will throw in the notion that really, the integration form of how something is built is not something that a package should almost ever decide for itself, but is instead something that the containing dependency of that package needs influence over (quite possibly even multiple levels deep, to some extent). I realize that "the ship has sailed" in some sense with this notion of how cargo is designed, but if I were to ever sit down and apply my 25 years of toolchain and build engineering experience to the problem of creating a package management tool (which I'm not sure is even a good idea in the abstract... I do this thing for specific projects, but I'm not sold on the idea of it being an entire ecosystem yet, given my experiences with every single attempt in this space having not worked well), I'd definitely make this be something that is directed in some sense by the top-level package (which might be something like "I want a .deb file with a dynamic .so in it", but is very often going to be "I want a .ipa file with a .app in it for distribution via the Apple App Store"... which is notably different than "I want a .deb file with a .app in it for distribution via Cydia Installer" and notably different even than "I want a .ipa file with a .app in it for distribution via Cydia Impactor by a user with access to only a free developer profile") along with the ability to flow through overrides on virtually everything about the tree of builds below it, as that just feels like "table stakes" for being able to deal with arbitrary packaging restrictions without having to like, constantly go beg upstream repositories to add more boilerplate build configuration for weird platforms (which Android, iOS, and Wasm all certainly are). (I don't even feel like autotools got this right, and I generally feel like autotools nailed a lot about complex build configuration... libtool just makes too many assumptions about the meaning of a "static" vs. a "dynamic" library to be able to correctly target every platform out of the box; that said, autotools does allow me to override almost everything quite easily, so there's that ;P.)
This also impacts folks trying to builds Python extension modules for iOS.
Is there consensus that the fix is to support specifying arbitrary keys on a per target basis, or is that merely a proposal and more design is required?
Last I heard the cargo team is not willing to take a PR to fix this currently and an RFC would need to happen. I think the more deeper problem that makes this hard to fix is that cargo parses the toml and then freezes it by passing around a reference. So there isn't an easy way to adjust the crate-type
key in the toml based on information gained later in the compilation.
A related request I have (which likely would use the same mechanics as a fix for this issue, so I'm mentioning it here, but can open a separate issue if desired) is enabling crate-type
to be controlled by feature flags. hyper 0.14.3
added a C FFI behind an ffi
feature flag, but to do so they added crate-type = ["lib", "staticlib", "cdylib"]
to their Cargo.toml
. This breaks cross-compilation for downstream staticlib
Rust users such as myself, because even though the ffi
feature flag is disabled, the (completely unused) cdylib
is still compiled for hyper
, and rustc
needs to know how to link for the target architecture (which is completely unnecessary for the staticlib
I want to compile for use in my C++ binary, so wasn't plumbed in). If hyper
could have placed the staticlib, cdylib
behind the ffi
feature flag, there would have been no downstream effects.
This really needs to be implemented. Without crate-type depending on target building cross platform crates supporting mobile platforms such as iOS and Android requires a lot fuss and workarounds.
Related issue: https://github.com/rust-lang/cargo/issues/6179
Related: rust-lang/rfcs#3180, and the follow-up: #10083. Cargo teams opinion on (parts of) this at the moment: https://github.com/rust-lang/rfcs/pull/3180#issuecomment-947032972.
While #12260 is a duplicate of this, it has more input from the cargo team, so I'm going to close in favor of that. If there is a reason to keep this open separately that I overlooked, let us know!
This is an issue that currently blocks me from porting a library to WASM:
I have a library called proj5, which I use in a backend server (in a regular Rust program). I wanted to port the library to wasm (the
wasm32-unknown-unknown
target) that is now available on nightly and found it to be impossible to do it while still being able to use it in the backend:The only way to get a WASM binary is by setting the
crate-type
to"cdylib"
in the Cargo.toml file. However, if I do this, I can't use the crate in my regular rust program anymore! And if I leave it out, there is not WASM output.So currently a crate can be compiled either for WASM or for use in a regular Rust program, not both (controlled by the target). I tried the following so far:
This doesn't work, the argument goes unused:
I also tried:
Same thing, same error message. The crate builds, but doesn't produce a WASM binary.
.cargo/config
) does not seem to have any effect. I tried:This just gives a cryptic error, and sets the crate-type twice:
No line number, no column number, nothing. Not sure where it failed - the error message could be heavily improved upon.
I also tried it with
crate_type
,-- --crate-type
,--crate-type dylib
. None of which work. I expected--crate-type=dylib
to work, because it is documented this way, however I suspect that the documentation is incorrect or out of date.So the last thing I tried was to override the crate type via
cfg_attr
:This is simply ignored by cargo. I still get a
.rlib
file, not a.wasm
file.So right now I'm out of options. Why is is so hard to build a library for both regular Rust use and WASM? Right now I can only choose either-or.
There is a workaround in that I make a second crate (as
cdylib
), which just exposes the first one (therlib
), but I don't think this is the way to go. This is important for feature-gating crates so that they can be compiled to WASM without any workarounds.