| author | |
| committer | |
| log | dee9f82f69db0d034251b844e0bc4083a1b25fdd |
| tree | 14adb7ca55844ef04872501174cd006812edbf43 |
| parent | e3424332d3fa1264e1f6861b76bb0d1b2996728d |
This allows running commands that take an output directory argument. The
main thing that was needed for this feature was generated file subpaths,
to allow access to the files in a generated directory. Additionally, a
minor change was required to so that the correct directory is created
for output directory args.12 files changed, 274 insertions(+), 121 deletions(-)
lib/std/Build.zig+87-80| ... | @@ -2131,28 +2131,23 @@ test dirnameAllowEmpty { | ... | @@ -2131,28 +2131,23 @@ test dirnameAllowEmpty { |
| 2131 | 2131 | ||
| 2132 | /// A reference to an existing or future path. | 2132 | /// A reference to an existing or future path. |
| 2133 | pub const LazyPath = union(enum) { | 2133 | pub const LazyPath = union(enum) { |
| 2134 | /// Deprecated; use the `path` function instead. | ||
| 2135 | path: []const u8, | ||
| 2136 | |||
| 2137 | /// A source file path relative to build root. | 2134 | /// A source file path relative to build root. |
| 2138 | src_path: struct { | 2135 | src_path: struct { |
| 2139 | owner: *std.Build, | 2136 | owner: *std.Build, |
| 2140 | sub_path: []const u8, | 2137 | sub_path: []const u8, |
| 2141 | }, | 2138 | }, |
| 2142 | 2139 | ||
| 2143 | /// A file that is generated by an interface. Those files usually are | 2140 | generated: struct { |
| 2144 | /// not available until built by a build step. | 2141 | file: *const GeneratedFile, |
| 2145 | generated: *const GeneratedFile, | ||
| 2146 | |||
| 2147 | /// One of the parent directories of a file generated by an interface. | ||
| 2148 | /// The path is not available until built by a build step. | ||
| 2149 | generated_dirname: struct { | ||
| 2150 | generated: *const GeneratedFile, | ||
| 2151 | 2142 | ||
| 2152 | /// The number of parent directories to go up. | 2143 | /// The number of parent directories to go up. |
| 2153 | /// 0 means the directory of the generated file, | 2144 | /// 0 means the generated file itself. |
| 2154 | /// 1 means the parent of that directory, and so on. | 2145 | /// 1 means the directory of the generated file. |
| 2155 | up: usize, | 2146 | /// 2 means the parent of that directory, and so on. |
| 2147 | up: usize = 0, | ||
| 2148 | |||
| 2149 | /// Applied after `up`. | ||
| 2150 | sub_path: []const u8 = "", | ||
| 2156 | }, | 2151 | }, |
| 2157 | 2152 | ||
| 2158 | /// An absolute path or a path relative to the current working directory of | 2153 | /// An absolute path or a path relative to the current working directory of |
| ... | @@ -2168,12 +2163,6 @@ pub const LazyPath = union(enum) { | ... | @@ -2168,12 +2163,6 @@ pub const LazyPath = union(enum) { |
| 2168 | sub_path: []const u8, | 2163 | sub_path: []const u8, |
| 2169 | }, | 2164 | }, |
| 2170 | 2165 | ||
| 2171 | /// Deprecated. Call `path` instead. | ||
| 2172 | pub fn relative(sub_path: []const u8) LazyPath { | ||
| 2173 | std.log.warn("deprecated. call std.Build.path instead", .{}); | ||
| 2174 | return .{ .path = sub_path }; | ||
| 2175 | } | ||
| 2176 | |||
| 2177 | /// Returns a lazy path referring to the directory containing this path. | 2166 | /// Returns a lazy path referring to the directory containing this path. |
| 2178 | /// | 2167 | /// |
| 2179 | /// The dirname is not allowed to escape the logical root for underlying path. | 2168 | /// The dirname is not allowed to escape the logical root for underlying path. |
| ... | @@ -2183,8 +2172,6 @@ pub const LazyPath = union(enum) { | ... | @@ -2183,8 +2172,6 @@ pub const LazyPath = union(enum) { |
| 2183 | /// the dirname is not allowed to traverse outside of zig-cache. | 2172 | /// the dirname is not allowed to traverse outside of zig-cache. |
| 2184 | pub fn dirname(lazy_path: LazyPath) LazyPath { | 2173 | pub fn dirname(lazy_path: LazyPath) LazyPath { |
| 2185 | return switch (lazy_path) { | 2174 | return switch (lazy_path) { |
| 2186 | .generated => |gen| .{ .generated_dirname = .{ .generated = gen, .up = 0 } }, | ||
| 2187 | .generated_dirname => |gen| .{ .generated_dirname = .{ .generated = gen.generated, .up = gen.up + 1 } }, | ||
| 2188 | .src_path => |sp| .{ .src_path = .{ | 2175 | .src_path => |sp| .{ .src_path = .{ |
| 2189 | .owner = sp.owner, | 2176 | .owner = sp.owner, |
| 2190 | .sub_path = dirnameAllowEmpty(sp.sub_path) orelse { | 2177 | .sub_path = dirnameAllowEmpty(sp.sub_path) orelse { |
| ... | @@ -2192,12 +2179,15 @@ pub const LazyPath = union(enum) { | ... | @@ -2192,12 +2179,15 @@ pub const LazyPath = union(enum) { |
| 2192 | @panic("misconfigured build script"); | 2179 | @panic("misconfigured build script"); |
| 2193 | }, | 2180 | }, |
| 2194 | } }, | 2181 | } }, |
| 2195 | .path => |sub_path| .{ | 2182 | .generated => |generated| .{ .generated = if (dirnameAllowEmpty(generated.sub_path)) |sub_dirname| .{ |
| 2196 | .path = dirnameAllowEmpty(sub_path) orelse { | 2183 | .file = generated.file, |
| 2197 | dumpBadDirnameHelp(null, null, "dirname() attempted to traverse outside the build root\n", .{}) catch {}; | 2184 | .up = generated.up, |
| 2198 | @panic("misconfigured build script"); | 2185 | .sub_path = sub_dirname, |
| 2199 | }, | 2186 | } else .{ |
| 2200 | }, | 2187 | .file = generated.file, |
| 2188 | .up = generated.up + 1, | ||
| 2189 | .sub_path = "", | ||
| 2190 | } }, | ||
| 2201 | .cwd_relative => |rel_path| .{ | 2191 | .cwd_relative => |rel_path| .{ |
| 2202 | .cwd_relative = dirnameAllowEmpty(rel_path) orelse { | 2192 | .cwd_relative = dirnameAllowEmpty(rel_path) orelse { |
| 2203 | // If we get null, it means one of two things: | 2193 | // If we get null, it means one of two things: |
| ... | @@ -2234,14 +2224,34 @@ pub const LazyPath = union(enum) { | ... | @@ -2234,14 +2224,34 @@ pub const LazyPath = union(enum) { |
| 2234 | }; | 2224 | }; |
| 2235 | } | 2225 | } |
| 2236 | 2226 | ||
| 2227 | pub fn path(lazy_path: LazyPath, b: *Build, sub_path: []const u8) LazyPath { | ||
| 2228 | return switch (lazy_path) { | ||
| 2229 | .src_path => |src| .{ .src_path = .{ | ||
| 2230 | .owner = src.owner, | ||
| 2231 | .sub_path = b.pathResolve(&.{ src.sub_path, sub_path }), | ||
| 2232 | } }, | ||
| 2233 | .generated => |gen| .{ .generated = .{ | ||
| 2234 | .file = gen.file, | ||
| 2235 | .up = gen.up, | ||
| 2236 | .sub_path = b.pathResolve(&.{ gen.sub_path, sub_path }), | ||
| 2237 | } }, | ||
| 2238 | .cwd_relative => |cwd_relative| .{ | ||
| 2239 | .cwd_relative = b.pathResolve(&.{ cwd_relative, sub_path }), | ||
| 2240 | }, | ||
| 2241 | .dependency => |dep| .{ .dependency = .{ | ||
| 2242 | .dependency = dep.dependency, | ||
| 2243 | .sub_path = b.pathResolve(&.{ dep.sub_path, sub_path }), | ||
| 2244 | } }, | ||
| 2245 | }; | ||
| 2246 | } | ||
| 2247 | |||
| 2237 | /// Returns a string that can be shown to represent the file source. | 2248 | /// Returns a string that can be shown to represent the file source. |
| 2238 | /// Either returns the path or `"generated"`. | 2249 | /// Either returns the path, `"generated"`, or `"dependency"`. |
| 2239 | pub fn getDisplayName(lazy_path: LazyPath) []const u8 { | 2250 | pub fn getDisplayName(lazy_path: LazyPath) []const u8 { |
| 2240 | return switch (lazy_path) { | 2251 | return switch (lazy_path) { |
| 2241 | .src_path => |src_path| src_path.sub_path, | 2252 | .src_path => |sp| sp.sub_path, |
| 2242 | .path, .cwd_relative => |sub_path| sub_path, | 2253 | .cwd_relative => |p| p, |
| 2243 | .generated => "generated", | 2254 | .generated => "generated", |
| 2244 | .generated_dirname => "generated", | ||
| 2245 | .dependency => "dependency", | 2255 | .dependency => "dependency", |
| 2246 | }; | 2256 | }; |
| 2247 | } | 2257 | } |
| ... | @@ -2249,9 +2259,8 @@ pub const LazyPath = union(enum) { | ... | @@ -2249,9 +2259,8 @@ pub const LazyPath = union(enum) { |
| 2249 | /// Adds dependencies this file source implies to the given step. | 2259 | /// Adds dependencies this file source implies to the given step. |
| 2250 | pub fn addStepDependencies(lazy_path: LazyPath, other_step: *Step) void { | 2260 | pub fn addStepDependencies(lazy_path: LazyPath, other_step: *Step) void { |
| 2251 | switch (lazy_path) { | 2261 | switch (lazy_path) { |
| 2252 | .src_path, .path, .cwd_relative, .dependency => {}, | 2262 | .src_path, .cwd_relative, .dependency => {}, |
| 2253 | .generated => |gen| other_step.dependOn(gen.step), | 2263 | .generated => |gen| other_step.dependOn(gen.file.step), |
| 2254 | .generated_dirname => |gen| other_step.dependOn(gen.generated.step), | ||
| 2255 | } | 2264 | } |
| 2256 | } | 2265 | } |
| 2257 | 2266 | ||
| ... | @@ -2268,47 +2277,48 @@ pub const LazyPath = union(enum) { | ... | @@ -2268,47 +2277,48 @@ pub const LazyPath = union(enum) { |
| 2268 | /// run that is asking for the path. | 2277 | /// run that is asking for the path. |
| 2269 | pub fn getPath2(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 { | 2278 | pub fn getPath2(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 { |
| 2270 | switch (lazy_path) { | 2279 | switch (lazy_path) { |
| 2271 | .path => |p| return src_builder.pathFromRoot(p), | ||
| 2272 | .src_path => |sp| return sp.owner.pathFromRoot(sp.sub_path), | 2280 | .src_path => |sp| return sp.owner.pathFromRoot(sp.sub_path), |
| 2273 | .cwd_relative => |p| return src_builder.pathFromCwd(p), | 2281 | .cwd_relative => |p| return src_builder.pathFromCwd(p), |
| 2274 | .generated => |gen| return gen.step.owner.pathFromRoot(gen.path orelse { | 2282 | .generated => |gen| { |
| 2275 | std.debug.getStderrMutex().lock(); | 2283 | var file_path: []const u8 = gen.file.step.owner.pathFromRoot(gen.file.path orelse { |
| 2276 | const stderr = std.io.getStdErr(); | 2284 | std.debug.getStderrMutex().lock(); |
| 2277 | dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {}; | 2285 | const stderr = std.io.getStdErr(); |
| 2278 | @panic("misconfigured build script"); | 2286 | dumpBadGetPathHelp(gen.file.step, stderr, src_builder, asking_step) catch {}; |
| 2279 | }), | 2287 | std.debug.getStderrMutex().unlock(); |
| 2280 | .generated_dirname => |gen| { | 2288 | @panic("misconfigured build script"); |
| 2281 | const cache_root_path = src_builder.cache_root.path orelse | 2289 | }); |
| 2282 | (src_builder.cache_root.join(src_builder.allocator, &.{"."}) catch @panic("OOM")); | 2290 | |
| 2283 | 2291 | if (gen.up > 0) { | |
| 2284 | const gen_step = gen.generated.step; | 2292 | const cache_root_path = src_builder.cache_root.path orelse |
| 2285 | var p = getPath2(LazyPath{ .generated = gen.generated }, src_builder, asking_step); | 2293 | (src_builder.cache_root.join(src_builder.allocator, &.{"."}) catch @panic("OOM")); |
| 2286 | var i: usize = 0; | 2294 | |
| 2287 | while (i <= gen.up) : (i += 1) { | 2295 | for (0..gen.up) |_| { |
| 2288 | // path is absolute. | 2296 | if (mem.eql(u8, file_path, cache_root_path)) { |
| 2289 | // dirname will return null only if we're at root. | 2297 | // If we hit the cache root and there's still more to go, |
| 2290 | // Typically, we'll stop well before that at the cache root. | 2298 | // the script attempted to go too far. |
| 2291 | p = fs.path.dirname(p) orelse { | 2299 | dumpBadDirnameHelp(gen.file.step, asking_step, |
| 2292 | dumpBadDirnameHelp(gen_step, asking_step, | 2300 | \\dirname() attempted to traverse outside the cache root. |
| 2293 | \\dirname() reached root. | 2301 | \\This is not allowed. |
| 2294 | \\No more directories left to go up. | 2302 | \\ |
| 2295 | \\ | 2303 | , .{}) catch {}; |
| 2296 | , .{}) catch {}; | 2304 | @panic("misconfigured build script"); |
| 2297 | @panic("misconfigured build script"); | 2305 | } |
| 2298 | }; | 2306 | |
| 2299 | 2307 | // path is absolute. | |
| 2300 | if (mem.eql(u8, p, cache_root_path) and i < gen.up) { | 2308 | // dirname will return null only if we're at root. |
| 2301 | // If we hit the cache root and there's still more to go, | 2309 | // Typically, we'll stop well before that at the cache root. |
| 2302 | // the script attempted to go too far. | 2310 | file_path = fs.path.dirname(file_path) orelse { |
| 2303 | dumpBadDirnameHelp(gen_step, asking_step, | 2311 | dumpBadDirnameHelp(gen.file.step, asking_step, |
| 2304 | \\dirname() attempted to traverse outside the cache root. | 2312 | \\dirname() reached root. |
| 2305 | \\This is not allowed. | 2313 | \\No more directories left to go up. |
| 2306 | \\ | 2314 | \\ |
| 2307 | , .{}) catch {}; | 2315 | , .{}) catch {}; |
| 2308 | @panic("misconfigured build script"); | 2316 | @panic("misconfigured build script"); |
| 2317 | }; | ||
| 2309 | } | 2318 | } |
| 2310 | } | 2319 | } |
| 2311 | return p; | 2320 | |
| 2321 | return src_builder.pathResolve(&.{ file_path, gen.sub_path }); | ||
| 2312 | }, | 2322 | }, |
| 2313 | .dependency => |dep| return dep.dependency.builder.pathFromRoot(dep.sub_path), | 2323 | .dependency => |dep| return dep.dependency.builder.pathFromRoot(dep.sub_path), |
| 2314 | } | 2324 | } |
| ... | @@ -2324,15 +2334,12 @@ pub const LazyPath = union(enum) { | ... | @@ -2324,15 +2334,12 @@ pub const LazyPath = union(enum) { |
| 2324 | .owner = sp.owner, | 2334 | .owner = sp.owner, |
| 2325 | .sub_path = sp.owner.dupePath(sp.sub_path), | 2335 | .sub_path = sp.owner.dupePath(sp.sub_path), |
| 2326 | } }, | 2336 | } }, |
| 2327 | .path => |p| .{ .path = b.dupePath(p) }, | ||
| 2328 | .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) }, | 2337 | .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) }, |
| 2329 | .generated => |gen| .{ .generated = gen }, | 2338 | .generated => |gen| .{ .generated = .{ |
| 2330 | .generated_dirname => |gen| .{ | 2339 | .file = gen.file, |
| 2331 | .generated_dirname = .{ | 2340 | .up = gen.up, |
| 2332 | .generated = gen.generated, | 2341 | .sub_path = b.dupePath(gen.sub_path), |
| 2333 | .up = gen.up, | 2342 | } }, |
| 2334 | }, | ||
| 2335 | }, | ||
| 2336 | .dependency => |dep| .{ .dependency = dep }, | 2343 | .dependency => |dep| .{ .dependency = dep }, |
| 2337 | }; | 2344 | }; |
| 2338 | } | 2345 | } |
lib/std/Build/Step/Compile.zig+2-4| ... | @@ -806,14 +806,12 @@ pub fn setLibCFile(compile: *Compile, libc_file: ?LazyPath) void { | ... | @@ -806,14 +806,12 @@ pub fn setLibCFile(compile: *Compile, libc_file: ?LazyPath) void { |
| 806 | } | 806 | } |
| 807 | 807 | ||
| 808 | fn getEmittedFileGeneric(compile: *Compile, output_file: *?*GeneratedFile) LazyPath { | 808 | fn getEmittedFileGeneric(compile: *Compile, output_file: *?*GeneratedFile) LazyPath { |
| 809 | if (output_file.*) |g| { | 809 | if (output_file.*) |file| return .{ .generated = .{ .file = file } }; |
| 810 | return .{ .generated = g }; | ||
| 811 | } | ||
| 812 | const arena = compile.step.owner.allocator; | 810 | const arena = compile.step.owner.allocator; |
| 813 | const generated_file = arena.create(GeneratedFile) catch @panic("OOM"); | 811 | const generated_file = arena.create(GeneratedFile) catch @panic("OOM"); |
| 814 | generated_file.* = .{ .step = &compile.step }; | 812 | generated_file.* = .{ .step = &compile.step }; |
| 815 | output_file.* = generated_file; | 813 | output_file.* = generated_file; |
| 816 | return .{ .generated = generated_file }; | 814 | return .{ .generated = .{ .file = generated_file } }; |
| 817 | } | 815 | } |
| 818 | 816 | ||
| 819 | /// Returns the path to the directory that contains the emitted binary file. | 817 | /// Returns the path to the directory that contains the emitted binary file. |
lib/std/Build/Step/ConfigHeader.zig+2-3| ... | @@ -59,8 +59,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader { | ... | @@ -59,8 +59,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader { |
| 59 | if (options.style.getPath()) |s| default_include_path: { | 59 | if (options.style.getPath()) |s| default_include_path: { |
| 60 | const sub_path = switch (s) { | 60 | const sub_path = switch (s) { |
| 61 | .src_path => |sp| sp.sub_path, | 61 | .src_path => |sp| sp.sub_path, |
| 62 | .path => |path| path, | 62 | .generated => break :default_include_path, |
| 63 | .generated, .generated_dirname => break :default_include_path, | ||
| 64 | .cwd_relative => |sub_path| sub_path, | 63 | .cwd_relative => |sub_path| sub_path, |
| 65 | .dependency => |dependency| dependency.sub_path, | 64 | .dependency => |dependency| dependency.sub_path, |
| 66 | }; | 65 | }; |
| ... | @@ -106,7 +105,7 @@ pub fn addValues(config_header: *ConfigHeader, values: anytype) void { | ... | @@ -106,7 +105,7 @@ pub fn addValues(config_header: *ConfigHeader, values: anytype) void { |
| 106 | } | 105 | } |
| 107 | 106 | ||
| 108 | pub fn getOutput(config_header: *ConfigHeader) std.Build.LazyPath { | 107 | pub fn getOutput(config_header: *ConfigHeader) std.Build.LazyPath { |
| 109 | return .{ .generated = &config_header.output_file }; | 108 | return .{ .generated = .{ .file = &config_header.output_file } }; |
| 110 | } | 109 | } |
| 111 | 110 | ||
| 112 | fn addValuesInner(config_header: *ConfigHeader, values: anytype) !void { | 111 | fn addValuesInner(config_header: *ConfigHeader, values: anytype) !void { |
lib/std/Build/Step/ObjCopy.zig+2-2| ... | @@ -84,10 +84,10 @@ pub fn create( | ... | @@ -84,10 +84,10 @@ pub fn create( |
| 84 | pub const getOutputSource = getOutput; | 84 | pub const getOutputSource = getOutput; |
| 85 | 85 | ||
| 86 | pub fn getOutput(objcopy: *const ObjCopy) std.Build.LazyPath { | 86 | pub fn getOutput(objcopy: *const ObjCopy) std.Build.LazyPath { |
| 87 | return .{ .generated = &objcopy.output_file }; | 87 | return .{ .generated = .{ .file = &objcopy.output_file } }; |
| 88 | } | 88 | } |
| 89 | pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath { | 89 | pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath { |
| 90 | return if (objcopy.output_file_debug) |*file| .{ .generated = file } else null; | 90 | return if (objcopy.output_file_debug) |*file| .{ .generated = .{ .file = file } } else null; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 93 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
lib/std/Build/Step/Options.zig+1-1| ... | @@ -407,7 +407,7 @@ pub const getSource = getOutput; | ... | @@ -407,7 +407,7 @@ pub const getSource = getOutput; |
| 407 | /// Returns the main artifact of this Build Step which is a Zig source file | 407 | /// Returns the main artifact of this Build Step which is a Zig source file |
| 408 | /// generated from the key-value pairs of the Options. | 408 | /// generated from the key-value pairs of the Options. |
| 409 | pub fn getOutput(options: *Options) LazyPath { | 409 | pub fn getOutput(options: *Options) LazyPath { |
| 410 | return .{ .generated = &options.generated_file }; | 410 | return .{ .generated = .{ .file = &options.generated_file } }; |
| 411 | } | 411 | } |
| 412 | 412 | ||
| 413 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 413 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
lib/std/Build/Step/Run.zig+113-26| ... | @@ -125,7 +125,8 @@ pub const Arg = union(enum) { | ... | @@ -125,7 +125,8 @@ pub const Arg = union(enum) { |
| 125 | lazy_path: PrefixedLazyPath, | 125 | lazy_path: PrefixedLazyPath, |
| 126 | directory_source: PrefixedLazyPath, | 126 | directory_source: PrefixedLazyPath, |
| 127 | bytes: []u8, | 127 | bytes: []u8, |
| 128 | output: *Output, | 128 | output_file: *Output, |
| 129 | output_directory: *Output, | ||
| 129 | }; | 130 | }; |
| 130 | 131 | ||
| 131 | pub const PrefixedLazyPath = struct { | 132 | pub const PrefixedLazyPath = struct { |
| ... | @@ -225,13 +226,13 @@ pub fn addPrefixedOutputFileArg( | ... | @@ -225,13 +226,13 @@ pub fn addPrefixedOutputFileArg( |
| 225 | .basename = b.dupe(basename), | 226 | .basename = b.dupe(basename), |
| 226 | .generated_file = .{ .step = &run.step }, | 227 | .generated_file = .{ .step = &run.step }, |
| 227 | }; | 228 | }; |
| 228 | run.argv.append(b.allocator, .{ .output = output }) catch @panic("OOM"); | 229 | run.argv.append(b.allocator, .{ .output_file = output }) catch @panic("OOM"); |
| 229 | 230 | ||
| 230 | if (run.rename_step_with_output_arg) { | 231 | if (run.rename_step_with_output_arg) { |
| 231 | run.setName(b.fmt("{s} ({s})", .{ run.step.name, basename })); | 232 | run.setName(b.fmt("{s} ({s})", .{ run.step.name, basename })); |
| 232 | } | 233 | } |
| 233 | 234 | ||
| 234 | return .{ .generated = &output.generated_file }; | 235 | return .{ .generated = .{ .file = &output.generated_file } }; |
| 235 | } | 236 | } |
| 236 | 237 | ||
| 237 | /// Appends an input file to the command line arguments. | 238 | /// Appends an input file to the command line arguments. |
| ... | @@ -270,6 +271,56 @@ pub fn addPrefixedFileArg(run: *Run, prefix: []const u8, lp: std.Build.LazyPath) | ... | @@ -270,6 +271,56 @@ pub fn addPrefixedFileArg(run: *Run, prefix: []const u8, lp: std.Build.LazyPath) |
| 270 | lp.addStepDependencies(&run.step); | 271 | lp.addStepDependencies(&run.step); |
| 271 | } | 272 | } |
| 272 | 273 | ||
| 274 | /// Provides a directory path as a command line argument to the command being run. | ||
| 275 | /// | ||
| 276 | /// Returns a `std.Build.LazyPath` which can be used as inputs to other APIs | ||
| 277 | /// throughout the build system. | ||
| 278 | /// | ||
| 279 | /// Related: | ||
| 280 | /// * `addPrefixedOutputDirectoryArg` - same thing but prepends a string to the argument | ||
| 281 | /// * `addDirectoryArg` - for input directories given to the child process | ||
| 282 | pub fn addOutputDirectoryArg(run: *Run, basename: []const u8) std.Build.LazyPath { | ||
| 283 | return run.addPrefixedOutputDirectoryArg("", basename); | ||
| 284 | } | ||
| 285 | |||
| 286 | /// Provides a directory path as a command line argument to the command being run. | ||
| 287 | /// Asserts `basename` is not empty. | ||
| 288 | /// | ||
| 289 | /// For example, a prefix of "-o" and basename of "output_dir" will result in | ||
| 290 | /// the child process seeing something like this: "-ozig-cache/.../output_dir" | ||
| 291 | /// | ||
| 292 | /// The child process will see a single argument, regardless of whether the | ||
| 293 | /// prefix or basename have spaces. | ||
| 294 | /// | ||
| 295 | /// The returned `std.Build.LazyPath` can be used as inputs to other APIs | ||
| 296 | /// throughout the build system. | ||
| 297 | /// | ||
| 298 | /// Related: | ||
| 299 | /// * `addOutputDirectoryArg` - same thing but without the prefix | ||
| 300 | /// * `addDirectoryArg` - for input directories given to the child process | ||
| 301 | pub fn addPrefixedOutputDirectoryArg( | ||
| 302 | run: *Run, | ||
| 303 | prefix: []const u8, | ||
| 304 | basename: []const u8, | ||
| 305 | ) std.Build.LazyPath { | ||
| 306 | if (basename.len == 0) @panic("basename must not be empty"); | ||
| 307 | const b = run.step.owner; | ||
| 308 | |||
| 309 | const output = b.allocator.create(Output) catch @panic("OOM"); | ||
| 310 | output.* = .{ | ||
| 311 | .prefix = b.dupe(prefix), | ||
| 312 | .basename = b.dupe(basename), | ||
| 313 | .generated_file = .{ .step = &run.step }, | ||
| 314 | }; | ||
| 315 | run.argv.append(b.allocator, .{ .output_directory = output }) catch @panic("OOM"); | ||
| 316 | |||
| 317 | if (run.rename_step_with_output_arg) { | ||
| 318 | run.setName(b.fmt("{s} ({s})", .{ run.step.name, basename })); | ||
| 319 | } | ||
| 320 | |||
| 321 | return .{ .generated = .{ .file = &output.generated_file } }; | ||
| 322 | } | ||
| 323 | |||
| 273 | /// deprecated: use `addDirectoryArg` | 324 | /// deprecated: use `addDirectoryArg` |
| 274 | pub const addDirectorySourceArg = addDirectoryArg; | 325 | pub const addDirectorySourceArg = addDirectoryArg; |
| 275 | 326 | ||
| ... | @@ -314,9 +365,9 @@ pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []co | ... | @@ -314,9 +365,9 @@ pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []co |
| 314 | 365 | ||
| 315 | run.dep_output_file = dep_file; | 366 | run.dep_output_file = dep_file; |
| 316 | 367 | ||
| 317 | run.argv.append(b.allocator, .{ .output = dep_file }) catch @panic("OOM"); | 368 | run.argv.append(b.allocator, .{ .output_file = dep_file }) catch @panic("OOM"); |
| 318 | 369 | ||
| 319 | return .{ .generated = &dep_file.generated_file }; | 370 | return .{ .generated = .{ .file = &dep_file.generated_file } }; |
| 320 | } | 371 | } |
| 321 | 372 | ||
| 322 | pub fn addArg(run: *Run, arg: []const u8) void { | 373 | pub fn addArg(run: *Run, arg: []const u8) void { |
| ... | @@ -432,7 +483,7 @@ pub fn addCheck(run: *Run, new_check: StdIo.Check) void { | ... | @@ -432,7 +483,7 @@ pub fn addCheck(run: *Run, new_check: StdIo.Check) void { |
| 432 | pub fn captureStdErr(run: *Run) std.Build.LazyPath { | 483 | pub fn captureStdErr(run: *Run) std.Build.LazyPath { |
| 433 | assert(run.stdio != .inherit); | 484 | assert(run.stdio != .inherit); |
| 434 | 485 | ||
| 435 | if (run.captured_stderr) |output| return .{ .generated = &output.generated_file }; | 486 | if (run.captured_stderr) |output| return .{ .generated = .{ .file = &output.generated_file } }; |
| 436 | 487 | ||
| 437 | const output = run.step.owner.allocator.create(Output) catch @panic("OOM"); | 488 | const output = run.step.owner.allocator.create(Output) catch @panic("OOM"); |
| 438 | output.* = .{ | 489 | output.* = .{ |
| ... | @@ -441,13 +492,13 @@ pub fn captureStdErr(run: *Run) std.Build.LazyPath { | ... | @@ -441,13 +492,13 @@ pub fn captureStdErr(run: *Run) std.Build.LazyPath { |
| 441 | .generated_file = .{ .step = &run.step }, | 492 | .generated_file = .{ .step = &run.step }, |
| 442 | }; | 493 | }; |
| 443 | run.captured_stderr = output; | 494 | run.captured_stderr = output; |
| 444 | return .{ .generated = &output.generated_file }; | 495 | return .{ .generated = .{ .file = &output.generated_file } }; |
| 445 | } | 496 | } |
| 446 | 497 | ||
| 447 | pub fn captureStdOut(run: *Run) std.Build.LazyPath { | 498 | pub fn captureStdOut(run: *Run) std.Build.LazyPath { |
| 448 | assert(run.stdio != .inherit); | 499 | assert(run.stdio != .inherit); |
| 449 | 500 | ||
| 450 | if (run.captured_stdout) |output| return .{ .generated = &output.generated_file }; | 501 | if (run.captured_stdout) |output| return .{ .generated = .{ .file = &output.generated_file } }; |
| 451 | 502 | ||
| 452 | const output = run.step.owner.allocator.create(Output) catch @panic("OOM"); | 503 | const output = run.step.owner.allocator.create(Output) catch @panic("OOM"); |
| 453 | output.* = .{ | 504 | output.* = .{ |
| ... | @@ -456,7 +507,7 @@ pub fn captureStdOut(run: *Run) std.Build.LazyPath { | ... | @@ -456,7 +507,7 @@ pub fn captureStdOut(run: *Run) std.Build.LazyPath { |
| 456 | .generated_file = .{ .step = &run.step }, | 507 | .generated_file = .{ .step = &run.step }, |
| 457 | }; | 508 | }; |
| 458 | run.captured_stdout = output; | 509 | run.captured_stdout = output; |
| 459 | return .{ .generated = &output.generated_file }; | 510 | return .{ .generated = .{ .file = &output.generated_file } }; |
| 460 | } | 511 | } |
| 461 | 512 | ||
| 462 | /// Adds an additional input files that, when modified, indicates that this Run | 513 | /// Adds an additional input files that, when modified, indicates that this Run |
| ... | @@ -484,7 +535,7 @@ fn hasAnyOutputArgs(run: Run) bool { | ... | @@ -484,7 +535,7 @@ fn hasAnyOutputArgs(run: Run) bool { |
| 484 | if (run.captured_stdout != null) return true; | 535 | if (run.captured_stdout != null) return true; |
| 485 | if (run.captured_stderr != null) return true; | 536 | if (run.captured_stderr != null) return true; |
| 486 | for (run.argv.items) |arg| switch (arg) { | 537 | for (run.argv.items) |arg| switch (arg) { |
| 487 | .output => return true, | 538 | .output_file, .output_directory => return true, |
| 488 | else => continue, | 539 | else => continue, |
| 489 | }; | 540 | }; |
| 490 | return false; | 541 | return false; |
| ... | @@ -520,6 +571,7 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { | ... | @@ -520,6 +571,7 @@ fn checksContainStderr(checks: []const StdIo.Check) bool { |
| 520 | 571 | ||
| 521 | const IndexedOutput = struct { | 572 | const IndexedOutput = struct { |
| 522 | index: usize, | 573 | index: usize, |
| 574 | tag: @typeInfo(Arg).Union.tag_type.?, | ||
| 523 | output: *Output, | 575 | output: *Output, |
| 524 | }; | 576 | }; |
| 525 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 577 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| ... | @@ -563,17 +615,18 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -563,17 +615,18 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 563 | 615 | ||
| 564 | _ = try man.addFile(file_path, null); | 616 | _ = try man.addFile(file_path, null); |
| 565 | }, | 617 | }, |
| 566 | .output => |output| { | 618 | .output_file, .output_directory => |output| { |
| 567 | man.hash.addBytes(output.prefix); | 619 | man.hash.addBytes(output.prefix); |
| 568 | man.hash.addBytes(output.basename); | 620 | man.hash.addBytes(output.basename); |
| 569 | // Add a placeholder into the argument list because we need the | 621 | // Add a placeholder into the argument list because we need the |
| 570 | // manifest hash to be updated with all arguments before the | 622 | // manifest hash to be updated with all arguments before the |
| 571 | // object directory is computed. | 623 | // object directory is computed. |
| 572 | try argv_list.append(""); | ||
| 573 | try output_placeholders.append(.{ | 624 | try output_placeholders.append(.{ |
| 574 | .index = argv_list.items.len - 1, | 625 | .index = argv_list.items.len, |
| 626 | .tag = arg, | ||
| 575 | .output = output, | 627 | .output = output, |
| 576 | }); | 628 | }); |
| 629 | _ = try argv_list.addOne(); | ||
| 577 | }, | 630 | }, |
| 578 | } | 631 | } |
| 579 | } | 632 | } |
| ... | @@ -599,11 +652,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -599,11 +652,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 599 | 652 | ||
| 600 | hashStdIo(&man.hash, run.stdio); | 653 | hashStdIo(&man.hash, run.stdio); |
| 601 | 654 | ||
| 602 | if (has_side_effects) { | ||
| 603 | try runCommand(run, argv_list.items, has_side_effects, null, prog_node); | ||
| 604 | return; | ||
| 605 | } | ||
| 606 | |||
| 607 | for (run.extra_file_dependencies) |file_path| { | 655 | for (run.extra_file_dependencies) |file_path| { |
| 608 | _ = try man.addFile(b.pathFromRoot(file_path), null); | 656 | _ = try man.addFile(b.pathFromRoot(file_path), null); |
| 609 | } | 657 | } |
| ... | @@ -611,7 +659,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -611,7 +659,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 611 | _ = try man.addFile(lazy_path.getPath2(b, step), null); | 659 | _ = try man.addFile(lazy_path.getPath2(b, step), null); |
| 612 | } | 660 | } |
| 613 | 661 | ||
| 614 | if (try step.cacheHit(&man)) { | 662 | if (try step.cacheHit(&man) and !has_side_effects) { |
| 615 | // cache hit, skip running command | 663 | // cache hit, skip running command |
| 616 | const digest = man.final(); | 664 | const digest = man.final(); |
| 617 | 665 | ||
| ... | @@ -628,13 +676,54 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -628,13 +676,54 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 628 | return; | 676 | return; |
| 629 | } | 677 | } |
| 630 | 678 | ||
| 679 | const dep_output_file = run.dep_output_file orelse { | ||
| 680 | // We already know the final output paths, use them directly. | ||
| 681 | const digest = man.final(); | ||
| 682 | |||
| 683 | try populateGeneratedPaths( | ||
| 684 | arena, | ||
| 685 | output_placeholders.items, | ||
| 686 | run.captured_stdout, | ||
| 687 | run.captured_stderr, | ||
| 688 | b.cache_root, | ||
| 689 | &digest, | ||
| 690 | ); | ||
| 691 | |||
| 692 | const output_dir_path = "o" ++ fs.path.sep_str ++ &digest; | ||
| 693 | for (output_placeholders.items) |placeholder| { | ||
| 694 | const output_sub_path = b.pathJoin(&.{ output_dir_path, placeholder.output.basename }); | ||
| 695 | const output_sub_dir_path = switch (placeholder.tag) { | ||
| 696 | .output_file => fs.path.dirname(output_sub_path).?, | ||
| 697 | .output_directory => output_sub_path, | ||
| 698 | else => unreachable, | ||
| 699 | }; | ||
| 700 | b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { | ||
| 701 | return step.fail("unable to make path '{}{s}': {s}", .{ | ||
| 702 | b.cache_root, output_sub_dir_path, @errorName(err), | ||
| 703 | }); | ||
| 704 | }; | ||
| 705 | const output_path = placeholder.output.generated_file.path.?; | ||
| 706 | argv_list.items[placeholder.index] = if (placeholder.output.prefix.len == 0) | ||
| 707 | output_path | ||
| 708 | else | ||
| 709 | b.fmt("{s}{s}", .{ placeholder.output.prefix, output_path }); | ||
| 710 | } | ||
| 711 | |||
| 712 | return runCommand(run, argv_list.items, has_side_effects, output_dir_path, prog_node); | ||
| 713 | }; | ||
| 714 | |||
| 715 | // We do not know the final output paths yet, use temp paths to run the command. | ||
| 631 | const rand_int = std.crypto.random.int(u64); | 716 | const rand_int = std.crypto.random.int(u64); |
| 632 | const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.Build.hex64(rand_int); | 717 | const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.Build.hex64(rand_int); |
| 633 | 718 | ||
| 634 | for (output_placeholders.items) |placeholder| { | 719 | for (output_placeholders.items) |placeholder| { |
| 635 | const output_components = .{ tmp_dir_path, placeholder.output.basename }; | 720 | const output_components = .{ tmp_dir_path, placeholder.output.basename }; |
| 636 | const output_sub_path = b.pathJoin(&output_components); | 721 | const output_sub_path = b.pathJoin(&output_components); |
| 637 | const output_sub_dir_path = fs.path.dirname(output_sub_path).?; | 722 | const output_sub_dir_path = switch (placeholder.tag) { |
| 723 | .output_file => fs.path.dirname(output_sub_path).?, | ||
| 724 | .output_directory => output_sub_path, | ||
| 725 | else => unreachable, | ||
| 726 | }; | ||
| 638 | b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { | 727 | b.cache_root.handle.makePath(output_sub_dir_path) catch |err| { |
| 639 | return step.fail("unable to make path '{}{s}': {s}", .{ | 728 | return step.fail("unable to make path '{}{s}': {s}", .{ |
| 640 | b.cache_root, output_sub_dir_path, @errorName(err), | 729 | b.cache_root, output_sub_dir_path, @errorName(err), |
| ... | @@ -642,17 +731,15 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -642,17 +731,15 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 642 | }; | 731 | }; |
| 643 | const output_path = try b.cache_root.join(arena, &output_components); | 732 | const output_path = try b.cache_root.join(arena, &output_components); |
| 644 | placeholder.output.generated_file.path = output_path; | 733 | placeholder.output.generated_file.path = output_path; |
| 645 | const cli_arg = if (placeholder.output.prefix.len == 0) | 734 | argv_list.items[placeholder.index] = if (placeholder.output.prefix.len == 0) |
| 646 | output_path | 735 | output_path |
| 647 | else | 736 | else |
| 648 | b.fmt("{s}{s}", .{ placeholder.output.prefix, output_path }); | 737 | b.fmt("{s}{s}", .{ placeholder.output.prefix, output_path }); |
| 649 | argv_list.items[placeholder.index] = cli_arg; | ||
| 650 | } | 738 | } |
| 651 | 739 | ||
| 652 | try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, prog_node); | 740 | try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, prog_node); |
| 653 | 741 | ||
| 654 | if (run.dep_output_file) |dep_output_file| | 742 | try man.addDepFilePost(std.fs.cwd(), dep_output_file.generated_file.getPath()); |
| 655 | try man.addDepFilePost(std.fs.cwd(), dep_output_file.generated_file.getPath()); | ||
| 656 | 743 | ||
| 657 | const digest = man.final(); | 744 | const digest = man.final(); |
| 658 | 745 | ||
| ... | @@ -777,7 +864,7 @@ fn runCommand( | ... | @@ -777,7 +864,7 @@ fn runCommand( |
| 777 | run: *Run, | 864 | run: *Run, |
| 778 | argv: []const []const u8, | 865 | argv: []const []const u8, |
| 779 | has_side_effects: bool, | 866 | has_side_effects: bool, |
| 780 | tmp_dir_path: ?[]const u8, | 867 | output_dir_path: []const u8, |
| 781 | prog_node: *std.Progress.Node, | 868 | prog_node: *std.Progress.Node, |
| 782 | ) !void { | 869 | ) !void { |
| 783 | const step = &run.step; | 870 | const step = &run.step; |
| ... | @@ -950,7 +1037,7 @@ fn runCommand( | ... | @@ -950,7 +1037,7 @@ fn runCommand( |
| 950 | }, | 1037 | }, |
| 951 | }) |stream| { | 1038 | }) |stream| { |
| 952 | if (stream.captured) |output| { | 1039 | if (stream.captured) |output| { |
| 953 | const output_components = .{ tmp_dir_path.?, output.basename }; | 1040 | const output_components = .{ output_dir_path, output.basename }; |
| 954 | const output_path = try b.cache_root.join(arena, &output_components); | 1041 | const output_path = try b.cache_root.join(arena, &output_components); |
| 955 | output.generated_file.path = output_path; | 1042 | output.generated_file.path = output_path; |
| 956 | 1043 |
lib/std/Build/Step/TranslateC.zig+1-1| ... | @@ -59,7 +59,7 @@ pub const AddExecutableOptions = struct { | ... | @@ -59,7 +59,7 @@ pub const AddExecutableOptions = struct { |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | pub fn getOutput(translate_c: *TranslateC) std.Build.LazyPath { | 61 | pub fn getOutput(translate_c: *TranslateC) std.Build.LazyPath { |
| 62 | return .{ .generated = &translate_c.output_file }; | 62 | return .{ .generated = .{ .file = &translate_c.output_file } }; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | /// Creates a step to build an executable from the translated source. | 65 | /// Creates a step to build an executable from the translated source. |
lib/std/Build/Step/WriteFile.zig+3-3| ... | @@ -31,7 +31,7 @@ pub const File = struct { | ... | @@ -31,7 +31,7 @@ pub const File = struct { |
| 31 | contents: Contents, | 31 | contents: Contents, |
| 32 | 32 | ||
| 33 | pub fn getPath(file: *File) std.Build.LazyPath { | 33 | pub fn getPath(file: *File) std.Build.LazyPath { |
| 34 | return .{ .generated = &file.generated_file }; | 34 | return .{ .generated = .{ .file = &file.generated_file } }; |
| 35 | } | 35 | } |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| ... | @@ -58,7 +58,7 @@ pub const Directory = struct { | ... | @@ -58,7 +58,7 @@ pub const Directory = struct { |
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | pub fn getPath(dir: *Directory) std.Build.LazyPath { | 60 | pub fn getPath(dir: *Directory) std.Build.LazyPath { |
| 61 | return .{ .generated = &dir.generated_dir }; | 61 | return .{ .generated = .{ .file = &dir.generated_dir } }; |
| 62 | } | 62 | } |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| ... | @@ -181,7 +181,7 @@ pub fn addBytesToSource(write_file: *WriteFile, bytes: []const u8, sub_path: []c | ... | @@ -181,7 +181,7 @@ pub fn addBytesToSource(write_file: *WriteFile, bytes: []const u8, sub_path: []c |
| 181 | /// Returns a `LazyPath` representing the base directory that contains all the | 181 | /// Returns a `LazyPath` representing the base directory that contains all the |
| 182 | /// files from this `WriteFile`. | 182 | /// files from this `WriteFile`. |
| 183 | pub fn getDirectory(write_file: *WriteFile) std.Build.LazyPath { | 183 | pub fn getDirectory(write_file: *WriteFile) std.Build.LazyPath { |
| 184 | return .{ .generated = &write_file.generated_directory }; | 184 | return .{ .generated = .{ .file = &write_file.generated_directory } }; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | fn maybeUpdateName(write_file: *WriteFile) void { | 187 | fn maybeUpdateName(write_file: *WriteFile) void { |
test/standalone/build.zig.zon+3| ... | @@ -164,6 +164,9 @@ | ... | @@ -164,6 +164,9 @@ |
| 164 | .dependencyFromBuildZig = .{ | 164 | .dependencyFromBuildZig = .{ |
| 165 | .path = "dependencyFromBuildZig", | 165 | .path = "dependencyFromBuildZig", |
| 166 | }, | 166 | }, |
| 167 | .run_output_paths = .{ | ||
| 168 | .path = "run_output_paths", | ||
| 169 | }, | ||
| 167 | }, | 170 | }, |
| 168 | .paths = .{ | 171 | .paths = .{ |
| 169 | "build.zig", | 172 | "build.zig", |
test/standalone/run_output_paths/build.zig created+40| ... | @@ -0,0 +1,40 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn build(b: *std.Build) void { | ||
| 4 | const test_step = b.step("test", "Test it"); | ||
| 5 | b.default_step = test_step; | ||
| 6 | |||
| 7 | const target = b.standardTargetOptions(.{}); | ||
| 8 | const optimize = b.standardOptimizeOption(.{}); | ||
| 9 | |||
| 10 | const create_file_exe = b.addExecutable(.{ | ||
| 11 | .name = "create_file", | ||
| 12 | .root_source_file = b.path("create_file.zig"), | ||
| 13 | .target = target, | ||
| 14 | .optimize = optimize, | ||
| 15 | }); | ||
| 16 | |||
| 17 | const create_first = b.addRunArtifact(create_file_exe); | ||
| 18 | const first_dir = create_first.addOutputDirectoryArg("first"); | ||
| 19 | create_first.addArg("hello1.txt"); | ||
| 20 | test_step.dependOn(&b.addCheckFile(first_dir.path(b, "hello1.txt"), .{ .expected_matches = &.{ | ||
| 21 | std.fs.path.sep_str ++ | ||
| 22 | \\first | ||
| 23 | \\hello1.txt | ||
| 24 | \\Hello, world! | ||
| 25 | \\ | ||
| 26 | , | ||
| 27 | } }).step); | ||
| 28 | |||
| 29 | const create_second = b.addRunArtifact(create_file_exe); | ||
| 30 | const second_dir = create_second.addPrefixedOutputDirectoryArg("--dir=", "second"); | ||
| 31 | create_second.addArg("hello2.txt"); | ||
| 32 | test_step.dependOn(&b.addCheckFile(second_dir.path(b, "hello2.txt"), .{ .expected_matches = &.{ | ||
| 33 | std.fs.path.sep_str ++ | ||
| 34 | \\second | ||
| 35 | \\hello2.txt | ||
| 36 | \\Hello, world! | ||
| 37 | \\ | ||
| 38 | , | ||
| 39 | } }).step); | ||
| 40 | } | ||
test/standalone/run_output_paths/create_file.zig created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn main() !void { | ||
| 4 | var args = try std.process.argsWithAllocator(std.heap.page_allocator); | ||
| 5 | _ = args.skip(); | ||
| 6 | const dir_name = args.next().?; | ||
| 7 | const dir = try std.fs.cwd().openDir(if (std.mem.startsWith(u8, dir_name, "--dir=")) | ||
| 8 | dir_name["--dir=".len..] | ||
| 9 | else | ||
| 10 | dir_name, .{}); | ||
| 11 | const file_name = args.next().?; | ||
| 12 | const file = try dir.createFile(file_name, .{}); | ||
| 13 | try file.writer().print( | ||
| 14 | \\{s} | ||
| 15 | \\{s} | ||
| 16 | \\Hello, world! | ||
| 17 | \\ | ||
| 18 | , .{ dir_name, file_name }); | ||
| 19 | } | ||
test/standalone/windows_resources/build.zig+1-1| ... | @@ -36,7 +36,7 @@ fn add( | ... | @@ -36,7 +36,7 @@ fn add( |
| 36 | .file = b.path("res/zig.rc"), | 36 | .file = b.path("res/zig.rc"), |
| 37 | .flags = &.{"/c65001"}, // UTF-8 code page | 37 | .flags = &.{"/c65001"}, // UTF-8 code page |
| 38 | .include_paths = &.{ | 38 | .include_paths = &.{ |
| 39 | .{ .generated = &generated_h_step.generated_directory }, | 39 | .{ .generated = .{ .file = &generated_h_step.generated_directory } }, |
| 40 | }, | 40 | }, |
| 41 | }); | 41 | }); |
| 42 | exe.rc_includes = switch (rc_includes) { | 42 | exe.rc_includes = switch (rc_includes) { |