authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-07 18:08:31-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:35-07:00
logecba6324bf47a68edf9c8d380f528088be68b5d7
tree160b8e7e1241ff81e2843b7cca1adf628b73b7f2
parent8a8bf5ad023451a22fd7abf438e6c7ee105ac6bf

configurer: update TranslateC step

and get zig's build.zig script fully compiling

13 files changed, 234 insertions(+), 214 deletions(-)

BRANCH_TODO+1
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1* pass overridden pkg-dir to maker
1* finish migrating the rest of the build steps2* finish migrating the rest of the build steps
2* inspect b4ffb402c082605c4b324e88120306fc8fb3cf32 diff and apply changes as needed (merge conflict)3* inspect b4ffb402c082605c4b324e88120306fc8fb3cf32 diff and apply changes as needed (merge conflict)
3* make zig-pkg path root configurable in maker (make sure --system still works)4* make zig-pkg path root configurable in maker (make sure --system still works)
lib/compiler/Maker.zig+4
...@@ -1804,6 +1804,10 @@ pub fn relativePath(maker: *const Maker, relative: Configuration.LazyPath.Relati...@@ -1804,6 +1804,10 @@ pub fn relativePath(maker: *const Maker, relative: Configuration.LazyPath.Relati
1804 .root_dir = graph.zig_lib_directory,1804 .root_dir = graph.zig_lib_directory,
1805 .sub_path = sub_path,1805 .sub_path = sub_path,
1806 },1806 },
1807 .install_prefix => maker.install_paths.prefix,
1808 .install_lib => maker.install_paths.lib,
1809 .install_bin => maker.install_paths.bin,
1810 .install_include => maker.install_paths.include,
1807 };1811 };
1808}1812}
18091813
lib/compiler/Maker/ScannedConfig.zig+5
...@@ -79,6 +79,11 @@ fn printValue(sc: *const ScannedConfig, s: *Serializer, comptime Field: type, fi...@@ -79,6 +79,11 @@ fn printValue(sc: *const ScannedConfig, s: *Serializer, comptime Field: type, fi
79 try printStruct(sc, &sub_struct, Configuration.Step.Run.Arg, field_value.get(c));79 try printStruct(sc, &sub_struct, Configuration.Step.Run.Arg, field_value.get(c));
80 try sub_struct.end();80 try sub_struct.end();
81 },81 },
82 Configuration.Step.ObjCopy.UpdateSection.Flags => {
83 var sub_struct = try s.beginStruct(.{});
84 try printStruct(sc, &sub_struct, Field, field_value);
85 try sub_struct.end();
86 },
82 Configuration.LazyPath.Index => {87 Configuration.LazyPath.Index => {
83 switch (field_value.get(c)) {88 switch (field_value.get(c)) {
84 inline else => |u| {89 inline else => |u| {
lib/compiler/Maker/Step/TranslateC.zig created+122
...@@ -0,0 +1,122 @@
1
2fn make(step: *Step, options: Step.MakeOptions) !void {
3 const prog_node = options.progress_node;
4 const b = step.owner;
5 const translate_c: *TranslateC = @fieldParentPtr("step", step);
6 const arena = b.graph.arena;
7
8 var argv_list = std.array_list.Managed([]const u8).init(b.allocator);
9 try argv_list.append(b.graph.zig_exe);
10 try argv_list.append("translate-c");
11 if (translate_c.link_libc) {
12 try argv_list.append("-lc");
13 }
14
15 try argv_list.append("--cache-dir");
16 try argv_list.append(b.cache_root.path orelse ".");
17
18 try argv_list.append("--global-cache-dir");
19 try argv_list.append(b.graph.global_cache_root.path orelse ".");
20
21 if (!translate_c.target.query.isNative()) {
22 try argv_list.append("-target");
23 try argv_list.append(try translate_c.target.query.zigTriple(b.allocator));
24 }
25
26 switch (translate_c.optimize) {
27 .Debug => {}, // Skip since it's the default.
28 else => try argv_list.append(b.fmt("-O{s}", .{@tagName(translate_c.optimize)})),
29 }
30
31 for (translate_c.include_dirs.items) |include_dir| {
32 try include_dir.appendZigProcessFlags(b, &argv_list, step);
33 }
34
35 for (translate_c.c_macros.items) |c_macro| {
36 try argv_list.append("-D");
37 try argv_list.append(c_macro);
38 }
39
40 var prev_search_strategy: std.Build.Module.SystemLib.SearchStrategy = .paths_first;
41 var prev_preferred_link_mode: std.builtin.LinkMode = .dynamic;
42
43 for (translate_c.system_libs.items) |*system_lib| {
44 var seen_system_libs: std.StringHashMapUnmanaged([]const []const u8) = .empty;
45 const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);
46 if (system_lib_gop.found_existing) {
47 try argv_list.appendSlice(system_lib_gop.value_ptr.*);
48 continue;
49 } else {
50 system_lib_gop.value_ptr.* = &.{};
51 }
52
53 if (system_lib.search_strategy != prev_search_strategy or
54 system_lib.preferred_link_mode != prev_preferred_link_mode)
55 {
56 switch (system_lib.search_strategy) {
57 .no_fallback => switch (system_lib.preferred_link_mode) {
58 .dynamic => try argv_list.append("-search_dylibs_only"),
59 .static => try argv_list.append("-search_static_only"),
60 },
61 .paths_first => switch (system_lib.preferred_link_mode) {
62 .dynamic => try argv_list.append("-search_paths_first"),
63 .static => try argv_list.append("-search_paths_first_static"),
64 },
65 .mode_first => switch (system_lib.preferred_link_mode) {
66 .dynamic => try argv_list.append("-search_dylibs_first"),
67 .static => try argv_list.append("-search_static_first"),
68 },
69 }
70 prev_search_strategy = system_lib.search_strategy;
71 prev_preferred_link_mode = system_lib.preferred_link_mode;
72 }
73
74 const prefix: []const u8 = prefix: {
75 if (system_lib.needed) break :prefix "-needed-l";
76 if (system_lib.weak) break :prefix "-weak-l";
77 break :prefix "-l";
78 };
79 switch (system_lib.use_pkg_config) {
80 .no => try argv_list.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })),
81 .yes, .force => {
82 if (Step.Compile.runPkgConfig(&translate_c.step, system_lib.name)) |result| {
83 try argv_list.appendSlice(result.cflags);
84 try argv_list.appendSlice(result.libs);
85 try seen_system_libs.put(arena, system_lib.name, result.cflags);
86 } else |err| switch (err) {
87 error.PkgConfigInvalidOutput,
88 error.PkgConfigCrashed,
89 error.PkgConfigFailed,
90 error.PkgConfigNotInstalled,
91 error.PackageNotFound,
92 => switch (system_lib.use_pkg_config) {
93 .yes => {
94 // pkg-config failed, so fall back to linking the library
95 // by name directly.
96 try argv_list.append(b.fmt("{s}{s}", .{
97 prefix,
98 system_lib.name,
99 }));
100 },
101 .force => {
102 std.debug.panic("pkg-config failed for library {s}", .{system_lib.name});
103 },
104 .no => unreachable,
105 },
106
107 else => |e| return e,
108 }
109 },
110 }
111 }
112
113 const c_source_path = translate_c.source.getPath2(b, step);
114 try argv_list.append(c_source_path);
115
116 try argv_list.append("--listen=-");
117 const output_dir = try step.evalZigProcess(argv_list.items, prog_node, false, options.web_server, options.gpa);
118
119 const basename = std.fs.path.stem(std.fs.path.basename(c_source_path));
120 translate_c.out_basename = b.fmt("{s}.zig", .{basename});
121 translate_c.output_file.path = output_dir.?.joinString(b.allocator, translate_c.out_basename) catch @panic("OOM");
122}
lib/std/Build.zig+12-6
...@@ -108,7 +108,10 @@ pub const Graph = struct {...@@ -108,7 +108,10 @@ pub const Graph = struct {
108 }108 }
109109
110 pub fn dupePath(graph: *const Graph, bytes: []const u8) []const u8 {110 pub fn dupePath(graph: *const Graph, bytes: []const u8) []const u8 {
111 const arena = graph.arena;111 return dupePathInner(graph.arena, bytes);
112 }
113
114 fn dupePathInner(arena: Allocator, bytes: []const u8) []const u8 {
112 if (builtin.os.tag != .windows) return arena.dupe(u8, bytes) catch @panic("OOM");115 if (builtin.os.tag != .windows) return arena.dupe(u8, bytes) catch @panic("OOM");
113 const the_copy = arena.dupe(u8, bytes) catch @panic("OOM");116 const the_copy = arena.dupe(u8, bytes) catch @panic("OOM");
114 mem.replaceScalar(u8, the_copy, '/', '\\');117 mem.replaceScalar(u8, the_copy, '/', '\\');
...@@ -2331,21 +2334,24 @@ pub const LazyPath = union(enum) {...@@ -2331,21 +2334,24 @@ pub const LazyPath = union(enum) {
23312334
2332 /// Copies the internal strings.2335 /// Copies the internal strings.
2333 ///2336 ///
2334 /// The `b` parameter is only used for its allocator. All *Build instances2337 /// The `graph` parameter is only used for the global arena allocator.
2335 /// share the same allocator.
2336 pub fn dupe(lazy_path: LazyPath, graph: *const Graph) LazyPath {2338 pub fn dupe(lazy_path: LazyPath, graph: *const Graph) LazyPath {
2339 return dupeInner(lazy_path, graph.arena);
2340 }
2341
2342 fn dupeInner(lazy_path: LazyPath, arena: Allocator) LazyPath {
2337 return switch (lazy_path) {2343 return switch (lazy_path) {
2338 .src_path => |sp| .{ .src_path = .{ .owner = sp.owner, .sub_path = sp.owner.dupePath(sp.sub_path) } },2344 .src_path => |sp| .{ .src_path = .{ .owner = sp.owner, .sub_path = sp.owner.dupePath(sp.sub_path) } },
2339 .cwd_relative => |p| .{ .cwd_relative = graph.dupePath(p) },2345 .cwd_relative => |p| .{ .cwd_relative = Graph.dupePathInner(arena, p) },
2340 .relative => |r| .{ .relative = r },2346 .relative => |r| .{ .relative = r },
2341 .generated => |gen| .{ .generated = .{2347 .generated => |gen| .{ .generated = .{
2342 .index = gen.index,2348 .index = gen.index,
2343 .up = gen.up,2349 .up = gen.up,
2344 .sub_path = graph.dupePath(gen.sub_path),2350 .sub_path = Graph.dupePathInner(arena, gen.sub_path),
2345 } },2351 } },
2346 .dependency => |dep| .{ .dependency = .{2352 .dependency => |dep| .{ .dependency = .{
2347 .dependency = dep.dependency,2353 .dependency = dep.dependency,
2348 .sub_path = graph.dupePath(dep.sub_path),2354 .sub_path = Graph.dupePathInner(arena, dep.sub_path),
2349 } },2355 } },
2350 };2356 };
2351 }2357 }
lib/std/Build/Configuration.zig+4
...@@ -1643,6 +1643,10 @@ pub const Path = extern struct {...@@ -1643,6 +1643,10 @@ pub const Path = extern struct {
1643 build_root,1643 build_root,
1644 zig_exe,1644 zig_exe,
1645 zig_lib,1645 zig_lib,
1646 install_prefix,
1647 install_lib,
1648 install_bin,
1649 install_include,
1646 };1650 };
16471651
1648 pub fn toCachePath(path: Path, c: *const Configuration, arena: Allocator) std.Build.Cache.Path {1652 pub fn toCachePath(path: Path, c: *const Configuration, arena: Allocator) std.Build.Cache.Path {
lib/std/Build/Step/TranslateC.zig+42-155
...@@ -1,25 +1,25 @@...@@ -1,25 +1,25 @@
1const TranslateC = @This();1const TranslateC = @This();
22
3const std = @import("std");3const std = @import("std");
4const Step = std.Build.Step;
5const LazyPath = std.Build.LazyPath;
6const fs = std.fs;4const fs = std.fs;
7const mem = std.mem;5const mem = std.mem;
6const allocPrint = std.fmt.allocPrint;
7const Step = std.Build.Step;
8const LazyPath = std.Build.LazyPath;
8const Configuration = std.Build.Configuration;9const Configuration = std.Build.Configuration;
910
10pub const base_tag: Step.Tag = .translate_c;
11
12step: Step,11step: Step,
13source: std.Build.LazyPath,12source: std.Build.LazyPath,
14include_dirs: std.array_list.Managed(std.Build.Module.IncludeDir),13include_dirs: std.ArrayList(std.Build.Module.IncludeDir),
15system_libs: std.ArrayList(std.Build.Module.SystemLib),14system_libs: std.ArrayList(std.Build.Module.SystemLib),
16c_macros: std.array_list.Managed([]const u8),15c_macros: std.ArrayList([]const u8),
17out_basename: []const u8,
18target: std.Build.ResolvedTarget,16target: std.Build.ResolvedTarget,
19optimize: std.builtin.OptimizeMode,17optimize: std.builtin.OptimizeMode,
20output_file: Configuration.GeneratedFileIndex,18output_file: Configuration.GeneratedFileIndex,
21link_libc: bool,19link_libc: bool,
2220
21pub const base_tag: Step.Tag = .translate_c;
22
23pub const Options = struct {23pub const Options = struct {
24 root_source_file: std.Build.LazyPath,24 root_source_file: std.Build.LazyPath,
25 target: std.Build.ResolvedTarget,25 target: std.Build.ResolvedTarget,
...@@ -29,20 +29,17 @@ pub const Options = struct {...@@ -29,20 +29,17 @@ pub const Options = struct {
2929
30pub fn create(owner: *std.Build, options: Options) *TranslateC {30pub fn create(owner: *std.Build, options: Options) *TranslateC {
31 const graph = owner.graph;31 const graph = owner.graph;
32 const arena = graph.arena;32 const translate_c = graph.create(TranslateC);
33 const translate_c = arena.create(TranslateC) catch @panic("OOM");
34 const source = options.root_source_file.dupe(graph);33 const source = options.root_source_file.dupe(graph);
35 translate_c.* = .{34 translate_c.* = .{
36 .step = Step.init(.{35 .step = .init(.{
37 .tag = base_tag,36 .tag = base_tag,
38 .name = "translate-c",37 .name = "translate-c",
39 .owner = owner,38 .owner = owner,
40 .makeFn = make,
41 }),39 }),
42 .source = source,40 .source = source,
43 .include_dirs = std.array_list.Managed(std.Build.Module.IncludeDir).init(arena),41 .include_dirs = .empty,
44 .c_macros = std.array_list.Managed([]const u8).init(arena),42 .c_macros = .empty,
45 .out_basename = undefined,
46 .target = options.target,43 .target = options.target,
47 .optimize = options.optimize,44 .optimize = options.optimize,
48 .output_file = graph.addGeneratedFile(&translate_c.step),45 .output_file = graph.addGeneratedFile(&translate_c.step),
...@@ -90,8 +87,8 @@ pub fn createModule(translate_c: *TranslateC) *std.Build.Module {...@@ -90,8 +87,8 @@ pub fn createModule(translate_c: *TranslateC) *std.Build.Module {
90}87}
9188
92fn setUpModule(translate_c: *TranslateC, module: *std.Build.Module) *std.Build.Module {89fn setUpModule(translate_c: *TranslateC, module: *std.Build.Module) *std.Build.Module {
93 const b = translate_c.step.owner;90 const graph = translate_c.step.owner.graph;
94 const arena = b.graph.arena;91 const arena = graph.arena;
9592
96 if (translate_c.link_libc) module.link_libc = true;93 if (translate_c.link_libc) module.link_libc = true;
9794
...@@ -103,42 +100,49 @@ fn setUpModule(translate_c: *TranslateC, module: *std.Build.Module) *std.Build.M...@@ -103,42 +100,49 @@ fn setUpModule(translate_c: *TranslateC, module: *std.Build.Module) *std.Build.M
103}100}
104101
105pub fn addAfterIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void {102pub fn addAfterIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void {
106 const b = translate_c.step.owner;103 const graph = translate_c.step.owner.graph;
107 translate_c.include_dirs.append(.{ .path_after = lazy_path.dupe(b) }) catch104 const arena = graph.arena;
105 translate_c.include_dirs.append(arena, .{ .path_after = lazy_path.dupe(graph) }) catch
108 @panic("OOM");106 @panic("OOM");
109 lazy_path.addStepDependencies(&translate_c.step);107 lazy_path.addStepDependencies(&translate_c.step);
110}108}
111109
112pub fn addSystemIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void {110pub fn addSystemIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void {
113 const b = translate_c.step.owner;111 const graph = translate_c.step.owner.graph;
114 translate_c.include_dirs.append(.{ .path_system = lazy_path.dupe(b) }) catch112 const arena = graph.arena;
113 translate_c.include_dirs.append(arena, .{ .path_system = lazy_path.dupe(graph) }) catch
115 @panic("OOM");114 @panic("OOM");
116 lazy_path.addStepDependencies(&translate_c.step);115 lazy_path.addStepDependencies(&translate_c.step);
117}116}
118117
119pub fn addIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void {118pub fn addIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void {
120 const b = translate_c.step.owner;119 const graph = translate_c.step.owner.graph;
121 translate_c.include_dirs.append(.{ .path = lazy_path.dupe(b) }) catch120 const arena = graph.arena;
121 translate_c.include_dirs.append(arena, .{ .path = lazy_path.dupe(graph) }) catch
122 @panic("OOM");122 @panic("OOM");
123 lazy_path.addStepDependencies(&translate_c.step);123 lazy_path.addStepDependencies(&translate_c.step);
124}124}
125125
126pub fn addConfigHeader(translate_c: *TranslateC, config_header: *Step.ConfigHeader) void {126pub fn addConfigHeader(translate_c: *TranslateC, config_header: *Step.ConfigHeader) void {
127 translate_c.include_dirs.append(.{ .config_header_step = config_header }) catch127 const graph = translate_c.step.owner.graph;
128 const arena = graph.arena;
129 translate_c.include_dirs.append(arena, .{ .config_header_step = config_header }) catch
128 @panic("OOM");130 @panic("OOM");
129 translate_c.step.dependOn(&config_header.step);131 translate_c.step.dependOn(&config_header.step);
130}132}
131133
132pub fn addSystemFrameworkPath(translate_c: *TranslateC, directory_path: LazyPath) void {134pub fn addSystemFrameworkPath(translate_c: *TranslateC, directory_path: LazyPath) void {
133 const b = translate_c.step.owner;135 const graph = translate_c.step.owner.graph;
134 translate_c.include_dirs.append(.{ .framework_path_system = directory_path.dupe(b) }) catch136 const arena = graph.arena;
137 translate_c.include_dirs.append(arena, .{ .framework_path_system = directory_path.dupe(graph) }) catch
135 @panic("OOM");138 @panic("OOM");
136 directory_path.addStepDependencies(&translate_c.step);139 directory_path.addStepDependencies(&translate_c.step);
137}140}
138141
139pub fn addFrameworkPath(translate_c: *TranslateC, directory_path: LazyPath) void {142pub fn addFrameworkPath(translate_c: *TranslateC, directory_path: LazyPath) void {
140 const b = translate_c.step.owner;143 const graph = translate_c.step.owner.graph;
141 translate_c.include_dirs.append(.{ .framework_path = directory_path.dupe(b) }) catch144 const arena = graph.arena;
145 translate_c.include_dirs.append(arena, .{ .framework_path = directory_path.dupe(graph) }) catch
142 @panic("OOM");146 @panic("OOM");
143 directory_path.addStepDependencies(&translate_c.step);147 directory_path.addStepDependencies(&translate_c.step);
144}148}
...@@ -154,135 +158,17 @@ pub fn addCheckFile(translate_c: *TranslateC, expected_matches: []const []const...@@ -154,135 +158,17 @@ pub fn addCheckFile(translate_c: *TranslateC, expected_matches: []const []const
154/// If the value is omitted, it is set to 1.158/// If the value is omitted, it is set to 1.
155/// `name` and `value` need not live longer than the function call.159/// `name` and `value` need not live longer than the function call.
156pub fn defineCMacro(translate_c: *TranslateC, name: []const u8, value: ?[]const u8) void {160pub fn defineCMacro(translate_c: *TranslateC, name: []const u8, value: ?[]const u8) void {
157 const macro = translate_c.step.owner.fmt("{s}={s}", .{ name, value orelse "1" });161 const graph = translate_c.step.owner.graph;
158 translate_c.c_macros.append(macro) catch @panic("OOM");162 const arena = graph.arena;
163 const macro = allocPrint(arena, "{s}={s}", .{ name, value orelse "1" }) catch @panic("OOM");
164 translate_c.c_macros.append(arena, macro) catch @panic("OOM");
159}165}
160166
161/// name_and_value looks like [name]=[value]. If the value is omitted, it is set to 1.167/// name_and_value looks like [name]=[value]. If the value is omitted, it is set to 1.
162pub fn defineCMacroRaw(translate_c: *TranslateC, name_and_value: []const u8) void {168pub fn defineCMacroRaw(translate_c: *TranslateC, name_and_value: []const u8) void {
163 translate_c.c_macros.append(translate_c.step.owner.dupe(name_and_value)) catch @panic("OOM");169 const graph = translate_c.step.owner.graph;
164}170 const arena = graph.arena;
165171 translate_c.c_macros.append(arena, translate_c.step.owner.dupe(name_and_value)) catch @panic("OOM");
166fn make(step: *Step, options: Step.MakeOptions) !void {
167 const prog_node = options.progress_node;
168 const b = step.owner;
169 const translate_c: *TranslateC = @fieldParentPtr("step", step);
170 const arena = b.graph.arena;
171
172 var argv_list = std.array_list.Managed([]const u8).init(b.allocator);
173 try argv_list.append(b.graph.zig_exe);
174 try argv_list.append("translate-c");
175 if (translate_c.link_libc) {
176 try argv_list.append("-lc");
177 }
178
179 try argv_list.append("--cache-dir");
180 try argv_list.append(b.cache_root.path orelse ".");
181
182 try argv_list.append("--global-cache-dir");
183 try argv_list.append(b.graph.global_cache_root.path orelse ".");
184
185 if (!translate_c.target.query.isNative()) {
186 try argv_list.append("-target");
187 try argv_list.append(try translate_c.target.query.zigTriple(b.allocator));
188 }
189
190 switch (translate_c.optimize) {
191 .Debug => {}, // Skip since it's the default.
192 else => try argv_list.append(b.fmt("-O{s}", .{@tagName(translate_c.optimize)})),
193 }
194
195 for (translate_c.include_dirs.items) |include_dir| {
196 try include_dir.appendZigProcessFlags(b, &argv_list, step);
197 }
198
199 for (translate_c.c_macros.items) |c_macro| {
200 try argv_list.append("-D");
201 try argv_list.append(c_macro);
202 }
203
204 var prev_search_strategy: std.Build.Module.SystemLib.SearchStrategy = .paths_first;
205 var prev_preferred_link_mode: std.builtin.LinkMode = .dynamic;
206
207 for (translate_c.system_libs.items) |*system_lib| {
208 var seen_system_libs: std.StringHashMapUnmanaged([]const []const u8) = .empty;
209 const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);
210 if (system_lib_gop.found_existing) {
211 try argv_list.appendSlice(system_lib_gop.value_ptr.*);
212 continue;
213 } else {
214 system_lib_gop.value_ptr.* = &.{};
215 }
216
217 if (system_lib.search_strategy != prev_search_strategy or
218 system_lib.preferred_link_mode != prev_preferred_link_mode)
219 {
220 switch (system_lib.search_strategy) {
221 .no_fallback => switch (system_lib.preferred_link_mode) {
222 .dynamic => try argv_list.append("-search_dylibs_only"),
223 .static => try argv_list.append("-search_static_only"),
224 },
225 .paths_first => switch (system_lib.preferred_link_mode) {
226 .dynamic => try argv_list.append("-search_paths_first"),
227 .static => try argv_list.append("-search_paths_first_static"),
228 },
229 .mode_first => switch (system_lib.preferred_link_mode) {
230 .dynamic => try argv_list.append("-search_dylibs_first"),
231 .static => try argv_list.append("-search_static_first"),
232 },
233 }
234 prev_search_strategy = system_lib.search_strategy;
235 prev_preferred_link_mode = system_lib.preferred_link_mode;
236 }
237
238 const prefix: []const u8 = prefix: {
239 if (system_lib.needed) break :prefix "-needed-l";
240 if (system_lib.weak) break :prefix "-weak-l";
241 break :prefix "-l";
242 };
243 switch (system_lib.use_pkg_config) {
244 .no => try argv_list.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })),
245 .yes, .force => {
246 if (Step.Compile.runPkgConfig(&translate_c.step, system_lib.name)) |result| {
247 try argv_list.appendSlice(result.cflags);
248 try argv_list.appendSlice(result.libs);
249 try seen_system_libs.put(arena, system_lib.name, result.cflags);
250 } else |err| switch (err) {
251 error.PkgConfigInvalidOutput,
252 error.PkgConfigCrashed,
253 error.PkgConfigFailed,
254 error.PkgConfigNotInstalled,
255 error.PackageNotFound,
256 => switch (system_lib.use_pkg_config) {
257 .yes => {
258 // pkg-config failed, so fall back to linking the library
259 // by name directly.
260 try argv_list.append(b.fmt("{s}{s}", .{
261 prefix,
262 system_lib.name,
263 }));
264 },
265 .force => {
266 std.debug.panic("pkg-config failed for library {s}", .{system_lib.name});
267 },
268 .no => unreachable,
269 },
270
271 else => |e| return e,
272 }
273 },
274 }
275 }
276
277 const c_source_path = translate_c.source.getPath2(b, step);
278 try argv_list.append(c_source_path);
279
280 try argv_list.append("--listen=-");
281 const output_dir = try step.evalZigProcess(argv_list.items, prog_node, false, options.web_server, options.gpa);
282
283 const basename = std.fs.path.stem(std.fs.path.basename(c_source_path));
284 translate_c.out_basename = b.fmt("{s}.zig", .{basename});
285 translate_c.output_file.path = output_dir.?.joinString(b.allocator, translate_c.out_basename) catch @panic("OOM");
286}172}
287173
288pub fn linkSystemLibrary(174pub fn linkSystemLibrary(
...@@ -290,9 +176,10 @@ pub fn linkSystemLibrary(...@@ -290,9 +176,10 @@ pub fn linkSystemLibrary(
290 name: []const u8,176 name: []const u8,
291 options: std.Build.Module.LinkSystemLibraryOptions,177 options: std.Build.Module.LinkSystemLibraryOptions,
292) void {178) void {
293 const b = translate_c.step.owner;179 const graph = translate_c.step.owner.graph;
294 translate_c.system_libs.append(b.allocator, .{180 const arena = graph.arena;
295 .name = b.dupe(name),181 translate_c.system_libs.append(arena, .{
182 .name = graph.dupeString(name),
296 .needed = options.needed,183 .needed = options.needed,
297 .weak = options.weak,184 .weak = options.weak,
298 .use_pkg_config = options.use_pkg_config,185 .use_pkg_config = options.use_pkg_config,
lib/std/Build/Step/WriteFile.zig+21-21
...@@ -119,34 +119,34 @@ pub fn add(write_file: *WriteFile, sub_path: []const u8, bytes: []const u8) std....@@ -119,34 +119,34 @@ pub fn add(write_file: *WriteFile, sub_path: []const u8, bytes: []const u8) std.
119 };119 };
120}120}
121121
122/// Place the file into the generated directory within the local cache,122/// Copies the provided file into the generated directory within the local
123/// along with all the rest of the files added to this step. The parameter123/// cache, along with all the rest of the files added to this step.
124/// here is the destination path relative to the local cache directory124///
125/// associated with this WriteFile. It may be a basename, or it may125/// `sub_path` is the destination path relative to the local cache directory
126/// include sub-directories, in which case this step will ensure the126/// associated with this WriteFile. It may be a basename, or it may include
127/// required sub-path exists.127/// subdirectories, which are created as needed.
128/// This is the option expected to be used most commonly with `addCopyFile`.
129pub fn addCopyFile(write_file: *WriteFile, source: std.Build.LazyPath, sub_path: []const u8) std.Build.LazyPath {128pub fn addCopyFile(write_file: *WriteFile, source: std.Build.LazyPath, sub_path: []const u8) std.Build.LazyPath {
130 const b = write_file.step.owner;129 const graph = write_file.step.owner.graph;
131 const gpa = b.allocator;130 const duped_path = graph.dupePath(sub_path);
132 const file = File{131 const arena = graph.arena;
133 .sub_path = b.dupePath(sub_path),132
133 write_file.files.append(arena, .{
134 .sub_path = duped_path,
134 .contents = .{ .copy = source },135 .contents = .{ .copy = source },
135 };136 }) catch @panic("OOM");
136 write_file.files.append(gpa, file) catch @panic("OOM");
137137
138 write_file.maybeUpdateName();138 write_file.maybeUpdateName();
139 source.addStepDependencies(&write_file.step);139 source.addStepDependencies(&write_file.step);
140 return .{140
141 .generated = .{141 return .{ .generated = .{
142 .index = write_file.generated_directory,142 .index = write_file.generated_directory,
143 .sub_path = file.sub_path,143 .sub_path = duped_path,
144 },144 } };
145 };
146}145}
147146
148/// Copy files matching the specified exclude/include patterns to the specified subdirectory147/// Copy files matching the specified exclude/include patterns to the specified
149/// relative to this step's generated directory.148/// subdirectory relative to this step's generated directory.
149///
150/// The returned value is a lazy path to the generated subdirectory.150/// The returned value is a lazy path to the generated subdirectory.
151pub fn addCopyDirectory(151pub fn addCopyDirectory(
152 write_file: *WriteFile,152 write_file: *WriteFile,
test/src/Cases.zig+18-10
...@@ -470,8 +470,9 @@ pub fn lowerToBuildSteps(...@@ -470,8 +470,9 @@ pub fn lowerToBuildSteps(
470 options: CaseTestOptions,470 options: CaseTestOptions,
471) void {471) void {
472 const io = self.io;472 const io = self.io;
473 const graph = b.graph;
474 const arena = graph.arena;
473 const host = b.resolveTargetQuery(.{});475 const host = b.resolveTargetQuery(.{});
474 const cases_dir_path = b.build_root.join(b.allocator, &.{ "test", "cases" }) catch @panic("OOM");
475476
476 for (self.cases.items) |case| {477 for (self.cases.items) |case| {
477 for (options.test_filters) |test_filter| {478 for (options.test_filters) |test_filter| {
...@@ -504,7 +505,7 @@ pub fn lowerToBuildSteps(...@@ -504,7 +505,7 @@ pub fn lowerToBuildSteps(
504 );505 );
505 if (options.skip_llvm and would_use_llvm) continue;506 if (options.skip_llvm and would_use_llvm) continue;
506507
507 const triple_txt = case.target.query.zigTriple(b.allocator) catch @panic("OOM");508 const triple_txt = case.target.query.zigTriple(arena) catch @panic("OOM");
508509
509 if (options.test_target_filters.len > 0) {510 if (options.test_target_filters.len > 0) {
510 for (options.test_target_filters) |filter| {511 for (options.test_target_filters) |filter| {
...@@ -516,7 +517,7 @@ pub fn lowerToBuildSteps(...@@ -516,7 +517,7 @@ pub fn lowerToBuildSteps(
516 continue;517 continue;
517518
518 const writefiles = b.addWriteFiles();519 const writefiles = b.addWriteFiles();
519 var file_sources = std.StringHashMap(std.Build.LazyPath).init(b.allocator);520 var file_sources = std.StringHashMap(std.Build.LazyPath).init(arena);
520 defer file_sources.deinit();521 defer file_sources.deinit();
521 const first_file = case.files.items[0];522 const first_file = case.files.items[0];
522 const root_source_file = writefiles.add(first_file.path, first_file.src);523 const root_source_file = writefiles.add(first_file.path, first_file.src);
...@@ -526,12 +527,15 @@ pub fn lowerToBuildSteps(...@@ -526,12 +527,15 @@ pub fn lowerToBuildSteps(
526 }527 }
527528
528 for (case.imports) |import_rel| {529 for (case.imports) |import_rel| {
529 const import_abs = std.fs.path.join(b.allocator, &.{530 _ = writefiles.addCopyFile(.{ .src_path = .{
530 cases_dir_path,531 .owner = b,
531 case.import_path orelse @panic("import_path not set"),532 .sub_path = b.pathJoin(&.{
532 import_rel,533 "test",
533 }) catch @panic("OOM");534 "cases",
534 _ = writefiles.addCopyFile(.{ .cwd_relative = import_abs }, import_rel);535 case.import_path orelse @panic("import_path not set"),
536 import_rel,
537 }),
538 } }, import_rel);
535 }539 }
536540
537 const mod = b.createModule(.{541 const mod = b.createModule(.{
...@@ -605,7 +609,11 @@ pub fn lowerToBuildSteps(...@@ -605,7 +609,11 @@ pub fn lowerToBuildSteps(
605 },609 },
606 .Execution => |expected_stdout| no_exec: {610 .Execution => |expected_stdout| no_exec: {
607 const run = if (case.target.result.ofmt == .c) run_step: {611 const run = if (case.target.result.ofmt == .c) run_step: {
608 if (getExternalExecutor(io, &host.result, &case.target.result, .{ .link_libc = true }) != .native) {612 if (getExternalExecutor(io, &case.target.result, .{
613 .host_cpu_arch = host.result.cpu.arch,
614 .host_os_tag = host.result.os.tag,
615 .link_libc = true,
616 }) != .native) {
609 // We wouldn't be able to run the compiled C code.617 // We wouldn't be able to run the compiled C code.
610 break :no_exec;618 break :no_exec;
611 }619 }
test/src/Libc.zig+3-1
...@@ -31,7 +31,9 @@ pub fn addLibcTestCase(...@@ -31,7 +31,9 @@ pub fn addLibcTestCase(
31 supports_wasi_libc: bool,31 supports_wasi_libc: bool,
32 options: LibcTestCaseOption,32 options: LibcTestCaseOption,
33) void {33) void {
34 const name = libc.b.dupe(path[0 .. path.len - std.fs.path.extension(path).len]);34 const graph = libc.b.graph;
35 const arena = graph.arena;
36 const name = arena.dupe(u8, path[0 .. path.len - std.fs.path.extension(path).len]) catch @panic("OOM");
35 std.mem.replaceScalar(u8, name, '/', '.');37 std.mem.replaceScalar(u8, name, '/', '.');
36 libc.test_cases.append(libc.b.allocator, .{38 libc.test_cases.append(libc.b.allocator, .{
37 .name = name,39 .name = name,
test/standalone/dependency_options/build.zig+1-1
...@@ -10,7 +10,7 @@ pub fn build(b: *std.Build) !void {...@@ -10,7 +10,7 @@ pub fn build(b: *std.Build) !void {
1010
11 const none_specified_mod = none_specified.module("dummy");11 const none_specified_mod = none_specified.module("dummy");
12 if (!none_specified_mod.resolved_target.?.query.eql(b.graph.host.query)) return error.TestFailed;12 if (!none_specified_mod.resolved_target.?.query.eql(b.graph.host.query)) return error.TestFailed;
13 const expected_optimize: std.builtin.OptimizeMode = switch (b.release_mode) {13 const expected_optimize: std.builtin.OptimizeMode = switch (b.graph.release_mode) {
14 .off => .Debug,14 .off => .Debug,
15 .any => unreachable,15 .any => unreachable,
16 .fast => .ReleaseFast,16 .fast => .ReleaseFast,
test/standalone/dirname/build.zig-19
...@@ -27,15 +27,6 @@ pub fn build(b: *std.Build) void {...@@ -27,15 +27,6 @@ pub fn build(b: *std.Build) void {
27 }),27 }),
28 });28 });
2929
30 const has_basename = b.addExecutable(.{
31 .name = "has_basename",
32 .root_module = b.createModule(.{
33 .root_source_file = b.path("has_basename.zig"),
34 .optimize = .Debug,
35 .target = target,
36 }),
37 });
38
39 // Known path:30 // Known path:
40 addTestRun(test_step, exists_in, touch_src.dirname(), &.{"touch.zig"});31 addTestRun(test_step, exists_in, touch_src.dirname(), &.{"touch.zig"});
4132
...@@ -47,16 +38,6 @@ pub fn build(b: *std.Build) void {...@@ -47,16 +38,6 @@ pub fn build(b: *std.Build) void {
47 "subdir" ++ std.fs.path.sep_str ++ "generated.txt",38 "subdir" ++ std.fs.path.sep_str ++ "generated.txt",
48 });39 });
4940
50 // Cache root:
51 const cache_dir = b.cache_root.path orelse
52 (b.cache_root.join(b.allocator, &.{"."}) catch @panic("OOM"));
53 addTestRun(
54 test_step,
55 has_basename,
56 generated.dirname().dirname().dirname().dirname(),
57 &.{std.fs.path.basename(cache_dir)},
58 );
59
60 // Absolute path:41 // Absolute path:
61 const write_files = b.addWriteFiles();42 const write_files = b.addWriteFiles();
62 _ = write_files.add("foo.txt", "");43 _ = write_files.add("foo.txt", "");
test/standalone/install_headers/build.zig+1-1
...@@ -106,7 +106,7 @@ pub fn build(b: *std.Build) void {...@@ -106,7 +106,7 @@ pub fn build(b: *std.Build) void {
106 "custom/include/foo/config.h",106 "custom/include/foo/config.h",
107 "custom/include/bar.h",107 "custom/include/bar.h",
108 });108 });
109 run_check_exists.setCwd(.{ .cwd_relative = b.getInstallPath(.prefix, "") });109 run_check_exists.setCwd(.{ .relative = .{ .base = .install_prefix } });
110 run_check_exists.expectExitCode(0);110 run_check_exists.expectExitCode(0);
111 run_check_exists.step.dependOn(&install_libfoo.step);111 run_check_exists.step.dependOn(&install_libfoo.step);
112 test_step.dependOn(&run_check_exists.step);112 test_step.dependOn(&run_check_exists.step);