diff --git a/lib/std/build.zig b/lib/std/build.zig index 349e689141..487dfe3a83 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -359,7 +359,7 @@ pub const Builder = struct { pub fn dupePkg(self: *Builder, package: Pkg) Pkg { var the_copy = Pkg{ .name = self.dupe(package.name), - .path = self.dupePath(package.path), + .path = package.path.dupe(self), }; if (package.dependencies) |dependencies| { @@ -1245,7 +1245,7 @@ pub const Target = std.zig.CrossTarget; pub const Pkg = struct { name: []const u8, - path: []const u8, + path: FileSource, dependencies: ?[]const Pkg = null, }; @@ -1284,6 +1284,20 @@ fn isLibCppLibrary(name: []const u8) bool { return false; } +/// A file that is generated by a build step. +/// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic. +pub const GeneratedFile = struct { + /// The step that generates the file + step: *Step, + + /// A function that returns the absolute path to the generated file. + getPathFn: fn (self: *const GeneratedFile) []const u8, + + pub fn getPath(self: *const GeneratedFile) []const u8 { + return self.getPathFn(self); + } +}; + pub const FileSource = union(enum) { /// Relative to build root path: []const u8, @@ -1291,13 +1305,17 @@ pub const FileSource = union(enum) { step: *WriteFileStep, basename: []const u8, }, - translate_c: *TranslateCStep, + generated: *const GeneratedFile, + + pub fn relative(path: []const u8) FileSource { + return FileSource{ .path = path }; + } pub fn addStepDependencies(self: FileSource, step: *Step) void { switch (self) { .path => {}, .write_file => |wf| step.dependOn(&wf.step.step), - .translate_c => |tc| step.dependOn(&tc.step), + .generated => |gen| step.dependOn(gen.step), } } @@ -1306,18 +1324,20 @@ pub const FileSource = union(enum) { return switch (self) { .path => |p| builder.pathFromRoot(p), .write_file => |wf| wf.step.getOutputPath(wf.basename), - .translate_c => |tc| tc.getOutputPath(), + .generated => |gen| gen.getPath(), }; } pub fn dupe(self: FileSource, b: *Builder) FileSource { return switch (self) { - .path => |p| .{ .path = b.dupe(p) }, - .write_file => |wf| .{ .write_file = .{ - .step = wf.step, - .basename = b.dupe(wf.basename), - } }, - .translate_c => |tc| .{ .translate_c = tc }, + .path => |p| .{ .path = b.dupePath(p) }, + .write_file => |wf| .{ + .write_file = .{ + .step = wf.step, + .basename = b.dupe(wf.basename), + }, + }, + .generated => |gen| .{ .generated = gen }, }; } }; @@ -2107,13 +2127,14 @@ pub const LibExeObjStep = struct { } pub fn addPackage(self: *LibExeObjStep, package: Pkg) void { + package.path.addStepDependencies(&self.step); self.packages.append(self.builder.dupePkg(package)) catch unreachable; } pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void { self.packages.append(Pkg{ .name = self.builder.dupe(name), - .path = self.builder.dupe(pkg_index_path), + .path = .{ .path = self.builder.dupe(pkg_index_path) }, }) catch unreachable; } @@ -2190,7 +2211,7 @@ pub const LibExeObjStep = struct { try zig_args.append("--pkg-begin"); try zig_args.append(pkg.name); - try zig_args.append(builder.pathFromRoot(pkg.path)); + try zig_args.append(builder.pathFromRoot(pkg.path.getPath(self.builder))); if (pkg.dependencies) |dependencies| { for (dependencies) |sub_pkg| { @@ -3137,11 +3158,11 @@ test "Builder.dupePkg()" { var pkg_dep = Pkg{ .name = "pkg_dep", - .path = "/not/a/pkg_dep.zig", + .path = FileSource.relative("/not/a/pkg_dep.zig"), }; var pkg_top = Pkg{ .name = "pkg_top", - .path = "/not/a/pkg_top.zig", + .path = FileSource.relative("/not/a/pkg_top.zig"), .dependencies = &[_]Pkg{pkg_dep}, }; const dupe = builder.dupePkg(pkg_top); @@ -3160,9 +3181,9 @@ test "Builder.dupePkg()" { // the same as those in stack allocated package's fields try std.testing.expect(dupe_deps.ptr != original_deps.ptr); try std.testing.expect(dupe.name.ptr != pkg_top.name.ptr); - try std.testing.expect(dupe.path.ptr != pkg_top.path.ptr); + try std.testing.expect(dupe.path.path.ptr != pkg_top.path.path.ptr); try std.testing.expect(dupe_deps[0].name.ptr != pkg_dep.name.ptr); - try std.testing.expect(dupe_deps[0].path.ptr != pkg_dep.path.ptr); + try std.testing.expect(dupe_deps[0].path.path.ptr != pkg_dep.path.path.ptr); } test "LibExeObjStep.addBuildOption" { @@ -3219,11 +3240,11 @@ test "LibExeObjStep.addPackage" { const pkg_dep = Pkg{ .name = "pkg_dep", - .path = "/not/a/pkg_dep.zig", + .path = FileSource.relative("/not/a/pkg_dep.zig"), }; const pkg_top = Pkg{ .name = "pkg_dep", - .path = "/not/a/pkg_top.zig", + .path = FileSource.relative("/not/a/pkg_top.zig"), .dependencies = &[_]Pkg{pkg_dep}, }; diff --git a/lib/std/build/translate_c.zig b/lib/std/build/translate_c.zig index 027837b55e..84a6735004 100644 --- a/lib/std/build/translate_c.zig +++ b/lib/std/build/translate_c.zig @@ -21,6 +21,7 @@ pub const TranslateCStep = struct { output_dir: ?[]const u8, out_basename: []const u8, target: CrossTarget = CrossTarget{}, + output_file: build.GeneratedFile, pub fn create(builder: *Builder, source: build.FileSource) *TranslateCStep { const self = builder.allocator.create(TranslateCStep) catch unreachable; @@ -31,11 +32,20 @@ pub const TranslateCStep = struct { .include_dirs = std.ArrayList([]const u8).init(builder.allocator), .output_dir = null, .out_basename = undefined, + .output_file = build.GeneratedFile{ + .step = &self.step, + .getPathFn = getGeneratedFilePath, + }, }; source.addStepDependencies(&self.step); return self; } + fn getGeneratedFilePath(file: *const build.GeneratedFile) []const u8 { + const self = @fieldParentPtr(TranslateCStep, "step", file.step); + return self.getOutputPath(); + } + /// Unless setOutputDir was called, this function must be called only in /// the make step, from a step that has declared a dependency on this one. /// To run an executable built with zig build, use `run`, or create an install step and invoke it. @@ -52,7 +62,7 @@ pub const TranslateCStep = struct { /// Creates a step to build an executable from the translated source. pub fn addExecutable(self: *TranslateCStep) *LibExeObjStep { - return self.builder.addExecutableSource("translated_c", @as(build.FileSource, .{ .translate_c = self })); + return self.builder.addExecutableSource("translated_c", @as(build.FileSource, .{ .generated = &self.output_file })); } pub fn addIncludeDir(self: *TranslateCStep, include_dir: []const u8) void { @@ -60,7 +70,7 @@ pub const TranslateCStep = struct { } pub fn addCheckFile(self: *TranslateCStep, expected_matches: []const []const u8) *CheckFileStep { - return CheckFileStep.create(self.builder, .{ .translate_c = self }, self.builder.dupeStrings(expected_matches)); + return CheckFileStep.create(self.builder, .{ .generated = &self.output_file }, self.builder.dupeStrings(expected_matches)); } fn make(step: *Step) !void {