diff --git a/BRANCH_TODO b/BRANCH_TODO index acecc8d1e583a2196780ee842adbc9d81d9ffd5c..ebc00a3d51d24216397354bb245fe6ef76421f0b 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,3 +1,4 @@ +* double check when targets get resolved (should be at configure time) * pass overridden pkg-dir to maker * finish migrating the rest of the build steps * inspect b4ffb402c082605c4b324e88120306fc8fb3cf32 diff and apply changes as needed (merge conflict) @@ -7,6 +8,7 @@ * solve the TODOs added in this branch * get zig tests passing * test a bunch of third party projects / help people migrate + * tetris * get the target from the parent process instead * [handle missing cache hits when chaining two run steps](https://codeberg.org/ziglang/zig/pulls/30762) @@ -80,6 +82,7 @@ closes #31397 * `b.build_root` (Directory) -> `b.root` (Path) * `ConfigHeader.Options`: `include_guard_override` -> `include_guard` +* `LazyPath`: `getDisplayName` -> `format` or `fmt` ### Perf Data Point: `zig build -h` (cached) diff --git a/lib/compiler/Maker/Step/Run.zig b/lib/compiler/Maker/Step/Run.zig index 2bc3ff73c6d9685a976878f2a50d1ab917ab788a..2cc2972bcb9a126d9895fcfdfe792dc033ab6543 100644 --- a/lib/compiler/Maker/Step/Run.zig +++ b/lib/compiler/Maker/Step/Run.zig @@ -184,6 +184,9 @@ pub fn make( man.hash.addListOfBytes(run_args); } }, + .cc_args => { + @panic("TODO Run make cc_args"); + }, } } diff --git a/lib/compiler/configurer.zig b/lib/compiler/configurer.zig index 214dd4cc61b2e1fee76584cc71f83c4a701b6991..a5a35a2d4b83bfc5b317392aa0a88dad9fa4d33a 100644 --- a/lib/compiler/configurer.zig +++ b/lib/compiler/configurer.zig @@ -312,6 +312,8 @@ const Serialize = struct { .producer = true, .generated = false, .dep_file = false, + .target_query = false, + .link_libc = false, }, .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, .suffix = .{ .value = null }, @@ -319,6 +321,7 @@ const Serialize = struct { .path = .{ .value = null }, .producer = .{ .value = stepIndex(s, &a.artifact.step) }, .generated = .{ .value = null }, + .target_query = .{ .value = null }, }, .lazy_path => |a| .{ .flags = .{ @@ -330,6 +333,8 @@ const Serialize = struct { .producer = false, .generated = false, .dep_file = false, + .target_query = false, + .link_libc = false, }, .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, .suffix = .{ .value = null }, @@ -337,6 +342,7 @@ const Serialize = struct { .path = .{ .value = try addLazyPath(s, a.lazy_path) }, .producer = .{ .value = null }, .generated = .{ .value = null }, + .target_query = .{ .value = null }, }, .decorated_directory => |a| .{ .flags = .{ @@ -348,6 +354,8 @@ const Serialize = struct { .producer = false, .generated = false, .dep_file = false, + .target_query = false, + .link_libc = false, }, .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, .suffix = .{ .value = try addOptionalString(s, a.suffix) }, @@ -355,6 +363,7 @@ const Serialize = struct { .path = .{ .value = try addLazyPath(s, a.lazy_path) }, .producer = .{ .value = null }, .generated = .{ .value = null }, + .target_query = .{ .value = null }, }, .file_content => |a| .{ .flags = .{ @@ -366,6 +375,8 @@ const Serialize = struct { .producer = false, .generated = false, .dep_file = false, + .target_query = false, + .link_libc = false, }, .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, .suffix = .{ .value = null }, @@ -373,6 +384,7 @@ const Serialize = struct { .path = .{ .value = try addLazyPath(s, a.lazy_path) }, .producer = .{ .value = null }, .generated = .{ .value = null }, + .target_query = .{ .value = null }, }, .bytes => |a| .{ .flags = .{ @@ -384,6 +396,8 @@ const Serialize = struct { .producer = false, .generated = false, .dep_file = false, + .target_query = false, + .link_libc = false, }, .prefix = .{ .value = try wc.addString(a) }, .suffix = .{ .value = null }, @@ -391,6 +405,7 @@ const Serialize = struct { .path = .{ .value = null }, .producer = .{ .value = null }, .generated = .{ .value = null }, + .target_query = .{ .value = null }, }, .output_file, .output_file_dep => |a, tag| .{ .flags = .{ @@ -402,6 +417,8 @@ const Serialize = struct { .producer = false, .generated = true, .dep_file = tag == .output_file_dep, + .target_query = false, + .link_libc = false, }, .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, .suffix = .{ .value = null }, @@ -409,6 +426,7 @@ const Serialize = struct { .path = .{ .value = null }, .producer = .{ .value = null }, .generated = .{ .value = a.generated_file }, + .target_query = .{ .value = null }, }, .output_directory => |a| .{ .flags = .{ @@ -420,6 +438,8 @@ const Serialize = struct { .producer = false, .generated = true, .dep_file = false, + .target_query = false, + .link_libc = false, }, .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, .suffix = .{ .value = null }, @@ -427,6 +447,7 @@ const Serialize = struct { .path = .{ .value = null }, .producer = .{ .value = null }, .generated = .{ .value = a.generated_file }, + .target_query = .{ .value = null }, }, .passthru => .{ .flags = .{ @@ -438,6 +459,8 @@ const Serialize = struct { .producer = false, .generated = false, .dep_file = false, + .target_query = false, + .link_libc = false, }, .prefix = .{ .value = null }, .suffix = .{ .value = null }, @@ -445,6 +468,28 @@ const Serialize = struct { .path = .{ .value = null }, .producer = .{ .value = null }, .generated = .{ .value = null }, + .target_query = .{ .value = null }, + }, + .cc_args => |a| .{ + .flags = .{ + .tag = .cc_args, + .prefix = false, + .suffix = false, + .basename = false, + .path = false, + .producer = false, + .generated = false, + .dep_file = false, + .target_query = a.target_query != .none, + .link_libc = a.link_libc, + }, + .prefix = .{ .value = null }, + .suffix = .{ .value = null }, + .basename = .{ .value = null }, + .path = .{ .value = null }, + .producer = .{ .value = null }, + .generated = .{ .value = null }, + .target_query = .{ .value = a.target_query.unwrap() }, }, }))); } @@ -1234,7 +1279,7 @@ fn addOptionalResolvedTarget( ) !Configuration.ResolvedTarget.OptionalIndex { const resolved_target = optional_resolved_target orelse return .none; return @enumFromInt(try wc.addDeduped(@as(Configuration.ResolvedTarget, .{ - .query = try wc.addTargetQuery(resolved_target.query), + .query = try wc.addTargetQuery(&resolved_target.query), .result = try wc.addTarget(resolved_target.result), }))); } diff --git a/lib/std/Build.zig b/lib/std/Build.zig index ad87bc246627a68fb3e769d9a8649d2dd3936edc..252d65f6cc3e0126657cec0001886a54a90668ac 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -129,13 +129,17 @@ pub const Graph = struct { /// /// Use of this function indicates a dependency on the host system. pub fn cwdRelativePath(graph: *Graph, sub_path: []const u8) LazyPath { + return @This().path(graph, .cwd, sub_path); + } + + /// A path whose components and contents are known at some point during + /// `Step` resolution, relative to the provided base directory. + pub fn path(graph: *Graph, base: Configuration.Path.Base, sub_path: []const u8) LazyPath { const wc = &graph.wip_configuration; - return .{ - .relative = .{ - .base = .cwd, - .sub_path = wc.addString(sub_path) catch @panic("OOM"), - }, - }; + return .{ .relative = .{ + .base = base, + .sub_path = wc.addString(sub_path) catch @panic("OOM"), + } }; } /// Allocates using the global process arena, failing the build on @@ -780,8 +784,10 @@ pub const AssemblyOptions = struct { /// it available to other packages which depend on this one. /// `createModule` can be used instead to create a private module. pub fn addModule(b: *Build, name: []const u8, options: Module.CreateOptions) *Module { + const graph = b.graph; + const arena = graph.arena; const module = Module.create(b, options); - b.modules.put(b.graph.arena, b.dupe(name), module) catch @panic("OOM"); + b.modules.put(arena, graph.dupeString(name), module) catch @panic("OOM"); return module; } @@ -913,13 +919,15 @@ pub fn addWriteFile(b: *Build, file_path: []const u8, data: []const u8) *Step.Wr } pub fn addNamedWriteFiles(b: *Build, name: []const u8) *Step.WriteFile { + const graph = b.graph; const wf = Step.WriteFile.create(b); - b.named_writefiles.put(b.graph.arena, b.dupe(name), wf) catch @panic("OOM"); + b.named_writefiles.put(graph.arena, graph.dupeString(name), wf) catch @panic("OOM"); return wf; } pub fn addNamedLazyPath(b: *Build, name: []const u8, lp: LazyPath) void { - b.named_lazy_paths.put(b.graph.arena, b.dupe(name), lp.dupe(b)) catch @panic("OOM"); + const graph = b.graph; + b.named_lazy_paths.put(graph.arena, graph.dupeString(name), lp.dupe(graph)) catch @panic("OOM"); } /// Creates a step for mutating files inside a temporary directory created lazily @@ -1183,16 +1191,18 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw } pub fn step(b: *Build, name: []const u8, description: []const u8) *Step { - const step_info = b.allocator.create(Step.TopLevel) catch @panic("OOM"); + const graph = b.graph; + const arena = graph.arena; + const step_info = arena.create(Step.TopLevel) catch @panic("OOM"); step_info.* = .{ .step = .init(.{ .tag = .top_level, .name = name, .owner = b, }), - .description = b.dupe(description), + .description = graph.dupeString(description), }; - const gop = b.top_level_steps.getOrPut(b.allocator, name) catch @panic("OOM"); + const gop = b.top_level_steps.getOrPut(arena, name) catch @panic("OOM"); if (gop.found_existing) panic("A top-level step with name \"{s}\" already exists", .{name}); gop.key_ptr.* = step_info.step.name; @@ -1302,6 +1312,9 @@ pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFaile /// Exposes standard `zig build` options for choosing a target. pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs) Target.Query { + const graph = b.graph; + const arena = graph.arena; + const maybe_triple = b.option( []const u8, "target", @@ -1350,20 +1363,22 @@ pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs for (whitelist) |q| { log.info("allowed target: -Dtarget={s} -Dcpu={s}", .{ - q.zigTriple(b.allocator) catch @panic("OOM"), - q.serializeCpuAlloc(b.allocator) catch @panic("OOM"), + q.zigTriple(arena) catch @panic("OOM"), + q.serializeCpuAlloc(arena) catch @panic("OOM"), }); } log.err("chosen target '{s}' does not match one of the allowed targets", .{ - selected_target.zigTriple(b.allocator) catch @panic("OOM"), + selected_target.zigTriple(arena) catch @panic("OOM"), }); b.markInvalidUserInput(); return args.default_target; } pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8) error{OutOfMemory}!bool { - const name = b.dupe(name_raw); - const value = b.dupe(value_raw); + const graph = b.graph; + const arena = graph.arena; + const name = graph.dupeString(name_raw); + const value = graph.dupeString(value_raw); const gop = try b.user_input_options.getOrPut(name); if (!gop.found_existing) { gop.value_ptr.* = UserInputOption{ @@ -1378,7 +1393,7 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8 switch (gop.value_ptr.value) { .scalar => |s| { // turn it into a list - var list = std.array_list.Managed([]const u8).init(b.allocator); + var list = std.array_list.Managed([]const u8).init(arena); try list.append(s); try list.append(value); try b.user_input_options.put(name, .{ @@ -1608,15 +1623,21 @@ pub fn pathList(b: *Build, sub_paths: []const []const u8) []const LazyPath { } pub fn pathJoin(b: *Build, paths: []const []const u8) []u8 { - return fs.path.join(b.allocator, paths) catch @panic("OOM"); + const graph = b.graph; + const arena = graph.arena; + return fs.path.join(arena, paths) catch @panic("OOM"); } pub fn pathResolve(b: *Build, paths: []const []const u8) []u8 { - return fs.path.resolve(b.allocator, paths) catch @panic("OOM"); + const graph = b.graph; + const arena = graph.arena; + return fs.path.resolve(arena, paths) catch @panic("OOM"); } pub fn fmt(b: *Build, comptime format: []const u8, args: anytype) []u8 { - return std.fmt.allocPrint(b.allocator, format, args) catch @panic("OOM"); + const graph = b.graph; + const arena = graph.arena; + return std.fmt.allocPrint(arena, format, args) catch @panic("OOM"); } /// Creates an anonymous `Step` that searches for an executable on the host that @@ -2264,7 +2285,9 @@ pub const LazyPath = union(enum) { } pub fn path(lazy_path: LazyPath, b: *Build, sub_path: []const u8) LazyPath { - return lazy_path.join(b.allocator, sub_path) catch @panic("OOM"); + const graph = b.graph; + const arena = graph.arena; + return lazy_path.join(arena, sub_path) catch @panic("OOM"); } pub fn join(lazy_path: LazyPath, arena: Allocator, sub_path: []const u8) Allocator.Error!LazyPath { @@ -2460,7 +2483,9 @@ pub fn systemIntegrationOption( name: []const u8, config: SystemIntegrationOptionConfig, ) bool { - const gop = b.graph.system_integration_options.getOrPut(b.allocator, name) catch @panic("OOM"); + const graph = b.graph; + const arena = graph.arena; + const gop = graph.system_integration_options.getOrPut(arena, name) catch @panic("OOM"); if (gop.found_existing) switch (gop.value_ptr.*) { .user_disabled => { gop.value_ptr.* = .declared_disabled; @@ -2473,8 +2498,8 @@ pub fn systemIntegrationOption( .declared_disabled => return false, .declared_enabled => return true, } else { - gop.key_ptr.* = b.dupe(name); - if (config.default orelse b.graph.system_package_mode) { + gop.key_ptr.* = graph.dupeString(name); + if (config.default orelse graph.system_package_mode) { gop.value_ptr.* = .declared_enabled; return true; } else { diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig index c008dcc90f31e445ea8b4701edf7ac0507e8e460..e79d9c58dc54376a649864e13e0e699a38c80723 100644 --- a/lib/std/Build/Configuration.zig +++ b/lib/std/Build/Configuration.zig @@ -230,7 +230,7 @@ pub const Wip = struct { return addString(wip, writer.buffered()); } - pub fn addTargetQuery(wip: *Wip, q: std.Target.Query) !TargetQuery.OptionalIndex { + pub fn addTargetQuery(wip: *Wip, q: *const std.Target.Query) !TargetQuery.OptionalIndex { if (q.isNative()) return .none; const gpa = wip.gpa; const cpu_name: ?String = switch (q.cpu_model) { @@ -575,6 +575,7 @@ pub const Step = extern struct { /// Always a compile step. producer: Storage.FlagOptional(.flags, .producer, Step.Index), generated: Storage.FlagOptional(.flags, .generated, GeneratedFileIndex), + target_query: Storage.FlagOptional(.flags, .target_query, TargetQuery.Index), pub const Flags = packed struct(u32) { tag: Arg.Tag, @@ -585,10 +586,12 @@ pub const Step = extern struct { producer: bool, generated: bool, dep_file: bool, - _: u22 = 0, + target_query: bool, + link_libc: bool, + _: u19 = 0, }; - pub const Tag = enum(u3) { + pub const Tag = enum(u4) { artifact, /// `path` contains the file. path_file, @@ -599,6 +602,7 @@ pub const Step = extern struct { output_file, output_directory, passthru, + cc_args, }; pub const Index = IndexType(@This()); diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 35699051fbfd511c399cb7033e613abebd9cf9d5..c2c5a4f7a38e8217d7e79e4414abbab5d3451b4f 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -143,6 +143,13 @@ pub const Arg = union(enum) { output_directory: *Output, /// The arguments passed after "--" on the "zig build" CLI. passthru, + /// Adds standard "-isystem" and "-iframework" arguments corresponding to the libc of the target. + cc_args: CcArgs, +}; + +pub const CcArgs = struct { + link_libc: bool, + target_query: Configuration.TargetQuery.OptionalIndex, }; pub const PrefixedArtifact = struct { @@ -529,6 +536,22 @@ pub fn addPassthruArgs(run: *Run) void { run.argv.append(arena, .passthru) catch @panic("OOM"); } +pub const AddCcArgs = struct { + link_libc: bool = false, + target_query: ?*const std.Target.Query = null, +}; + +/// Appends C compiler flags for the target and for including libc. +pub fn addCcArgs(run: *Run, options: AddCcArgs) void { + const graph = run.step.owner.graph; + const arena = graph.arena; + const wc = &graph.wip_configuration; + run.argv.append(arena, .{ .cc_args = .{ + .link_libc = options.link_libc, + .target_query = if (options.target_query) |q| wc.addTargetQuery(q) catch @panic("OOM") else .none, + } }) catch @panic("OOM"); +} + pub fn setStdIn(run: *Run, stdin: StdIn) void { switch (stdin) { .lazy_path => |lazy_path| lazy_path.addStepDependencies(&run.step),