mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
configurer: make string duplication also intern
I had this idea to make b.dupe() also intern the strings since they will be ultimately serialized to Configuration. Unfortunately the idea does not work, because although a process-lived arena is used for the string_bytes ArrayList of the Configuration.Wip, when the ArrayList is resized, Allocator.free() memsets the freed memory to undefined, even though it still technically lives due to being in a process-scoped arena. So this commit will need to be partially reverted. However, I kept it for posterity, and there are some more changes which I will now note below. - dupePaths: don't rewrite backslashes to forward slashes. backslashes are valid in filenames on non-windows systems. - always compile configurer in single-threaded mode - use arena allocator for everything, no gpa for anything - construct the Configuration.Wip instance earlier, so some stuff can be prepopulated as desired. - don't forget to flush
This commit is contained in:
+1
-1
@@ -1,10 +1,10 @@
|
||||
* remove Cache from configurer
|
||||
* implement the build options
|
||||
* don't forget to add -listen arg back
|
||||
* get zig init template working
|
||||
* finish migrating the rest of the build steps
|
||||
* make zig-pkg path root configurable in maker (make sure --system still works)
|
||||
* eliminate calls to getPath, getPath2, getPath3
|
||||
* replace b.dupe() with string internment
|
||||
* solve the TODOs added in this branch
|
||||
* get zig tests passing
|
||||
* test a bunch of third party projects / help people migrate
|
||||
|
||||
+22
-24
@@ -24,31 +24,22 @@ pub const std_options: std.Options = .{
|
||||
};
|
||||
|
||||
pub fn main(init: process.Init.Minimal) !void {
|
||||
// The build runner is often short-lived, but thanks to `--watch` and `--webui`, that's not
|
||||
// always the case. So, we do need a true gpa for some things.
|
||||
var debug_gpa_state: std.heap.DebugAllocator(.{
|
||||
// We'd rather have `zig build` run faster than catch harmless leaks in
|
||||
// the user's build.zig script.
|
||||
.stack_trace_frames = 0,
|
||||
}) = .init;
|
||||
defer _ = debug_gpa_state.deinit();
|
||||
const gpa = debug_gpa_state.allocator();
|
||||
var arena_allocator: std.heap.ArenaAllocator = .init(std.heap.page_allocator);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
var threaded: std.Io.Threaded = .init(gpa, .{
|
||||
// The configurer is always short-lived because all it does is serialize
|
||||
// the configuration, which is picked up by a separate maker process.
|
||||
var threaded: std.Io.Threaded = .init(arena, .{
|
||||
.environ = init.environ,
|
||||
.argv0 = .init(init.args),
|
||||
});
|
||||
defer threaded.deinit();
|
||||
const io = threaded.io();
|
||||
|
||||
// ...but we'll back our arena by `std.heap.page_allocator` for efficiency.
|
||||
var arena_allocator: std.heap.ArenaAllocator = .init(std.heap.page_allocator);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const args = try init.args.toSlice(arena);
|
||||
|
||||
// skip my own exe name
|
||||
// Skip own executable name.
|
||||
var arg_idx: usize = 1;
|
||||
|
||||
const zig_exe = expectArgOrFatal(args, &arg_idx, "--zig");
|
||||
@@ -84,7 +75,7 @@ pub fn main(init: process.Init.Minimal) !void {
|
||||
.arena = arena,
|
||||
.cache = .{
|
||||
.io = io,
|
||||
.gpa = gpa,
|
||||
.gpa = arena,
|
||||
.manifest_dir = try local_cache_directory.handle.createDirPathOpen(io, "h", .{}),
|
||||
.cwd = try process.currentPathAlloc(io, arena),
|
||||
},
|
||||
@@ -97,7 +88,18 @@ pub fn main(init: process.Init.Minimal) !void {
|
||||
.result = try std.zig.system.resolveTargetQuery(io, .{}),
|
||||
},
|
||||
.generated_files = .empty,
|
||||
|
||||
// Created before running the user's configure script so that some things
|
||||
// can be added during script execution such as strings.
|
||||
//
|
||||
// Use of arena here is load-bearing because `std.Build.dupe` is
|
||||
// implemented by string internment, and then returning the interned
|
||||
// slice. When the string bytes array is reallocated, that reference
|
||||
// must stay alive.
|
||||
.wip_configuration = .init(arena),
|
||||
};
|
||||
assert(try graph.wip_configuration.addString("") == .empty);
|
||||
assert(try graph.wip_configuration.addString("root") == .root);
|
||||
|
||||
graph.cache.addPrefix(.{ .path = null, .handle = cwd });
|
||||
graph.cache.addPrefix(build_root_directory);
|
||||
@@ -200,19 +202,15 @@ pub fn main(init: process.Init.Minimal) !void {
|
||||
fatal(" access the help menu with 'zig build -h'", .{});
|
||||
}
|
||||
|
||||
var wc: Configuration.Wip = .init(gpa);
|
||||
defer wc.deinit();
|
||||
assert(try wc.addString("") == .empty);
|
||||
assert(try wc.addString("root") == .root);
|
||||
|
||||
try serializeSystemIntegrationOptions(&graph, &wc);
|
||||
try serializeSystemIntegrationOptions(&graph, &graph.wip_configuration);
|
||||
|
||||
var stdout_buffer: [1024]u8 = undefined;
|
||||
var file_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer);
|
||||
serialize(builder, &wc, &file_writer.interface) catch |err| switch (err) {
|
||||
serialize(builder, &graph.wip_configuration, &file_writer.interface) catch |err| switch (err) {
|
||||
error.WriteFailed => fatal("failed to write configuration output: {t}", .{file_writer.err.?}),
|
||||
error.OutOfMemory => |e| return e,
|
||||
};
|
||||
file_writer.flush() catch |err| fatal("failed to write configuration output: {t}", .{err});
|
||||
|
||||
// This executable is short-lived and run in Debug mode, so we'd rather
|
||||
// have `zig build` run faster than catch resource leaks in the user's
|
||||
|
||||
+38
-37
@@ -115,11 +115,37 @@ pub const Graph = struct {
|
||||
|
||||
/// Indexes correspond to `Configuration.GeneratedFileIndex`.
|
||||
generated_files: std.ArrayList(*Step),
|
||||
wip_configuration: Configuration.Wip,
|
||||
|
||||
pub fn addGeneratedFile(graph: *Graph, owner: *Step) Configuration.GeneratedFileIndex {
|
||||
graph.generated_files.append(graph.arena, owner) catch @panic("OOM");
|
||||
return @enumFromInt(graph.generated_files.items.len - 1);
|
||||
}
|
||||
|
||||
pub fn dupeString(graph: *Graph, bytes: []const u8) [:0]const u8 {
|
||||
// This code assumes the `Configuration.Wip` uses arena allocation such
|
||||
// that references to string_bytes never die even when the ArrayList is
|
||||
// reallocated.
|
||||
const wc = &graph.wip_configuration;
|
||||
const i = wc.addString(bytes) catch @panic("OOM");
|
||||
return wc.string_bytes.items[@intFromEnum(i)..][0..bytes.len :0];
|
||||
}
|
||||
|
||||
pub fn dupePath(graph: *Graph, bytes: []const u8) [:0]const u8 {
|
||||
if (builtin.os.tag != .windows) return dupeString(graph, bytes);
|
||||
const arena = graph.arena;
|
||||
const the_copy = arena.dupe(u8, bytes) catch @panic("OOM");
|
||||
defer arena.free(the_copy);
|
||||
mem.replaceScalar(u8, the_copy, '/', '\\');
|
||||
return dupeString(graph, the_copy);
|
||||
}
|
||||
|
||||
pub fn dupeStrings(graph: *Graph, strings: []const []const u8) []const []const u8 {
|
||||
const arena = graph.arena;
|
||||
const array = arena.alloc([]const u8, strings.len) catch @panic("OOM");
|
||||
for (array, strings) |*dest, source| dest.* = dupeString(graph, source);
|
||||
return array;
|
||||
}
|
||||
};
|
||||
|
||||
const AvailableDeps = []const struct { []const u8, []const u8 };
|
||||
@@ -869,36 +895,18 @@ pub fn addConfigHeader(
|
||||
return config_header_step;
|
||||
}
|
||||
|
||||
/// Allocator.dupe without the need to handle out of memory.
|
||||
pub fn dupe(b: *Build, bytes: []const u8) []u8 {
|
||||
return dupeInner(b.allocator, bytes);
|
||||
}
|
||||
|
||||
pub fn dupeInner(allocator: Allocator, bytes: []const u8) []u8 {
|
||||
return allocator.dupe(u8, bytes) catch @panic("OOM");
|
||||
pub fn dupe(b: *Build, bytes: []const u8) [:0]const u8 {
|
||||
return b.graph.dupeString(bytes);
|
||||
}
|
||||
|
||||
/// Duplicates an array of strings without the need to handle out of memory.
|
||||
pub fn dupeStrings(b: *Build, strings: []const []const u8) [][]u8 {
|
||||
const array = b.allocator.alloc([]u8, strings.len) catch @panic("OOM");
|
||||
for (array, strings) |*dest, source| dest.* = b.dupe(source);
|
||||
return array;
|
||||
pub fn dupeStrings(b: *Build, strings: []const []const u8) []const []const u8 {
|
||||
return b.graph.dupeStrings(strings);
|
||||
}
|
||||
|
||||
/// Duplicates a path and converts all slashes to the OS's canonical path separator.
|
||||
pub fn dupePath(b: *Build, bytes: []const u8) []u8 {
|
||||
return dupePathInner(b.allocator, bytes);
|
||||
}
|
||||
|
||||
fn dupePathInner(allocator: Allocator, bytes: []const u8) []u8 {
|
||||
const the_copy = dupeInner(allocator, bytes);
|
||||
for (the_copy) |*byte| {
|
||||
switch (byte.*) {
|
||||
'/', '\\' => byte.* = fs.path.sep,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
return the_copy;
|
||||
/// Duplicates a path, canonicalizing path separators.
|
||||
pub fn dupePath(b: *Build, bytes: []const u8) [:0]const u8 {
|
||||
return b.graph.dupePath(bytes);
|
||||
}
|
||||
|
||||
pub fn addWriteFile(b: *Build, file_path: []const u8, data: []const u8) *Step.WriteFile {
|
||||
@@ -2268,25 +2276,18 @@ pub const LazyPath = union(enum) {
|
||||
///
|
||||
/// The `b` parameter is only used for its allocator. All *Build instances
|
||||
/// share the same allocator.
|
||||
pub fn dupe(lazy_path: LazyPath, b: *Build) LazyPath {
|
||||
return lazy_path.dupeInner(b.allocator);
|
||||
}
|
||||
|
||||
fn dupeInner(lazy_path: LazyPath, allocator: Allocator) LazyPath {
|
||||
pub fn dupe(lazy_path: LazyPath, graph: *Graph) LazyPath {
|
||||
return switch (lazy_path) {
|
||||
.src_path => |sp| .{ .src_path = .{
|
||||
.owner = sp.owner,
|
||||
.sub_path = sp.owner.dupePath(sp.sub_path),
|
||||
} },
|
||||
.cwd_relative => |p| .{ .cwd_relative = dupePathInner(allocator, p) },
|
||||
.src_path => |sp| .{ .src_path = .{ .owner = sp.owner, .sub_path = sp.owner.dupePath(sp.sub_path) } },
|
||||
.cwd_relative => |p| .{ .cwd_relative = graph.dupePath(p) },
|
||||
.generated => |gen| .{ .generated = .{
|
||||
.index = gen.index,
|
||||
.up = gen.up,
|
||||
.sub_path = dupePathInner(allocator, gen.sub_path),
|
||||
.sub_path = graph.dupePath(gen.sub_path),
|
||||
} },
|
||||
.dependency => |dep| .{ .dependency = .{
|
||||
.dependency = dep.dependency,
|
||||
.sub_path = dupePathInner(allocator, dep.sub_path),
|
||||
.sub_path = graph.dupePath(dep.sub_path),
|
||||
} },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1419,13 +1419,6 @@ pub const Path = extern struct {
|
||||
global_cache,
|
||||
build_root,
|
||||
};
|
||||
|
||||
pub fn toCachePath(path: Path, c: *const Configuration, arena: Allocator) std.Build.Cache.Path {
|
||||
_ = c;
|
||||
_ = arena;
|
||||
_ = path;
|
||||
@panic("TODO");
|
||||
}
|
||||
};
|
||||
|
||||
pub const InstallDestDir = enum(u32) {
|
||||
|
||||
@@ -240,13 +240,14 @@ pub fn init(
|
||||
owner: *std.Build,
|
||||
value: union(enum) { options: CreateOptions, existing: *const Module },
|
||||
) void {
|
||||
const allocator = owner.allocator;
|
||||
const graph = owner.graph;
|
||||
const arena = graph.arena;
|
||||
|
||||
switch (value) {
|
||||
.options => |options| {
|
||||
m.* = .{
|
||||
.owner = owner,
|
||||
.root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null,
|
||||
.root_source_file = if (options.root_source_file) |lp| lp.dupe(graph) else null,
|
||||
.import_table = .empty,
|
||||
.resolved_target = options.target,
|
||||
.optimize = options.optimize,
|
||||
@@ -277,7 +278,7 @@ pub fn init(
|
||||
.no_builtin = options.no_builtin,
|
||||
};
|
||||
|
||||
m.import_table.ensureUnusedCapacity(allocator, options.imports.len) catch @panic("OOM");
|
||||
m.import_table.ensureUnusedCapacity(arena, options.imports.len) catch @panic("OOM");
|
||||
for (options.imports) |dep| {
|
||||
m.import_table.putAssumeCapacity(dep.name, dep.module);
|
||||
}
|
||||
|
||||
@@ -296,10 +296,10 @@ pub const HeaderInstallation = union(enum) {
|
||||
source: LazyPath,
|
||||
dest_rel_path: []const u8,
|
||||
|
||||
pub fn dupe(file: File, b: *std.Build) File {
|
||||
pub fn dupe(file: File, graph: *std.Build.Graph) File {
|
||||
return .{
|
||||
.source = file.source.dupe(b),
|
||||
.dest_rel_path = b.dupePath(file.dest_rel_path),
|
||||
.source = file.source.dupe(graph),
|
||||
.dest_rel_path = graph.dupePath(file.dest_rel_path),
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -424,13 +424,13 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
|
||||
};
|
||||
|
||||
if (options.zig_lib_dir) |lp| {
|
||||
compile.zig_lib_dir = lp.dupe(compile.step.owner);
|
||||
compile.zig_lib_dir = lp.dupe(graph);
|
||||
lp.addStepDependencies(&compile.step);
|
||||
}
|
||||
|
||||
if (options.test_runner) |runner| {
|
||||
compile.test_runner = .{
|
||||
.path = runner.path.dupe(compile.step.owner),
|
||||
.path = runner.path.dupe(graph),
|
||||
.mode = runner.mode,
|
||||
};
|
||||
runner.path.addStepDependencies(&compile.step);
|
||||
@@ -440,20 +440,20 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
|
||||
// gets embedded, so for any other target the manifest file is just ignored.
|
||||
if (target.ofmt == .coff) {
|
||||
if (options.win32_manifest) |lp| {
|
||||
compile.win32_manifest = lp.dupe(compile.step.owner);
|
||||
compile.win32_manifest = lp.dupe(graph);
|
||||
lp.addStepDependencies(&compile.step);
|
||||
}
|
||||
if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
|
||||
// Building a Win32 DLL, check for win32 .def file.
|
||||
if (options.win32_module_definition) |lp| {
|
||||
compile.win32_module_definition = lp.dupe(compile.step.owner);
|
||||
compile.win32_module_definition = lp.dupe(graph);
|
||||
lp.addStepDependencies(&compile.step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options.entitlements) |lp| {
|
||||
compile.entitlements = lp.dupe(compile.step.owner);
|
||||
compile.entitlements = lp.dupe(graph);
|
||||
lp.addStepDependencies(&compile.step);
|
||||
}
|
||||
|
||||
@@ -464,12 +464,13 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
|
||||
/// When a module links with this artifact, all headers marked for installation are added to that
|
||||
/// module's include search path.
|
||||
pub fn installHeader(cs: *Compile, source: LazyPath, dest_rel_path: []const u8) void {
|
||||
const b = cs.step.owner;
|
||||
const graph = cs.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
const installation: HeaderInstallation = .{ .file = .{
|
||||
.source = source.dupe(b),
|
||||
.dest_rel_path = b.dupePath(dest_rel_path),
|
||||
.source = source.dupe(graph),
|
||||
.dest_rel_path = graph.dupePath(dest_rel_path),
|
||||
} };
|
||||
cs.installed_headers.append(b.allocator, installation) catch @panic("OOM");
|
||||
cs.installed_headers.append(arena, installation) catch @panic("OOM");
|
||||
cs.addHeaderInstallationToIncludeTree(installation);
|
||||
installation.getSource().addStepDependencies(&cs.step);
|
||||
}
|
||||
@@ -483,13 +484,14 @@ pub fn installHeadersDirectory(
|
||||
dest_rel_path: []const u8,
|
||||
options: HeaderInstallation.Directory.Options,
|
||||
) void {
|
||||
const b = cs.step.owner;
|
||||
const graph = cs.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
const installation: HeaderInstallation = .{ .directory = .{
|
||||
.source = source.dupe(b),
|
||||
.dest_rel_path = b.dupePath(dest_rel_path),
|
||||
.options = options.dupe(b),
|
||||
.source = source.dupe(graph),
|
||||
.dest_rel_path = graph.dupePath(dest_rel_path),
|
||||
.options = options.dupe(graph),
|
||||
} };
|
||||
cs.installed_headers.append(b.allocator, installation) catch @panic("OOM");
|
||||
cs.installed_headers.append(arena, installation) catch @panic("OOM");
|
||||
cs.addHeaderInstallationToIncludeTree(installation);
|
||||
installation.getSource().addStepDependencies(&cs.step);
|
||||
}
|
||||
@@ -506,9 +508,10 @@ pub fn installConfigHeader(cs: *Compile, config_header: *Step.ConfigHeader) void
|
||||
/// module's include search path.
|
||||
pub fn installLibraryHeaders(cs: *Compile, lib: *Compile) void {
|
||||
assert(lib.kind == .lib);
|
||||
const arena = cs.owner.allocator;
|
||||
const graph = cs.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
for (lib.installed_headers.items) |installation| {
|
||||
const installation_copy = installation.dupe(lib.step.owner);
|
||||
const installation_copy = installation.dupe(graph);
|
||||
cs.installed_headers.append(arena, installation_copy) catch @panic("OOM");
|
||||
cs.addHeaderInstallationToIncludeTree(installation_copy);
|
||||
installation_copy.getSource().addStepDependencies(&cs.step);
|
||||
@@ -560,21 +563,21 @@ pub fn checkObject(compile: *Compile) *Step.CheckObject {
|
||||
}
|
||||
|
||||
pub fn setLinkerScript(compile: *Compile, source: LazyPath) void {
|
||||
const b = compile.step.owner;
|
||||
compile.linker_script = source.dupe(b);
|
||||
const graph = compile.step.owner.graph;
|
||||
compile.linker_script = source.dupe(graph);
|
||||
source.addStepDependencies(&compile.step);
|
||||
}
|
||||
|
||||
pub fn setVersionScript(compile: *Compile, source: LazyPath) void {
|
||||
const b = compile.step.owner;
|
||||
compile.version_script = source.dupe(b);
|
||||
const graph = compile.step.owner.graph;
|
||||
compile.version_script = source.dupe(graph);
|
||||
source.addStepDependencies(&compile.step);
|
||||
}
|
||||
|
||||
pub fn forceUndefinedSymbol(compile: *Compile, symbol_name: []const u8) void {
|
||||
const b = compile.step.owner;
|
||||
const arena = b.allocator;
|
||||
compile.force_undefined_symbols.put(arena, b.dupe(symbol_name), {}) catch @panic("OOM");
|
||||
const graph = compile.step.owner.graph;
|
||||
const arena = graph.allocator;
|
||||
compile.force_undefined_symbols.put(arena, graph.dupeString(symbol_name), {}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// Returns whether the library, executable, or object depends on a particular system library.
|
||||
@@ -659,9 +662,9 @@ pub fn setVerboseCC(compile: *Compile, value: bool) void {
|
||||
}
|
||||
|
||||
pub fn setLibCFile(compile: *Compile, libc_file: ?LazyPath) void {
|
||||
const b = compile.step.owner;
|
||||
const graph = compile.step.owner.graph;
|
||||
if (libc_file) |f| {
|
||||
compile.libc_file = f.dupe(b);
|
||||
compile.libc_file = f.dupe(graph);
|
||||
f.addStepDependencies(&compile.step);
|
||||
} else {
|
||||
compile.libc_file = null;
|
||||
@@ -737,11 +740,12 @@ pub fn getEmittedLlvmBc(compile: *Compile) LazyPath {
|
||||
}
|
||||
|
||||
pub fn setExecCmd(compile: *Compile, args: []const ?[]const u8) void {
|
||||
const b = compile.step.owner;
|
||||
const graph = compile.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
assert(compile.kind == .@"test");
|
||||
const duped_args = b.allocator.alloc(?[]u8, args.len) catch @panic("OOM");
|
||||
const duped_args = arena.alloc(?[]u8, args.len) catch @panic("OOM");
|
||||
for (args, 0..) |arg, i| {
|
||||
duped_args[i] = if (arg) |a| b.dupe(a) else null;
|
||||
duped_args[i] = if (arg) |a| graph.dupeString(a) else null;
|
||||
}
|
||||
compile.exec_cmd_args = duped_args;
|
||||
}
|
||||
|
||||
+57
-43
@@ -139,7 +139,7 @@ pub const Arg = union(enum) {
|
||||
lazy_path: PrefixedLazyPath,
|
||||
decorated_directory: DecoratedLazyPath,
|
||||
file_content: PrefixedLazyPath,
|
||||
bytes: []u8,
|
||||
bytes: [:0]const u8,
|
||||
output_file: *Output,
|
||||
output_directory: *Output,
|
||||
/// The arguments passed after "--" on the "zig build" CLI.
|
||||
@@ -228,13 +228,14 @@ pub fn addArtifactArg(run: *Run, artifact: *Step.Compile) void {
|
||||
}
|
||||
|
||||
pub fn addPrefixedArtifactArg(run: *Run, prefix: []const u8, artifact: *Step.Compile) void {
|
||||
const b = run.step.owner;
|
||||
const graph = run.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
|
||||
const prefixed_artifact: PrefixedArtifact = .{
|
||||
.prefix = b.dupe(prefix),
|
||||
.prefix = graph.dupeString(prefix),
|
||||
.artifact = artifact,
|
||||
};
|
||||
run.argv.append(b.allocator, .{ .artifact = prefixed_artifact }) catch @panic("OOM");
|
||||
run.argv.append(arena, .{ .artifact = prefixed_artifact }) catch @panic("OOM");
|
||||
|
||||
const bin_file = artifact.getEmittedBin();
|
||||
bin_file.addStepDependencies(&run.step);
|
||||
@@ -279,8 +280,8 @@ pub fn addPrefixedOutputFileArg(
|
||||
|
||||
const output = arena.create(Output) catch @panic("OOM");
|
||||
output.* = .{
|
||||
.prefix = b.dupe(prefix),
|
||||
.basename = b.dupe(basename),
|
||||
.prefix = graph.dupeString(prefix),
|
||||
.basename = graph.dupeString(basename),
|
||||
.generated_file = graph.addGeneratedFile(&run.step),
|
||||
};
|
||||
run.argv.append(arena, .{ .output_file = output }) catch @panic("OOM");
|
||||
@@ -318,13 +319,14 @@ pub fn addFileArg(run: *Run, lp: std.Build.LazyPath) void {
|
||||
/// * `addFileArg` - same thing but without the prefix
|
||||
/// * `addOutputFileArg` - for files generated by the child process
|
||||
pub fn addPrefixedFileArg(run: *Run, prefix: []const u8, lp: std.Build.LazyPath) void {
|
||||
const b = run.step.owner;
|
||||
const graph = run.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
|
||||
const prefixed_file_source: PrefixedLazyPath = .{
|
||||
.prefix = b.dupe(prefix),
|
||||
.lazy_path = lp.dupe(b),
|
||||
.prefix = graph.dupeString(prefix),
|
||||
.lazy_path = lp.dupe(graph),
|
||||
};
|
||||
run.argv.append(b.allocator, .{ .lazy_path = prefixed_file_source }) catch @panic("OOM");
|
||||
run.argv.append(arena, .{ .lazy_path = prefixed_file_source }) catch @panic("OOM");
|
||||
lp.addStepDependencies(&run.step);
|
||||
}
|
||||
|
||||
@@ -365,7 +367,8 @@ pub fn addFileContentArg(run: *Run, lp: std.Build.LazyPath) void {
|
||||
/// Related:
|
||||
/// * `addFileContentArg` - same thing but without the prefix
|
||||
pub fn addPrefixedFileContentArg(run: *Run, prefix: []const u8, lp: std.Build.LazyPath) void {
|
||||
const b = run.step.owner;
|
||||
const graph = run.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
|
||||
// Some parts of this step's configure phase API rely on the first argument being somewhat
|
||||
// transparent/readable, but the content of the file specified by `lp` remains completely
|
||||
@@ -375,10 +378,10 @@ pub fn addPrefixedFileContentArg(run: *Run, prefix: []const u8, lp: std.Build.La
|
||||
}
|
||||
|
||||
const prefixed_file_source: PrefixedLazyPath = .{
|
||||
.prefix = b.dupe(prefix),
|
||||
.lazy_path = lp.dupe(b),
|
||||
.prefix = graph.dupeString(prefix),
|
||||
.lazy_path = lp.dupe(graph),
|
||||
};
|
||||
run.argv.append(b.allocator, .{ .file_content = prefixed_file_source }) catch @panic("OOM");
|
||||
run.argv.append(arena, .{ .file_content = prefixed_file_source }) catch @panic("OOM");
|
||||
lp.addStepDependencies(&run.step);
|
||||
}
|
||||
|
||||
@@ -415,18 +418,19 @@ pub fn addPrefixedOutputDirectoryArg(
|
||||
basename: []const u8,
|
||||
) std.Build.LazyPath {
|
||||
if (basename.len == 0) @panic("basename must not be empty");
|
||||
const b = run.step.owner;
|
||||
const graph = run.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
|
||||
const output = b.allocator.create(Output) catch @panic("OOM");
|
||||
const output = arena.create(Output) catch @panic("OOM");
|
||||
output.* = .{
|
||||
.prefix = b.dupe(prefix),
|
||||
.basename = b.dupe(basename),
|
||||
.prefix = graph.dupeString(prefix),
|
||||
.basename = graph.dupeString(basename),
|
||||
.generated_file = .{ .step = &run.step },
|
||||
};
|
||||
run.argv.append(b.allocator, .{ .output_directory = output }) catch @panic("OOM");
|
||||
run.argv.append(arena, .{ .output_directory = output }) catch @panic("OOM");
|
||||
|
||||
if (run.rename_step_with_output_arg) {
|
||||
run.setName(b.fmt("{s} ({s})", .{ run.step.name, basename }));
|
||||
run.setName(std.fmt.allocPrint(arena, "{s} ({s})", .{ run.step.name, basename }) catch @panic("OOM"));
|
||||
}
|
||||
|
||||
return .{ .generated = .{ .file = &output.generated_file } };
|
||||
@@ -437,10 +441,11 @@ pub fn addDirectoryArg(run: *Run, lazy_directory: std.Build.LazyPath) void {
|
||||
}
|
||||
|
||||
pub fn addPrefixedDirectoryArg(run: *Run, prefix: []const u8, lazy_directory: std.Build.LazyPath) void {
|
||||
const b = run.step.owner;
|
||||
run.argv.append(b.allocator, .{ .decorated_directory = .{
|
||||
.prefix = b.dupe(prefix),
|
||||
.lazy_path = lazy_directory.dupe(b),
|
||||
const graph = run.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
run.argv.append(arena, .{ .decorated_directory = .{
|
||||
.prefix = graph.dupeString(prefix),
|
||||
.lazy_path = lazy_directory.dupe(graph),
|
||||
.suffix = "",
|
||||
} }) catch @panic("OOM");
|
||||
lazy_directory.addStepDependencies(&run.step);
|
||||
@@ -452,11 +457,12 @@ pub fn addDecoratedDirectoryArg(
|
||||
lazy_directory: std.Build.LazyPath,
|
||||
suffix: []const u8,
|
||||
) void {
|
||||
const b = run.step.owner;
|
||||
run.argv.append(b.allocator, .{ .decorated_directory = .{
|
||||
.prefix = b.dupe(prefix),
|
||||
.lazy_path = lazy_directory.dupe(b),
|
||||
.suffix = b.dupe(suffix),
|
||||
const graph = run.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
run.argv.append(arena, .{ .decorated_directory = .{
|
||||
.prefix = graph.dupeString(prefix),
|
||||
.lazy_path = lazy_directory.dupe(graph),
|
||||
.suffix = graph.dupeString(suffix),
|
||||
} }) catch @panic("OOM");
|
||||
lazy_directory.addStepDependencies(&run.step);
|
||||
}
|
||||
@@ -479,8 +485,8 @@ pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []co
|
||||
|
||||
const dep_file = arena.create(Output) catch @panic("OOM");
|
||||
dep_file.* = .{
|
||||
.prefix = b.dupe(prefix),
|
||||
.basename = b.dupe(basename),
|
||||
.prefix = graph.dupeString(prefix),
|
||||
.basename = graph.dupeString(basename),
|
||||
.generated_file = graph.addGeneratedFile(&run.step),
|
||||
};
|
||||
|
||||
@@ -492,8 +498,9 @@ pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []co
|
||||
}
|
||||
|
||||
pub fn addArg(run: *Run, arg: []const u8) void {
|
||||
const b = run.step.owner;
|
||||
run.argv.append(b.allocator, .{ .bytes = b.dupe(arg) }) catch @panic("OOM");
|
||||
const graph = run.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
run.argv.append(arena, .{ .bytes = graph.dupeString(arg) }) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addArgs(run: *Run, args: []const []const u8) void {
|
||||
@@ -509,8 +516,9 @@ pub fn setStdIn(run: *Run, stdin: StdIn) void {
|
||||
}
|
||||
|
||||
pub fn setCwd(run: *Run, cwd: Build.LazyPath) void {
|
||||
const graph = run.step.owner.graph;
|
||||
cwd.addStepDependencies(&run.step);
|
||||
run.cwd = cwd.dupe(run.step.owner);
|
||||
run.cwd = cwd.dupe(graph);
|
||||
}
|
||||
|
||||
pub fn clearEnvironment(run: *Run) void {
|
||||
@@ -580,24 +588,28 @@ pub fn removeEnvironmentVariable(run: *Run, key: []const u8) void {
|
||||
|
||||
/// Adds a check for exact stderr match. Does not add any other checks.
|
||||
pub fn expectStdErrEqual(run: *Run, bytes: []const u8) void {
|
||||
run.addCheck(.{ .expect_stderr_exact = run.step.owner.dupe(bytes) });
|
||||
const graph = run.step.owner.graph;
|
||||
run.addCheck(.{ .expect_stderr_exact = graph.dupeString(bytes) });
|
||||
}
|
||||
|
||||
pub fn expectStdErrMatch(run: *Run, bytes: []const u8) void {
|
||||
run.addCheck(.{ .expect_stderr_match = run.step.owner.dupe(bytes) });
|
||||
const graph = run.step.owner.graph;
|
||||
run.addCheck(.{ .expect_stderr_match = graph.dupeString(bytes) });
|
||||
}
|
||||
|
||||
/// Adds a check for exact stdout match as well as a check for exit code 0, if
|
||||
/// there is not already an expected termination check.
|
||||
pub fn expectStdOutEqual(run: *Run, bytes: []const u8) void {
|
||||
run.addCheck(.{ .expect_stdout_exact = run.step.owner.dupe(bytes) });
|
||||
const graph = run.step.owner.graph;
|
||||
run.addCheck(.{ .expect_stdout_exact = graph.dupeString(bytes) });
|
||||
if (!run.hasTermCheck()) run.expectExitCode(0);
|
||||
}
|
||||
|
||||
/// Adds a check for stdout match as well as a check for exit code 0, if there
|
||||
/// is not already an expected termination check.
|
||||
pub fn expectStdOutMatch(run: *Run, bytes: []const u8) void {
|
||||
run.addCheck(.{ .expect_stdout_match = run.step.owner.dupe(bytes) });
|
||||
const graph = run.step.owner.graph;
|
||||
run.addCheck(.{ .expect_stdout_match = graph.dupeString(bytes) });
|
||||
if (!run.hasTermCheck()) run.expectExitCode(0);
|
||||
}
|
||||
|
||||
@@ -641,7 +653,7 @@ pub fn captureStdErr(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPa
|
||||
captured.* = .{
|
||||
.output = .{
|
||||
.prefix = "",
|
||||
.basename = if (options.basename) |basename| b.dupe(basename) else "stderr",
|
||||
.basename = if (options.basename) |basename| graph.dupeString(basename) else "stderr",
|
||||
.generated_file = graph.addGeneratedFile(&run.step),
|
||||
},
|
||||
.trim_whitespace = options.trim_whitespace,
|
||||
@@ -664,7 +676,7 @@ pub fn captureStdOut(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPa
|
||||
captured.* = .{
|
||||
.output = .{
|
||||
.prefix = "",
|
||||
.basename = if (options.basename) |basename| b.dupe(basename) else "stdout",
|
||||
.basename = if (options.basename) |basename| graph.dupeString(basename) else "stdout",
|
||||
.generated_file = graph.addGeneratedFile(&run.step),
|
||||
},
|
||||
.trim_whitespace = options.trim_whitespace,
|
||||
@@ -678,7 +690,9 @@ pub fn captureStdOut(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPa
|
||||
/// If the Run step is determined to have side-effects, the Run step is always
|
||||
/// executed when it appears in the build graph, regardless of whether this
|
||||
/// file has been modified.
|
||||
pub fn addFileInput(self: *Run, file_input: std.Build.LazyPath) void {
|
||||
file_input.addStepDependencies(&self.step);
|
||||
self.file_inputs.append(self.step.owner.allocator, file_input.dupe(self.step.owner)) catch @panic("OOM");
|
||||
pub fn addFileInput(run: *Run, file_input: std.Build.LazyPath) void {
|
||||
const graph = run.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
file_input.addStepDependencies(&run.step);
|
||||
run.file_inputs.append(arena, file_input.dupe(graph)) catch @panic("OOM");
|
||||
}
|
||||
|
||||
@@ -55,10 +55,10 @@ pub const Directory = struct {
|
||||
/// `exclude_extensions` takes precedence over `include_extensions`.
|
||||
include_extensions: ?[]const []const u8 = null,
|
||||
|
||||
pub fn dupe(opts: Options, b: *std.Build) Options {
|
||||
pub fn dupe(opts: Options, graph: *std.Build.Graph) Options {
|
||||
return .{
|
||||
.exclude_extensions = b.dupeStrings(opts.exclude_extensions),
|
||||
.include_extensions = if (opts.include_extensions) |incs| b.dupeStrings(incs) else null,
|
||||
.exclude_extensions = graph.dupeStrings(opts.exclude_extensions),
|
||||
.include_extensions = if (opts.include_extensions) |incs| graph.dupeStrings(incs) else null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,13 +103,13 @@ pub fn create(owner: *std.Build) *WriteFile {
|
||||
}
|
||||
|
||||
pub fn add(write_file: *WriteFile, sub_path: []const u8, bytes: []const u8) std.Build.LazyPath {
|
||||
const b = write_file.step.owner;
|
||||
const gpa = b.allocator;
|
||||
const file = File{
|
||||
.sub_path = b.dupePath(sub_path),
|
||||
.contents = .{ .bytes = b.dupe(bytes) },
|
||||
const graph = write_file.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
const file: File = .{
|
||||
.sub_path = graph.dupePath(sub_path),
|
||||
.contents = .{ .bytes = graph.dupeString(bytes) },
|
||||
};
|
||||
write_file.files.append(gpa, file) catch @panic("OOM");
|
||||
write_file.files.append(arena, file) catch @panic("OOM");
|
||||
write_file.maybeUpdateName();
|
||||
return .{
|
||||
.generated = .{
|
||||
@@ -154,14 +154,14 @@ pub fn addCopyDirectory(
|
||||
sub_path: []const u8,
|
||||
options: Directory.Options,
|
||||
) std.Build.LazyPath {
|
||||
const b = write_file.step.owner;
|
||||
const gpa = b.allocator;
|
||||
const graph = write_file.step.owner.graph;
|
||||
const arena = graph.arena;
|
||||
const dir = Directory{
|
||||
.source = source.dupe(b),
|
||||
.sub_path = b.dupePath(sub_path),
|
||||
.options = options.dupe(b),
|
||||
.source = source.dupe(graph),
|
||||
.sub_path = graph.dupePath(sub_path),
|
||||
.options = options.dupe(graph),
|
||||
};
|
||||
write_file.directories.append(gpa, dir) catch @panic("OOM");
|
||||
write_file.directories.append(arena, dir) catch @panic("OOM");
|
||||
|
||||
write_file.maybeUpdateName();
|
||||
source.addStepDependencies(&write_file.step);
|
||||
|
||||
@@ -5369,6 +5369,7 @@ fn cmdBuild(
|
||||
.cc_argv = &.{},
|
||||
.inherited = .{
|
||||
.resolved_target = resolved_target,
|
||||
.single_threaded = true,
|
||||
},
|
||||
.global = config,
|
||||
.parent = null,
|
||||
|
||||
Reference in New Issue
Block a user