Commit 4ed567d12e

Felix (xq) Queißner <git@mq32.de>
2021-02-22 21:23:44
Adds more FileSources everywhere.
1 parent 437f81a
Changed files (4)
lib/std/build/run.zig
@@ -47,12 +47,9 @@ pub const RunStep = struct {
     };
 
     pub const Arg = union(enum) {
-        Artifact: *LibExeObjStep,
-        WriteFile: struct {
-            step: *WriteFileStep,
-            file_name: []const u8,
-        },
-        Bytes: []u8,
+        artifact: *LibExeObjStep,
+        file_source: build.FileSource,
+        bytes: []u8,
     };
 
     pub fn create(builder: *Builder, name: []const u8) *RunStep {
@@ -68,22 +65,19 @@ pub const RunStep = struct {
     }
 
     pub fn addArtifactArg(self: *RunStep, artifact: *LibExeObjStep) void {
-        self.argv.append(Arg{ .Artifact = artifact }) catch unreachable;
+        self.argv.append(Arg{ .artifact = artifact }) catch unreachable;
         self.step.dependOn(&artifact.step);
     }
 
-    pub fn addWriteFileArg(self: *RunStep, write_file: *WriteFileStep, file_name: []const u8) void {
+    pub fn addFileSourceArg(self: *RunStep, file_source: build.FileSource) void {
         self.argv.append(Arg{
-            .WriteFile = .{
-                .step = write_file,
-                .file_name = self.builder.dupePath(file_name),
-            },
+            .file_source = file_source,
         }) catch unreachable;
-        self.step.dependOn(&write_file.step);
+        file_source.addStepDependencies(&self.step);
     }
 
     pub fn addArg(self: *RunStep, arg: []const u8) void {
-        self.argv.append(Arg{ .Bytes = self.builder.dupe(arg) }) catch unreachable;
+        self.argv.append(Arg{ .bytes = self.builder.dupe(arg) }) catch unreachable;
     }
 
     pub fn addArgs(self: *RunStep, args: []const []const u8) void {
@@ -162,11 +156,9 @@ pub const RunStep = struct {
         var argv_list = ArrayList([]const u8).init(self.builder.allocator);
         for (self.argv.items) |arg| {
             switch (arg) {
-                Arg.Bytes => |bytes| try argv_list.append(bytes),
-                Arg.WriteFile => |file| {
-                    try argv_list.append(file.step.getOutputPath(file.file_name));
-                },
-                Arg.Artifact => |artifact| {
+                .bytes => |bytes| try argv_list.append(bytes),
+                .file_source => |file| try argv_list.append(file.getPath(self.builder)),
+                .artifact => |artifact| {
                     if (artifact.target.isWindows()) {
                         // On Windows we don't have rpaths so we have to add .dll search paths to PATH
                         self.addPathForDynLibs(artifact);
lib/std/build/translate_c.zig
@@ -62,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, .{ .generated = &self.output_file }));
+        return self.builder.addExecutableSource("translated_c", build.FileSource{ .generated = &self.output_file }, false);
     }
 
     pub fn addIncludeDir(self: *TranslateCStep, include_dir: []const u8) void {
lib/std/build/write_file.zig
@@ -15,9 +15,10 @@ pub const WriteFileStep = struct {
     step: Step,
     builder: *Builder,
     output_dir: []const u8,
-    files: ArrayList(File),
+    files: std.TailQueue(File),
 
     pub const File = struct {
+        source: build.GeneratedFile,
         basename: []const u8,
         bytes: []const u8,
     };
@@ -26,25 +27,49 @@ pub const WriteFileStep = struct {
         return WriteFileStep{
             .builder = builder,
             .step = Step.init(.WriteFile, "writefile", builder.allocator, make),
-            .files = ArrayList(File).init(builder.allocator),
+            .files = .{},
             .output_dir = undefined,
         };
     }
 
     pub fn add(self: *WriteFileStep, basename: []const u8, bytes: []const u8) void {
-        self.files.append(.{
-            .basename = self.builder.dupePath(basename),
-            .bytes = self.builder.dupe(bytes),
-        }) catch unreachable;
+        const node = self.builder.allocator.create(std.TailQueue(File).Node) catch unreachable;
+        node.* = .{
+            .data = .{
+                .source = build.GeneratedFile{
+                    .step = &self.step,
+                    .getPathFn = getFilePath,
+                },
+                .basename = self.builder.dupePath(basename),
+                .bytes = self.builder.dupe(bytes),
+            },
+        };
+
+        self.files.append(node);
     }
 
     /// 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.
-    pub fn getOutputPath(self: *WriteFileStep, basename: []const u8) []const u8 {
+    //pub const getOutputPath = @compileError("WriteFileStep.getOutputPath is deprecated! Use getFileSource to retrieve a ");
+    /// Gets a file source for the given basename. If the file does not exist, returns `null`.
+    pub fn getFileSource(step: *WriteFileStep, basename: []const u8) ?build.FileSource {
+        var it = step.files.first;
+        while (it) |node| : (it = node.next) {
+            if (std.mem.eql(u8, node.data.basename, basename))
+                return build.FileSource{ .generated = &node.data.source };
+        }
+        return null;
+    }
+
+    /// Returns the
+    fn getFilePath(source: *const build.GeneratedFile) []const u8 {
+        const file = @fieldParentPtr(File, "source", source);
+        const step = @fieldParentPtr(WriteFileStep, "step", source.step);
+
         return fs.path.join(
-            self.builder.allocator,
-            &[_][]const u8{ self.output_dir, basename },
+            step.builder.allocator,
+            &[_][]const u8{ step.output_dir, file.basename },
         ) catch unreachable;
     }
 
@@ -67,10 +92,13 @@ pub const WriteFileStep = struct {
         // new random bytes when WriteFileStep implementation is modified
         // in a non-backwards-compatible way.
         hash.update("eagVR1dYXoE7ARDP");
-        for (self.files.items) |file| {
-            hash.update(file.basename);
-            hash.update(file.bytes);
-            hash.update("|");
+        {
+            var it = self.files.first;
+            while (it) |node| : (it = node.next) {
+                hash.update(node.data.basename);
+                hash.update(node.data.bytes);
+                hash.update("|");
+            }
         }
         var digest: [48]u8 = undefined;
         hash.final(&digest);
@@ -88,15 +116,18 @@ pub const WriteFileStep = struct {
         };
         var dir = try fs.cwd().openDir(self.output_dir, .{});
         defer dir.close();
-        for (self.files.items) |file| {
-            dir.writeFile(file.basename, file.bytes) catch |err| {
-                warn("unable to write {s} into {s}: {s}\n", .{
-                    file.basename,
-                    self.output_dir,
-                    @errorName(err),
-                });
-                return err;
-            };
+        {
+            var it = self.files.first;
+            while (it) |node| : (it = node.next) {
+                dir.writeFile(node.data.basename, node.data.bytes) catch |err| {
+                    warn("unable to write {s} into {s}: {s}\n", .{
+                        node.data.basename,
+                        self.output_dir,
+                        @errorName(err),
+                    });
+                    return err;
+                };
+            }
         }
     }
 };
lib/std/build.zig
@@ -204,55 +204,24 @@ pub const Builder = struct {
         self.h_dir = fs.path.join(self.allocator, &[_][]const u8{ self.install_path, "include" }) catch unreachable;
     }
 
-    pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
-        return LibExeObjStep.createExecutable(
-            self,
-            name,
-            if (root_src) |p| FileSource{ .path = p } else null,
-            false,
-        );
+    fn convertOptionalPathToFileSource(path: ?[]const u8) ?FileSource {
+        return if (path) |p|
+            FileSource.relative(p)
+        else
+            null;
     }
 
-    pub fn addExecutableFromWriteFileStep(
-        self: *Builder,
-        name: []const u8,
-        wfs: *WriteFileStep,
-        basename: []const u8,
-    ) *LibExeObjStep {
-        return LibExeObjStep.createExecutable(self, name, @as(FileSource, .{
-            .write_file = .{
-                .step = wfs,
-                .basename = basename,
-            },
-        }), false);
+    pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
+        return addExecutableSource(self, name, convertOptionalPathToFileSource(root_src), false);
     }
 
-    pub fn addExecutableSource(
-        self: *Builder,
-        name: []const u8,
-        root_src: ?FileSource,
-    ) *LibExeObjStep {
-        return LibExeObjStep.createExecutable(self, name, root_src, false);
-    }
+    pub const addExecutableSource = LibExeObjStep.createExecutable;
 
     pub fn addObject(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
-        const root_src_param = if (root_src) |p| @as(FileSource, .{ .path = p }) else null;
-        return LibExeObjStep.createObject(self, name, root_src_param);
+        return addObjectSource(self, name, convertOptionalPathToFileSource(root_src));
     }
 
-    pub fn addObjectFromWriteFileStep(
-        self: *Builder,
-        name: []const u8,
-        wfs: *WriteFileStep,
-        basename: []const u8,
-    ) *LibExeObjStep {
-        return LibExeObjStep.createObject(self, name, @as(FileSource, .{
-            .write_file = .{
-                .step = wfs,
-                .basename = basename,
-            },
-        }));
-    }
+    pub const addObjectSource = LibExeObjStep.createObject;
 
     pub fn addSharedLibrary(
         self: *Builder,
@@ -260,64 +229,33 @@ pub const Builder = struct {
         root_src: ?[]const u8,
         kind: LibExeObjStep.SharedLibKind,
     ) *LibExeObjStep {
-        const root_src_param = if (root_src) |p| @as(FileSource, .{ .path = p }) else null;
-        return LibExeObjStep.createSharedLibrary(self, name, root_src_param, kind);
+        return addSharedLibrarySource(self, name, convertOptionalPathToFileSource(root_src), kind);
     }
 
-    pub fn addSharedLibraryFromWriteFileStep(
-        self: *Builder,
-        name: []const u8,
-        wfs: *WriteFileStep,
-        basename: []const u8,
-        kind: LibExeObjStep.SharedLibKind,
-    ) *LibExeObjStep {
-        return LibExeObjStep.createSharedLibrary(self, name, @as(FileSource, .{
-            .write_file = .{
-                .step = wfs,
-                .basename = basename,
-            },
-        }), kind);
-    }
+    pub const addSharedLibrarySource = LibExeObjStep.createSharedLibrary;
 
     pub fn addStaticLibrary(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
         const root_src_param = if (root_src) |p| @as(FileSource, .{ .path = p }) else null;
         return LibExeObjStep.createStaticLibrary(self, name, root_src_param);
     }
 
-    pub fn addStaticLibraryFromWriteFileStep(
-        self: *Builder,
-        name: []const u8,
-        wfs: *WriteFileStep,
-        basename: []const u8,
-    ) *LibExeObjStep {
-        return LibExeObjStep.createStaticLibrary(self, name, @as(FileSource, .{
-            .write_file = .{
-                .step = wfs,
-                .basename = basename,
-            },
-        }));
-    }
+    pub const addStaticLibrarySource = LibExeObjStep.createStaticLibrary;
 
     pub fn addTest(self: *Builder, root_src: []const u8) *LibExeObjStep {
         return LibExeObjStep.createTest(self, "test", .{ .path = root_src });
     }
 
-    pub fn addTestFromWriteFileStep(
-        self: *Builder,
-        wfs: *WriteFileStep,
-        basename: []const u8,
-    ) *LibExeObjStep {
-        return LibExeObjStep.createTest(self, "test", @as(FileSource, .{
-            .write_file = .{
-                .step = wfs,
-                .basename = basename,
-            },
-        }));
+    pub fn addTestSource(self: *Builder, root_src: FileSource) *LibExeObjStep {
+        return LibExeObjStep.createTest(self, "test", root_src);
     }
 
     pub fn addAssemble(self: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {
+        return addAssembleSource(self, name, FileSource.relative(src));
+    }
+
+    pub fn addAssembleSource(self: *Builder, name: []const u8, src: FileSource) *LibExeObjStep {
         const obj_step = LibExeObjStep.createObject(self, name, null);
-        obj_step.addAssemblyFile(src);
+        obj_step.addAssemblyFileSource(src);
         return obj_step;
     }
 
@@ -938,7 +876,7 @@ pub const Builder = struct {
 
     ///`dest_rel_path` is relative to prefix path
     pub fn installFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) void {
-        self.getInstallStep().dependOn(&self.addInstallFileWithDir(src_path, .Prefix, dest_rel_path).step);
+        self.getInstallStep().dependOn(&self.addInstallFileWithDir(FileSource.relative(src_path), .Prefix, dest_rel_path).step);
     }
 
     pub fn installDirectory(self: *Builder, options: InstallDirectoryOptions) void {
@@ -947,12 +885,12 @@ pub const Builder = struct {
 
     ///`dest_rel_path` is relative to bin path
     pub fn installBinFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) void {
-        self.getInstallStep().dependOn(&self.addInstallFileWithDir(src_path, .Bin, dest_rel_path).step);
+        self.getInstallStep().dependOn(&self.addInstallFileWithDir(FileSource.relative(src_path), .Bin, dest_rel_path).step);
     }
 
     ///`dest_rel_path` is relative to lib path
     pub fn installLibFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) void {
-        self.getInstallStep().dependOn(&self.addInstallFileWithDir(src_path, .Lib, dest_rel_path).step);
+        self.getInstallStep().dependOn(&self.addInstallFileWithDir(FileSource.relative(src_path), .Lib, dest_rel_path).step);
     }
 
     pub fn installRaw(self: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8) void {
@@ -961,17 +899,17 @@ pub const Builder = struct {
 
     ///`dest_rel_path` is relative to install prefix path
     pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep {
-        return self.addInstallFileWithDir(src_path, .Prefix, dest_rel_path);
+        return self.addInstallFileWithDir(FileSource.relative(src_path), .Prefix, dest_rel_path);
     }
 
     ///`dest_rel_path` is relative to bin path
     pub fn addInstallBinFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep {
-        return self.addInstallFileWithDir(src_path, .Bin, dest_rel_path);
+        return self.addInstallFileWithDir(FileSource.relative(src_path), .Bin, dest_rel_path);
     }
 
     ///`dest_rel_path` is relative to lib path
     pub fn addInstallLibFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep {
-        return self.addInstallFileWithDir(src_path, .Lib, dest_rel_path);
+        return self.addInstallFileWithDir(FileSource.relative(src_path), .Lib, dest_rel_path);
     }
 
     pub fn addInstallRaw(self: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8) *InstallRawStep {
@@ -980,7 +918,7 @@ pub const Builder = struct {
 
     pub fn addInstallFileWithDir(
         self: *Builder,
-        src_path: []const u8,
+        source: FileSource,
         install_dir: InstallDir,
         dest_rel_path: []const u8,
     ) *InstallFileStep {
@@ -988,7 +926,7 @@ pub const Builder = struct {
             panic("dest_rel_path must be non-empty", .{});
         }
         const install_step = self.allocator.create(InstallFileStep) catch unreachable;
-        install_step.* = InstallFileStep.init(self, src_path, install_dir, dest_rel_path);
+        install_step.* = InstallFileStep.init(self, source, install_dir, dest_rel_path);
         return install_step;
     }
 
@@ -1301,42 +1239,41 @@ pub const GeneratedFile = struct {
 pub const FileSource = union(enum) {
     /// Relative to build root
     path: []const u8,
-    write_file: struct {
-        step: *WriteFileStep,
-        basename: []const u8,
-    },
     generated: *const GeneratedFile,
 
     pub fn relative(path: []const u8) FileSource {
         return FileSource{ .path = path };
     }
 
+    /// Returns a string that can be shown to represent the file source.
+    /// Either returns the path or `"generated"`.
+    pub fn getDisplayName(self: FileSource) []const u8 {
+        return switch (self) {
+            .path => self.path,
+            .generated => "generated",
+        };
+    }
+
     pub fn addStepDependencies(self: FileSource, step: *Step) void {
         switch (self) {
             .path => {},
-            .write_file => |wf| step.dependOn(&wf.step.step),
             .generated => |gen| step.dependOn(gen.step),
         }
     }
 
-    /// Should only be called during make()
+    /// Should only be called during make(), returns an absolute path to the file.
     pub fn getPath(self: FileSource, builder: *Builder) []const u8 {
-        return switch (self) {
+        const path = switch (self) {
             .path => |p| builder.pathFromRoot(p),
-            .write_file => |wf| wf.step.getOutputPath(wf.basename),
             .generated => |gen| gen.getPath(),
         };
+        std.debug.assert(std.fs.path.isAbsolute(path));
+        return path;
     }
 
     pub fn dupe(self: FileSource, b: *Builder) FileSource {
         return switch (self) {
             .path => |p| .{ .path = b.dupePath(p) },
-            .write_file => |wf| .{
-                .write_file = .{
-                    .step = wf.step,
-                    .basename = b.dupe(wf.basename),
-                },
-            },
             .generated => |gen| .{ .generated = gen },
         };
     }
@@ -1967,15 +1904,6 @@ pub const LibExeObjStep = struct {
         }) catch unreachable;
     }
 
-    pub fn addAssemblyFileFromWriteFileStep(self: *LibExeObjStep, wfs: *WriteFileStep, basename: []const u8) void {
-        self.addAssemblyFileSource(.{
-            .write_file = .{
-                .step = wfs,
-                .basename = self.builder.dupe(basename),
-            },
-        });
-    }
-
     pub fn addAssemblyFileSource(self: *LibExeObjStep, source: FileSource) void {
         const source_duped = source.dupe(self.builder);
         self.link_objects.append(LinkObject{ .AssemblyFile = source_duped }) catch unreachable;
@@ -2834,21 +2762,21 @@ pub const InstallArtifactStep = struct {
 pub const InstallFileStep = struct {
     step: Step,
     builder: *Builder,
-    src_path: []const u8,
+    source: FileSource,
     dir: InstallDir,
     dest_rel_path: []const u8,
 
     pub fn init(
         builder: *Builder,
-        src_path: []const u8,
+        source: FileSource,
         dir: InstallDir,
         dest_rel_path: []const u8,
     ) InstallFileStep {
         builder.pushInstalledFile(dir, dest_rel_path);
         return InstallFileStep{
             .builder = builder,
-            .step = Step.init(.InstallFile, builder.fmt("install {s}", .{src_path}), builder.allocator, make),
-            .src_path = builder.dupePath(src_path),
+            .step = Step.init(.InstallFile, builder.fmt("install {s} to {s}", .{ source.getDisplayName(), dest_rel_path }), builder.allocator, make),
+            .source = source.dupe(builder),
             .dir = dir.dupe(builder),
             .dest_rel_path = builder.dupePath(dest_rel_path),
         };
@@ -2857,7 +2785,7 @@ pub const InstallFileStep = struct {
     fn make(step: *Step) !void {
         const self = @fieldParentPtr(InstallFileStep, "step", step);
         const full_dest_path = self.builder.getInstallPath(self.dir, self.dest_rel_path);
-        const full_src_path = self.builder.pathFromRoot(self.src_path);
+        const full_src_path = self.source.getPath(self.builder);
         try self.builder.updateFile(full_src_path, full_dest_path);
     }
 };