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

New env vars for better support custom targets-spec for build-scripts #14208

Open
boozook opened this issue Jul 7, 2024 · 3 comments
Open

New env vars for better support custom targets-spec for build-scripts #14208

boozook opened this issue Jul 7, 2024 · 3 comments
Labels
A-build-scripts Area: build.rs scripts A-target-spec Area: target JSON spec files C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-triage Status: This issue is waiting on initial triage.

Comments

@boozook
Copy link

boozook commented Jul 7, 2024

I propose that cargo shares more information about the target in the case of custom target-spec json file used, such as name of base target (llvm-target) and CPU.

Solving this problem will give the possibility to build-scripts and crates (like cc and bingen) used in the build-script-environment to properly configure underlying non-rust build-pipeline such as build c/c++ dependencies, generating bindings, as well as just asking rustc with the requested target as does autocfg crate. Currently it's impossible in most cases.

Problem

The problem is that it is now impossible to determine all the necessary information about a non-builtin target. In other words they can't properly choose a compiler/linker to use and configure it because they don't know the base target and overlapped parameters, such as CPU, codegen parameters, overridden layout and more.

As we all know, the env var TARGET that is shared by cargo, contains rustc's "short target name", definitely not target-triple. It can be triple only if builtin target is requested. And in case we are using the user's target-spec json file we can interpret it only as a random identifier.

Wrong idea:
It could be possible to read and parse a json file, but first of all, for the entire build-pipeline it will be an extra one read-n-parse exercise, and it's a bad thing assuming future changes of unstable format. Anyway, we could try it, even though it's not reliable, and fragile. After getting the path from a user cargo canonicalises it, then shares only the file-stem. What if initially the path is relative, pointing to the outside, and looks like --target=../file.json? We definitely can't realize the path by the stem from the build-script context. It is unreal to properly work with it.

What is needed?

Environment variables: (name are not final)

  1. TARGET_CPU - cpu field from spec or cli-arg, can be empty if not set
  2. TARGET_TRIPLE LLVM-target-triple from the spec file, can be empty or mirror TARGET in case of builtin target used
  3. TARGET_IS_CUSTOM as answer for "Is user custom target currently using? Or otherwise, can I interpret TARGET as triple?"
  4. Could be good to expose c-enum-min-bits, frame-pointer, data-layout, panic strategy and unwinding from the spec
  5. May be more, e.g. path to the spec, questionable - need to discuss

Possible implementation note

TARGET_IS_CUSTOM is the easiest. We already know the full path to the file. unit.kind.name.is_file.
Getting other vars (such as TARGET_CPU) require reading-n-parsing json file or asking nightly rustc for it. Second option is much better, but requires nightly compiler. But if we add it to the rustc print cfg as patch, it could be easy to implement on the cargo side. I suppose this is the best option.

Nothing existing is deleted or changed. Only new things are added. So no breaking changes for API and UI.

If we could want to expose path to the spec, I suppose it's not a good idea to share path and trust the build-script with the user's original target file. If I were cargo, I would make a temporary copy of the spec in case the script changes it, before sharing it with the build-script. Because the build-script can do absolutely anything now. Definitely I could be wrong. Or just as an option, take a json source, minify and share it instead of path.

filling envs here


Also about RUSTC_LINKER and linker in a spec

I see in the source RUSTC_LINKER is for "user-specified linker". It could be useful for purposes described above.

Cargo sets this var only if build_runner.compilation.target_linker(unit.kind).
However, in my case I have never seen a cargo set RUSTC_LINKER.
That is, even if I explicitly specify the linker RUSTFLAGS="-Clinker=arm-none-eabi-ld" I don't find the RUSTC_LINKER variable available in build-script-environment. I probably don't understand how this works.
I tried cargo feature advanced-env too, but it is mostly for CARGO_PROFILE_DEV_PACKAGE_.

I'm pretty sure that the linker specified by the user in the target spec json file is also a "user-specified linker" and should also be specified if RUSTC_LINKER is not already specified. Maybe it could be a var with another name, like TARGET_LINKER.

Disclaimer: there is problem explanation, questions and my (not only my) thoughts. That's why an issue, not RFC or PR.


I could take some parts, I know what to do as I suppose. One more open question is - should I write issue or RFC before patch rustc print cfg?

@boozook boozook added C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-triage Status: This issue is waiting on initial triage. labels Jul 7, 2024
@boozook boozook changed the title More env vars for better support custom targets-spec for build-scripts New env vars for better support custom targets-spec for build-scripts Jul 7, 2024
boozook added a commit to boozook/cargo that referenced this issue Jul 8, 2024
@epage epage added A-build-scripts Area: build.rs scripts A-target-spec Area: target JSON spec files labels Jul 8, 2024
@cuviper
Copy link
Member

cuviper commented Jul 8, 2024

For the purpose of autocfg, I really just need the right value for rustc --target X, whether that's a triple or spec file. The rest of the target specifics don't matter to me, per se, but exposing more in rustc --print cfg sounds natural.

@soloturn
Copy link
Contributor

@boozook what is the use case of this, and what do other build tools do to get this right?

@madsmtm
Copy link
Contributor

madsmtm commented Oct 31, 2024

I'd be wary of exposing the LLVM target-triple, that very much feels like an implementation detail. Especially so in the language (i.e. via. rustc --print cfg / #[cfg(target_llvm_triple = "...")]).

At the very least, it should be optional, and only set when using a custom target-spec.


Also, cross-linking rust-lang/cc-rs#1120 for reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-build-scripts Area: build.rs scripts A-target-spec Area: target JSON spec files C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-triage Status: This issue is waiting on initial triage.
Projects
None yet
Development

No branches or pull requests

5 participants