Skip to content

Tracking Issue for target-spec-json (flexible target specifications) #151528

Open

Description

@ehuss

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 Area: Compile-target specifications

Unresolved Questions

  • Should the file format be JSON or something else like TOML?
  • 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

Activity

  1. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    A-target-specsArea: Compile-target specifications
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Jan 23, 2026
  2. added 2 commits that reference this issue on Jan 27, 2026
  3. added 6 commits that reference this issue on Feb 4, 2026
  4. added a commit that references this issue on Feb 4, 2026
  5. dvdhrm commented on Apr 17, 2026

    @dvdhrm
    Contributor

    We're also gathering use cases for custom targets on the
    tracking issue (#151528) as we consider whether
    some form of this feature should eventually be stabilized.

    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.

  6. pellico commented on Apr 17, 2026

    @pellico

    We're also gathering use cases for custom targets on the
    tracking issue (#151528) as we consider whether
    some form of this feature should eventually be stabilized.

    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.

  7. bjorn3 commented on Apr 17, 2026

    @bjorn3
    Member

    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.

  8. m-mueller678 commented on Apr 17, 2026

    @m-mueller678

    We're also gathering use cases for custom targets on the
    tracking issue (#151528) as we consider whether
    some form of this feature should eventually be stabilized.

    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.

  9. heitbaum commented on Apr 21, 2026

    @heitbaum
    Contributor

    With Rust 1.95 intentionally destabilized support for custom JSON target specifications, gating them behind -Z unstable-options and therefore nightly-only toolchains. This breaks our build for the ...-libreelec-linux-gnu target, 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-gnu target 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-spec was introduced alongside this change to address the breakage. However, as a -Z flag 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-std is 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-spec as 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.

  10. bjorn3 commented on Apr 21, 2026

    @bjorn3
    Member

    This breaks our build for the ...-libreelec-linux-gnu target, which previously worked correctly on stable Rust going back several releases.

    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.

  11. heitbaum commented on Apr 21, 2026

    @heitbaum
    Contributor

    This breaks our build for the ...-libreelec-linux-gnu target, which previously worked correctly on stable Rust going back several releases.

    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.

    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/

  12. bjorn3 commented on Apr 21, 2026

    @bjorn3
    Member

    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

    supported_targets! {

  13. Noratrieb commented on Apr 22, 2026

    @Noratrieb
    Member

    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.

  14. jsgf commented on Apr 24, 2026

    @jsgf
    Contributor

    @bjorn3:

    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 target features which change the ABI/calling convention, I believe you need to use a target spec - for example f (float) or d (double). Not sure about e (embedded, half-size GPR set) or v (vector).

  15. bjorn3 commented on Apr 24, 2026

    @bjorn3
    Member

    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.

  16. syntactically commented on Jun 11, 2026

    @syntactically
    Contributor

    We're also gathering use cases for custom targets on the
    tracking issue (#151528) as we consider whether
    some form of this feature should eventually be stabilized.

    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.

  17. davidtwco commented on Jun 12, 2026

    @davidtwco
    Member

    We're also gathering use cases for custom targets on the
    tracking issue (#151528) as we consider whether
    some form of this feature should eventually be stabilized.

    We are/were also using stable loading of target spec jsons in Hyperlight when building payloads to run in micro vms.

    Can you share what these json files look like? What are you tweaking compared to our built-in targets?

  18. syntactically commented on Jun 12, 2026

    @syntactically
    Contributor

    Can you share what these json files look like? What are you tweaking compared to our built-in targets?

    Currently, on x86_64, we modify x86_64-unknown-none:

    • Most importantly, we remove 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)
    • We set pre-link-args
    • We set code-model, linker, linker-flavor, and features, which I believe could be replaced by codegen opts

    Currently, on aarch64, we modify aarch64-unknown-none:

    • We set direct-access-external-data: true and position-independent-executables: true
    • We set pre-link-args
    • We set code-model, linker, linker-flavor, features, and relocation-model, which I believe could be replaced by codegen opts.
  19. added a commit that references this issue on Oct 2, 2026
  20. added a commit that references this issue on Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-target-specsArea: Compile-target specificationsC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions