zig/src/dev.zig
Jacob Young f58200e3f2 Elf2: create a new linker from scratch
This iteration already has significantly better incremental support.

Closes #24110
2025-09-21 14:09:14 -07:00

330 lines
9.6 KiB
Zig

pub const Env = enum {
/// zig1 features
/// - `-ofmt=c` only
/// - `-OReleaseFast` or `-OReleaseSmall` only
/// - no `@setRuntimeSafety(true)`
bootstrap,
/// zig2 features
core,
/// stage3 features
full,
/// - `zig cc`
/// - `zig c++`
/// - `zig translate-c`
c_source,
/// - `zig ast-check`
/// - `zig changelist`
/// - `zig dump-zir`
ast_gen,
/// - ast_gen
/// - `zig build-* -fno-emit-bin`
sema,
/// - sema
/// - `zig build-* -fincremental -fno-llvm -fno-lld -target aarch64-linux --listen=-`
@"aarch64-linux",
/// - `zig build-* -ofmt=c`
cbe,
/// - sema
/// - `zig build-* -fincremental -fno-llvm -fno-lld -target powerpc(64)(le)-linux --listen=-`
@"powerpc-linux",
/// - sema
/// - `zig build-* -fno-llvm -fno-lld -target riscv64-linux`
@"riscv64-linux",
/// - sema
/// - `zig build-* -fno-llvm -fno-lld -target spirv(32/64)-* --listen=-`
spirv,
/// - sema
/// - `zig build-* -fno-llvm -fno-lld -target wasm32-* --listen=-`
wasm,
/// - sema
/// - `zig build-* -fincremental -fno-llvm -fno-lld -target x86_64-linux --listen=-`
@"x86_64-linux",
pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool {
return switch (dev_env) {
.full => true,
.bootstrap => switch (feature) {
.build_exe_command,
.build_obj_command,
.ast_gen,
.sema,
.c_backend,
.c_linker,
=> true,
else => false,
},
.core => switch (feature) {
.build_exe_command,
.build_lib_command,
.build_obj_command,
.test_command,
.run_command,
.ar_command,
.build_command,
.clang_command,
.stdio_listen,
.build_import_lib,
.make_executable,
.make_writable,
.incremental,
.ast_gen,
.sema,
.legalize,
.c_compiler,
.llvm_backend,
.c_backend,
.wasm_backend,
.arm_backend,
.x86_64_backend,
.aarch64_backend,
.x86_backend,
.powerpc_backend,
.riscv64_backend,
.sparc64_backend,
.spirv_backend,
.lld_linker,
.coff_linker,
.elf_linker,
.elf2_linker,
.macho_linker,
.c_linker,
.wasm_linker,
.spirv_linker,
.plan9_linker,
.goff_linker,
.xcoff_linker,
=> true,
.cc_command,
.translate_c_command,
.fmt_command,
.jit_command,
.fetch_command,
.init_command,
.targets_command,
.version_command,
.env_command,
.zen_command,
.help_command,
.ast_check_command,
.detect_cpu_command,
.changelist_command,
.dump_zir_command,
.llvm_ints_command,
.docs_emit,
// Avoid dragging networking into zig2.c because it adds dependencies on some
// linker symbols that are annoying to satisfy while bootstrapping.
.network_listen,
.win32_resource,
=> false,
},
.c_source => switch (feature) {
.clang_command,
.cc_command,
.translate_c_command,
.c_compiler,
=> true,
else => false,
},
.ast_gen => switch (feature) {
.ast_check_command,
.changelist_command,
.dump_zir_command,
.make_executable,
.make_writable,
.incremental,
.ast_gen,
=> true,
else => false,
},
.sema => switch (feature) {
.build_exe_command,
.build_lib_command,
.build_obj_command,
.test_command,
.run_command,
.sema,
=> true,
else => Env.ast_gen.supports(feature),
},
.@"aarch64-linux" => switch (feature) {
.build_command,
.stdio_listen,
.incremental,
.aarch64_backend,
.elf_linker,
.elf2_linker,
=> true,
else => Env.sema.supports(feature),
},
.cbe => switch (feature) {
.legalize,
.c_backend,
.c_linker,
=> true,
else => Env.sema.supports(feature),
},
.@"powerpc-linux" => switch (feature) {
.build_command,
.stdio_listen,
.incremental,
.x86_64_backend,
.elf_linker,
=> true,
else => Env.sema.supports(feature),
},
.@"riscv64-linux" => switch (feature) {
.riscv64_backend,
.elf_linker,
=> true,
else => Env.sema.supports(feature),
},
.spirv => switch (feature) {
.spirv_backend,
.spirv_linker,
.legalize,
=> true,
else => Env.sema.supports(feature),
},
.wasm => switch (feature) {
.stdio_listen,
.incremental,
.wasm_backend,
.wasm_linker,
=> true,
else => Env.sema.supports(feature),
},
.@"x86_64-linux" => switch (feature) {
.build_command,
.stdio_listen,
.incremental,
.legalize,
.x86_64_backend,
.elf_linker,
.elf2_linker,
=> true,
else => Env.sema.supports(feature),
},
};
}
pub inline fn supportsAny(comptime dev_env: Env, comptime features: []const Feature) bool {
inline for (features) |feature| if (dev_env.supports(feature)) return true;
return false;
}
pub inline fn supportsAll(comptime dev_env: Env, comptime features: []const Feature) bool {
inline for (features) |feature| if (!dev_env.supports(feature)) return false;
return true;
}
};
pub const Feature = enum {
build_exe_command,
build_lib_command,
build_obj_command,
test_command,
run_command,
ar_command,
build_command,
clang_command,
cc_command,
translate_c_command,
fmt_command,
jit_command,
fetch_command,
init_command,
targets_command,
version_command,
env_command,
zen_command,
help_command,
ast_check_command,
detect_cpu_command,
changelist_command,
dump_zir_command,
llvm_ints_command,
docs_emit,
stdio_listen,
network_listen,
build_import_lib,
win32_resource,
make_executable,
make_writable,
incremental,
ast_gen,
sema,
legalize,
c_compiler,
llvm_backend,
c_backend,
wasm_backend,
arm_backend,
x86_64_backend,
aarch64_backend,
x86_backend,
powerpc_backend,
riscv64_backend,
sparc64_backend,
spirv_backend,
lld_linker,
coff_linker,
elf_linker,
elf2_linker,
macho_linker,
c_linker,
wasm_linker,
spirv_linker,
plan9_linker,
goff_linker,
xcoff_linker,
};
/// Makes the code following the call to this function unreachable if `feature` is disabled.
pub fn check(comptime feature: Feature) if (env.supports(feature)) void else noreturn {
if (env.supports(feature)) return;
@panic("development environment " ++ @tagName(env) ++ " does not support feature " ++ @tagName(feature));
}
/// Makes the code following the call to this function unreachable if all of `features` are disabled.
pub fn checkAny(comptime features: []const Feature) if (env.supportsAny(features)) void else noreturn {
if (env.supportsAny(features)) return;
comptime var feature_tags: []const u8 = "";
inline for (features[0 .. features.len - 1]) |feature| feature_tags = feature_tags ++ @tagName(feature) ++ ", ";
feature_tags = feature_tags ++ "or " ++ @tagName(features[features.len - 1]);
@panic("development environment " ++ @tagName(env) ++ " does not support feature " ++ feature_tags);
}
/// Makes the code following the call to this function unreachable if any of `features` are disabled.
pub fn checkAll(comptime features: []const Feature) if (env.supportsAll(features)) void else noreturn {
if (env.supportsAll(features)) return;
inline for (features) |feature| if (!env.supports(feature))
@panic("development environment " ++ @tagName(env) ++ " does not support feature " ++ @tagName(feature));
}
const build_options = @import("build_options");
pub const env: Env = if (@hasDecl(build_options, "dev"))
@field(Env, @tagName(build_options.dev))
else if (@hasDecl(build_options, "only_c") and build_options.only_c)
.bootstrap
else if (@hasDecl(build_options, "only_core_functionality") and build_options.only_core_functionality)
.core
else
.full;