authorgravatar for me@gasinfinity.devGasInfinity <me@gasinfinity.dev> 2026-01-28 20:04:27+01:00
committergravatar for me@gasinfinity.devGasInfinity <me@gasinfinity.dev> 2026-01-29 10:31:56+01:00
loge7baa09ce46181a5ffd55879a24a8cb72cea3093
treec7098acca147a886754c62f30db8ad2e4db26fc4
parent204fa8959a8f9d5457705f338eb0461e54155796
signaturebadge-check Signed by SSH key SHA256:p3IHbr0lyK2ekfDC1Zi7dOEV/9T6lGghNawhl5sBnM4

feat(Compilation): make libzigc share zcu if possible


3 files changed, 65 insertions(+), 8 deletions(-)

src/Compilation.zig+58-7
...@@ -80,6 +80,7 @@ sysroot: ?[]const u8,...@@ -80,6 +80,7 @@ sysroot: ?[]const u8,
80root_name: [:0]const u8,80root_name: [:0]const u8,
81compiler_rt_strat: RtStrat,81compiler_rt_strat: RtStrat,
82ubsan_rt_strat: RtStrat,82ubsan_rt_strat: RtStrat,
83zigc_strat: RtStrat,
83/// Resolved into known paths, any GNU ld scripts already resolved.84/// Resolved into known paths, any GNU ld scripts already resolved.
84link_inputs: []const link.Input,85link_inputs: []const link.Input,
85/// Needed only for passing -F args to clang.86/// Needed only for passing -F args to clang.
...@@ -2101,6 +2102,47 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2101,6 +2102,47 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2101 try options.root_mod.deps.putNoClobber(arena, "ubsan_rt", ubsan_rt_mod);2102 try options.root_mod.deps.putNoClobber(arena, "ubsan_rt", ubsan_rt_mod);
2102 }2103 }
21032104
2105 // Like with ubsan_rt we want to go through the `_ = @import("zigc")`
2106 // approach if possible since it uses even more of the standard library
2107 // and can thus reduce further unnecesary bloat.
2108 const zigc_strat: RtStrat = s: {
2109 if (options.skip_linker_dependencies) break :s .none;
2110 if (target.ofmt == .c) break :s .none;
2111 if (!link_libc or !is_exe_or_dyn_lib) break :s .none;
2112 if (!target_util.wantsZigC(target, options.config.link_mode)) break :s .none;
2113 if (have_zcu) break :s .zcu;
2114 break :s .lib;
2115 };
2116
2117 if (zigc_strat == .zcu) {
2118 const zigc_mod = Package.Module.create(arena, .{
2119 .paths = .{
2120 .root = .zig_lib_root,
2121 .root_src_path = "c.zig",
2122 },
2123 .fully_qualified_name = "zigc",
2124 .cc_argv = &.{},
2125 .inherited = .{},
2126 .global = options.config,
2127 .parent = options.root_mod,
2128 }) catch |err| switch (err) {
2129 error.OutOfMemory => |e| return e,
2130 // None of these are possible because the configuration matches the root module
2131 // which already passed these checks.
2132 error.ValgrindUnsupportedOnTarget => unreachable,
2133 error.TargetRequiresSingleThreaded => unreachable,
2134 error.BackendRequiresSingleThreaded => unreachable,
2135 error.TargetRequiresPic => unreachable,
2136 error.PieRequiresPic => unreachable,
2137 error.DynamicLinkingRequiresPic => unreachable,
2138 error.TargetHasNoRedZone => unreachable,
2139 error.StackCheckUnsupportedByTarget => unreachable,
2140 error.StackProtectorUnsupportedByTarget => unreachable,
2141 error.StackProtectorUnavailableWithoutLibC => unreachable,
2142 };
2143 try options.root_mod.deps.putNoClobber(arena, "zigc", zigc_mod);
2144 }
2145
2104 if (options.verbose_llvm_cpu_features) {2146 if (options.verbose_llvm_cpu_features) {
2105 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| {2147 if (options.root_mod.resolved_target.llvm_cpu_features) |cf| {
2106 const stderr = try io.lockStderr(&.{}, null);2148 const stderr = try io.lockStderr(&.{}, null);
...@@ -2296,6 +2338,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2296,6 +2338,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2296 .libc_installation = libc_dirs.libc_installation,2338 .libc_installation = libc_dirs.libc_installation,
2297 .compiler_rt_strat = compiler_rt_strat,2339 .compiler_rt_strat = compiler_rt_strat,
2298 .ubsan_rt_strat = ubsan_rt_strat,2340 .ubsan_rt_strat = ubsan_rt_strat,
2341 .zigc_strat = zigc_strat,
2299 .link_inputs = options.link_inputs,2342 .link_inputs = options.link_inputs,
2300 .framework_dirs = options.framework_dirs,2343 .framework_dirs = options.framework_dirs,
2301 .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,2344 .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,
...@@ -2651,13 +2694,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2651,13 +2694,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2651 } else {2694 } else {
2652 return diag.fail(.cross_libc_unavailable);2695 return diag.fail(.cross_libc_unavailable);
2653 }2696 }
2654
2655 if ((target.isMuslLibC() and comp.config.link_mode == .static) or
2656 target.isWasiLibC() or
2657 target.isMinGW())
2658 {
2659 comp.queued_jobs.zigc_lib = true;
2660 }
2661 }2697 }
26622698
2663 // Generate Windows import libs.2699 // Generate Windows import libs.
...@@ -2711,6 +2747,15 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,...@@ -2711,6 +2747,15 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
2711 .dyn_lib => unreachable, // hack for compiler_rt only2747 .dyn_lib => unreachable, // hack for compiler_rt only
2712 }2748 }
27132749
2750 switch (comp.zigc_strat) {
2751 .none, .zcu => {},
2752 .lib => {
2753 log.debug("queuing a job to build libzigc", .{});
2754 comp.queued_jobs.zigc_lib = true;
2755 },
2756 .obj, .dyn_lib => unreachable, // only available as a static library or inside an existing ZCU
2757 }
2758
2714 if (is_exe_or_dyn_lib and comp.config.any_fuzz) {2759 if (is_exe_or_dyn_lib and comp.config.any_fuzz) {
2715 log.debug("queuing a job to build libfuzzer", .{});2760 log.debug("queuing a job to build libfuzzer", .{});
2716 comp.queued_jobs.fuzzer_lib = true;2761 comp.queued_jobs.fuzzer_lib = true;
...@@ -3100,6 +3145,11 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -3100,6 +3145,11 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
3100 zcu.analysis_roots_buffer[zcu.analysis_roots_len] = ubsan_rt_mod;3145 zcu.analysis_roots_buffer[zcu.analysis_roots_len] = ubsan_rt_mod;
3101 zcu.analysis_roots_len += 1;3146 zcu.analysis_roots_len += 1;
3102 }3147 }
3148
3149 if (zcu.root_mod.deps.get("zigc")) |zigc_mod| {
3150 zcu.analysis_roots_buffer[zcu.analysis_roots_len] = zigc_mod;
3151 zcu.analysis_roots_len += 1;
3152 }
3103 }3153 }
31043154
3105 // The linker progress node is set up here instead of in `performAllTheWork`, because3155 // The linker progress node is set up here instead of in `performAllTheWork`, because
...@@ -3531,6 +3581,7 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -3531,6 +3581,7 @@ fn addNonIncrementalStuffToCacheManifest(
3531 man.hash.add(comp.skip_linker_dependencies);3581 man.hash.add(comp.skip_linker_dependencies);
3532 man.hash.add(comp.compiler_rt_strat);3582 man.hash.add(comp.compiler_rt_strat);
3533 man.hash.add(comp.ubsan_rt_strat);3583 man.hash.add(comp.ubsan_rt_strat);
3584 man.hash.add(comp.zigc_strat);
3534 man.hash.add(comp.rc_includes);3585 man.hash.add(comp.rc_includes);
3535 man.hash.addListOfBytes(comp.force_undefined_symbols.keys());3586 man.hash.addListOfBytes(comp.force_undefined_symbols.keys());
3536 man.hash.addListOfBytes(comp.framework_dirs);3587 man.hash.addListOfBytes(comp.framework_dirs);
src/Zcu.zig+1-1
...@@ -269,7 +269,7 @@ nav_val_analysis_queued: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, voi...@@ -269,7 +269,7 @@ nav_val_analysis_queued: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, voi
269269
270/// These are the modules which we initially queue for analysis in `Compilation.update`.270/// These are the modules which we initially queue for analysis in `Compilation.update`.
271/// `resolveReferences` will use these as the root of its reachability traversal.271/// `resolveReferences` will use these as the root of its reachability traversal.
272analysis_roots_buffer: [4]*Package.Module,272analysis_roots_buffer: [5]*Package.Module,
273analysis_roots_len: usize = 0,273analysis_roots_len: usize = 0,
274/// This is the cached result of `Zcu.resolveReferences`. It is computed on-demand, and274/// This is the cached result of `Zcu.resolveReferences`. It is computed on-demand, and
275/// reset to `null` when any semantic analysis occurs (since this invalidates the data).275/// reset to `null` when any semantic analysis occurs (since this invalidates the data).
src/target.zig+6
...@@ -423,6 +423,12 @@ pub fn canBuildLibUbsanRt(target: *const std.Target) enum { no, yes, llvm_only,...@@ -423,6 +423,12 @@ pub fn canBuildLibUbsanRt(target: *const std.Target) enum { no, yes, llvm_only,
423 };423 };
424}424}
425425
426/// Whether libzigc can fill-in the gaps of an existing libc
427/// or *is* the libc of the target.
428pub fn wantsZigC(target: *const std.Target, link_mode: std.builtin.LinkMode) bool {
429 return (target.isMuslLibC() and link_mode == .static) or target.isWasiLibC() or target.isMinGW();
430}
431
426pub fn hasRedZone(target: *const std.Target) bool {432pub fn hasRedZone(target: *const std.Target) bool {
427 return switch (target.cpu.arch) {433 return switch (target.cpu.arch) {
428 .aarch64,434 .aarch64,