Cargo: Expose target-cpu/target-feature

Created on 9 Jan 2015  路  14Comments  路  Source: rust-lang/cargo

rustc won't use e.g. AVX instructions without being told that it's ok to compile to a non-lowest-common-denominator CPU, and programmers may wish to opt-in to these more specialised instructions.

Most helpful comment

RUSTFLAGS is a very unsatisfactory solution.

  1. set RUSTFLAGS= is a shared mutable state. It's easy to forget to set the flags, and easy to forget to change the flags when switching between projects.

  2. Syntax for setting env vars is OS-dependent. It leads to silly cases where a Windows-only setting is documented using a Unix-specific syntax that doesn't work in Windows command prompt:

    RUSTFLAGS='-C target-feature=+crt-static' cargo build --target x86_64-pc-windows-msvc

    'RUSTFLAGS' is not recognized as an internal or external command,
    operable program or batch file.

  3. RUSTFLAGS is separate from Cargo.toml, so once a project depends on the flags, it is no longer a pure self-documenting Cargo project. The flags need to be documented or set using a custom (non-Cargo) build script.

    What I admire about Rust/Cargo is that complex projects can be built without RTFM, with just a plain cargo build. Dependency on RUSTFLAGS breaks that, which is a huge loss for me.

  4. Accidentally running cargo build without appropriate RUSTFLAGS may appear to work, but build subtly wrong things, e.g. a Windows exe that will work on my machine, but won't work on other people's machines.

  5. It's not suitable for cross-compilation, because during the build you may need different flags for native build.rs and cross-compiled products.

All 14 comments

Now that cargo rustc is implemented (and this is part of custom target specs), I'm going to close this as I think the need is probably less pressing for now. I'd still like to continue to avoid exposing all flags of the compiler through Cargo itself, and cargo rustc should be a good escape hatch for this behavior for now.

Hm, it was pointed out to me that cargo rustc doesn't quite handle everything. Specifically, AFAIK, it doesn't allow one to easily build dependencies with the given codegen options, which can be pretty important.

(I could be wrong, but reopening so this doesn't get forgotten. Close if I am.)

Yeah cargo rustc is not appropriate for the use case of "I'd like to apply this set of LLVM features to the entire compile", but I also don't think that exposing these flags is the right option. The "correct" way to do that is to create a custom target specification which has the right set of features listed, depending on your use case.

Can you elaborate on what the use case is for this? I would expect that a one-off compile (testing using new instructions) would be done through cargo rustc, but do you want this saved into Cargo.toml, for example? (without switching targets fundamentally).

"Make this binary run as fast as possible here" essentially implies feeding -C target-cpu=native to each crate. I suppose it could be handled via target specs, but that seems... way more difficult than necessary. Maybe a built-in target like cargo build --target=native.

However, that doesn't cover cases like "I'm building for other computers where every CPU is guaranteed to support SSE4.1 (but not necessarily anything later)". It does seem like a custom target may work better for this: e.g. my-data-center-target.json.

Another case I can imagine is running tests/benchmarks with various cpu-... options, but this is maybe less important?

Hm yeah I think those are compelling enough to not be totally covered by cargo rustc + custom target specs. I suspect that "run as fast as possible" typically doesn't require that _all_ crates are compiled with target-cpu=native but rather just one or two particular ones, but the point definitely still stands.

Before we expose something like this I just want to make sure that we have a clear policy on what is/isn't exposed. I don't want all compiler options to become Cargo options in 3 different places (taken to the extreme).

With support for RUSTFLAGS now landed, I'm going to close this in favor of that as I believe it's possible to pass through that vector.

RUSTFLAGS is a very unsatisfactory solution.

  1. set RUSTFLAGS= is a shared mutable state. It's easy to forget to set the flags, and easy to forget to change the flags when switching between projects.

  2. Syntax for setting env vars is OS-dependent. It leads to silly cases where a Windows-only setting is documented using a Unix-specific syntax that doesn't work in Windows command prompt:

    RUSTFLAGS='-C target-feature=+crt-static' cargo build --target x86_64-pc-windows-msvc

    'RUSTFLAGS' is not recognized as an internal or external command,
    operable program or batch file.

  3. RUSTFLAGS is separate from Cargo.toml, so once a project depends on the flags, it is no longer a pure self-documenting Cargo project. The flags need to be documented or set using a custom (non-Cargo) build script.

    What I admire about Rust/Cargo is that complex projects can be built without RTFM, with just a plain cargo build. Dependency on RUSTFLAGS breaks that, which is a huge loss for me.

  4. Accidentally running cargo build without appropriate RUSTFLAGS may appear to work, but build subtly wrong things, e.g. a Windows exe that will work on my machine, but won't work on other people's machines.

  5. It's not suitable for cross-compilation, because during the build you may need different flags for native build.rs and cross-compiled products.

I'd like to echo everything said in the above comment.

Exactly as predicted, I forgot to set RUSTFLAGS and distributed a "broken" executable to my users.

Please, please, please, allow target-feature to be set permanently in Cargo.toml!

@kornelski For what it's worth, you can at least set rustflags in your .cargo/config on a per target basis. You can even put that .cargo/config in your project folder and check it in to git (although it won't have any effect when someone merely depends on your crate).

+1 on this request. It's really important to be able to control this more easily than with an environment variable.

I would also greatly appreciate if target-feature could be set in Cargo.toml

For example, it would allow to more easily measure the performance impact of retpoline on specific models of CPU's.

Can we please get this in. This would be unimaginably helpful.

Was this page helpful?
0 / 5 - 0 ratings