Proposal
We augment the builtin targets specs with a target_family identifying their executable format, where appropriate. For example x86_64-unknown-linux-gnu would get target_family = "elf" for ELF, aarch64-apple-darwin would get target_family = "mach-o" for Mach-O, and i686-pc-windows-msvc would get target_family = "coff" for COFF.
Target families are defined by the Reference as "a more generic description of a target, such as the family of the operating systems or architectures that the target generally falls into. Any number of target_family key-value pairs can be set." Extrapolating this to family of operating systems or architectures or executable formats is a natural fit.
Targets are allowed to belong to any number of target families, so this feature does not interfere with targets that already have "unix" or "windows" as a target family. For example cfg(target_family = "unix") and cfg(target_family = "elf") might both evaluate true on the same target.
Having target families for executable format is useful in the ecosystem because it supersedes the use of target_os as a proxy for this purpose, for example in the inventory or linkme crates which deal with executable-format-specific link sections.
Before:
#[cfg_attr(
any(
target_os = "linux",
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "haiku",
target_os = "illumos",
target_os = "openbsd",
target_os = "psp",
),
link_section = ".init_array",
)]
#[cfg_attr(
any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "visionos",
),
link_section = "__DATA,__mod_init_func",
)]
static __CTOR: unsafe extern "C" fn() = __ctor;
After:
#[cfg_attr(target_family = "elf", link_section = ".init_array")]
#[cfg_attr(target_family = "mach-o", link_section = "__DATA,__mod_init_func")]
static __CTOR: unsafe extern "C" fn() = __ctor;
This approach based on target_family is friendlier to custom targets. For example the target spec for seL4 userspace components, which uses target_os = "none", can just set an "elf" target family in its target specifications and thereby pick up ELF-specific functionality in the ecosystem. Having the ecosystem conflate target_os = "none" with ELF as currently most often done is unwise. Additionally, target_family plays nicely with private / closed source operating systems compared to target_os. Some company with an internal target for a private OS doesn't want to push a PR to all the crates to add a case for their private ELF-based target_os for which maybe the name isn't even public.
Mentors or Reviewers
@dtolnay with guidance from @nspin
Process
The main points of the Major Change Process are as follows:
You can read more about Major Change Proposals on forge.
Comments
This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.
Proposal
We augment the builtin targets specs with a
target_familyidentifying their executable format, where appropriate. For example x86_64-unknown-linux-gnu would gettarget_family = "elf"for ELF, aarch64-apple-darwin would gettarget_family = "mach-o"for Mach-O, and i686-pc-windows-msvc would gettarget_family = "coff"for COFF.Target families are defined by the Reference as "a more generic description of a target, such as the family of the operating systems or architectures that the target generally falls into. Any number of target_family key-value pairs can be set." Extrapolating this to family of operating systems or architectures or executable formats is a natural fit.
Targets are allowed to belong to any number of target families, so this feature does not interfere with targets that already have
"unix"or"windows"as a target family. For examplecfg(target_family = "unix")andcfg(target_family = "elf")might both evaluate true on the same target.Having target families for executable format is useful in the ecosystem because it supersedes the use of
target_osas a proxy for this purpose, for example in theinventoryorlinkmecrates which deal with executable-format-specific link sections.Before:
After:
This approach based on
target_familyis friendlier to custom targets. For example the target spec for seL4 userspace components, which usestarget_os = "none", can just set an"elf"target family in its target specifications and thereby pick up ELF-specific functionality in the ecosystem. Having the ecosystem conflatetarget_os = "none"with ELF as currently most often done is unwise. Additionally,target_familyplays nicely with private / closed source operating systems compared totarget_os. Some company with an internal target for a private OS doesn't want to push a PR to all the crates to add a case for their private ELF-basedtarget_osfor which maybe the name isn't even public.Mentors or Reviewers
@dtolnay with guidance from @nspin
Process
The main points of the Major Change Process are as follows:
@rustbot second.-C flag, then full team check-off is required.@rfcbot fcp mergeon either the MCP or the PR.You can read more about Major Change Proposals on forge.
Comments
This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.