| author | |
| committer | |
| log | b4dbe483a720f3e06559e659a410152511087395 |
| tree | 786b85f7c6237896c59dc70bbae95a46387f491b |
| parent | e3b7cad81e483dc79716a388676f39c483589642 |
Remove the RemoveDir step with no replacement. This step had no valid
purpose. Mutating source files? That should be done with
UpdateSourceFiles step. Deleting temporary directories? That required
creating the tmp directories in the configure phase which is broken.
Deleting cached artifacts? That's going to cause problems.
Similarly, remove the `Build.makeTempPath` function. This was used to
create a temporary path in the configure place which, again, is the
wrong place to do it.
Instead, the WriteFile step has been updated with more functionality:
tmp mode: In this mode, the directory will be placed inside "tmp" rather
than "o", and caching will be skipped. During the `make` phase, the step
will always do all the file system operations, and on successful build
completion, the dir will be deleted along with all other tmp
directories. The directory is therefore eligible to be used for
mutations by other steps. `Build.addTempFiles` is introduced to
initialize a WriteFile step with this mode.
mutate mode: The operations will not be performed against a freshly
created directory, but instead act against a temporary directory.
`Build.addMutateFiles` is introduced to initialize a WriteFile step with
this mode.
`Build.tmpPath` is introduced, which is a shortcut for
`Build.addTempFiles` followed by `WriteFile.getDirectory`.
* give Cache a gpa rather than arena because that's what it asks for7 files changed, 218 insertions(+), 213 deletions(-)
lib/compiler/build_runner.zig+1-1| ... | @@ -82,7 +82,7 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -82,7 +82,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 82 | .arena = arena, | 82 | .arena = arena, |
| 83 | .cache = .{ | 83 | .cache = .{ |
| 84 | .io = io, | 84 | .io = io, |
| 85 | .gpa = arena, | 85 | .gpa = gpa, |
| 86 | .manifest_dir = try local_cache_directory.handle.createDirPathOpen(io, "h", .{}), | 86 | .manifest_dir = try local_cache_directory.handle.createDirPathOpen(io, "h", .{}), |
| 87 | .cwd = try process.getCwdAlloc(single_threaded_arena.allocator()), | 87 | .cwd = try process.getCwdAlloc(single_threaded_arena.allocator()), |
| 88 | }, | 88 | }, |
lib/std/Build.zig+42-19| ... | @@ -111,6 +111,7 @@ pub const ReleaseMode = enum { | ... | @@ -111,6 +111,7 @@ pub const ReleaseMode = enum { |
| 111 | /// Settings that are here rather than in Build are not configurable per-package. | 111 | /// Settings that are here rather than in Build are not configurable per-package. |
| 112 | pub const Graph = struct { | 112 | pub const Graph = struct { |
| 113 | io: Io, | 113 | io: Io, |
| 114 | /// Process lifetime. | ||
| 114 | arena: Allocator, | 115 | arena: Allocator, |
| 115 | system_library_options: std.StringArrayHashMapUnmanaged(SystemLibraryMode) = .empty, | 116 | system_library_options: std.StringArrayHashMapUnmanaged(SystemLibraryMode) = .empty, |
| 116 | system_package_mode: bool = false, | 117 | system_package_mode: bool = false, |
| ... | @@ -1057,6 +1058,38 @@ pub fn addNamedLazyPath(b: *Build, name: []const u8, lp: LazyPath) void { | ... | @@ -1057,6 +1058,38 @@ pub fn addNamedLazyPath(b: *Build, name: []const u8, lp: LazyPath) void { |
| 1057 | b.named_lazy_paths.put(b.dupe(name), lp.dupe(b)) catch @panic("OOM"); | 1058 | b.named_lazy_paths.put(b.dupe(name), lp.dupe(b)) catch @panic("OOM"); |
| 1058 | } | 1059 | } |
| 1059 | 1060 | ||
| 1061 | /// Creates a step for mutating files inside a temporary directory created lazily | ||
| 1062 | /// and automatically cleaned up upon successful build. | ||
| 1063 | /// | ||
| 1064 | /// The directory will be placed inside "tmp" rather than "o", and caching will | ||
| 1065 | /// be skipped. During the `make` phase, the step will always do all the file | ||
| 1066 | /// system operations, and on successful build completion, the dir will be | ||
| 1067 | /// deleted along with all other tmp directories. The directory is therefore | ||
| 1068 | /// eligible to be used for mutations by other steps. | ||
| 1069 | /// | ||
| 1070 | /// See also: | ||
| 1071 | /// * `addWriteFiles` | ||
| 1072 | /// * `addMutateFiles` | ||
| 1073 | pub fn addTempFiles(b: *Build) *Step.WriteFile { | ||
| 1074 | const wf = addWriteFiles(b); | ||
| 1075 | wf.mode = .tmp; | ||
| 1076 | return wf; | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | /// Creates a step for mutating temporary directories created with `addTempFiles`. | ||
| 1080 | /// | ||
| 1081 | /// Consider instead `addWriteFiles` which is for creating a cached directory | ||
| 1082 | /// of files to operate on. | ||
| 1083 | /// | ||
| 1084 | /// This should only be used with a `tmp_path` obtained via `addTempFiles` or | ||
| 1085 | /// `tmpPath`. | ||
| 1086 | pub fn addMutateFiles(b: *Build, tmp_path: LazyPath) *Step.WriteFile { | ||
| 1087 | const wf = addWriteFiles(b); | ||
| 1088 | wf.mode = .{ .mutate = tmp_path }; | ||
| 1089 | tmp_path.addStepDependencies(&wf.step); | ||
| 1090 | return wf; | ||
| 1091 | } | ||
| 1092 | |||
| 1060 | pub fn addWriteFiles(b: *Build) *Step.WriteFile { | 1093 | pub fn addWriteFiles(b: *Build) *Step.WriteFile { |
| 1061 | return Step.WriteFile.create(b); | 1094 | return Step.WriteFile.create(b); |
| 1062 | } | 1095 | } |
| ... | @@ -1065,10 +1098,6 @@ pub fn addUpdateSourceFiles(b: *Build) *Step.UpdateSourceFiles { | ... | @@ -1065,10 +1098,6 @@ pub fn addUpdateSourceFiles(b: *Build) *Step.UpdateSourceFiles { |
| 1065 | return Step.UpdateSourceFiles.create(b); | 1098 | return Step.UpdateSourceFiles.create(b); |
| 1066 | } | 1099 | } |
| 1067 | 1100 | ||
| 1068 | pub fn addRemoveDirTree(b: *Build, dir_path: LazyPath) *Step.RemoveDir { | ||
| 1069 | return Step.RemoveDir.create(b, dir_path); | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | pub fn addFail(b: *Build, error_msg: []const u8) *Step.Fail { | 1101 | pub fn addFail(b: *Build, error_msg: []const u8) *Step.Fail { |
| 1073 | return Step.Fail.create(b, error_msg); | 1102 | return Step.Fail.create(b, error_msg); |
| 1074 | } | 1103 | } |
| ... | @@ -2235,9 +2264,8 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void { | ... | @@ -2235,9 +2264,8 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void { |
| 2235 | /// A file that is generated by a build step. | 2264 | /// A file that is generated by a build step. |
| 2236 | /// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic. | 2265 | /// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic. |
| 2237 | pub const GeneratedFile = struct { | 2266 | pub const GeneratedFile = struct { |
| 2238 | /// The step that generates the file | 2267 | /// The step that generates the file. |
| 2239 | step: *Step, | 2268 | step: *Step, |
| 2240 | |||
| 2241 | /// The path to the generated file. Must be either absolute or relative to the build runner cwd. | 2269 | /// The path to the generated file. Must be either absolute or relative to the build runner cwd. |
| 2242 | /// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards. | 2270 | /// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards. |
| 2243 | path: ?[]const u8 = null, | 2271 | path: ?[]const u8 = null, |
| ... | @@ -2321,9 +2349,11 @@ pub const LazyPath = union(enum) { | ... | @@ -2321,9 +2349,11 @@ pub const LazyPath = union(enum) { |
| 2321 | 2349 | ||
| 2322 | /// An absolute path or a path relative to the current working directory of | 2350 | /// An absolute path or a path relative to the current working directory of |
| 2323 | /// the build runner process. | 2351 | /// the build runner process. |
| 2352 | /// | ||
| 2324 | /// This is uncommon but used for system environment paths such as `--zig-lib-dir` which | 2353 | /// This is uncommon but used for system environment paths such as `--zig-lib-dir` which |
| 2325 | /// ignore the file system path of build.zig and instead are relative to the directory from | 2354 | /// ignore the file system path of build.zig and instead are relative to the directory from |
| 2326 | /// which `zig build` was invoked. | 2355 | /// which `zig build` was invoked. |
| 2356 | /// | ||
| 2327 | /// Use of this tag indicates a dependency on the host system. | 2357 | /// Use of this tag indicates a dependency on the host system. |
| 2328 | cwd_relative: []const u8, | 2358 | cwd_relative: []const u8, |
| 2329 | 2359 | ||
| ... | @@ -2646,19 +2676,12 @@ pub const InstallDir = union(enum) { | ... | @@ -2646,19 +2676,12 @@ pub const InstallDir = union(enum) { |
| 2646 | } | 2676 | } |
| 2647 | }; | 2677 | }; |
| 2648 | 2678 | ||
| 2649 | /// This function is intended to be called in the `configure` phase only. | 2679 | /// Creates a path leading to a directory inside "tmp" subdirectory of |
| 2650 | /// It returns an absolute directory path, which is potentially going to be a | 2680 | /// `cache_root` which is created on demand and cleaned up by the build runner |
| 2651 | /// source of API breakage in the future, so keep that in mind when using this | 2681 | /// upon success. |
| 2652 | /// function. | 2682 | pub fn tmpPath(b: *Build) LazyPath { |
| 2653 | pub fn makeTempPath(b: *Build) []const u8 { | 2683 | const wf = b.addTempFiles(); |
| 2654 | const io = b.graph.io; | 2684 | return wf.getDirectory(); |
| 2655 | const rand_int = std.crypto.random.int(u64); | ||
| 2656 | const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); | ||
| 2657 | const result_path = b.cache_root.join(b.allocator, &.{tmp_dir_sub_path}) catch @panic("OOM"); | ||
| 2658 | b.cache_root.handle.createDirPath(io, tmp_dir_sub_path) catch |err| { | ||
| 2659 | std.debug.print("unable to make tmp path '{s}': {t}\n", .{ result_path, err }); | ||
| 2660 | }; | ||
| 2661 | return result_path; | ||
| 2662 | } | 2685 | } |
| 2663 | 2686 | ||
| 2664 | /// A pair of target query and fully resolved target. | 2687 | /// A pair of target query and fully resolved target. |
lib/std/Build/Step.zig-3| ... | @@ -173,7 +173,6 @@ pub const Id = enum { | ... | @@ -173,7 +173,6 @@ pub const Id = enum { |
| 173 | .install_artifact => InstallArtifact, | 173 | .install_artifact => InstallArtifact, |
| 174 | .install_file => InstallFile, | 174 | .install_file => InstallFile, |
| 175 | .install_dir => InstallDir, | 175 | .install_dir => InstallDir, |
| 176 | .remove_dir => RemoveDir, | ||
| 177 | .fail => Fail, | 176 | .fail => Fail, |
| 178 | .fmt => Fmt, | 177 | .fmt => Fmt, |
| 179 | .translate_c => TranslateC, | 178 | .translate_c => TranslateC, |
| ... | @@ -201,7 +200,6 @@ pub const InstallFile = @import("Step/InstallFile.zig"); | ... | @@ -201,7 +200,6 @@ pub const InstallFile = @import("Step/InstallFile.zig"); |
| 201 | pub const ObjCopy = @import("Step/ObjCopy.zig"); | 200 | pub const ObjCopy = @import("Step/ObjCopy.zig"); |
| 202 | pub const Compile = @import("Step/Compile.zig"); | 201 | pub const Compile = @import("Step/Compile.zig"); |
| 203 | pub const Options = @import("Step/Options.zig"); | 202 | pub const Options = @import("Step/Options.zig"); |
| 204 | pub const RemoveDir = @import("Step/RemoveDir.zig"); | ||
| 205 | pub const Run = @import("Step/Run.zig"); | 203 | pub const Run = @import("Step/Run.zig"); |
| 206 | pub const TranslateC = @import("Step/TranslateC.zig"); | 204 | pub const TranslateC = @import("Step/TranslateC.zig"); |
| 207 | pub const WriteFile = @import("Step/WriteFile.zig"); | 205 | pub const WriteFile = @import("Step/WriteFile.zig"); |
| ... | @@ -1008,7 +1006,6 @@ test { | ... | @@ -1008,7 +1006,6 @@ test { |
| 1008 | _ = ObjCopy; | 1006 | _ = ObjCopy; |
| 1009 | _ = Compile; | 1007 | _ = Compile; |
| 1010 | _ = Options; | 1008 | _ = Options; |
| 1011 | _ = RemoveDir; | ||
| 1012 | _ = Run; | 1009 | _ = Run; |
| 1013 | _ = TranslateC; | 1010 | _ = TranslateC; |
| 1014 | _ = WriteFile; | 1011 | _ = WriteFile; |
lib/std/Build/Step/RemoveDir.zig deleted-45| ... | @@ -1,45 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const fs = std.fs; | ||
| 3 | const Step = std.Build.Step; | ||
| 4 | const RemoveDir = @This(); | ||
| 5 | const LazyPath = std.Build.LazyPath; | ||
| 6 | |||
| 7 | pub const base_id: Step.Id = .remove_dir; | ||
| 8 | |||
| 9 | step: Step, | ||
| 10 | doomed_path: LazyPath, | ||
| 11 | |||
| 12 | pub fn create(owner: *std.Build, doomed_path: LazyPath) *RemoveDir { | ||
| 13 | const remove_dir = owner.allocator.create(RemoveDir) catch @panic("OOM"); | ||
| 14 | remove_dir.* = .{ | ||
| 15 | .step = Step.init(.{ | ||
| 16 | .id = base_id, | ||
| 17 | .name = owner.fmt("RemoveDir {s}", .{doomed_path.getDisplayName()}), | ||
| 18 | .owner = owner, | ||
| 19 | .makeFn = make, | ||
| 20 | }), | ||
| 21 | .doomed_path = doomed_path.dupe(owner), | ||
| 22 | }; | ||
| 23 | return remove_dir; | ||
| 24 | } | ||
| 25 | |||
| 26 | fn make(step: *Step, options: Step.MakeOptions) !void { | ||
| 27 | _ = options; | ||
| 28 | |||
| 29 | const b = step.owner; | ||
| 30 | const io = b.graph.io; | ||
| 31 | const remove_dir: *RemoveDir = @fieldParentPtr("step", step); | ||
| 32 | |||
| 33 | step.clearWatchInputs(); | ||
| 34 | try step.addWatchInput(remove_dir.doomed_path); | ||
| 35 | |||
| 36 | const full_doomed_path = remove_dir.doomed_path.getPath2(b, step); | ||
| 37 | |||
| 38 | b.build_root.handle.deleteTree(io, full_doomed_path) catch |err| { | ||
| 39 | if (b.build_root.path) |base| { | ||
| 40 | return step.fail("unable to recursively delete path '{s}/{s}': {t}", .{ base, full_doomed_path, err }); | ||
| 41 | } else { | ||
| 42 | return step.fail("unable to recursively delete path '{s}': {t}", .{ full_doomed_path, err }); | ||
| 43 | } | ||
| 44 | }; | ||
| 45 | } | ||
lib/std/Build/Step/WriteFile.zig+142-84| ... | @@ -1,22 +1,42 @@ | ... | @@ -1,22 +1,42 @@ |
| 1 | //! WriteFile is used to create a directory in an appropriate location inside | 1 | //! WriteFile is used to create a directory in an appropriate location inside |
| 2 | //! the local cache which has a set of files that have either been generated | 2 | //! the local cache which has a set of files that have either been generated |
| 3 | //! during the build, or are copied from the source package. | 3 | //! during the build, or are copied from the source package. |
| 4 | const WriteFile = @This(); | ||
| 5 | |||
| 4 | const std = @import("std"); | 6 | const std = @import("std"); |
| 5 | const Io = std.Io; | 7 | const Io = std.Io; |
| 8 | const Dir = std.Io.Dir; | ||
| 6 | const Step = std.Build.Step; | 9 | const Step = std.Build.Step; |
| 7 | const fs = std.fs; | ||
| 8 | const ArrayList = std.ArrayList; | 10 | const ArrayList = std.ArrayList; |
| 9 | const WriteFile = @This(); | 11 | const assert = std.debug.assert; |
| 10 | 12 | ||
| 11 | step: Step, | 13 | step: Step, |
| 12 | 14 | ||
| 13 | // The elements here are pointers because we need stable pointers for the GeneratedFile field. | 15 | /// The elements here are pointers because we need stable pointers for the GeneratedFile field. |
| 14 | files: std.ArrayList(File), | 16 | files: std.ArrayList(File), |
| 15 | directories: std.ArrayList(Directory), | 17 | directories: std.ArrayList(Directory), |
| 16 | generated_directory: std.Build.GeneratedFile, | 18 | generated_directory: std.Build.GeneratedFile, |
| 19 | mode: Mode = .whole_cached, | ||
| 17 | 20 | ||
| 18 | pub const base_id: Step.Id = .write_file; | 21 | pub const base_id: Step.Id = .write_file; |
| 19 | 22 | ||
| 23 | pub const Mode = union(enum) { | ||
| 24 | /// Default mode. Integrates with the cache system. The directory should be | ||
| 25 | /// read-only during the make phase. Any different inputs result in | ||
| 26 | /// different "o" subdirectory. | ||
| 27 | whole_cached, | ||
| 28 | /// In this mode, the directory will be placed inside "tmp" rather than | ||
| 29 | /// "o", and caching will be skipped. During the `make` phase, the step | ||
| 30 | /// will always do all the file system operations, and on successful build | ||
| 31 | /// completion, the dir will be deleted along with all other tmp | ||
| 32 | /// directories. The directory is therefore eligible to be used for | ||
| 33 | /// mutations by other steps. | ||
| 34 | tmp, | ||
| 35 | /// The operations will not be performed against a freshly created | ||
| 36 | /// directory, but instead act against a temporary directory. | ||
| 37 | mutate: std.Build.LazyPath, | ||
| 38 | }; | ||
| 39 | |||
| 20 | pub const File = struct { | 40 | pub const File = struct { |
| 21 | sub_path: []const u8, | 41 | sub_path: []const u8, |
| 22 | contents: Contents, | 42 | contents: Contents, |
| ... | @@ -175,115 +195,155 @@ fn maybeUpdateName(write_file: *WriteFile) void { | ... | @@ -175,115 +195,155 @@ fn maybeUpdateName(write_file: *WriteFile) void { |
| 175 | fn make(step: *Step, options: Step.MakeOptions) !void { | 195 | fn make(step: *Step, options: Step.MakeOptions) !void { |
| 176 | _ = options; | 196 | _ = options; |
| 177 | const b = step.owner; | 197 | const b = step.owner; |
| 178 | const io = b.graph.io; | 198 | const graph = b.graph; |
| 199 | const io = graph.io; | ||
| 179 | const arena = b.allocator; | 200 | const arena = b.allocator; |
| 180 | const gpa = arena; | 201 | const gpa = graph.cache.gpa; |
| 181 | const write_file: *WriteFile = @fieldParentPtr("step", step); | 202 | const write_file: *WriteFile = @fieldParentPtr("step", step); |
| 182 | step.clearWatchInputs(); | ||
| 183 | |||
| 184 | // The cache is used here not really as a way to speed things up - because writing | ||
| 185 | // the data to a file would probably be very fast - but as a way to find a canonical | ||
| 186 | // location to put build artifacts. | ||
| 187 | 203 | ||
| 188 | // If, for example, a hard-coded path was used as the location to put WriteFile | 204 | const open_dir_cache = try arena.alloc(Io.Dir, write_file.directories.items.len); |
| 189 | // files, then two WriteFiles executing in parallel might clobber each other. | 205 | var open_dirs_count: usize = 0; |
| 206 | defer Io.Dir.closeMany(io, open_dir_cache[0..open_dirs_count]); | ||
| 190 | 207 | ||
| 191 | var man = b.graph.cache.obtain(); | 208 | switch (write_file.mode) { |
| 192 | defer man.deinit(); | 209 | .whole_cached => { |
| 210 | step.clearWatchInputs(); | ||
| 193 | 211 | ||
| 194 | for (write_file.files.items) |file| { | 212 | // The cache is used here not really as a way to speed things up - because writing |
| 195 | man.hash.addBytes(file.sub_path); | 213 | // the data to a file would probably be very fast - but as a way to find a canonical |
| 214 | // location to put build artifacts. | ||
| 196 | 215 | ||
| 197 | switch (file.contents) { | 216 | // If, for example, a hard-coded path was used as the location to put WriteFile |
| 198 | .bytes => |bytes| { | 217 | // files, then two WriteFiles executing in parallel might clobber each other. |
| 199 | man.hash.addBytes(bytes); | ||
| 200 | }, | ||
| 201 | .copy => |lazy_path| { | ||
| 202 | const path = lazy_path.getPath3(b, step); | ||
| 203 | _ = try man.addFilePath(path, null); | ||
| 204 | try step.addWatchInput(lazy_path); | ||
| 205 | }, | ||
| 206 | } | ||
| 207 | } | ||
| 208 | 218 | ||
| 209 | const open_dir_cache = try arena.alloc(Io.Dir, write_file.directories.items.len); | 219 | var man = b.graph.cache.obtain(); |
| 210 | var open_dirs_count: usize = 0; | 220 | defer man.deinit(); |
| 211 | defer Io.Dir.closeMany(io, open_dir_cache[0..open_dirs_count]); | ||
| 212 | 221 | ||
| 213 | for (write_file.directories.items, open_dir_cache) |dir, *open_dir_cache_elem| { | 222 | for (write_file.files.items) |file| { |
| 214 | man.hash.addBytes(dir.sub_path); | 223 | man.hash.addBytes(file.sub_path); |
| 215 | for (dir.options.exclude_extensions) |ext| man.hash.addBytes(ext); | ||
| 216 | if (dir.options.include_extensions) |incs| for (incs) |inc| man.hash.addBytes(inc); | ||
| 217 | 224 | ||
| 218 | const need_derived_inputs = try step.addDirectoryWatchInput(dir.source); | 225 | switch (file.contents) { |
| 219 | const src_dir_path = dir.source.getPath3(b, step); | 226 | .bytes => |bytes| { |
| 227 | man.hash.addBytes(bytes); | ||
| 228 | }, | ||
| 229 | .copy => |lazy_path| { | ||
| 230 | const path = lazy_path.getPath3(b, step); | ||
| 231 | _ = try man.addFilePath(path, null); | ||
| 232 | try step.addWatchInput(lazy_path); | ||
| 233 | }, | ||
| 234 | } | ||
| 235 | } | ||
| 220 | 236 | ||
| 221 | var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { | 237 | for (write_file.directories.items, open_dir_cache) |dir, *open_dir_cache_elem| { |
| 222 | return step.fail("unable to open source directory '{f}': {s}", .{ | 238 | man.hash.addBytes(dir.sub_path); |
| 223 | src_dir_path, @errorName(err), | 239 | for (dir.options.exclude_extensions) |ext| man.hash.addBytes(ext); |
| 224 | }); | 240 | if (dir.options.include_extensions) |incs| for (incs) |inc| man.hash.addBytes(inc); |
| 225 | }; | ||
| 226 | open_dir_cache_elem.* = src_dir; | ||
| 227 | open_dirs_count += 1; | ||
| 228 | 241 | ||
| 229 | var it = try src_dir.walk(gpa); | 242 | const need_derived_inputs = try step.addDirectoryWatchInput(dir.source); |
| 230 | defer it.deinit(); | 243 | const src_dir_path = dir.source.getPath3(b, step); |
| 231 | while (try it.next(io)) |entry| { | ||
| 232 | if (!dir.options.pathIncluded(entry.path)) continue; | ||
| 233 | 244 | ||
| 234 | switch (entry.kind) { | 245 | var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { |
| 235 | .directory => { | 246 | return step.fail("unable to open source directory '{f}': {s}", .{ |
| 236 | if (need_derived_inputs) { | 247 | src_dir_path, @errorName(err), |
| 237 | const entry_path = try src_dir_path.join(arena, entry.path); | 248 | }); |
| 238 | try step.addDirectoryWatchInputFromPath(entry_path); | 249 | }; |
| 250 | open_dir_cache_elem.* = src_dir; | ||
| 251 | open_dirs_count += 1; | ||
| 252 | |||
| 253 | var it = try src_dir.walk(gpa); | ||
| 254 | defer it.deinit(); | ||
| 255 | while (try it.next(io)) |entry| { | ||
| 256 | if (!dir.options.pathIncluded(entry.path)) continue; | ||
| 257 | |||
| 258 | switch (entry.kind) { | ||
| 259 | .directory => { | ||
| 260 | if (need_derived_inputs) { | ||
| 261 | const entry_path = try src_dir_path.join(arena, entry.path); | ||
| 262 | try step.addDirectoryWatchInputFromPath(entry_path); | ||
| 263 | } | ||
| 264 | }, | ||
| 265 | .file => { | ||
| 266 | const entry_path = try src_dir_path.join(arena, entry.path); | ||
| 267 | _ = try man.addFilePath(entry_path, null); | ||
| 268 | }, | ||
| 269 | else => continue, | ||
| 239 | } | 270 | } |
| 240 | }, | 271 | } |
| 241 | .file => { | ||
| 242 | const entry_path = try src_dir_path.join(arena, entry.path); | ||
| 243 | _ = try man.addFilePath(entry_path, null); | ||
| 244 | }, | ||
| 245 | else => continue, | ||
| 246 | } | 272 | } |
| 247 | } | ||
| 248 | } | ||
| 249 | 273 | ||
| 250 | if (try step.cacheHit(&man)) { | 274 | if (try step.cacheHit(&man)) { |
| 251 | const digest = man.final(); | 275 | const digest = man.final(); |
| 252 | write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest }); | 276 | write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest }); |
| 253 | step.result_cached = true; | 277 | assert(step.result_cached); |
| 254 | return; | 278 | return; |
| 255 | } | 279 | } |
| 280 | |||
| 281 | const digest = man.final(); | ||
| 282 | const cache_path = "o" ++ Dir.path.sep_str ++ digest; | ||
| 283 | |||
| 284 | write_file.generated_directory.path = try b.cache_root.join(arena, &.{cache_path}); | ||
| 285 | |||
| 286 | try operate(write_file, open_dir_cache, .{ | ||
| 287 | .root_dir = b.cache_root, | ||
| 288 | .sub_path = cache_path, | ||
| 289 | }); | ||
| 290 | |||
| 291 | try step.writeManifest(&man); | ||
| 292 | }, | ||
| 293 | .tmp => { | ||
| 294 | step.result_cached = false; | ||
| 295 | |||
| 296 | const rand_int = std.crypto.random.int(u64); | ||
| 297 | const tmp_dir_sub_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int); | ||
| 256 | 298 | ||
| 257 | const digest = man.final(); | 299 | write_file.generated_directory.path = try b.cache_root.join(arena, &.{tmp_dir_sub_path}); |
| 258 | const cache_path = "o" ++ fs.path.sep_str ++ digest; | 300 | |
| 301 | try operate(write_file, open_dir_cache, .{ | ||
| 302 | .root_dir = b.cache_root, | ||
| 303 | .sub_path = tmp_dir_sub_path, | ||
| 304 | }); | ||
| 305 | }, | ||
| 306 | .mutate => |lp| { | ||
| 307 | step.result_cached = false; | ||
| 308 | const root_path = try lp.getPath4(b, step); | ||
| 309 | write_file.generated_directory.path = try root_path.toString(arena); | ||
| 310 | try operate(write_file, open_dir_cache, root_path); | ||
| 311 | }, | ||
| 312 | } | ||
| 313 | } | ||
| 259 | 314 | ||
| 260 | write_file.generated_directory.path = try b.cache_root.join(arena, &.{ "o", &digest }); | 315 | fn operate(write_file: *WriteFile, open_dir_cache: []const Io.Dir, root_path: std.Build.Cache.Path) !void { |
| 316 | const step = &write_file.step; | ||
| 317 | const b = step.owner; | ||
| 318 | const io = b.graph.io; | ||
| 319 | const gpa = b.graph.cache.gpa; | ||
| 320 | const arena = b.allocator; | ||
| 261 | 321 | ||
| 262 | var cache_dir = b.cache_root.handle.createDirPathOpen(io, cache_path, .{}) catch |err| | 322 | var cache_dir = root_path.root_dir.handle.createDirPathOpen(io, root_path.sub_path, .{}) catch |err| |
| 263 | return step.fail("unable to make path '{f}{s}': {t}", .{ b.cache_root, cache_path, err }); | 323 | return step.fail("unable to make path {f}: {t}", .{ root_path, err }); |
| 264 | defer cache_dir.close(io); | 324 | defer cache_dir.close(io); |
| 265 | 325 | ||
| 266 | for (write_file.files.items) |file| { | 326 | for (write_file.files.items) |file| { |
| 267 | if (fs.path.dirname(file.sub_path)) |dirname| { | 327 | if (Dir.path.dirname(file.sub_path)) |dirname| { |
| 268 | cache_dir.createDirPath(io, dirname) catch |err| { | 328 | cache_dir.createDirPath(io, dirname) catch |err| { |
| 269 | return step.fail("unable to make path '{f}{s}{c}{s}': {t}", .{ | 329 | return step.fail("unable to make path '{f}{c}{s}': {t}", .{ |
| 270 | b.cache_root, cache_path, fs.path.sep, dirname, err, | 330 | root_path, Dir.path.sep, dirname, err, |
| 271 | }); | 331 | }); |
| 272 | }; | 332 | }; |
| 273 | } | 333 | } |
| 274 | switch (file.contents) { | 334 | switch (file.contents) { |
| 275 | .bytes => |bytes| { | 335 | .bytes => |bytes| { |
| 276 | cache_dir.writeFile(io, .{ .sub_path = file.sub_path, .data = bytes }) catch |err| { | 336 | cache_dir.writeFile(io, .{ .sub_path = file.sub_path, .data = bytes }) catch |err| { |
| 277 | return step.fail("unable to write file '{f}{s}{c}{s}': {t}", .{ | 337 | return step.fail("unable to write file '{f}{c}{s}': {t}", .{ |
| 278 | b.cache_root, cache_path, fs.path.sep, file.sub_path, err, | 338 | root_path, Dir.path.sep, file.sub_path, err, |
| 279 | }); | 339 | }); |
| 280 | }; | 340 | }; |
| 281 | }, | 341 | }, |
| 282 | .copy => |file_source| { | 342 | .copy => |file_source| { |
| 283 | const source_path = file_source.getPath2(b, step); | 343 | const source_path = file_source.getPath2(b, step); |
| 284 | const prev_status = Io.Dir.updateFile(.cwd(), io, source_path, cache_dir, file.sub_path, .{}) catch |err| { | 344 | const prev_status = Io.Dir.updateFile(.cwd(), io, source_path, cache_dir, file.sub_path, .{}) catch |err| { |
| 285 | return step.fail("unable to update file from '{s}' to '{f}{s}{c}{s}': {t}", .{ | 345 | return step.fail("unable to update file from '{s}' to '{f}{c}{s}': {t}", .{ |
| 286 | source_path, b.cache_root, cache_path, fs.path.sep, file.sub_path, err, | 346 | source_path, root_path, Dir.path.sep, file.sub_path, err, |
| 287 | }); | 347 | }); |
| 288 | }; | 348 | }; |
| 289 | // At this point we already will mark the step as a cache miss. | 349 | // At this point we already will mark the step as a cache miss. |
| ... | @@ -301,8 +361,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -301,8 +361,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 301 | 361 | ||
| 302 | if (dest_dirname.len != 0) { | 362 | if (dest_dirname.len != 0) { |
| 303 | cache_dir.createDirPath(io, dest_dirname) catch |err| { | 363 | cache_dir.createDirPath(io, dest_dirname) catch |err| { |
| 304 | return step.fail("unable to make path '{f}{s}{c}{s}': {s}", .{ | 364 | return step.fail("unable to make path '{f}{c}{s}': {t}", .{ |
| 305 | b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err), | 365 | root_path, Dir.path.sep, dest_dirname, err, |
| 306 | }); | 366 | }); |
| 307 | }; | 367 | }; |
| 308 | } | 368 | } |
| ... | @@ -325,8 +385,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -325,8 +385,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 325 | dest_path, | 385 | dest_path, |
| 326 | .{}, | 386 | .{}, |
| 327 | ) catch |err| { | 387 | ) catch |err| { |
| 328 | return step.fail("unable to update file from '{f}' to '{f}{s}{c}{s}': {s}", .{ | 388 | return step.fail("unable to update file from '{f}' to '{f}{c}{s}': {t}", .{ |
| 329 | src_entry_path, b.cache_root, cache_path, fs.path.sep, dest_path, @errorName(err), | 389 | src_entry_path, root_path, Dir.path.sep, dest_path, err, |
| 330 | }); | 390 | }); |
| 331 | }; | 391 | }; |
| 332 | _ = prev_status; | 392 | _ = prev_status; |
| ... | @@ -335,6 +395,4 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -335,6 +395,4 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 335 | } | 395 | } |
| 336 | } | 396 | } |
| 337 | } | 397 | } |
| 338 | |||
| 339 | try step.writeManifest(&man); | ||
| 340 | } | 398 | } |
test/standalone/dirname/build.zig+3-13| ... | @@ -58,19 +58,9 @@ pub fn build(b: *std.Build) void { | ... | @@ -58,19 +58,9 @@ pub fn build(b: *std.Build) void { |
| 58 | ); | 58 | ); |
| 59 | 59 | ||
| 60 | // Absolute path: | 60 | // Absolute path: |
| 61 | const abs_path = setup_abspath: { | 61 | const write_files = b.addWriteFiles(); |
| 62 | // TODO this is a bad pattern, don't do this | 62 | _ = write_files.add("foo.txt", ""); |
| 63 | const io = b.graph.io; | 63 | const abs_path = write_files.getDirectory(); |
| 64 | const temp_dir = b.makeTempPath(); | ||
| 65 | |||
| 66 | var dir = std.Io.Dir.cwd().openDir(io, temp_dir, .{}) catch @panic("failed to open temp dir"); | ||
| 67 | defer dir.close(io); | ||
| 68 | |||
| 69 | var file = dir.createFile(io, "foo.txt", .{}) catch @panic("failed to create file"); | ||
| 70 | file.close(io); | ||
| 71 | |||
| 72 | break :setup_abspath std.Build.LazyPath{ .cwd_relative = temp_dir }; | ||
| 73 | }; | ||
| 74 | addTestRun(test_step, exists_in, abs_path, &.{"foo.txt"}); | 64 | addTestRun(test_step, exists_in, abs_path, &.{"foo.txt"}); |
| 75 | } | 65 | } |
| 76 | 66 |
test/tests.zig+30-48| ... | @@ -2026,13 +2026,12 @@ pub fn addLinkTests( | ... | @@ -2026,13 +2026,12 @@ pub fn addLinkTests( |
| 2026 | pub fn addCliTests(b: *std.Build) *Step { | 2026 | pub fn addCliTests(b: *std.Build) *Step { |
| 2027 | const step = b.step("test-cli", "Test the command line interface"); | 2027 | const step = b.step("test-cli", "Test the command line interface"); |
| 2028 | const s = std.fs.path.sep_str; | 2028 | const s = std.fs.path.sep_str; |
| 2029 | const io = b.graph.io; | ||
| 2030 | 2029 | ||
| 2031 | { | 2030 | { |
| 2032 | // Test `zig init`. | 2031 | // Test `zig init`. |
| 2033 | const tmp_path = b.makeTempPath(); | 2032 | const tmp_path = b.tmpPath(); |
| 2034 | const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" }); | 2033 | const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" }); |
| 2035 | init_exe.setCwd(.{ .cwd_relative = tmp_path }); | 2034 | init_exe.setCwd(tmp_path); |
| 2036 | init_exe.setName("zig init"); | 2035 | init_exe.setName("zig init"); |
| 2037 | init_exe.expectStdOutEqual(""); | 2036 | init_exe.expectStdOutEqual(""); |
| 2038 | init_exe.expectStdErrEqual("info: created build.zig\n" ++ | 2037 | init_exe.expectStdErrEqual("info: created build.zig\n" ++ |
| ... | @@ -2053,31 +2052,28 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -2053,31 +2052,28 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 2053 | run_bad.step.dependOn(&init_exe.step); | 2052 | run_bad.step.dependOn(&init_exe.step); |
| 2054 | 2053 | ||
| 2055 | const run_test = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "test" }); | 2054 | const run_test = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "test" }); |
| 2056 | run_test.setCwd(.{ .cwd_relative = tmp_path }); | 2055 | run_test.setCwd(tmp_path); |
| 2057 | run_test.setName("zig build test"); | 2056 | run_test.setName("zig build test"); |
| 2058 | run_test.expectStdOutEqual(""); | 2057 | run_test.expectStdOutEqual(""); |
| 2059 | run_test.step.dependOn(&init_exe.step); | 2058 | run_test.step.dependOn(&init_exe.step); |
| 2060 | 2059 | ||
| 2061 | const run_run = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "run" }); | 2060 | const run_run = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "run" }); |
| 2062 | run_run.setCwd(.{ .cwd_relative = tmp_path }); | 2061 | run_run.setCwd(tmp_path); |
| 2063 | run_run.setName("zig build run"); | 2062 | run_run.setName("zig build run"); |
| 2064 | run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n"); | 2063 | run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n"); |
| 2065 | run_run.expectStdErrMatch("All your codebase are belong to us.\n"); | 2064 | run_run.expectStdErrMatch("All your codebase are belong to us.\n"); |
| 2066 | run_run.step.dependOn(&init_exe.step); | 2065 | run_run.step.dependOn(&init_exe.step); |
| 2067 | 2066 | ||
| 2068 | const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path }); | 2067 | step.dependOn(&run_test.step); |
| 2069 | cleanup.step.dependOn(&run_test.step); | 2068 | step.dependOn(&run_run.step); |
| 2070 | cleanup.step.dependOn(&run_run.step); | 2069 | step.dependOn(&run_bad.step); |
| 2071 | cleanup.step.dependOn(&run_bad.step); | ||
| 2072 | |||
| 2073 | step.dependOn(&cleanup.step); | ||
| 2074 | } | 2070 | } |
| 2075 | 2071 | ||
| 2076 | { | 2072 | { |
| 2077 | // Test `zig init -m`. | 2073 | // Test `zig init -m`. |
| 2078 | const tmp_path = b.makeTempPath(); | 2074 | const tmp_path = b.tmpPath(); |
| 2079 | const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init", "-m" }); | 2075 | const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init", "-m" }); |
| 2080 | init_exe.setCwd(.{ .cwd_relative = tmp_path }); | 2076 | init_exe.setCwd(tmp_path); |
| 2081 | init_exe.setName("zig init -m"); | 2077 | init_exe.setName("zig init -m"); |
| 2082 | init_exe.expectStdOutEqual(""); | 2078 | init_exe.expectStdOutEqual(""); |
| 2083 | init_exe.expectStdErrEqual("info: successfully populated 'build.zig.zon' and 'build.zig'\n"); | 2079 | init_exe.expectStdErrEqual("info: successfully populated 'build.zig.zon' and 'build.zig'\n"); |
| ... | @@ -2085,7 +2081,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -2085,7 +2081,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 2085 | 2081 | ||
| 2086 | // Test Godbolt API | 2082 | // Test Godbolt API |
| 2087 | if (builtin.os.tag == .linux and builtin.cpu.arch == .x86_64) { | 2083 | if (builtin.os.tag == .linux and builtin.cpu.arch == .x86_64) { |
| 2088 | const tmp_path = b.makeTempPath(); | 2084 | const tmp_path = b.tmpPath(); |
| 2089 | 2085 | ||
| 2090 | const example_zig = b.addWriteFiles().add("example.zig", | 2086 | const example_zig = b.addWriteFiles().add("example.zig", |
| 2091 | \\// Type your code here, or load an example. | 2087 | \\// Type your code here, or load an example. |
| ... | @@ -2101,13 +2097,9 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -2101,13 +2097,9 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 2101 | ); | 2097 | ); |
| 2102 | 2098 | ||
| 2103 | // This is intended to be the exact CLI usage used by godbolt.org. | 2099 | // This is intended to be the exact CLI usage used by godbolt.org. |
| 2104 | const run = b.addSystemCommand(&.{ | 2100 | const run = b.addSystemCommand(&.{ b.graph.zig_exe, "build-obj", "--cache-dir" }); |
| 2105 | b.graph.zig_exe, "build-obj", | 2101 | run.addDirectoryArg(tmp_path); |
| 2106 | "--cache-dir", tmp_path, | 2102 | run.addArgs(&.{ "--name", "example", "-fno-emit-bin", "-fno-emit-h", "-fstrip", "-OReleaseFast" }); |
| 2107 | "--name", "example", | ||
| 2108 | "-fno-emit-bin", "-fno-emit-h", | ||
| 2109 | "-fstrip", "-OReleaseFast", | ||
| 2110 | }); | ||
| 2111 | run.addFileArg(example_zig); | 2103 | run.addFileArg(example_zig); |
| 2112 | const example_s = run.addPrefixedOutputFileArg("-femit-asm=", "example.s"); | 2104 | const example_s = run.addPrefixedOutputFileArg("-femit-asm=", "example.s"); |
| 2113 | 2105 | ||
| ... | @@ -2120,10 +2112,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -2120,10 +2112,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 2120 | }); | 2112 | }); |
| 2121 | checkfile.setName("check godbolt.org CLI usage generating valid asm"); | 2113 | checkfile.setName("check godbolt.org CLI usage generating valid asm"); |
| 2122 | 2114 | ||
| 2123 | const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path }); | 2115 | step.dependOn(&checkfile.step); |
| 2124 | cleanup.step.dependOn(&checkfile.step); | ||
| 2125 | |||
| 2126 | step.dependOn(&cleanup.step); | ||
| 2127 | } | 2116 | } |
| 2128 | 2117 | ||
| 2129 | { | 2118 | { |
| ... | @@ -2132,22 +2121,19 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -2132,22 +2121,19 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 2132 | // directory because this test will be mutating the files. The cache | 2121 | // directory because this test will be mutating the files. The cache |
| 2133 | // system relies on cache directories being mutated only by their | 2122 | // system relies on cache directories being mutated only by their |
| 2134 | // owners. | 2123 | // owners. |
| 2135 | const tmp_path = b.makeTempPath(); | 2124 | const tmp_wf = b.addTempFiles(); |
| 2136 | const unformatted_code = " // no reason for indent"; | 2125 | const unformatted_code = " // no reason for indent"; |
| 2137 | 2126 | ||
| 2138 | var dir = std.Io.Dir.cwd().openDir(io, tmp_path, .{}) catch @panic("unhandled"); | 2127 | _ = tmp_wf.add("fmt1.zig", unformatted_code); |
| 2139 | defer dir.close(io); | 2128 | _ = tmp_wf.add("fmt2.zig", unformatted_code); |
| 2140 | dir.writeFile(io, .{ .sub_path = "fmt1.zig", .data = unformatted_code }) catch @panic("unhandled"); | 2129 | _ = tmp_wf.add("subdir/fmt3.zig", unformatted_code); |
| 2141 | dir.writeFile(io, .{ .sub_path = "fmt2.zig", .data = unformatted_code }) catch @panic("unhandled"); | 2130 | |
| 2142 | dir.createDir(io, "subdir", .default_dir) catch @panic("unhandled"); | 2131 | const tmp_path = tmp_wf.getDirectory(); |
| 2143 | var subdir = dir.openDir(io, "subdir", .{}) catch @panic("unhandled"); | ||
| 2144 | defer subdir.close(io); | ||
| 2145 | subdir.writeFile(io, .{ .sub_path = "fmt3.zig", .data = unformatted_code }) catch @panic("unhandled"); | ||
| 2146 | 2132 | ||
| 2147 | // Test zig fmt affecting only the appropriate files. | 2133 | // Test zig fmt affecting only the appropriate files. |
| 2148 | const run1 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "fmt1.zig" }); | 2134 | const run1 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "fmt1.zig" }); |
| 2149 | run1.setName("run zig fmt one file"); | 2135 | run1.setName("run zig fmt one file"); |
| 2150 | run1.setCwd(.{ .cwd_relative = tmp_path }); | 2136 | run1.setCwd(tmp_path); |
| 2151 | run1.has_side_effects = true; | 2137 | run1.has_side_effects = true; |
| 2152 | // stdout should be file path + \n | 2138 | // stdout should be file path + \n |
| 2153 | run1.expectStdOutEqual("fmt1.zig\n"); | 2139 | run1.expectStdOutEqual("fmt1.zig\n"); |
| ... | @@ -2155,7 +2141,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -2155,7 +2141,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 2155 | // Test excluding files and directories from a run | 2141 | // Test excluding files and directories from a run |
| 2156 | const run2 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." }); | 2142 | const run2 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." }); |
| 2157 | run2.setName("run zig fmt on directory with exclusions"); | 2143 | run2.setName("run zig fmt on directory with exclusions"); |
| 2158 | run2.setCwd(.{ .cwd_relative = tmp_path }); | 2144 | run2.setCwd(tmp_path); |
| 2159 | run2.has_side_effects = true; | 2145 | run2.has_side_effects = true; |
| 2160 | run2.expectStdOutEqual(""); | 2146 | run2.expectStdOutEqual(""); |
| 2161 | run2.step.dependOn(&run1.step); | 2147 | run2.step.dependOn(&run1.step); |
| ... | @@ -2163,7 +2149,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -2163,7 +2149,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 2163 | // Test excluding non-existent file | 2149 | // Test excluding non-existent file |
| 2164 | const run3 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." }); | 2150 | const run3 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." }); |
| 2165 | run3.setName("run zig fmt on directory with non-existent exclusion"); | 2151 | run3.setName("run zig fmt on directory with non-existent exclusion"); |
| 2166 | run3.setCwd(.{ .cwd_relative = tmp_path }); | 2152 | run3.setCwd(tmp_path); |
| 2167 | run3.has_side_effects = true; | 2153 | run3.has_side_effects = true; |
| 2168 | run3.expectStdOutEqual("." ++ s ++ "subdir" ++ s ++ "fmt3.zig\n"); | 2154 | run3.expectStdOutEqual("." ++ s ++ "subdir" ++ s ++ "fmt3.zig\n"); |
| 2169 | run3.step.dependOn(&run2.step); | 2155 | run3.step.dependOn(&run2.step); |
| ... | @@ -2171,7 +2157,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -2171,7 +2157,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 2171 | // running it on the dir, only the new file should be changed | 2157 | // running it on the dir, only the new file should be changed |
| 2172 | const run4 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); | 2158 | const run4 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); |
| 2173 | run4.setName("run zig fmt the directory"); | 2159 | run4.setName("run zig fmt the directory"); |
| 2174 | run4.setCwd(.{ .cwd_relative = tmp_path }); | 2160 | run4.setCwd(tmp_path); |
| 2175 | run4.has_side_effects = true; | 2161 | run4.has_side_effects = true; |
| 2176 | run4.expectStdOutEqual("." ++ s ++ "fmt2.zig\n"); | 2162 | run4.expectStdOutEqual("." ++ s ++ "fmt2.zig\n"); |
| 2177 | run4.step.dependOn(&run3.step); | 2163 | run4.step.dependOn(&run3.step); |
| ... | @@ -2179,37 +2165,33 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -2179,37 +2165,33 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 2179 | // both files have been formatted, nothing should change now | 2165 | // both files have been formatted, nothing should change now |
| 2180 | const run5 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); | 2166 | const run5 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); |
| 2181 | run5.setName("run zig fmt with nothing to do"); | 2167 | run5.setName("run zig fmt with nothing to do"); |
| 2182 | run5.setCwd(.{ .cwd_relative = tmp_path }); | 2168 | run5.setCwd(tmp_path); |
| 2183 | run5.has_side_effects = true; | 2169 | run5.has_side_effects = true; |
| 2184 | run5.expectStdOutEqual(""); | 2170 | run5.expectStdOutEqual(""); |
| 2185 | run5.step.dependOn(&run4.step); | 2171 | run5.step.dependOn(&run4.step); |
| 2186 | 2172 | ||
| 2187 | const unformatted_code_utf16 = "\xff\xfe \x00 \x00 \x00 \x00/\x00/\x00 \x00n\x00o\x00 \x00r\x00e\x00a\x00s\x00o\x00n\x00"; | 2173 | const unformatted_code_utf16 = "\xff\xfe \x00 \x00 \x00 \x00/\x00/\x00 \x00n\x00o\x00 \x00r\x00e\x00a\x00s\x00o\x00n\x00"; |
| 2188 | const fmt6_path = b.pathJoin(&.{ tmp_path, "fmt6.zig" }); | 2174 | const write6 = b.addMutateFiles(tmp_path); |
| 2189 | const write6 = b.addUpdateSourceFiles(); | 2175 | const fmt6_path = write6.add("fmt6.zig", unformatted_code_utf16); |
| 2190 | write6.addBytesToSource(unformatted_code_utf16, fmt6_path); | ||
| 2191 | write6.step.dependOn(&run5.step); | 2176 | write6.step.dependOn(&run5.step); |
| 2192 | 2177 | ||
| 2193 | // Test `zig fmt` handling UTF-16 decoding. | 2178 | // Test `zig fmt` handling UTF-16 decoding. |
| 2194 | const run6 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); | 2179 | const run6 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); |
| 2195 | run6.setName("run zig fmt convert UTF-16 to UTF-8"); | 2180 | run6.setName("run zig fmt convert UTF-16 to UTF-8"); |
| 2196 | run6.setCwd(.{ .cwd_relative = tmp_path }); | 2181 | run6.setCwd(tmp_path); |
| 2197 | run6.has_side_effects = true; | 2182 | run6.has_side_effects = true; |
| 2198 | run6.expectStdOutEqual("." ++ s ++ "fmt6.zig\n"); | 2183 | run6.expectStdOutEqual("." ++ s ++ "fmt6.zig\n"); |
| 2199 | run6.step.dependOn(&write6.step); | 2184 | run6.step.dependOn(&write6.step); |
| 2200 | 2185 | ||
| 2201 | // TODO change this to an exact match | 2186 | // TODO change this to an exact match |
| 2202 | const check6 = b.addCheckFile(.{ .cwd_relative = fmt6_path }, .{ | 2187 | const check6 = b.addCheckFile(fmt6_path, .{ |
| 2203 | .expected_matches = &.{ | 2188 | .expected_matches = &.{ |
| 2204 | "// no reason", | 2189 | "// no reason", |
| 2205 | }, | 2190 | }, |
| 2206 | }); | 2191 | }); |
| 2207 | check6.step.dependOn(&run6.step); | 2192 | check6.step.dependOn(&run6.step); |
| 2208 | 2193 | ||
| 2209 | const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path }); | 2194 | step.dependOn(&check6.step); |
| 2210 | cleanup.step.dependOn(&check6.step); | ||
| 2211 | |||
| 2212 | step.dependOn(&cleanup.step); | ||
| 2213 | } | 2195 | } |
| 2214 | 2196 | ||
| 2215 | { | 2197 | { |