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 {...@@ -187,9 +187,10 @@ pub fn main(init: process.Init.Minimal) !void {
187 .random_seed = parseRandomSeed(seed_arg),187 .random_seed = parseRandomSeed(seed_arg),
188 };188 };
189189
190 const cmd = stringToEnum(enum { init, fetch, build }, cmd_name) orelse190 const cmd = stringToEnum(enum { libc, init, fetch, build }, cmd_name) orelse
191 fatal("bad command name: {q}", .{cmd_name});191 fatal("bad command name: {q}", .{cmd_name});
192 switch (cmd) {192 switch (cmd) {
193 .libc => return cmdLibC(gpa, &graph, args[arg_i..]),
193 .init => return cmdInit(gpa, &graph, args[arg_i..]),194 .init => return cmdInit(gpa, &graph, args[arg_i..]),
194 .fetch => return cmdFetch(gpa, &graph, args[arg_i..]),195 .fetch => return cmdFetch(gpa, &graph, args[arg_i..]),
195 .build => {},196 .build => {},
...@@ -1746,6 +1747,25 @@ const usage_init =...@@ -1746,6 +1747,25 @@ const usage_init =
1746 \\1747 \\
1747;1748;
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
1749fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {1769fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
1750 const arena = graph.arena;1770 const arena = graph.arena;
1751 const io = graph.io;1771 const io = graph.io;
...@@ -1851,6 +1871,112 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {...@@ -1851,6 +1871,112 @@ fn cmdInit(gpa: Allocator, graph: *Graph, args: []const []const u8) !void {
1851 }1871 }
1852}1872}
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
1854fn markFailedStepsDirty(maker: *Maker) void {1980fn markFailedStepsDirty(maker: *Maker) void {
1855 const all_steps = maker.step_stack.keys();1981 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(...@@ -639,7 +639,7 @@ fn getIncludePaths(
639 };639 };
640 const target = std.zig.resolveTargetQueryOrFatal(io, target_query);640 const target = std.zig.resolveTargetQueryOrFatal(io, target_query);
641 const is_native_abi = target_query.isNativeAbi();641 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 {
643 if (includes == .any) {643 if (includes == .any) {
644 // fall back to mingw644 // fall back to mingw
645 includes = .gnu;645 includes = .gnu;
...@@ -668,7 +668,7 @@ fn getIncludePaths(...@@ -668,7 +668,7 @@ fn getIncludePaths(
668 const detected_libc = std.zig.LibCDirs.detect(668 const detected_libc = std.zig.LibCDirs.detect(
669 arena,669 arena,
670 io,670 io,
671 zig_lib_dir,671 .{ .root_dir = .cwd, .sub_path = zig_lib_dir },
672 &target,672 &target,
673 is_native_abi,673 is_native_abi,
674 true,674 true,
lib/std/zig/LibCDirs.zig+16-31
...@@ -5,6 +5,7 @@ const std = @import("../std.zig");...@@ -5,6 +5,7 @@ const std = @import("../std.zig");
5const Io = std.Io;5const Io = std.Io;
6const LibCInstallation = std.zig.LibCInstallation;6const LibCInstallation = std.zig.LibCInstallation;
7const Allocator = std.mem.Allocator;7const Allocator = std.mem.Allocator;
8const Path = std.Build.Cache.Path;
89
9libc_include_dir_list: []const []const u8,10libc_include_dir_list: []const []const u8,
10libc_installation: ?*const LibCInstallation,11libc_installation: ?*const LibCInstallation,
...@@ -23,7 +24,7 @@ pub const DarwinSdkLayout = enum {...@@ -23,7 +24,7 @@ pub const DarwinSdkLayout = enum {
23pub fn detect(24pub fn detect(
24 arena: Allocator,25 arena: Allocator,
25 io: Io,26 io: Io,
26 zig_lib_dir: []const u8,27 zig_lib_dir: Path,
27 target: *const std.Target,28 target: *const std.Target,
28 is_native_abi: bool,29 is_native_abi: bool,
29 link_libc: bool,30 link_libc: bool,
...@@ -166,20 +167,12 @@ fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *con...@@ -166,20 +167,12 @@ fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *con
166 };167 };
167}168}
168169
169pub fn detectFromBuilding(170pub fn detectFromBuilding(arena: Allocator, zig_lib_dir: Path, target: *const std.Target) !LibCDirs {
170 arena: Allocator,
171 zig_lib_dir: []const u8,
172 target: *const std.Target,
173) !LibCDirs {
174 const s = std.fs.path.sep_str;171 const s = std.fs.path.sep_str;
175172
176 if (target.os.tag.isDarwin()) {173 if (target.os.tag.isDarwin()) {
177 const list = try arena.alloc([]const u8, 1);174 const list = try arena.alloc([]const u8, 1);
178 list[0] = try std.fmt.allocPrint(175 list[0] = try arena.print("{f}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-darwin-any", .{zig_lib_dir});
179 arena,
180 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-darwin-any",
181 .{zig_lib_dir},
182 );
183 return .{176 return .{
184 .libc_include_dir_list = list,177 .libc_include_dir_list = list,
185 .libc_installation = null,178 .libc_installation = null,
...@@ -212,27 +205,19 @@ pub fn detectFromBuilding(...@@ -212,27 +205,19 @@ pub fn detectFromBuilding(
212 std.zig.target.netbsdAbiNameHeaders(target.abi)205 std.zig.target.netbsdAbiNameHeaders(target.abi)
213 else206 else
214 @tagName(target.abi);207 @tagName(target.abi);
215 const arch_include_dir = try std.fmt.allocPrint(208 const arch_include_dir = try arena.print("{f}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}", .{
216 arena,209 zig_lib_dir, arch_name, os_name, abi_name,
217 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}",210 });
218 .{ zig_lib_dir, arch_name, os_name, abi_name },211 const generic_include_dir = try arena.print("{f}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}", .{
219 );212 zig_lib_dir, generic_name,
220 const generic_include_dir = try std.fmt.allocPrint(213 });
221 arena,
222 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}",
223 .{ zig_lib_dir, generic_name },
224 );
225 const generic_arch_name = std.zig.target.osArchName(target);214 const generic_arch_name = std.zig.target.osArchName(target);
226 const arch_os_include_dir = try std.fmt.allocPrint(215 const arch_os_include_dir = try arena.print("{f}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any", .{
227 arena,216 zig_lib_dir, generic_arch_name, os_name,
228 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any",217 });
229 .{ zig_lib_dir, generic_arch_name, os_name },218 const generic_os_include_dir = try arena.print("{f}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any", .{
230 );219 zig_lib_dir, os_name,
231 const generic_os_include_dir = try std.fmt.allocPrint(220 });
232 arena,
233 "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
234 .{ zig_lib_dir, os_name },
235 );
236221
237 const list = try arena.alloc([]const u8, 4);222 const list = try arena.alloc([]const u8, 4);
238 list[0] = arch_include_dir;223 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,...@@ -1729,7 +1729,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
1729 const libc_dirs = std.zig.LibCDirs.detect(1729 const libc_dirs = std.zig.LibCDirs.detect(
1730 arena,1730 arena,
1731 io,1731 io,
1732 options.dirs.zig_lib.path.?,1732 .{ .root_dir = options.dirs.zig_lib },
1733 target,1733 target,
1734 options.root_mod.resolved_target.is_native_abi,1734 options.root_mod.resolved_target.is_native_abi,
1735 link_libc,1735 link_libc,
src/main.zig+1-8
...@@ -352,7 +352,7 @@ fn mainArgs(...@@ -352,7 +352,7 @@ fn mainArgs(
352 dev.check(.ar_command);352 dev.check(.ar_command);
353 return process.exit(try llvmArMain(arena, args));353 return process.exit(try llvmArMain(arena, args));
354 },354 },
355 .build, .fetch, .init => {355 .build, .fetch, .init, .libc => {
356 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{356 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
357 .cmd_name = "maker",357 .cmd_name = "maker",
358 .root_src_path = "Maker.zig",358 .root_src_path = "Maker.zig",
...@@ -409,13 +409,6 @@ fn mainArgs(...@@ -409,13 +409,6 @@ fn mainArgs(
409 .root_src_path = "objdump.zig",409 .root_src_path = "objdump.zig",
410 });410 });
411 },411 },
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 },
419 .std => {412 .std => {
420 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{413 return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
421 .cmd_name = "std",414 .cmd_name = "std",