Repository navigation
Description
This is a tracking issue for the RFC "Flexible target specification" (rust-lang/rfcs#131).
About tracking issues
Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Discussion comments will get marked as off-topic or deleted.
Repeated discussions on the tracking issue may lead to the tracking issue getting locked.
Overview
This is the tracking issue for the ability to specify custom targets using a file that defines the target (currently JSON).
See also #38338 for the related --print=target-spec-json.
Documentation: https://doc.rust-lang.org/nightly/rustc/targets/custom.html
Issues:
A-target-specs
Unresolved Questions
- Should the file format be JSON or something else like TOML?
- See target-spec-toml draft davidtwco/rfcs#5 for a draft RFC proposal that also includes stability information.
- The format is somewhat tied to LLVM. There are some concerns that may make using other backends more difficult. Here is a suggestion for making the backend explicit.
- How will stability be handled?
- Validate that the standard library can be reliably built (no TARGET detection, see Target specification? wg-cargo-std-aware#6 (comment)).
Implementation history
- Original tracking issue: Implement flexible target specs #16093
- Initial implementation: Implement flexible target specification #16156
- Added
--print target-spec-json: print option to dump target spec as JSON #38061 - Support for absolute paths: Introduce a TargetTriple enum to support absolute target paths #49019
- Added sysroot path search: Add default search path to
Target::search()#83800 - Target search cleanup: Adjust target search algorithm for rustlib path #85152
- Added
--print target-spec-json-schema: Add --print target-spec-json-schema #144498 - Destabilization:
- Destabilise
target-spec-json#150151 - target: fix destabilising target-spec-json #151534
- compiletest:
-Zunstable-optionsfor json targets #152236 - Support JSON target specs in bootstrap #152677
- [beta] Revert destabilise target-spec-json #152721
- bootstrap:
-Zjson-target-specfor synthetic targets #154428 - Add -Z json-target-spec cargo#16557
- Destabilise
Activity
Rollup merge of rust-lang#151534 - davidtwco:destabilise-target-spec-…
Rollup merge of rust-lang#151534 - davidtwco:destabilise-target-spec-…
Rollup merge of rust-lang#151534 - davidtwco:destabilise-target-spec-…
Rollup merge of rust-lang#151534 - davidtwco:destabilise-target-spec-…
Rollup merge of rust-lang#151534 - davidtwco:destabilise-target-spec-…
Rollup merge of rust-lang#151534 - davidtwco:destabilise-target-spec-…
Rollup merge of rust-lang#151534 - davidtwco:destabilise-target-spec-…
Rollup merge of rust-lang#151534 - davidtwco:destabilise-target-spec-…
Unrolled build for #151534
dvdhrm commentedon Apr 17, 2026
We used this to bootstrap rustc on UEFI systems (which is now merged into rustc). We could have modified and recompiled rustc, but the json-targets made it so much more convenient. This certainly did not require stabilization of the feature.
I would love for some version of those target configurations to be available in the future, so other platforms can be bootstrapped just as easily as UEFI.
pellico commentedon Apr 17, 2026
RiscV has large number of features that can be activated concurrently, therefore the number of possible combination is very high and the number of new RiscV cores is increasing every year.
This feature would be very helpful.
Presently we solved the issue as in previous post of @dvdhrm by recompiling the rustc.
bjorn3 commentedon Apr 17, 2026
For riscv target features, you don't need custom targets. You can use an existing target with only supported features enabled and then enable the rest of the features using
-Ctarget-feature. For also getting the standard library compiled with those features you need-Zbuild-std, but custom targets also needs that. We don't use a separate target for every combination of features on other architectures either.m-mueller678 commentedon Apr 17, 2026
We are using custom targets for unikernels, mostly on x86_64 and aarch64. We want precise control over the set of enabled cpu features, which TLS model, redzone, PIE, linking, stack probes, and probably a few things I am forgetting right now. We do not plan to ever merge this target like UEFI or Hermit did. We are fine with this remaining on nightly, as we have to use nightly for many other reasons anyway. But it would be nice to have the guarantee that these features will remain available in some shape or form in the future.
heitbaum commentedon Apr 21, 2026
With Rust 1.95 intentionally destabilized support for custom JSON target specifications, gating them behind
-Z unstable-optionsand therefore nightly-only toolchains. This breaks our build for the...-libreelec-linux-gnutarget, which previously worked correctly on stable Rust going back several releases.We are currently blocked with no viable path forward on a stable toolchain.
We cannot pin to Rust 1.94 as we have updated LLVM to a version that is incompatible with 1.94. We cannot move to 1.95+ without resolving the JSON target spec issue. We cannot use nightly in production. We are stuck entirely due to this upstream change.
The
...-libreelec-linux-gnutarget is a custom JSON target spec describing the LibreELEC embedded Linux environment. LibreELEC ships a minimal sysroot that does not correspond to any of Rust's built-in target triples, so a custom spec is the correct and intended mechanism for targeting it. This is precisely the use case the JSON target spec format was designed for.We understand that
-Z json-target-specwas introduced alongside this change to address the breakage. However, as a-Zflag it is itself nightly-only, which provides no relief for stable toolchain users. It papers over the problem without solving it for the people most affected.We understand the desire to keep the format flexible ahead of the build-std stabilization work, and the longer-term goal of a cleaner, more deliberately designed target spec format is reasonable. We are not arguing against that goal. We are arguing that the way this change was executed causes serious, avoidable harm to a legitimate class of stable Rust users. We have already been adjusting the the changes that have been made to the json over time.
Custom JSON target specs are not an obscure feature. They are the primary mechanism by which Rust supports embedded, appliance, and non-standard Linux targets that do not fit neatly into the built-in triple taxonomy. Projects targeting systems like LibreELEC, Yocto-built sysroots, and other vendor-specific Linux environments rely on this feature on stable Rust because their deployment pipelines cannot carry a dependency on nightly. Nightly toolchains carry no stability guarantees, rotate daily, and are unsuitable for production build systems where reproducibility and auditability matter.
The framing that JSON target specs "de facto require nightly" because
-Z build-stdis needed to rebuild core is not accurate for all users. Many cross-compilation environments — including ours — supply a pre-built standard library via a maintained sysroot, and have been building successfully against stable Rust without-Z build-std. The destabilization breaks these setups even though the underlying concern — locking in the JSON format before build-std stabilizes — does not apply to them.We would have preferred the team gate this change on an explicit opt-in: a deprecation warning cycle, a Cargo edition mechanism, or a targeted stable flag. The introduction of
-Z json-target-specas a mitigation underscores that the team recognizes breakage occurred. It would have been preferable to ship that flag as a stable interface from the outset, or to preserve existing stable behaviour while the new format is designed.The compounding problem is that this destabilization cannot be worked around by simply pinning to an older Rust release. An LLVM upgrade in our toolchain renders 1.94 unbuildable, leaving us with no supported stable path forward at all. This is the practical consequence of destabilizing a feature without a stable migration path: downstream projects can find themselves completely blocked through no fault of their own.
bjorn3 commentedon Apr 21, 2026
How did that work at all? We don't ship a standard library for libreelec and building a standard library for a custom target has always been unstable. If you were using the env var to allow unstable features on stable, then users can set this too. If you were building the compiler from scratch with your custom target, you could patch it to make the custom target a builtin target.
heitbaum commentedon Apr 21, 2026
Correct the compiler is being built from scratch. With the custom targets being https://github.com/LibreELEC/LibreELEC.tv/tree/master/packages/rust/rust/targets with the targets finally added to ${TOOLCHAIN}/lib/rustlib/
bjorn3 commentedon Apr 21, 2026
Would it be an option to patch rustc to add those targets? You can add the targest to compiler/rustc_target/src/spec/targets as rust file and then reference them in
rust/compiler/rustc_target/src/spec/mod.rs
Line 1456 in d2f88d4
Noratrieb commentedon Apr 22, 2026
Please do not discuss how to resolve this specific person's problem on this tracking issue, that's not what tracking issues are for (the original message was fine). Let's do that in #155620.
jsgf commentedon Apr 24, 2026
@bjorn3:
For target features which change the ABI/calling convention, I believe you need to use a target spec - for example
f(float) ord(double). Not sure aboute(embedded, half-size GPR set) orv(vector).bjorn3 commentedon Apr 24, 2026
Enabling the f and d features doesn't actually change the ABI. Rather there is a separate field in the target spec that indicates the abi. Same for the e feature. So you can enable the f and d features on riscv64i-unknown-none. This will result in a soft-float abi with computations done using float instructions rather than libcalls. I believe you are not allowed to pass simd types at all in the C ABI if the v feature is disabled and the Rust ABI always passes vectors on the stack to ensure
#[target_feature]doesn't affect the ABI.syntactically commentedon Jun 11, 2026
We are/were also using stable loading of target spec jsons in Hyperlight when building payloads to run in micro vms. We have downstream users who very much want all non-Rust Project code to be built with stable toolchains & without unstable features if it's used in production deployments, partially because this gives assurance that incomplete/potentially unsound/less scrutinised language features are not being used (rather than because of an expectation that upgrading Rust should be possible without breakage). On the other hand, using unstable features to build libcore and liballoc is not considered to be a problem, since that happens anyway, and our release/support flow allows validating/updating the target generation when Rust versions are bumped. (We also build our target jsons by applying relatively minor diffs to the default ones, which slightly reduces issues as well).
Because of this, we did not have a problem setting RUSTC_BOOTSTRAP when building std, but it is a bit difficult for us to require all code compiled towards the target to use it (or a nightly or custom-built compiler).
Upstreaming our targets as Tier 3 (or at least the parts of them that can't be overridden via stable RUSTFLAGS) is a possibility; we haven't so far mainly because keeping them out of tree makes iterating on them a lot easier & reduces how tightly we are tied to rustc release cycles to make changes. Even if we move to upstream sooner than we otherwise would have (accepting the little bit of extra friction), it is unfortunate that it seems like there will be a good few stable rust versions (between 1.95 and whatever release might include our targets) which won't be usable for building Hyperlight guests.
davidtwco commentedon Jun 12, 2026
Can you share what these json files look like? What are you tweaking compared to our built-in targets?
syntactically commentedon Jun 12, 2026
Currently, on x86_64, we modify x86_64-unknown-none:
rustc-abi: x86-softfloat, to get the hardfloat ABI. This is especially important, since not doing it leads to an ABI mismatch with Cranelift-generated code (documented here)pre-link-argscode-model,linker,linker-flavor, andfeatures, which I believe could be replaced by codegen optsCurrently, on aarch64, we modify aarch64-unknown-none:
direct-access-external-data: trueandposition-independent-executables: truepre-link-argscode-model,linker,linker-flavor,features, andrelocation-model, which I believe could be replaced by codegen opts.Rollup merge of rust-lang#163144 - syntactically:hyperlight-targets, …
Unrolled build for #163144 in rollup 163630
Rollup merge of #163144 - syntactically:hyperlight-targets, r=wesleyw…