ziglang/zig

move -mcpu to be part of the target triple

andrewrk opened this issue · 4 comments

This is a follow-up issue from #4550.

std.zig.CrossTarget has the ability to represent CPU features, as well as std.Target.

Curently, "parsing" a target triple also wants to know the CPU model name and feature set at the same time, in order to produce a target. So this is a proposal to merge the concepts together. It mainly involves the CLI.

The proposal is to change this (example):

-target arm-linux-gnu -mcpu=generic+v8a-neon

to this:

-target arm.generic+v8a~neon-linux-gnu

The main idea here is that -mcpu is deleted as a command line parameter, and -target gains even more expressiveness.

This works by replacing - with ~, because - is a field separator in the -target command line parameter. This would not affect the #3089 CLI which would have -mcpu to match C compilers. Note that ~ means "binary not" in many contexts, which would be a reasonable mnemonic to remember the syntax by.

The main area where this would be helpful would be the Zig build system, because standardTargetOptions would only need to be concerned with -Dtarget rather than -Dtarget and -Dmcpu. The fact that CPU features are part of both std.Target and std.zig.CrossTarget is a strong hint that this data belongs together.

As another example, std.zig.CrossTarget.parse wants to know the -mcpu parameter in order to produce a result:

pub const ParseOptions = struct {
/// This is sometimes called a "triple". It looks roughly like this:
/// riscv64-linux-musl
/// The fields are, respectively:
/// * CPU Architecture
/// * Operating System (and optional version range)
/// * C ABI (optional, with optional glibc version)
/// The string "native" can be used for CPU architecture as well as Operating System.
/// If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted.
arch_os_abi: []const u8 = "native",
/// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e"
/// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features
/// to remove from the set.
/// The following special strings are recognized for CPU Model name:
/// * "baseline" - The "default" set of CPU features for cross-compiling. A conservative set
/// of features that is expected to be supported on most available hardware.
/// * "native" - The native CPU model is to be detected when compiling.
/// If this field is not provided (`null`), then the value will depend on the
/// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline".
cpu_features: ?[]const u8 = null,
/// Absolute path to dynamic linker, to override the default, which is either a natively
/// detected path, or a standard path.
dynamic_linker: ?[]const u8 = null,
/// If this is provided, the function will populate some information about parsing failures,
/// so that user-friendly error messages can be delivered.
diagnostics: ?*Diagnostics = null,
pub const Diagnostics = struct {
/// If the architecture was determined, this will be populated.
arch: ?Target.Cpu.Arch = null,
/// If the OS name was determined, this will be populated.
os_name: ?[]const u8 = null,
/// If the OS tag was determined, this will be populated.
os_tag: ?Target.Os.Tag = null,
/// If the ABI was determined, this will be populated.
abi: ?Target.Abi = null,
/// If the CPU name was determined, this will be populated.
cpu_name: ?[]const u8 = null,
/// If error.UnknownCpuFeature is returned, this will be populated.
unknown_feature_name: ?[]const u8 = null,
};
};
pub fn parse(args: ParseOptions) !CrossTarget {

EDIT: Resolved, I misread the proposed structure... several times over...

The main area where this would be helpful would be the Zig build system, because standardTargetOptions would only need to be concerned with -Dtarget rather than -Dtarget and -Dmcpu. The fact that CPU features are part of both std.Target and std.zig.CrossTarget is a strong hint that this data belongs together.

As far as I can see, standardTargetOptions doesn't currently support -Dmcpu either, and hence there is no way to pass a model?

Argument for status quo:

zig … -target x86_64.nehalem+sgx+sse3+tsxldtrk~prefer_128_bit-linux.4.13-gnueabihf …

I cannot really read that compared to a -target x86_64-linux.4.13-gnueabihf And even that is not really well readable, i'd even prefer to put OS version into a separate command line flag and just have -target x86_64-linux-gnueabihf

Does the current behavior prevent zig cc from being able to cross-compile to a Raspberry Pi B (armv6l)? If so, are there any workarounds?

I came to this issue from #4875 and I'm seeing the same behavior as reported there: zig cc interprets "arm" as "armv7", and I don't see a way to tell it to target "armv6l" instead (contrast with zig build, where -Dcpu=arm1176jzf_s for Raspberry Pi B works great).