authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-06-24 21:27:04-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-06-29 23:50:20-07:00
log10bd6cad759fa37d2b6c127ad97635f83261c4ac
treeee2d57541b323fa95b74e5a45fe3029efe082fda
parent39342e6ce73467474388ad53fc1f897862b53064

implement zig libc inside maker process

The jitcmd mechanism is handy but let's not go overboard. There is overhead when users have to wait for each subcommand independently. We can save time by combining some stuff together.

6 files changed, 147 insertions(+), 183 deletions(-)

lib/compiler/Maker.zig+127-1
......@@ -187,9 +187,10 @@ pub fn main(init: process.Init.Minimal) !void {
187187 .random_seed = parseRandomSeed(seed_arg),
188188 };
189189
190 const cmd = stringToEnum(enum { init, fetch, build }, cmd_name) orelse
190 const cmd = stringToEnum(enum { libc, init, fetch, build }, cmd_name) orelse
191191 fatal("bad command name: {q}", .{cmd_name});
192192 switch (cmd) {
193 .libc => return cmdLibC(gpa, &graph, args[arg_i..]),
193194 .init => return cmdInit(gpa, &graph, args[arg_i..]),
194195 .fetch => return cmdFetch(gpa, &graph, args[arg_i..]),
195196 .build => {},
......@@ -1746,6 +1747,25 @@ const usage_init =
17461747 \\
17471748;
17481749
1750const usage_libc =
1751 \\Usage: zig libc
1752 \\
1753 \\ Detect the native libc installation and print the resulting
1754 \\ paths to stdout. You can save this into a file and then edit
1755 \\ the paths to create a cross compilation libc kit. Then you
1756 \\ can pass `--libc [file]` for Zig to use it.
1757 \\
1758 \\Usage: zig libc [paths_file]
1759 \\
1760 \\ Parse a libc installation text file and validate it.
1761 \\
1762 \\Options:
1763 \\ -h, --help Print this help and exit
1764 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
1765 \\ -includes Print the libc include directories for the target
1766 \\
1767;
1768
17491769fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
17501770 const arena = graph.arena;
17511771 const io = graph.io;
......@@ -1851,6 +1871,112 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
18511871 }
18521872}
18531873
1874fn cmdLibC(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
1875 const environ_map = &graph.environ_map;
1876 const io = graph.io;
1877 const arena = graph.arena;
1878 const LibCInstallation = std.zig.LibCInstallation;
1879
1880 var input_file: ?[]const u8 = null;
1881 var target_arch_os_abi: []const u8 = "native";
1882 var print_includes: bool = false;
1883 const stdout = initStdoutWriter(io);
1884 {
1885 var i: usize = 0;
1886 while (i < args.len) : (i += 1) {
1887 const arg = args[i];
1888 if (mem.startsWith(u8, arg, "-")) {
1889 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
1890 try stdout.writeAll(usage_libc);
1891 try stdout.flush();
1892 return std.process.cleanExit(io);
1893 } else if (mem.eql(u8, arg, "-target")) {
1894 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
1895 i += 1;
1896 target_arch_os_abi = args[i];
1897 } else if (mem.eql(u8, arg, "-includes")) {
1898 print_includes = true;
1899 } else {
1900 fatal("unrecognized parameter: '{s}'", .{arg});
1901 }
1902 } else if (input_file != null) {
1903 fatal("unexpected extra parameter: '{s}'", .{arg});
1904 } else {
1905 input_file = arg;
1906 }
1907 }
1908 }
1909
1910 const target_query = std.zig.parseTargetQueryOrReportFatalError(gpa, .{
1911 .arch_os_abi = target_arch_os_abi,
1912 });
1913 const target = std.zig.resolveTargetQueryOrFatal(io, target_query);
1914
1915 if (print_includes) {
1916 const libc_installation: ?*LibCInstallation = libc: {
1917 if (input_file) |libc_file| {
1918 const libc = try arena.create(LibCInstallation);
1919 libc.* = LibCInstallation.parse(arena, io, libc_file, &target) catch |err| {
1920 fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err });
1921 };
1922 break :libc libc;
1923 } else {
1924 break :libc null;
1925 }
1926 };
1927
1928 const is_native_abi = target_query.isNativeAbi();
1929
1930 const libc_dirs = std.zig.LibCDirs.detect(
1931 arena,
1932 io,
1933 .{ .root_dir = graph.zig_lib_directory },
1934 &target,
1935 is_native_abi,
1936 true,
1937 libc_installation,
1938 environ_map,
1939 ) catch |err| {
1940 const zig_target = try target.zigTriple(arena);
1941 fatal("unable to detect libc for target {s}: {t}", .{ zig_target, err });
1942 };
1943
1944 if (libc_dirs.libc_include_dir_list.len == 0) {
1945 const zig_target = try target.zigTriple(arena);
1946 fatal("no include dirs detected for target {s}", .{zig_target});
1947 }
1948
1949 for (libc_dirs.libc_include_dir_list) |include_dir| {
1950 try stdout.writeAll(include_dir);
1951 try stdout.writeByte('\n');
1952 }
1953 try stdout.flush();
1954 return std.process.cleanExit(io);
1955 }
1956
1957 if (input_file) |libc_file| {
1958 var libc = LibCInstallation.parse(gpa, io, libc_file, &target) catch |err| {
1959 fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err });
1960 };
1961 defer libc.deinit(gpa);
1962 } else {
1963 if (!target_query.canDetectLibC()) {
1964 fatal("unable to detect libc for non-native target", .{});
1965 }
1966 var libc = LibCInstallation.findNative(gpa, io, .{
1967 .verbose = true,
1968 .target = &target,
1969 .environ_map = environ_map,
1970 }) catch |err| {
1971 fatal("unable to detect native libc: {t}", .{err});
1972 };
1973 defer libc.deinit(gpa);
1974
1975 try libc.render(stdout);
1976 try stdout.flush();
1977 }
1978}
1979
18541980fn markFailedStepsDirty(maker: *Maker) void {
18551981 const all_steps = maker.step_stack.keys();
18561982
lib/compiler/libc.zig deleted-140
......@@ -1,140 +0,0 @@
1const std = @import("std");
2const Io = std.Io;
3const mem = std.mem;
4const LibCInstallation = std.zig.LibCInstallation;
5
6const usage_libc =
7 \\Usage: zig libc
8 \\
9 \\ Detect the native libc installation and print the resulting
10 \\ paths to stdout. You can save this into a file and then edit
11 \\ the paths to create a cross compilation libc kit. Then you
12 \\ can pass `--libc [file]` for Zig to use it.
13 \\
14 \\Usage: zig libc [paths_file]
15 \\
16 \\ Parse a libc installation text file and validate it.
17 \\
18 \\Options:
19 \\ -h, --help Print this help and exit
20 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
21 \\ -includes Print the libc include directories for the target
22 \\
23;
24
25var stdout_buffer: [4096]u8 = undefined;
26
27pub fn main(init: std.process.Init) !void {
28 const arena = init.arena.allocator();
29 const gpa = init.gpa;
30 const io = init.io;
31 const args = try init.minimal.args.toSlice(arena);
32 const environ_map = init.environ_map;
33
34 const zig_lib_directory = args[1];
35
36 var input_file: ?[]const u8 = null;
37 var target_arch_os_abi: []const u8 = "native";
38 var print_includes: bool = false;
39 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
40 const stdout = &stdout_writer.interface;
41 {
42 var i: usize = 2;
43 while (i < args.len) : (i += 1) {
44 const arg = args[i];
45 if (mem.startsWith(u8, arg, "-")) {
46 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
47 try stdout.writeAll(usage_libc);
48 try stdout.flush();
49 return std.process.cleanExit(io);
50 } else if (mem.eql(u8, arg, "-target")) {
51 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
52 i += 1;
53 target_arch_os_abi = args[i];
54 } else if (mem.eql(u8, arg, "-includes")) {
55 print_includes = true;
56 } else {
57 fatal("unrecognized parameter: '{s}'", .{arg});
58 }
59 } else if (input_file != null) {
60 fatal("unexpected extra parameter: '{s}'", .{arg});
61 } else {
62 input_file = arg;
63 }
64 }
65 }
66
67 const target_query = std.zig.parseTargetQueryOrReportFatalError(gpa, .{
68 .arch_os_abi = target_arch_os_abi,
69 });
70 const target = std.zig.resolveTargetQueryOrFatal(io, target_query);
71
72 if (print_includes) {
73 const libc_installation: ?*LibCInstallation = libc: {
74 if (input_file) |libc_file| {
75 const libc = try arena.create(LibCInstallation);
76 libc.* = LibCInstallation.parse(arena, io, libc_file, &target) catch |err| {
77 fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err });
78 };
79 break :libc libc;
80 } else {
81 break :libc null;
82 }
83 };
84
85 const is_native_abi = target_query.isNativeAbi();
86
87 const libc_dirs = std.zig.LibCDirs.detect(
88 arena,
89 io,
90 zig_lib_directory,
91 &target,
92 is_native_abi,
93 true,
94 libc_installation,
95 environ_map,
96 ) catch |err| {
97 const zig_target = try target.zigTriple(arena);
98 fatal("unable to detect libc for target {s}: {t}", .{ zig_target, err });
99 };
100
101 if (libc_dirs.libc_include_dir_list.len == 0) {
102 const zig_target = try target.zigTriple(arena);
103 fatal("no include dirs detected for target {s}", .{zig_target});
104 }
105
106 for (libc_dirs.libc_include_dir_list) |include_dir| {
107 try stdout.writeAll(include_dir);
108 try stdout.writeByte('\n');
109 }
110 try stdout.flush();
111 return std.process.cleanExit(io);
112 }
113
114 if (input_file) |libc_file| {
115 var libc = LibCInstallation.parse(gpa, io, libc_file, &target) catch |err| {
116 fatal("unable to parse libc file at path {s}: {t}", .{ libc_file, err });
117 };
118 defer libc.deinit(gpa);
119 } else {
120 if (!target_query.canDetectLibC()) {
121 fatal("unable to detect libc for non-native target", .{});
122 }
123 var libc = LibCInstallation.findNative(gpa, io, .{
124 .verbose = true,
125 .target = &target,
126 .environ_map = environ_map,
127 }) catch |err| {
128 fatal("unable to detect native libc: {t}", .{err});
129 };
130 defer libc.deinit(gpa);
131
132 try libc.render(stdout);
133 try stdout.flush();
134 }
135}
136
137fn fatal(comptime format: []const u8, args: anytype) noreturn {
138 std.log.err(format, args);
139 std.process.exit(1);
140}
lib/compiler/resinator/main.zig+2-2
......@@ -639,7 +639,7 @@ fn getIncludePaths(
639639 };
640640 const target = std.zig.resolveTargetQueryOrFatal(io, target_query);
641641 const is_native_abi = target_query.isNativeAbi();
642 const detected_libc = std.zig.LibCDirs.detect(arena, io, zig_lib_dir, &target, is_native_abi, true, null, environ_map) catch {
642 const detected_libc = std.zig.LibCDirs.detect(arena, io, .{ .root_dir = .cwd, .sub_path = zig_lib_dir }, &target, is_native_abi, true, null, environ_map) catch {
643643 if (includes == .any) {
644644 // fall back to mingw
645645 includes = .gnu;
......@@ -668,7 +668,7 @@ fn getIncludePaths(
668668 const detected_libc = std.zig.LibCDirs.detect(
669669 arena,
670670 io,
671 zig_lib_dir,
671 .{ .root_dir = .cwd, .sub_path = zig_lib_dir },
672672 &target,
673673 is_native_abi,
674674 true,
lib/std/zig/LibCDirs.zig+16-31
......@@ -5,6 +5,7 @@ const std = @import("../std.zig");
55const Io = std.Io;
66const LibCInstallation = std.zig.LibCInstallation;
77const Allocator = std.mem.Allocator;
8const Path = std.Build.Cache.Path;
89
910libc_include_dir_list: []const []const u8,
1011libc_installation: ?*const LibCInstallation,
......@@ -23,7 +24,7 @@ pub const DarwinSdkLayout = enum {
2324pub fn detect(
2425 arena: Allocator,
2526 io: Io,
26 zig_lib_dir: []const u8,
27 zig_lib_dir: Path,
2728 target: *const std.Target,
2829 is_native_abi: bool,
2930 link_libc: bool,
......@@ -166,20 +167,12 @@ fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *con
166167 };
167168}
168169
169pub fn detectFromBuilding(
170 arena: Allocator,
171 zig_lib_dir: []const u8,
172 target: *const std.Target,
173) !LibCDirs {
170pub fn detectFromBuilding(arena: Allocator, zig_lib_dir: Path, target: *const std.Target) !LibCDirs {
174171 const s = std.fs.path.sep_str;
175172
176173 if (target.os.tag.isDarwin()) {
177174 const list = try arena.alloc([]const u8, 1);
178 list[0] = try std.fmt.allocPrint(
179 arena,
180 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-darwin-any",
181 .{zig_lib_dir},
182 );
175 list[0] = try arena.print("{f}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-darwin-any", .{zig_lib_dir});
183176 return .{
184177 .libc_include_dir_list = list,
185178 .libc_installation = null,
......@@ -212,27 +205,19 @@ pub fn detectFromBuilding(
212205 std.zig.target.netbsdAbiNameHeaders(target.abi)
213206 else
214207 @tagName(target.abi);
215 const arch_include_dir = try std.fmt.allocPrint(
216 arena,
217 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}",
218 .{ zig_lib_dir, arch_name, os_name, abi_name },
219 );
220 const generic_include_dir = try std.fmt.allocPrint(
221 arena,
222 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}",
223 .{ zig_lib_dir, generic_name },
224 );
208 const arch_include_dir = try arena.print("{f}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}", .{
209 zig_lib_dir, arch_name, os_name, abi_name,
210 });
211 const generic_include_dir = try arena.print("{f}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}", .{
212 zig_lib_dir, generic_name,
213 });
225214 const generic_arch_name = std.zig.target.osArchName(target);
226 const arch_os_include_dir = try std.fmt.allocPrint(
227 arena,
228 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any",
229 .{ zig_lib_dir, generic_arch_name, os_name },
230 );
231 const generic_os_include_dir = try std.fmt.allocPrint(
232 arena,
233 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
234 .{ zig_lib_dir, os_name },
235 );
215 const arch_os_include_dir = try arena.print("{f}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any", .{
216 zig_lib_dir, generic_arch_name, os_name,
217 });
218 const generic_os_include_dir = try arena.print("{f}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any", .{
219 zig_lib_dir, os_name,
220 });
236221
237222 const list = try arena.alloc([]const u8, 4);
238223 list[0] = arch_include_dir;
src/Compilation.zig+1-1
......@@ -1729,7 +1729,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
17291729 const libc_dirs = std.zig.LibCDirs.detect(
17301730 arena,
17311731 io,
1732 options.dirs.zig_lib.path.?,
1732 .{ .root_dir = options.dirs.zig_lib },
17331733 target,
17341734 options.root_mod.resolved_target.is_native_abi,
17351735 link_libc,
src/main.zig+1-8
......@@ -352,7 +352,7 @@ fn mainArgs(
352352 dev.check(.ar_command);
353353 return process.exit(try llvmArMain(arena, args));
354354 },
355 .build, .fetch, .init => {
355 .build, .fetch, .init, .libc => {
356356 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
357357 .cmd_name = "maker",
358358 .root_src_path = "Maker.zig",
......@@ -409,13 +409,6 @@ fn mainArgs(
409409 .root_src_path = "objdump.zig",
410410 });
411411 },
412 .libc => {
413 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
414 .cmd_name = "libc",
415 .root_src_path = "libc.zig",
416 .prepend_zig_lib_dir_path = true,
417 });
418 },
419412 .std => {
420413 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
421414 .cmd_name = "std",