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

Per crate build target in workspace #7004

Closed
jonblack opened this issue Jun 3, 2019 · 29 comments · Fixed by #9030
Closed

Per crate build target in workspace #7004

jonblack opened this issue Jun 3, 2019 · 29 comments · Fixed by #9030
Labels
A-configuration Area: cargo config files and env vars A-cross-compiling Area: using --target flag for other platforms C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`

Comments

@jonblack
Copy link

jonblack commented Jun 3, 2019

Describe the problem you are trying to solve

I have a project with two crates in a workspace. The first crate should compile to asmjs with --target asmjs-unknown-emscripten and the result is used in the second crate, which should compile to the native binary format (default target).

When I run cargo build in the root crate that contains the workspace configuration in Cargo.toml, it builds both crates using the default target.

Describe the solution you'd like

I'd like to be able to specify the target for each crate. I'm not sure if this belongs in each crates' Cargo.toml or in the root crate's Cargo.toml.

@jonblack jonblack added the C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` label Jun 3, 2019
@j16r
Copy link

j16r commented Jun 6, 2019

Are you setting the target with a .cargo/config file in the second crate?

@jonblack
Copy link
Author

jonblack commented Jun 6, 2019

If I add a .cargo/config in the first crate with the contents:

[build]

target = "asmjs-unknown-emscripten"

And then run cargo build from the root crate, I get the same compilation failure. It seems cargo ignores this.

@ehuss ehuss added A-configuration Area: cargo config files and env vars A-cross-compiling Area: using --target flag for other platforms labels Sep 21, 2019
@kaimast
Copy link

kaimast commented Sep 22, 2019

I have a similar problem, where I want to build some parts of my workspace as an SGX enclave (using the x86_64-fortanix-unknown-sgx target) and other parts as a regular binary.

Is there a hack-ish way to do this right now, that is simpler than writing a bash script that invokes cargo build in every crate of the workspace?

@j16r
Copy link

j16r commented Sep 25, 2019

@autodidaddict
Copy link

If I add a .cargo/config in the first crate with the contents:

[build]

target = "asmjs-unknown-emscripten"

And then run cargo build from the root crate, I get the same compilation failure. It seems cargo ignores this.

I have this exact same problem. Cargo is ignoring the .cargo/config files when I build, which makes it difficult to set up a CI build.

@leordev
Copy link

leordev commented Jan 27, 2020

I'm experiencing this problem a lot because my workspace has wasms and non-wasms crates...

@diondokter
Copy link

I ran into this problem too and it cost me 4 hours before I understood what was going on.

My situation:
I'm have an embedded project. My binary is in one workspace member and there are two no_std libraries in the workspace as well. The libraries are made for specific chips that are on board of the hardware.

The solution would be that every member can have its own .Cargo/config and when that isn't found, it will then go look in the parent directories.

@haraldh
Copy link

haraldh commented Apr 22, 2020

The solution would be that every member can have its own .Cargo/config and when that isn't found, it will then go look in the parent directories.

Yeah, one would logically think that is the current case... General common config in the topdir.. specialized config in the subdirs.

@diondokter
Copy link

Yeah, one would logically think that is the current case... General common config in the topdir.. specialized config in the subdirs.

They do work if you call cargo build in the workspace member itself. But when building from the workspace root, they get ignored.

I have no idea if it's trivial to fix that. It may also break existing workspaces.

@bkolobara
Copy link

I also just run into this problem trying to set up a WASM sub crate. I think I will just use a Makefile to manually run the build per crate instead. But it is a bit inconvenient to do so.

@whizsid
Copy link

whizsid commented May 16, 2020

I have faced this issue today. I want to compile one crate with musl and the other crates with glibc. Now I am compiling with using separate cargo commands.

@kristoff3r
Copy link

I also faced this issue with a workspace of mostly normal crates and 2 wasm crates. It would be very convenient if the .cargo/config target setting was respected by the workspace.

@mikevoronov
Copy link

So, today and I have stumbled with the same issue with wasm and non-wasm crates in one project.

@devsnek
Copy link

devsnek commented Oct 10, 2020

Just ran into this. This seems pretty key as long as rust considers wasm a first class target.

@TheAifam5
Copy link

TheAifam5 commented Oct 19, 2020

Same problem. Any workaround? I really need it since I build stuff around efi and bios.

Use case:

  • rlib with 'x86_64-unknown-none'
  • efi application with 'x86_64-unknown-efi'
  • stage1 + stageN bootloader with 'x86_64-unknown-none'

@repi
Copy link

repi commented Oct 19, 2020

One workaround, albeit not a great one, but one we do use is to divide up the workspace into multiple workspaces, one per target, have them in different folders and have a .cargo/config in each that picks the target to build for.

It is not great though, you don't have a single workspace to build anymore. but doing cargo build inside each separate folder and workspace does build and run on the right target.

@TheAifam5
Copy link

