Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The bindeps feature with cdylib artefact doesn't work when cross compiling for musl target #15095

Open
zzsergant opened this issue Jan 16, 2025 · 8 comments
Labels
A-cross-compiling Area: using --target flag for other platforms C-bug Category: bug S-triage Status: This issue is waiting on initial triage. Z-bindeps Nightly: binary artifact dependencies

Comments

@zzsergant
Copy link

I have a workspace with two crates:

  • foo - cdylib library with extern "C" functions
  • bar - application, that uses foo library (as shared library)

The bar crate uses unstable bindeps feature of cargo to specify build dependency on artefact cdylib of foo library in Cargo.toml.

Everything works fine when built for native toolchain, but when I build bar with specifying a --target aarch64-unknown-linux-musl for cross compiling, then I get an error:

/work # cargo build --release --target aarch64-unknown-linux-musl -p bar
error: cannot produce cdylib for `foo v0.1.0 (/work/foo)` as the target `x86_64-unknown-linux-musl` does not support these crate types

In the error above it says it can't produce cdylib for target x86_64, even though I specified aarch64.

If I build foo library, it compiled successfully:

/work # cargo build --release --target aarch64-unknown-linux-musl -p foo
   Compiling foo v0.1.0 (/work/foo)
    Finished `release` profile [optimized] target(s) in 0.14s

I've attached a minimal example to reproduce that issue:
musl_cdylib.zip

It contains a workspace with foo and bar crates, Dockerfile to setup environment for cross compilation, and README.md with steps to build an image.

Meta

rustc --version --verbose:

rustc 1.86.0-nightly (419b3e2d3 2025-01-15)
binary: rustc
commit-hash: 419b3e2d3e350822550eee0e82eeded4d324d584
commit-date: 2025-01-15
host: x86_64-unknown-linux-gnu
release: 1.86.0-nightly
LLVM version: 19.1.6
@zzsergant zzsergant added the C-bug Category: bug label Jan 16, 2025
@zzsergant
Copy link
Author

It seems that bindeps does not respect specified --target and build dependency with default toolchain.

@bjorn3
Copy link
Member

bjorn3 commented Jan 16, 2025

There are two halves to this:

  • bindep ignoring --target. This is a cargo issue.
  • Not being able to compile a cdylib for musl. This is because -Ctarget-feature=+crt-static is the default, which statically links libc into the linked artifact. This is incompatible with dynamic linking. Instead you will have to make the cdylib and host executable get compiled with -Ctarget-feature=-crt-static. For the host executable RUSTFLAGS="-Ctarget-feature=-crt-static" should work, but for bindeps I don't know how to pass extra flags to rustc.

@zzsergant
Copy link
Author

The problem I'm trying to solve with bindeps is that I have a workspace with multiple cdylib crates, some of which depends on other cdylib crates in the same workspace and I need to control build order of the crates, because the dependent foo.dll.lib or libfoo.so is required at link stage of other crates.

I've tried bindeps and at first it seems did a trick, in build.rs I've used CARGO_CDYLIB_DIR_FOO to locate cdylib artifact folder and add it to link search dirs. But, that doesn't work with cross compilation, because bindeps ignoring --target.

Is there any way to make one cdylib crate dependent by another cdylib crate and specify resulting artifact (.lib/.so) in build.rs for it within the same workspace?

I've tried to locate target folder in build.rs and add it to link search dirs. Sometimes it work, but sometimes doesn't (depending on build order or timing issue).

@bjorn3
Copy link
Member

bjorn3 commented Jan 16, 2025

If you use bindep you get the path to the compiled cdylib as env var passed to your build.rs, right?

@zzsergant
Copy link
Author

If you use bindep you get the path to the compiled cdylib as env var passed to your build.rs, right?

Yes, that is right. With bindeps and [build-dependency] I can use environment variable CARGO_<artifact_type>_DIR_<lib> to locate cdylib artifacts (.so/.lib). The only issue is that doesn't work with cross compilation with --target.

@zzsergant
Copy link
Author

I've found, that it is possible to specify target = "target" parameter for bindep artifact in bar Cargo.toml and it will build for target platform (not host):

[build-dependencies]
foo = { path = "../foo", artifact = "cdylib", version = "*", target = "target" }

That way my problem is solved and cross compilation works.

@jieyouxu jieyouxu added O-musl OS: musl targets T-cargo Team: Cargo A-linkage Area: linker issues, dylib, cdylib, shared libraries, so labels Jan 24, 2025
@jieyouxu
Copy link
Member

jieyouxu commented Jan 24, 2025

AFAICT this is no longer a concern for rust-lang/rust, but sending this over to the cargo issue tracker for the

bindep ignoring --target. This is a cargo issue.

bit for further triage by T-cargo.

@rustbot transfer cargo

@rustbot rustbot transferred this issue from rust-lang/rust Jan 24, 2025
@jieyouxu
Copy link
Member

@rustbot label: +S-triage

@rustbot rustbot added the S-triage Status: This issue is waiting on initial triage. label Jan 24, 2025
@epage epage added Z-bindeps Nightly: binary artifact dependencies A-cross-compiling Area: using --target flag for other platforms and removed A-linkage Area: linker issues, dylib, cdylib, shared libraries, so O-musl OS: musl targets T-cargo Team: Cargo labels Jan 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-cross-compiling Area: using --target flag for other platforms C-bug Category: bug S-triage Status: This issue is waiting on initial triage. Z-bindeps Nightly: binary artifact dependencies
Projects
None yet
Development

No branches or pull requests

5 participants