| ... | @@ -13,8 +13,9 @@ const Configuration = std.Build.Configuration; | ... | @@ -13,8 +13,9 @@ const Configuration = std.Build.Configuration; |
| 13 | | 13 | |
| 14 | step: Step, | 14 | step: Step, |
| 15 | | 15 | |
| 16 | files: std.ArrayList(File), | 16 | embeds: std.ArrayList(Embed) = .empty, |
| 17 | directories: std.ArrayList(Directory), | 17 | copies: std.ArrayList(Copy) = .empty, |
| | 18 | directories: std.ArrayList(Directory) = .empty, |
| 18 | generated_directory: Configuration.GeneratedFileIndex, | 19 | generated_directory: Configuration.GeneratedFileIndex, |
| 19 | mode: Mode = .whole_cached, | 20 | mode: Mode = .whole_cached, |
| 20 | | 21 | |
| ... | @@ -37,158 +38,152 @@ pub const Mode = union(enum) { | ... | @@ -37,158 +38,152 @@ pub const Mode = union(enum) { |
| 37 | mutate: std.Build.LazyPath, | 38 | mutate: std.Build.LazyPath, |
| 38 | }; | 39 | }; |
| 39 | | 40 | |
| 40 | pub const File = struct { | 41 | pub const Embed = Configuration.Step.WriteFile.Embed; |
| 41 | sub_path: []const u8, | | |
| 42 | contents: Contents, | | |
| 43 | }; | | |
| 44 | | 42 | |
| 45 | pub const Directory = struct { | 43 | pub const Copy = struct { |
| 46 | source: std.Build.LazyPath, | 44 | sub_path: Configuration.String, |
| 47 | sub_path: []const u8, | 45 | src_file: std.Build.LazyPath, |
| 48 | options: Options, | | |
| 49 | | | |
| 50 | pub const Options = struct { | | |
| 51 | /// File paths that end in any of these suffixes will be excluded from copying. | | |
| 52 | exclude_extensions: []const []const u8 = &.{}, | | |
| 53 | /// Only file paths that end in any of these suffixes will be included in copying. | | |
| 54 | /// `null` means that all suffixes will be included. | | |
| 55 | /// `exclude_extensions` takes precedence over `include_extensions`. | | |
| 56 | include_extensions: ?[]const []const u8 = null, | | |
| 57 | | | |
| 58 | pub fn dupe(opts: Options, graph: *std.Build.Graph) Options { | | |
| 59 | return .{ | | |
| 60 | .exclude_extensions = graph.dupeStrings(opts.exclude_extensions), | | |
| 61 | .include_extensions = if (opts.include_extensions) |incs| graph.dupeStrings(incs) else null, | | |
| 62 | }; | | |
| 63 | } | | |
| 64 | | | |
| 65 | pub fn pathIncluded(opts: Options, path: []const u8) bool { | | |
| 66 | for (opts.exclude_extensions) |ext| { | | |
| 67 | if (std.mem.endsWith(u8, path, ext)) | | |
| 68 | return false; | | |
| 69 | } | | |
| 70 | if (opts.include_extensions) |incs| { | | |
| 71 | for (incs) |inc| { | | |
| 72 | if (std.mem.endsWith(u8, path, inc)) | | |
| 73 | return true; | | |
| 74 | } else { | | |
| 75 | return false; | | |
| 76 | } | | |
| 77 | } | | |
| 78 | return true; | | |
| 79 | } | | |
| 80 | }; | | |
| 81 | }; | 46 | }; |
| 82 | | 47 | |
| 83 | pub const Contents = union(enum) { | 48 | pub const Directory = struct { |
| 84 | bytes: []const u8, | 49 | sub_path: Configuration.String, |
| 85 | copy: std.Build.LazyPath, | 50 | src_path: std.Build.LazyPath, |
| | 51 | exclude_extensions: Configuration.OptionalStringList, |
| | 52 | include_extensions: Configuration.OptionalStringList, |
| 86 | }; | 53 | }; |
| 87 | | 54 | |
| 88 | pub fn create(owner: *std.Build) *WriteFile { | 55 | pub fn create(owner: *std.Build) *WriteFile { |
| 89 | const graph = owner.graph; | 56 | const graph = owner.graph; |
| 90 | const arena = graph.arena; | 57 | const wf = graph.create(WriteFile); |
| 91 | const write_file = arena.create(WriteFile) catch @panic("OOM"); | 58 | wf.* = .{ |
| 92 | write_file.* = .{ | 59 | .step = .init(.{ |
| 93 | .step = Step.init(.{ | | |
| 94 | .tag = base_tag, | 60 | .tag = base_tag, |
| 95 | .name = "WriteFile", | 61 | .name = "WriteFile", |
| 96 | .owner = owner, | 62 | .owner = owner, |
| 97 | }), | 63 | }), |
| 98 | .files = .empty, | 64 | .generated_directory = graph.addGeneratedFile(&wf.step), |
| 99 | .directories = .empty, | | |
| 100 | .generated_directory = graph.addGeneratedFile(&write_file.step), | | |
| 101 | }; | 65 | }; |
| 102 | return write_file; | 66 | return wf; |
| 103 | } | 67 | } |
| 104 | | 68 | |
| 105 | pub fn add(write_file: *WriteFile, sub_path: []const u8, bytes: []const u8) std.Build.LazyPath { | 69 | /// Writes `contents` to a file at `sub_path` relative to the output |
| 106 | const graph = write_file.step.owner.graph; | 70 | /// directory. |
| | 71 | /// |
| | 72 | /// `sub_path` may be a basename, or it may include subdirectories, which are |
| | 73 | /// created as needed. |
| | 74 | pub fn add(wf: *WriteFile, sub_path: []const u8, contents: []const u8) std.Build.LazyPath { |
| | 75 | const graph = wf.step.owner.graph; |
| | 76 | const wc = &graph.wip_configuration; |
| 107 | const arena = graph.arena; | 77 | const arena = graph.arena; |
| 108 | const file: File = .{ | 78 | |
| 109 | .sub_path = graph.dupePath(sub_path), | 79 | wf.embeds.append(arena, .{ |
| 110 | .contents = .{ .bytes = graph.dupeString(bytes) }, | 80 | .sub_path = wc.addString(sub_path) catch @panic("OOM"), |
| 111 | }; | 81 | .contents = wc.addBytes(contents) catch @panic("OOM"), |
| 112 | write_file.files.append(arena, file) catch @panic("OOM"); | 82 | }) catch @panic("OOM"); |
| 113 | write_file.maybeUpdateName(); | 83 | |
| | 84 | wf.maybeUpdateName(); |
| | 85 | |
| 114 | return .{ | 86 | return .{ |
| 115 | .generated = .{ | 87 | .generated = .{ |
| 116 | .index = write_file.generated_directory, | 88 | .index = wf.generated_directory, |
| 117 | .sub_path = file.sub_path, | 89 | .sub_path = graph.dupeString(sub_path), |
| 118 | }, | 90 | }, |
| 119 | }; | 91 | }; |
| 120 | } | 92 | } |
| 121 | | 93 | |
| 122 | /// Copies the provided file into the generated directory within the local | 94 | /// Copies the provided file to `sub_path` relative to the output directory. |
| 123 | /// cache, along with all the rest of the files added to this step. | | |
| 124 | /// | 95 | /// |
| 125 | /// `sub_path` is the destination path relative to the local cache directory | 96 | /// `sub_path` may be a basename, or it may include subdirectories, which are |
| 126 | /// associated with this WriteFile. It may be a basename, or it may include | 97 | /// created as needed. |
| 127 | /// subdirectories, which are created as needed. | 98 | pub fn addCopyFile(wf: *WriteFile, src_file: std.Build.LazyPath, sub_path: []const u8) std.Build.LazyPath { |
| 128 | pub fn addCopyFile(write_file: *WriteFile, source: std.Build.LazyPath, sub_path: []const u8) std.Build.LazyPath { | 99 | const graph = wf.step.owner.graph; |
| 129 | const graph = write_file.step.owner.graph; | 100 | const wc = &graph.wip_configuration; |
| 130 | const duped_path = graph.dupePath(sub_path); | | |
| 131 | const arena = graph.arena; | 101 | const arena = graph.arena; |
| 132 | | 102 | |
| 133 | write_file.files.append(arena, .{ | 103 | wf.copies.append(arena, .{ |
| 134 | .sub_path = duped_path, | 104 | .sub_path = wc.addString(sub_path) catch @panic("OOM"), |
| 135 | .contents = .{ .copy = source }, | 105 | .src_file = src_file.dupe(graph), |
| 136 | }) catch @panic("OOM"); | 106 | }) catch @panic("OOM"); |
| 137 | | 107 | |
| 138 | write_file.maybeUpdateName(); | 108 | wf.maybeUpdateName(); |
| 139 | source.addStepDependencies(&write_file.step); | 109 | |
| | 110 | src_file.addStepDependencies(&wf.step); |
| 140 | | 111 | |
| 141 | return .{ .generated = .{ | 112 | return .{ .generated = .{ |
| 142 | .index = write_file.generated_directory, | 113 | .index = wf.generated_directory, |
| 143 | .sub_path = duped_path, | 114 | .sub_path = graph.dupePath(sub_path), |
| 144 | } }; | 115 | } }; |
| 145 | } | 116 | } |
| 146 | | 117 | |
| | 118 | pub const CopyDirectoryOptions = struct { |
| | 119 | /// File paths that end in any of these suffixes will be excluded from copying. |
| | 120 | exclude_extensions: []const []const u8 = &.{}, |
| | 121 | /// Only file paths that end in any of these suffixes will be included in copying. |
| | 122 | /// `null` means that all suffixes will be included. |
| | 123 | /// `exclude_extensions` takes precedence over `include_extensions`. |
| | 124 | include_extensions: ?[]const []const u8 = null, |
| | 125 | }; |
| | 126 | |
| 147 | /// Copy files matching the specified exclude/include patterns to the specified | 127 | /// Copy files matching the specified exclude/include patterns to the specified |
| 148 | /// subdirectory relative to this step's generated directory. | 128 | /// subdirectory relative to this step's generated directory. |
| 149 | /// | 129 | /// |
| 150 | /// The returned value is a lazy path to the generated subdirectory. | 130 | /// The returned value is a lazy path to the generated subdirectory. |
| 151 | pub fn addCopyDirectory( | 131 | pub fn addCopyDirectory( |
| 152 | write_file: *WriteFile, | 132 | wf: *WriteFile, |
| 153 | source: std.Build.LazyPath, | 133 | src_path: std.Build.LazyPath, |
| 154 | sub_path: []const u8, | 134 | sub_path: []const u8, |
| 155 | options: Directory.Options, | 135 | options: CopyDirectoryOptions, |
| 156 | ) std.Build.LazyPath { | 136 | ) std.Build.LazyPath { |
| 157 | const graph = write_file.step.owner.graph; | 137 | const graph = wf.step.owner.graph; |
| | 138 | const wc = &graph.wip_configuration; |
| 158 | const arena = graph.arena; | 139 | const arena = graph.arena; |
| 159 | const dir = Directory{ | | |
| 160 | .source = source.dupe(graph), | | |
| 161 | .sub_path = graph.dupePath(sub_path), | | |
| 162 | .options = options.dupe(graph), | | |
| 163 | }; | | |
| 164 | write_file.directories.append(arena, dir) catch @panic("OOM"); | | |
| 165 | | 140 | |
| 166 | write_file.maybeUpdateName(); | 141 | wf.directories.append(arena, .{ |
| 167 | source.addStepDependencies(&write_file.step); | 142 | .sub_path = wc.addString(sub_path) catch @panic("OOM"), |
| | 143 | .src_path = src_path.dupe(graph), |
| | 144 | .exclude_extensions = if (options.exclude_extensions.len != 0) |
| | 145 | .init(wc.addStringList(options.exclude_extensions) catch @panic("OOM")) |
| | 146 | else |
| | 147 | .none, |
| | 148 | .include_extensions = if (options.include_extensions) |list| |
| | 149 | .init(wc.addStringList(list) catch @panic("OOM")) |
| | 150 | else |
| | 151 | .none, |
| | 152 | }) catch @panic("OOM"); |
| | 153 | |
| | 154 | wf.maybeUpdateName(); |
| | 155 | |
| | 156 | src_path.addStepDependencies(&wf.step); |
| | 157 | |
| 168 | return .{ | 158 | return .{ |
| 169 | .generated = .{ | 159 | .generated = .{ |
| 170 | .index = write_file.generated_directory, | 160 | .index = wf.generated_directory, |
| 171 | .sub_path = dir.sub_path, | 161 | .sub_path = graph.dupePath(sub_path), |
| 172 | }, | 162 | }, |
| 173 | }; | 163 | }; |
| 174 | } | 164 | } |
| 175 | | 165 | |
| 176 | /// Returns a `LazyPath` representing the base directory that contains all the | 166 | /// Returns a `LazyPath` representing the base directory that contains all the |
| 177 | /// files from this `WriteFile`. | 167 | /// files from this `WriteFile`. |
| 178 | pub fn getDirectory(write_file: *WriteFile) std.Build.LazyPath { | 168 | pub fn getDirectory(wf: *WriteFile) std.Build.LazyPath { |
| 179 | return .{ .generated = .{ .index = write_file.generated_directory } }; | 169 | return .{ .generated = .{ .index = wf.generated_directory } }; |
| 180 | } | 170 | } |
| 181 | | 171 | |
| 182 | fn maybeUpdateName(write_file: *WriteFile) void { | 172 | fn maybeUpdateName(wf: *WriteFile) void { |
| 183 | if (write_file.files.items.len == 1 and write_file.directories.items.len == 0) { | 173 | const graph = wf.step.owner.graph; |
| | 174 | const wc = &graph.wip_configuration; |
| | 175 | const files_count = wf.embeds.items.len + wf.copies.items.len; |
| | 176 | if (files_count == 1 and wf.directories.items.len == 0) { |
| 184 | // First time adding a file; update name. | 177 | // First time adding a file; update name. |
| 185 | if (std.mem.eql(u8, write_file.step.name, "WriteFile")) { | 178 | const sub_path = if (wf.embeds.items.len == 1) wf.embeds.items[0].sub_path else wf.copies.items[0].sub_path; |
| 186 | write_file.step.name = write_file.step.owner.fmt("WriteFile {s}", .{write_file.files.items[0].sub_path}); | 179 | if (std.mem.eql(u8, wf.step.name, "WriteFile")) { |
| | 180 | wf.step.name = wf.step.owner.fmt("WriteFile {s}", .{wc.stringSlice(sub_path)}); |
| 187 | } | 181 | } |
| 188 | } else if (write_file.directories.items.len == 1 and write_file.files.items.len == 0) { | 182 | } else if (wf.directories.items.len == 1 and files_count == 0) { |
| 189 | // First time adding a directory; update name. | 183 | // First time adding a directory; update name. |
| 190 | if (std.mem.eql(u8, write_file.step.name, "WriteFile")) { | 184 | const dir_name = wc.stringSlice(wf.directories.items[0].sub_path); |
| 191 | write_file.step.name = write_file.step.owner.fmt("WriteFile {s}", .{write_file.directories.items[0].sub_path}); | 185 | if (std.mem.eql(u8, wf.step.name, "WriteFile")) { |
| | 186 | wf.step.name = wf.step.owner.fmt("WriteFile {s}", .{dir_name}); |
| 192 | } | 187 | } |
| 193 | } | 188 | } |
| 194 | } | 189 | } |