TheAifam5 commented Oct 19, 2020

I've decided to go with rust-make and remove Cargo.toml workspace file and use rust-make's internal one. So I have Makefile.toml and just execute "cargo make" to build them all, it goes to each folder and executes "cargo build"

@Richard-W
Copy link

Richard-W commented Oct 20, 2020

I have looked into this. cargo completely ignores config files in member directories if cargo is called from the workspace root. I came up with 3 different options to implement per-crate build targets but sadly none of them are trivial:

1. Parse member's .cargo/config.toml

Not a good idea. While this would work for some keys like build.target it is not a good idea for others like build.jobs. cargo could ignore such definitions in workspace members of course but it seems very hacky.

2. Dedicated .cargo/member.toml configuration

Special configuration file with a scope limited to a single member crate and a limited set of configuration values like build.target. Reusing config file parsing code from cargo would be difficult though since it all pretty much depends on Config (e.g. ConfigRelativePath::resolve_path takes &Config as its argument).

Example
# workspace/foo/.cargo/member.toml
[build]
target = "wasm32-unknown-unknown"

3. [member.'name'] table in toplevel .cargo/config.toml

Similar to .cargo/member.toml proposal but all information goes into the toplevel .cargo config.toml

Example
# workspace/.cargo/config.toml
[build]
# Default target
target = "x86_64-unknown-linux-gnu"

[member.foo]
# Override default target for `foo`
target = "wasm32-unknown-unknown"

I have implemented proposal 3 (here) and it seems to work fine (all tests pass). It's not an elegant implementation though and it feels pretty "wedged in".

Richard-W added a commit to Richard-W/cargo that referenced this issue Oct 20, 2020
The member table right now only contains the `target` member. It defines
the build target for a single workspace member overriding both the
`build.target` config value and the '--target' switch.

Fixes rust-lang#7004
@TheAifam5
Copy link

TheAifam5 commented Oct 20, 2020

IMHO much better idea would be to allow use of the workspace’s config as a base, where each package have the ability to overwrite properties in context of a package.

I am not aware how it works internally but if there is only once „Config” instance, maybe building „Config” for each package and switching it would also be an option?

@Richard-W
Copy link

Richard-W commented Oct 21, 2020

IMHO much better idea would be to allow use of the workspace’s config as a base, where each package have the ability to overwrite properties in context of a package.

I am not aware how it works internally but if there is only once „Config” instance, maybe building „Config” for each package and switching it would also be an option?

I started work on this with a similar approach but I had to abandon it. The current configuration system in cargo is just not designed to deal with multiple configs in one run. Changing this would be a major refactoring and would probably lead to backwards-compatibility problems too.

Using [member.'crate'] tables just circumvents the problem by not challenging cargo's assumption that there is only one configuration per run.

@kaimast
Copy link

kaimast commented Dec 24, 2020

It is great that progress is made on this issue :)

I started work on this with a similar approach but I had to abandon it. The current configuration system in cargo is just not designed to deal with multiple configs in one run. Changing this would be a major refactoring and would probably lead to backwards-compatibility problems too.

I think eventually this refactor needs to happen or the Rust community has to decide on a meta build tool that is used on top of cargo.
Many projects (especially those involving WASM or SGX) use Makefiles right now to circumvent these limitations, which is somewhat ugly and does not work on all platform.

@lf-
Copy link
Contributor

lf- commented Dec 30, 2020

This thread has a proposal on a fix to this, discussed by the cargo team (was linked on #8797): https://internals.rust-lang.org/t/proposal-move-some-cargo-config-settings-to-cargo-toml/13336

It appears the current status is that PRs are welcome for adding the properties discussed there to Cargo.toml.

@Ekleog
Copy link
Contributor

Ekleog commented Dec 31, 2020

Hey! In case people are interested, I've just submitted #9030 which should implement the solution discussed in the irlo thread listed just above.

@TheAifam5
Copy link

Additionally would be awesome to have in Cargo.toml possibility to define triplets for each [[bin]] :) Just an idea.

@tobin-crypto
Copy link

@kaimast I'm doing this currently: https://github.com/smartcontractkit/chainlink/blob/develop/sgx/Makefile

This link is broken.

@ryanc-me
Copy link

ryanc-me commented Jan 1, 2022

Thanks for your work @Ekleog, this was very helpful in a project I'm working on!

In case any newbies (like me) come across this in the future, and are confused about how to use the fix, it's documented here: https://doc.rust-lang.org/cargo/reference/unstable.html#per-package-target

Google is still showing this issue as the 1st result, so the doc link may be helpful.

@Trolldemorted
Copy link

@ryanc-me are there any solutions for stable rust?

@mikkelens
Copy link

I would also love to know which solution is recommended for stable rust.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-configuration Area: cargo config files and env vars A-cross-compiling Area: using --target flag for other platforms C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`
Projects
None yet