| ... | @@ -607,17 +607,17 @@ pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: | ... | @@ -607,17 +607,17 @@ pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: |
| 607 | var h_list = [_][]const u8{ self.install_path, "include" }; | 607 | var h_list = [_][]const u8{ self.install_path, "include" }; |
| 608 | | 608 | |
| 609 | if (dir_list.lib_dir) |dir| { | 609 | if (dir_list.lib_dir) |dir| { |
| 610 | if (std.fs.path.isAbsolute(dir)) lib_list[0] = self.dest_dir orelse ""; | 610 | if (fs.path.isAbsolute(dir)) lib_list[0] = self.dest_dir orelse ""; |
| 611 | lib_list[1] = dir; | 611 | lib_list[1] = dir; |
| 612 | } | 612 | } |
| 613 | | 613 | |
| 614 | if (dir_list.exe_dir) |dir| { | 614 | if (dir_list.exe_dir) |dir| { |
| 615 | if (std.fs.path.isAbsolute(dir)) exe_list[0] = self.dest_dir orelse ""; | 615 | if (fs.path.isAbsolute(dir)) exe_list[0] = self.dest_dir orelse ""; |
| 616 | exe_list[1] = dir; | 616 | exe_list[1] = dir; |
| 617 | } | 617 | } |
| 618 | | 618 | |
| 619 | if (dir_list.include_dir) |dir| { | 619 | if (dir_list.include_dir) |dir| { |
| 620 | if (std.fs.path.isAbsolute(dir)) h_list[0] = self.dest_dir orelse ""; | 620 | if (fs.path.isAbsolute(dir)) h_list[0] = self.dest_dir orelse ""; |
| 621 | h_list[1] = dir; | 621 | h_list[1] = dir; |
| 622 | } | 622 | } |
| 623 | | 623 | |
| ... | @@ -858,7 +858,7 @@ pub const TestOptions = struct { | ... | @@ -858,7 +858,7 @@ pub const TestOptions = struct { |
| 858 | /// deprecated: use `.filters = &.{filter}` instead of `.filter = filter`. | 858 | /// deprecated: use `.filters = &.{filter}` instead of `.filter = filter`. |
| 859 | filter: ?[]const u8 = null, | 859 | filter: ?[]const u8 = null, |
| 860 | filters: []const []const u8 = &.{}, | 860 | filters: []const []const u8 = &.{}, |
| 861 | test_runner: ?[]const u8 = null, | 861 | test_runner: ?LazyPath = null, |
| 862 | link_libc: ?bool = null, | 862 | link_libc: ?bool = null, |
| 863 | single_threaded: ?bool = null, | 863 | single_threaded: ?bool = null, |
| 864 | pic: ?bool = null, | 864 | pic: ?bool = null, |
| ... | @@ -1635,6 +1635,18 @@ pub fn truncateFile(self: *Build, dest_path: []const u8) !void { | ... | @@ -1635,6 +1635,18 @@ pub fn truncateFile(self: *Build, dest_path: []const u8) !void { |
| 1635 | src_file.close(); | 1635 | src_file.close(); |
| 1636 | } | 1636 | } |
| 1637 | | 1637 | |
| | 1638 | /// References a file or directory relative to the source root. |
| | 1639 | pub fn path(b: *Build, sub_path: []const u8) LazyPath { |
| | 1640 | assert(!fs.path.isAbsolute(sub_path)); |
| | 1641 | return .{ .src_path = .{ |
| | 1642 | .owner = b, |
| | 1643 | .sub_path = sub_path, |
| | 1644 | } }; |
| | 1645 | } |
| | 1646 | |
| | 1647 | /// This is low-level implementation details of the build system, not meant to |
| | 1648 | /// be called by users' build scripts. Even in the build system itself it is a |
| | 1649 | /// code smell to call this function. |
| 1638 | pub fn pathFromRoot(b: *Build, p: []const u8) []u8 { | 1650 | pub fn pathFromRoot(b: *Build, p: []const u8) []u8 { |
| 1639 | return fs.path.resolve(b.allocator, &.{ b.build_root.path orelse ".", p }) catch @panic("OOM"); | 1651 | return fs.path.resolve(b.allocator, &.{ b.build_root.path orelse ".", p }) catch @panic("OOM"); |
| 1640 | } | 1652 | } |
| ... | @@ -1674,10 +1686,9 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con | ... | @@ -1674,10 +1686,9 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con |
| 1674 | return name; | 1686 | return name; |
| 1675 | } | 1687 | } |
| 1676 | var it = mem.tokenizeScalar(u8, PATH, fs.path.delimiter); | 1688 | var it = mem.tokenizeScalar(u8, PATH, fs.path.delimiter); |
| 1677 | while (it.next()) |path| { | 1689 | while (it.next()) |p| { |
| 1678 | const full_path = self.pathJoin(&.{ | 1690 | const full_path = self.pathJoin(&.{ |
| 1679 | path, | 1691 | p, self.fmt("{s}{s}", .{ name, exe_extension }), |
| 1680 | self.fmt("{s}{s}", .{ name, exe_extension }), | | |
| 1681 | }); | 1692 | }); |
| 1682 | return fs.realpathAlloc(self.allocator, full_path) catch continue; | 1693 | return fs.realpathAlloc(self.allocator, full_path) catch continue; |
| 1683 | } | 1694 | } |
| ... | @@ -1687,10 +1698,9 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con | ... | @@ -1687,10 +1698,9 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con |
| 1687 | if (fs.path.isAbsolute(name)) { | 1698 | if (fs.path.isAbsolute(name)) { |
| 1688 | return name; | 1699 | return name; |
| 1689 | } | 1700 | } |
| 1690 | for (paths) |path| { | 1701 | for (paths) |p| { |
| 1691 | const full_path = self.pathJoin(&.{ | 1702 | const full_path = self.pathJoin(&.{ |
| 1692 | path, | 1703 | p, self.fmt("{s}{s}", .{ name, exe_extension }), |
| 1693 | self.fmt("{s}{s}", .{ name, exe_extension }), | | |
| 1694 | }); | 1704 | }); |
| 1695 | return fs.realpathAlloc(self.allocator, full_path) catch continue; | 1705 | return fs.realpathAlloc(self.allocator, full_path) catch continue; |
| 1696 | } | 1706 | } |
| ... | @@ -1771,7 +1781,7 @@ pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) | ... | @@ -1771,7 +1781,7 @@ pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) |
| 1771 | .bin => self.exe_dir, | 1781 | .bin => self.exe_dir, |
| 1772 | .lib => self.lib_dir, | 1782 | .lib => self.lib_dir, |
| 1773 | .header => self.h_dir, | 1783 | .header => self.h_dir, |
| 1774 | .custom => |path| self.pathJoin(&.{ self.install_path, path }), | 1784 | .custom => |p| self.pathJoin(&.{ self.install_path, p }), |
| 1775 | }; | 1785 | }; |
| 1776 | return fs.path.resolve( | 1786 | return fs.path.resolve( |
| 1777 | self.allocator, | 1787 | self.allocator, |
| ... | @@ -2032,7 +2042,7 @@ fn dependencyInner( | ... | @@ -2032,7 +2042,7 @@ fn dependencyInner( |
| 2032 | | 2042 | |
| 2033 | const build_root: std.Build.Cache.Directory = .{ | 2043 | const build_root: std.Build.Cache.Directory = .{ |
| 2034 | .path = build_root_string, | 2044 | .path = build_root_string, |
| 2035 | .handle = std.fs.cwd().openDir(build_root_string, .{}) catch |err| { | 2045 | .handle = fs.cwd().openDir(build_root_string, .{}) catch |err| { |
| 2036 | std.debug.print("unable to open '{s}': {s}\n", .{ | 2046 | std.debug.print("unable to open '{s}': {s}\n", .{ |
| 2037 | build_root_string, @errorName(err), | 2047 | build_root_string, @errorName(err), |
| 2038 | }); | 2048 | }); |
| ... | @@ -2093,9 +2103,9 @@ pub const GeneratedFile = struct { | ... | @@ -2093,9 +2103,9 @@ pub const GeneratedFile = struct { |
| 2093 | // so that we can join it with another path (e.g. build root, cache root, etc.) | 2103 | // so that we can join it with another path (e.g. build root, cache root, etc.) |
| 2094 | // | 2104 | // |
| 2095 | // dirname("") should still be null, because we can't go up any further. | 2105 | // dirname("") should still be null, because we can't go up any further. |
| 2096 | fn dirnameAllowEmpty(path: []const u8) ?[]const u8 { | 2106 | fn dirnameAllowEmpty(full_path: []const u8) ?[]const u8 { |
| 2097 | return fs.path.dirname(path) orelse { | 2107 | return fs.path.dirname(full_path) orelse { |
| 2098 | if (fs.path.isAbsolute(path) or path.len == 0) return null; | 2108 | if (fs.path.isAbsolute(full_path) or full_path.len == 0) return null; |
| 2099 | | 2109 | |
| 2100 | return ""; | 2110 | return ""; |
| 2101 | }; | 2111 | }; |
| ... | @@ -2117,11 +2127,15 @@ test dirnameAllowEmpty { | ... | @@ -2117,11 +2127,15 @@ test dirnameAllowEmpty { |
| 2117 | | 2127 | |
| 2118 | /// A reference to an existing or future path. | 2128 | /// A reference to an existing or future path. |
| 2119 | pub const LazyPath = union(enum) { | 2129 | pub const LazyPath = union(enum) { |
| 2120 | /// A source file path relative to build root. | 2130 | /// Deprecated; use the `path` function instead. |
| 2121 | /// This should not be an absolute path, but in an older iteration of the zig build | | |
| 2122 | /// system API, it was allowed to be absolute. Absolute paths should use `cwd_relative`. | | |
| 2123 | path: []const u8, | 2131 | path: []const u8, |
| 2124 | | 2132 | |
| | 2133 | /// A source file path relative to build root. |
| | 2134 | src_path: struct { |
| | 2135 | owner: *std.Build, |
| | 2136 | sub_path: []const u8, |
| | 2137 | }, |
| | 2138 | |
| 2125 | /// A file that is generated by an interface. Those files usually are | 2139 | /// A file that is generated by an interface. Those files usually are |
| 2126 | /// not available until built by a build step. | 2140 | /// not available until built by a build step. |
| 2127 | generated: *const GeneratedFile, | 2141 | generated: *const GeneratedFile, |
| ... | @@ -2150,11 +2164,10 @@ pub const LazyPath = union(enum) { | ... | @@ -2150,11 +2164,10 @@ pub const LazyPath = union(enum) { |
| 2150 | sub_path: []const u8, | 2164 | sub_path: []const u8, |
| 2151 | }, | 2165 | }, |
| 2152 | | 2166 | |
| 2153 | /// Returns a new file source that will have a relative path to the build root guaranteed. | 2167 | /// Deprecated. Call `path` instead. |
| 2154 | /// Asserts the parameter is not an absolute path. | 2168 | pub fn relative(p: []const u8) LazyPath { |
| 2155 | pub fn relative(path: []const u8) LazyPath { | 2169 | std.log.warn("deprecated. call std.Build.path instead", .{}); |
| 2156 | std.debug.assert(!std.fs.path.isAbsolute(path)); | 2170 | return .{ .path = p }; |
| 2157 | return LazyPath{ .path = path }; | | |
| 2158 | } | 2171 | } |
| 2159 | | 2172 | |
| 2160 | /// Returns a lazy path referring to the directory containing this path. | 2173 | /// Returns a lazy path referring to the directory containing this path. |
| ... | @@ -2168,13 +2181,16 @@ pub const LazyPath = union(enum) { | ... | @@ -2168,13 +2181,16 @@ pub const LazyPath = union(enum) { |
| 2168 | return switch (self) { | 2181 | return switch (self) { |
| 2169 | .generated => |gen| .{ .generated_dirname = .{ .generated = gen, .up = 0 } }, | 2182 | .generated => |gen| .{ .generated_dirname = .{ .generated = gen, .up = 0 } }, |
| 2170 | .generated_dirname => |gen| .{ .generated_dirname = .{ .generated = gen.generated, .up = gen.up + 1 } }, | 2183 | .generated_dirname => |gen| .{ .generated_dirname = .{ .generated = gen.generated, .up = gen.up + 1 } }, |
| | 2184 | .src_path => |sp| .{ .src_path = .{ |
| | 2185 | .owner = sp.owner, |
| | 2186 | .sub_path = dirnameAllowEmpty(sp.sub_path) orelse { |
| | 2187 | dumpBadDirnameHelp(null, null, "dirname() attempted to traverse outside the build root\n", .{}) catch {}; |
| | 2188 | @panic("misconfigured build script"); |
| | 2189 | }, |
| | 2190 | } }, |
| 2171 | .path => |p| .{ | 2191 | .path => |p| .{ |
| 2172 | .path = dirnameAllowEmpty(p) orelse { | 2192 | .path = dirnameAllowEmpty(p) orelse { |
| 2173 | dumpBadDirnameHelp(null, null, | 2193 | dumpBadDirnameHelp(null, null, "dirname() attempted to traverse outside the build root\n", .{}) catch {}; |
| 2174 | \\dirname() attempted to traverse outside the build root. | | |
| 2175 | \\This is not allowed. | | |
| 2176 | \\ | | |
| 2177 | , .{}) catch {}; | | |
| 2178 | @panic("misconfigured build script"); | 2194 | @panic("misconfigured build script"); |
| 2179 | }, | 2195 | }, |
| 2180 | }, | 2196 | }, |
| ... | @@ -2195,7 +2211,6 @@ pub const LazyPath = union(enum) { | ... | @@ -2195,7 +2211,6 @@ pub const LazyPath = union(enum) { |
| 2195 | } else { | 2211 | } else { |
| 2196 | dumpBadDirnameHelp(null, null, | 2212 | dumpBadDirnameHelp(null, null, |
| 2197 | \\dirname() attempted to traverse outside the current working directory. | 2213 | \\dirname() attempted to traverse outside the current working directory. |
| 2198 | \\This is not allowed. | | |
| 2199 | \\ | 2214 | \\ |
| 2200 | , .{}) catch {}; | 2215 | , .{}) catch {}; |
| 2201 | @panic("misconfigured build script"); | 2216 | @panic("misconfigured build script"); |
| ... | @@ -2207,7 +2222,6 @@ pub const LazyPath = union(enum) { | ... | @@ -2207,7 +2222,6 @@ pub const LazyPath = union(enum) { |
| 2207 | .sub_path = dirnameAllowEmpty(dep.sub_path) orelse { | 2222 | .sub_path = dirnameAllowEmpty(dep.sub_path) orelse { |
| 2208 | dumpBadDirnameHelp(null, null, | 2223 | dumpBadDirnameHelp(null, null, |
| 2209 | \\dirname() attempted to traverse outside the dependency root. | 2224 | \\dirname() attempted to traverse outside the dependency root. |
| 2210 | \\This is not allowed. | | |
| 2211 | \\ | 2225 | \\ |
| 2212 | , .{}) catch {}; | 2226 | , .{}) catch {}; |
| 2213 | @panic("misconfigured build script"); | 2227 | @panic("misconfigured build script"); |
| ... | @@ -2220,7 +2234,8 @@ pub const LazyPath = union(enum) { | ... | @@ -2220,7 +2234,8 @@ pub const LazyPath = union(enum) { |
| 2220 | /// Either returns the path or `"generated"`. | 2234 | /// Either returns the path or `"generated"`. |
| 2221 | pub fn getDisplayName(self: LazyPath) []const u8 { | 2235 | pub fn getDisplayName(self: LazyPath) []const u8 { |
| 2222 | return switch (self) { | 2236 | return switch (self) { |
| 2223 | .path, .cwd_relative => self.path, | 2237 | .src_path => |sp| sp.sub_path, |
| | 2238 | .path, .cwd_relative => |p| p, |
| 2224 | .generated => "generated", | 2239 | .generated => "generated", |
| 2225 | .generated_dirname => "generated", | 2240 | .generated_dirname => "generated", |
| 2226 | .dependency => "dependency", | 2241 | .dependency => "dependency", |
| ... | @@ -2230,7 +2245,7 @@ pub const LazyPath = union(enum) { | ... | @@ -2230,7 +2245,7 @@ pub const LazyPath = union(enum) { |
| 2230 | /// Adds dependencies this file source implies to the given step. | 2245 | /// Adds dependencies this file source implies to the given step. |
| 2231 | pub fn addStepDependencies(self: LazyPath, other_step: *Step) void { | 2246 | pub fn addStepDependencies(self: LazyPath, other_step: *Step) void { |
| 2232 | switch (self) { | 2247 | switch (self) { |
| 2233 | .path, .cwd_relative, .dependency => {}, | 2248 | .src_path, .path, .cwd_relative, .dependency => {}, |
| 2234 | .generated => |gen| other_step.dependOn(gen.step), | 2249 | .generated => |gen| other_step.dependOn(gen.step), |
| 2235 | .generated_dirname => |gen| other_step.dependOn(gen.generated.step), | 2250 | .generated_dirname => |gen| other_step.dependOn(gen.generated.step), |
| 2236 | } | 2251 | } |
| ... | @@ -2250,6 +2265,7 @@ pub const LazyPath = union(enum) { | ... | @@ -2250,6 +2265,7 @@ pub const LazyPath = union(enum) { |
| 2250 | pub fn getPath2(self: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 { | 2265 | pub fn getPath2(self: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 { |
| 2251 | switch (self) { | 2266 | switch (self) { |
| 2252 | .path => |p| return src_builder.pathFromRoot(p), | 2267 | .path => |p| return src_builder.pathFromRoot(p), |
| | 2268 | .src_path => |sp| return sp.owner.pathFromRoot(sp.sub_path), |
| 2253 | .cwd_relative => |p| return src_builder.pathFromCwd(p), | 2269 | .cwd_relative => |p| return src_builder.pathFromCwd(p), |
| 2254 | .generated => |gen| return gen.path orelse { | 2270 | .generated => |gen| return gen.path orelse { |
| 2255 | std.debug.getStderrMutex().lock(); | 2271 | std.debug.getStderrMutex().lock(); |
| ... | @@ -2262,13 +2278,13 @@ pub const LazyPath = union(enum) { | ... | @@ -2262,13 +2278,13 @@ pub const LazyPath = union(enum) { |
| 2262 | (src_builder.cache_root.join(src_builder.allocator, &.{"."}) catch @panic("OOM")); | 2278 | (src_builder.cache_root.join(src_builder.allocator, &.{"."}) catch @panic("OOM")); |
| 2263 | | 2279 | |
| 2264 | const gen_step = gen.generated.step; | 2280 | const gen_step = gen.generated.step; |
| 2265 | var path = getPath2(LazyPath{ .generated = gen.generated }, src_builder, asking_step); | 2281 | var p = getPath2(LazyPath{ .generated = gen.generated }, src_builder, asking_step); |
| 2266 | var i: usize = 0; | 2282 | var i: usize = 0; |
| 2267 | while (i <= gen.up) : (i += 1) { | 2283 | while (i <= gen.up) : (i += 1) { |
| 2268 | // path is absolute. | 2284 | // path is absolute. |
| 2269 | // dirname will return null only if we're at root. | 2285 | // dirname will return null only if we're at root. |
| 2270 | // Typically, we'll stop well before that at the cache root. | 2286 | // Typically, we'll stop well before that at the cache root. |
| 2271 | path = fs.path.dirname(path) orelse { | 2287 | p = fs.path.dirname(p) orelse { |
| 2272 | dumpBadDirnameHelp(gen_step, asking_step, | 2288 | dumpBadDirnameHelp(gen_step, asking_step, |
| 2273 | \\dirname() reached root. | 2289 | \\dirname() reached root. |
| 2274 | \\No more directories left to go up. | 2290 | \\No more directories left to go up. |
| ... | @@ -2277,7 +2293,7 @@ pub const LazyPath = union(enum) { | ... | @@ -2277,7 +2293,7 @@ pub const LazyPath = union(enum) { |
| 2277 | @panic("misconfigured build script"); | 2293 | @panic("misconfigured build script"); |
| 2278 | }; | 2294 | }; |
| 2279 | | 2295 | |
| 2280 | if (mem.eql(u8, path, cache_root_path) and i < gen.up) { | 2296 | if (mem.eql(u8, p, cache_root_path) and i < gen.up) { |
| 2281 | // If we hit the cache root and there's still more to go, | 2297 | // If we hit the cache root and there's still more to go, |
| 2282 | // the script attempted to go too far. | 2298 | // the script attempted to go too far. |
| 2283 | dumpBadDirnameHelp(gen_step, asking_step, | 2299 | dumpBadDirnameHelp(gen_step, asking_step, |
| ... | @@ -2288,7 +2304,7 @@ pub const LazyPath = union(enum) { | ... | @@ -2288,7 +2304,7 @@ pub const LazyPath = union(enum) { |
| 2288 | @panic("misconfigured build script"); | 2304 | @panic("misconfigured build script"); |
| 2289 | } | 2305 | } |
| 2290 | } | 2306 | } |
| 2291 | return path; | 2307 | return p; |
| 2292 | }, | 2308 | }, |
| 2293 | .dependency => |dep| { | 2309 | .dependency => |dep| { |
| 2294 | return dep.dependency.builder.pathJoin(&[_][]const u8{ | 2310 | return dep.dependency.builder.pathJoin(&[_][]const u8{ |
| ... | @@ -2302,6 +2318,10 @@ pub const LazyPath = union(enum) { | ... | @@ -2302,6 +2318,10 @@ pub const LazyPath = union(enum) { |
| 2302 | /// Duplicates the file source for a given builder. | 2318 | /// Duplicates the file source for a given builder. |
| 2303 | pub fn dupe(self: LazyPath, b: *Build) LazyPath { | 2319 | pub fn dupe(self: LazyPath, b: *Build) LazyPath { |
| 2304 | return switch (self) { | 2320 | return switch (self) { |
| | 2321 | .src_path => |sp| .{ .src_path = .{ |
| | 2322 | .owner = sp.owner, |
| | 2323 | .sub_path = b.dupePath(sp.sub_path), |
| | 2324 | } }, |
| 2305 | .path => |p| .{ .path = b.dupePath(p) }, | 2325 | .path => |p| .{ .path = b.dupePath(p) }, |
| 2306 | .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) }, | 2326 | .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) }, |
| 2307 | .generated => |gen| .{ .generated = gen }, | 2327 | .generated => |gen| .{ .generated = gen }, |