Commit 437f81aa9a

Felix (xq) Queißner <git@mq32.de>
2021-02-05 15:45:18
Starts to replace special cases in std.build.FileSource.
1 parent 138afd5
Changed files (2)
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 {
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},
     };