authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-20 13:51:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:36-07:00
log91a7ea4ff41fd21e7465ddfe68bace533ab8c77d
tree82b0b6d903cb5c7523ece42694fa846538dc5ce6
parent88e066bb7b69d065758fa05442de6e317625df68

Maker: implement TranslateC


3 files changed, 124 insertions(+), 94 deletions(-)

lib/compiler/Maker/Step.zig+2-1
......@@ -26,6 +26,7 @@ pub const InstallFile = @import("Step/InstallFile.zig");
2626pub const ObjCopy = @import("Step/ObjCopy.zig");
2727pub const Options = @import("Step/Options.zig");
2828pub const Run = @import("Step/Run.zig");
29pub const TranslateC = @import("Step/TranslateC.zig");
2930pub const UpdateSourceFiles = @import("Step/UpdateSourceFiles.zig");
3031pub const WriteFile = @import("Step/WriteFile.zig");
3132
......@@ -86,7 +87,7 @@ pub const Extended = union(enum) {
8687 options: Options,
8788 run: Run,
8889 top_level: TopLevel,
89 translate_c: Todo,
90 translate_c: TranslateC,
9091 update_source_files: UpdateSourceFiles,
9192 write_file: WriteFile,
9293
lib/compiler/Maker/Step/Compile.zig+13-15
......@@ -291,18 +291,19 @@ fn lowerZigArgs(
291291 system_lib.flags.preferred_link_mode != prev_preferred_link_mode) and
292292 conf_comp.flags2.linkage != .static)
293293 {
294 try zig_args.ensureUnusedCapacity(gpa, 1);
294295 switch (system_lib.flags.search_strategy) {
295296 .no_fallback => switch (system_lib.flags.preferred_link_mode) {
296 .dynamic => try zig_args.append(gpa, "-search_dylibs_only"),
297 .static => try zig_args.append(gpa, "-search_static_only"),
297 .dynamic => zig_args.appendAssumeCapacity("-search_dylibs_only"),
298 .static => zig_args.appendAssumeCapacity("-search_static_only"),
298299 },
299300 .paths_first => switch (system_lib.flags.preferred_link_mode) {
300 .dynamic => try zig_args.append(gpa, "-search_paths_first"),
301 .static => try zig_args.append(gpa, "-search_paths_first_static"),
301 .dynamic => zig_args.appendAssumeCapacity("-search_paths_first"),
302 .static => zig_args.appendAssumeCapacity("-search_paths_first_static"),
302303 },
303304 .mode_first => switch (system_lib.flags.preferred_link_mode) {
304 .dynamic => try zig_args.append(gpa, "-search_dylibs_first"),
305 .static => try zig_args.append(gpa, "-search_static_first"),
305 .dynamic => zig_args.appendAssumeCapacity("-search_dylibs_first"),
306 .static => zig_args.appendAssumeCapacity("-search_static_first"),
306307 },
307308 }
308309 prev_search_strategy = system_lib.flags.search_strategy;
......@@ -1317,6 +1318,7 @@ fn appendModuleFlags(
13171318 try zig_args.append(gpa, try allocPrint(arena, "--export={s}", .{symbol_name.slice(conf)}));
13181319 }
13191320
1321 try zig_args.ensureUnusedCapacity(gpa, 2 * m.include_dirs.len);
13201322 for (0..m.include_dirs.len) |i|
13211323 try appendIncludeDirFlags(m.include_dirs.get(conf.extra, i), zig_args, asking_step, maker);
13221324
......@@ -1343,17 +1345,16 @@ fn appendModuleFlags(
13431345 };
13441346}
13451347
1346fn appendIncludeDirFlags(
1348/// Assumes unused capacity for at least 2 items.
1349pub fn appendIncludeDirFlags(
13471350 include_dir: Configuration.Module.IncludeDir,
13481351 zig_args: *std.ArrayList([]const u8),
13491352 asking_step: Configuration.Step.Index,
13501353 maker: *const Maker,
13511354) !void {
1352 const gpa = maker.gpa;
13531355 const graph = maker.graph;
13541356 const arena = graph.arena; // TODO don't leak into the process arena
13551357
1356 try zig_args.ensureUnusedCapacity(gpa, 2);
13571358 switch (include_dir) {
13581359 .path => |lp| {
13591360 zig_args.appendAssumeCapacity("-I");
......@@ -1386,12 +1387,9 @@ fn appendIncludeDirFlags(
13861387 comp.installed_headers_include_tree.?.getDirectory();
13871388 },
13881389 .embed_path => |lazy_path| {
1389 try zig_args.append(
1390 gpa,
1391 try allocPrint(arena, "--embed-dir={f}", .{
1392 try maker.resolveLazyPathIndex(arena, lazy_path, asking_step),
1393 }),
1394 );
1390 zig_args.appendAssumeCapacity(try allocPrint(arena, "--embed-dir={f}", .{
1391 try maker.resolveLazyPathIndex(arena, lazy_path, asking_step),
1392 }));
13951393 },
13961394 }
13971395}
lib/compiler/Maker/Step/TranslateC.zig+109-78
......@@ -1,121 +1,152 @@
1fn make(step: *Step, options: Step.MakeOptions) !void {
2 const prog_node = options.progress_node;
3 const b = step.owner;
4 const translate_c: *TranslateC = @fieldParentPtr("step", step);
5 const arena = b.graph.arena;
6
7 var argv_list = std.array_list.Managed([]const u8).init(b.allocator);
8 try argv_list.append(b.graph.zig_exe);
9 try argv_list.append("translate-c");
10 if (translate_c.link_libc) {
11 try argv_list.append("-lc");
12 }
1const TranslateC = @This();
2
3const std = @import("std");
4const Io = std.Io;
5const Configuration = std.Build.Configuration;
6const allocPrint = std.fmt.allocPrint;
7const assert = std.debug.assert;
8
9const Step = @import("../Step.zig");
10const Maker = @import("../../Maker.zig");
11const PkgConfig = @import("../PkgConfig.zig");
1312
14 try argv_list.append("--cache-dir");
15 try argv_list.append(b.cache_root.path orelse ".");
13pub fn make(
14 translate_c: *TranslateC,
15 step_index: Configuration.Step.Index,
16 maker: *Maker,
17 progress_node: std.Progress.Node,
18) Step.ExtendedMakeError!void {
19 _ = translate_c;
20 const graph = maker.graph;
21 const arena = graph.arena; // TODO don't leak into the process arena
22 const step = maker.stepByIndex(step_index);
23 const conf = &maker.scanned_config.configuration;
24 const conf_step = step_index.ptr(conf);
25 const conf_tc = conf_step.extended.get(conf.extra).translate_c;
26 const cache_root = graph.local_cache_root;
1627
17 try argv_list.append("--global-cache-dir");
18 try argv_list.append(b.graph.global_cache_root.path orelse ".");
28 var argv: std.ArrayList([]const u8) = .empty;
1929
20 if (!translate_c.target.query.isNative()) {
21 try argv_list.append("-target");
22 try argv_list.append(try translate_c.target.query.zigTriple(b.allocator));
30 try argv.ensureUnusedCapacity(arena, 10);
31 argv.appendAssumeCapacity(graph.zig_exe);
32 argv.appendAssumeCapacity("translate-c");
33 if (conf_tc.flags.link_libc) {
34 argv.appendAssumeCapacity("-lc");
2335 }
2436
25 switch (translate_c.optimize) {
26 .Debug => {}, // Skip since it's the default.
27 else => try argv_list.append(b.fmt("-O{s}", .{@tagName(translate_c.optimize)})),
37 argv.appendAssumeCapacity("--cache-dir");
38 argv.appendAssumeCapacity(cache_root.path orelse ".");
39
40 argv.appendAssumeCapacity("--global-cache-dir");
41 argv.appendAssumeCapacity(graph.global_cache_root.path orelse ".");
42
43 if (conf_tc.target.get(conf).?.query.unwrap()) |compact_query| {
44 const query = compact_query.get(conf).unwrap(conf);
45 argv.appendAssumeCapacity("-target");
46 argv.appendAssumeCapacity(try query.zigTriple(arena));
2847 }
2948
30 for (translate_c.include_dirs.items) |include_dir| {
31 try include_dir.appendZigProcessFlags(b, &argv_list, step);
49 switch (conf_tc.flags.optimize) {
50 .debug, .default => {}, // Skip since it's the default.
51 else => argv.appendAssumeCapacity(try allocPrint(arena, "-O{t}", .{conf_tc.flags.optimize})),
3252 }
3353
34 for (translate_c.c_macros.items) |c_macro| {
35 try argv_list.append("-D");
36 try argv_list.append(c_macro);
54 try argv.ensureUnusedCapacity(arena, conf_tc.include_dirs.len * 2);
55 for (0..conf_tc.include_dirs.len) |i|
56 try Step.Compile.appendIncludeDirFlags(conf_tc.include_dirs.get(conf.extra, i), &argv, step_index, maker);
57
58 for (conf_tc.c_macros.slice) |c_macro| {
59 (try argv.addManyAsArray(arena, 2)).* = .{ "-D", c_macro.slice(conf) };
3760 }
3861
3962 var prev_search_strategy: std.Build.Module.SystemLib.SearchStrategy = .paths_first;
4063 var prev_preferred_link_mode: std.builtin.LinkMode = .dynamic;
64 var seen_system_libs: std.AutoArrayHashMapUnmanaged(Configuration.String, []const []const u8) = .empty;
4165
42 for (translate_c.system_libs.items) |*system_lib| {
43 var seen_system_libs: std.StringHashMapUnmanaged([]const []const u8) = .empty;
66 for (conf_tc.system_libs.slice) |system_lib_index| {
67 const system_lib = system_lib_index.get(conf);
68 const system_lib_name = system_lib.name.slice(conf);
4469 const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);
4570 if (system_lib_gop.found_existing) {
46 try argv_list.appendSlice(system_lib_gop.value_ptr.*);
71 try argv.appendSlice(arena, system_lib_gop.value_ptr.*);
4772 continue;
4873 } else {
4974 system_lib_gop.value_ptr.* = &.{};
5075 }
5176
52 if (system_lib.search_strategy != prev_search_strategy or
53 system_lib.preferred_link_mode != prev_preferred_link_mode)
77 if ((system_lib.flags.search_strategy != prev_search_strategy or
78 system_lib.flags.preferred_link_mode != prev_preferred_link_mode))
5479 {
55 switch (system_lib.search_strategy) {
56 .no_fallback => switch (system_lib.preferred_link_mode) {
57 .dynamic => try argv_list.append("-search_dylibs_only"),
58 .static => try argv_list.append("-search_static_only"),
80 try argv.ensureUnusedCapacity(arena, 1);
81 switch (system_lib.flags.search_strategy) {
82 .no_fallback => switch (system_lib.flags.preferred_link_mode) {
83 .dynamic => argv.appendAssumeCapacity("-search_dylibs_only"),
84 .static => argv.appendAssumeCapacity("-search_static_only"),
5985 },
60 .paths_first => switch (system_lib.preferred_link_mode) {
61 .dynamic => try argv_list.append("-search_paths_first"),
62 .static => try argv_list.append("-search_paths_first_static"),
86 .paths_first => switch (system_lib.flags.preferred_link_mode) {
87 .dynamic => argv.appendAssumeCapacity("-search_paths_first"),
88 .static => argv.appendAssumeCapacity("-search_paths_first_static"),
6389 },
64 .mode_first => switch (system_lib.preferred_link_mode) {
65 .dynamic => try argv_list.append("-search_dylibs_first"),
66 .static => try argv_list.append("-search_static_first"),
90 .mode_first => switch (system_lib.flags.preferred_link_mode) {
91 .dynamic => argv.appendAssumeCapacity("-search_dylibs_first"),
92 .static => argv.appendAssumeCapacity("-search_static_first"),
6793 },
6894 }
69 prev_search_strategy = system_lib.search_strategy;
70 prev_preferred_link_mode = system_lib.preferred_link_mode;
95 prev_search_strategy = system_lib.flags.search_strategy;
96 prev_preferred_link_mode = system_lib.flags.preferred_link_mode;
7197 }
7298
7399 const prefix: []const u8 = prefix: {
74 if (system_lib.needed) break :prefix "-needed-l";
75 if (system_lib.weak) break :prefix "-weak-l";
100 if (system_lib.flags.needed) break :prefix "-needed-l";
101 if (system_lib.flags.weak) break :prefix "-weak-l";
76102 break :prefix "-l";
77103 };
78 switch (system_lib.use_pkg_config) {
79 .no => try argv_list.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })),
80 .yes, .force => {
81 if (Step.Compile.runPkgConfig(&translate_c.step, system_lib.name)) |result| {
82 try argv_list.appendSlice(result.cflags);
83 try argv_list.appendSlice(result.libs);
104 l: {
105 pc: {
106 const force = switch (system_lib.flags.use_pkg_config) {
107 .no => break :pc,
108 .yes => false,
109 .force => true,
110 };
111
112 const pkg_conf_node = progress_node.start("pkg-config", 0);
113 defer pkg_conf_node.end();
114
115 if (PkgConfig.run(maker, step, pkg_conf_node, system_lib_name, force)) |result| {
116 try argv.appendSlice(arena, result.cflags);
117 try argv.appendSlice(arena, result.libs);
84118 try seen_system_libs.put(arena, system_lib.name, result.cflags);
119 break :l;
85120 } else |err| switch (err) {
86 error.PkgConfigInvalidOutput,
87 error.PkgConfigCrashed,
88 error.PkgConfigFailed,
89 error.PkgConfigNotInstalled,
121 error.PkgConfigUnavailable,
90122 error.PackageNotFound,
91 => switch (system_lib.use_pkg_config) {
92 .yes => {
93 // pkg-config failed, so fall back to linking the library
94 // by name directly.
95 try argv_list.append(b.fmt("{s}{s}", .{
96 prefix,
97 system_lib.name,
98 }));
99 },
100 .force => {
101 std.debug.panic("pkg-config failed for library {s}", .{system_lib.name});
102 },
103 .no => unreachable,
123 => {
124 // pkg-config failed, so fall back to linking the library by name directly.
125 assert(!force);
126 break :pc;
104127 },
105
106128 else => |e| return e,
107129 }
108 },
130 }
131 try argv.append(arena, try allocPrint(arena, "{s}{s}", .{
132 prefix, system_lib_name,
133 }));
109134 }
110135 }
111136
112 const c_source_path = translate_c.source.getPath2(b, step);
113 try argv_list.append(c_source_path);
137 try argv.ensureUnusedCapacity(arena, 2);
138
139 const c_source_path = try maker.resolveLazyPathIndexAbs(arena, conf_tc.src_path, step_index);
140 argv.appendAssumeCapacity(c_source_path);
141
142 argv.appendAssumeCapacity("--listen=-");
143 const output_dir_path = (Step.evalZigProcess(step_index, maker, argv.items, progress_node, false) catch |err| switch (err) {
144 error.NeedCompileErrorCheck => unreachable,
145 else => |e| return e,
146 }).?;
114147
115 try argv_list.append("--listen=-");
116 const output_dir = try step.evalZigProcess(argv_list.items, prog_node, false, options.web_server, options.gpa);
148 const stem = Io.Dir.path.stem(Io.Dir.path.basename(c_source_path));
149 const out_basename = try allocPrint(arena, "{s}.zig", .{stem});
117150
118 const basename = std.fs.path.stem(std.fs.path.basename(c_source_path));
119 translate_c.out_basename = b.fmt("{s}.zig", .{basename});
120 translate_c.output_file.path = output_dir.?.joinString(b.allocator, translate_c.out_basename) catch @panic("OOM");
151 maker.generatedPath(conf_tc.output_file).* = try output_dir_path.join(arena, out_basename);
121152}