| author | |
| committer | |
| log | 435cd6f129172733fdc4b9bd62abe3c94f91d583 |
| tree | 8346c38b5f579ec0ddfda202806e5e70b6b497ba |
| parent | 8e091047b5a8fd2f8a74d56a7353f16fd66dff25 |
| parent | c8ecfad41a322260fae38a4115a94345ed9f94b7 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/306837 files changed, 232 insertions(+), 213 deletions(-)
lib/compiler/build_runner.zig+15-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 | }, |
| ... | @@ -784,6 +784,9 @@ fn runStepNames( | ... | @@ -784,6 +784,9 @@ fn runStepNames( |
| 784 | var pending_count: usize = 0; | 784 | var pending_count: usize = 0; |
| 785 | var total_compile_errors: usize = 0; | 785 | var total_compile_errors: usize = 0; |
| 786 | 786 | ||
| 787 | var cleanup_task = io.async(cleanTmpFiles, .{ io, step_stack.keys() }); | ||
| 788 | defer cleanup_task.await(io); | ||
| 789 | |||
| 787 | for (step_stack.keys()) |s| { | 790 | for (step_stack.keys()) |s| { |
| 788 | test_pass_count += s.test_results.passCount(); | 791 | test_pass_count += s.test_results.passCount(); |
| 789 | test_skip_count += s.test_results.skip_count; | 792 | test_skip_count += s.test_results.skip_count; |
| ... | @@ -1849,3 +1852,14 @@ fn initStdoutWriter(io: Io) *Writer { | ... | @@ -1849,3 +1852,14 @@ fn initStdoutWriter(io: Io) *Writer { |
| 1849 | stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation); | 1852 | stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation); |
| 1850 | return &stdout_writer_allocation.interface; | 1853 | return &stdout_writer_allocation.interface; |
| 1851 | } | 1854 | } |
| 1855 | |||
| 1856 | fn cleanTmpFiles(io: Io, steps: []const *Step) void { | ||
| 1857 | for (steps) |step| { | ||
| 1858 | const wf = step.cast(std.Build.Step.WriteFile) orelse continue; | ||
| 1859 | if (wf.mode != .tmp) continue; | ||
| 1860 | const path = wf.generated_directory.path orelse continue; | ||
| 1861 | Io.Dir.cwd().deleteTree(io, path) catch |err| { | ||
| 1862 | std.log.warn("failed to delete {s}: {t}", .{ path, err }); | ||
| 1863 | }; | ||
| 1864 | } | ||
| 1865 | } |
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 | { |