| author | |
| committer | |
| log | 04b6f33e5eb46bc3070b1e8d95e364db65e0cd7a |
| tree | ec378b7321410d1d04283574ea59987aa1ca2210 |
| parent | f1531406979b7c196ec535008a159b5f411cf78f |
| parent | 1fce802929a3db8971d1127e6b81c3799b00021c |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/360094 files changed, 1369 insertions(+), 1354 deletions(-)
lib/compiler/Maker.zig+25-26| ... | @@ -881,22 +881,6 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { | ... | @@ -881,22 +881,6 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { |
| 881 | const io = graph.io; | 881 | const io = graph.io; |
| 882 | const arena = graph.arena; | 882 | const arena = graph.arena; |
| 883 | 883 | ||
| 884 | // Cache lookup for configure options. If we get a match, we can skip | ||
| 885 | // execution of the configure script. If not, we get the file path to pass | ||
| 886 | // to the configure process. | ||
| 887 | // | ||
| 888 | // In the hot path, we only check this cache, which means that also | ||
| 889 | // configure source files need to go in here. | ||
| 890 | var config_man = graph.cache.obtain(); | ||
| 891 | defer config_man.deinit(); | ||
| 892 | |||
| 893 | for (options.cached_passthru_configure) |i| | ||
| 894 | config_man.hash.addBytes(configure_argv[i]); | ||
| 895 | |||
| 896 | // Prevents a `zig build` from getting a false positive cache hit following | ||
| 897 | // a `zig build --cache-poison=ignored`. | ||
| 898 | config_man.hash.add(options.cache_poison == .ignored); | ||
| 899 | |||
| 900 | configure_argv[options.conf_argv_index_build_root] = options.build_root.directory.path orelse options.cwd_path; | 884 | configure_argv[options.conf_argv_index_build_root] = options.build_root.directory.path orelse options.cwd_path; |
| 901 | 885 | ||
| 902 | var http_client: std.http.Client = .{ .allocator = gpa, .io = io }; | 886 | var http_client: std.http.Client = .{ .allocator = gpa, .io = io }; |
| ... | @@ -958,7 +942,6 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { | ... | @@ -958,7 +942,6 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { |
| 958 | // some code to help when debugging edits to the build runner so that you | 942 | // some code to help when debugging edits to the build runner so that you |
| 959 | // can make sure it compiles successfully on other targets. | 943 | // can make sure it compiles successfully on other targets. |
| 960 | const target_arch_os_abi: ?[]const u8 = if (options.debug_target) |triple| t: { | 944 | const target_arch_os_abi: ?[]const u8 = if (options.debug_target) |triple| t: { |
| 961 | config_man.hash.addBytes(triple); | ||
| 962 | try build_configurer_argv.appendSlice(gpa, &.{ "-target", triple }); | 945 | try build_configurer_argv.appendSlice(gpa, &.{ "-target", triple }); |
| 963 | break :t triple; | 946 | break :t triple; |
| 964 | } else null; | 947 | } else null; |
| ... | @@ -997,7 +980,26 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { | ... | @@ -997,7 +980,26 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { |
| 997 | 980 | ||
| 998 | // This loop is re-evaluated when the build script exits with an indication that it | 981 | // This loop is re-evaluated when the build script exits with an indication that it |
| 999 | // could not continue due to missing lazy dependencies. | 982 | // could not continue due to missing lazy dependencies. |
| 1000 | const configuration_path: Path, const poisoned: bool = cp: while (true) { | 983 | const configuration_path: Path, var configuration_lock: ?Cache.Lock = cp: while (true) { |
| 984 | // Cache lookup for configure options. If we get a match, we can skip | ||
| 985 | // execution of the configure script. If not, we get the file path to pass | ||
| 986 | // to the configure process. | ||
| 987 | // | ||
| 988 | // In the hot path, we only check this cache, which means that also | ||
| 989 | // configure source files need to go in here. | ||
| 990 | var config_man = graph.cache.obtain(); | ||
| 991 | defer config_man.deinit(); | ||
| 992 | |||
| 993 | for (options.cached_passthru_configure) |i| | ||
| 994 | config_man.hash.addBytes(configure_argv[i]); | ||
| 995 | |||
| 996 | if (target_arch_os_abi) |triple| | ||
| 997 | config_man.hash.addBytes(triple); | ||
| 998 | |||
| 999 | // Prevents a `zig build` from getting a false positive cache hit following | ||
| 1000 | // a `zig build --cache-poison=ignored`. | ||
| 1001 | config_man.hash.add(options.cache_poison == .ignored); | ||
| 1002 | |||
| 1001 | build_mod.deps.clearRetainingCapacity(); | 1003 | build_mod.deps.clearRetainingCapacity(); |
| 1002 | deps_mod.deps.clearRetainingCapacity(); | 1004 | deps_mod.deps.clearRetainingCapacity(); |
| 1003 | 1005 | ||
| ... | @@ -1223,7 +1225,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { | ... | @@ -1223,7 +1225,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { |
| 1223 | .root_dir = graph.local_cache_root, | 1225 | .root_dir = graph.local_cache_root, |
| 1224 | .sub_path = try arena.print("c/{s}", .{&digest}), | 1226 | .sub_path = try arena.print("c/{s}", .{&digest}), |
| 1225 | }, | 1227 | }, |
| 1226 | false, | 1228 | config_man.toOwnedLock(), |
| 1227 | }; | 1229 | }; |
| 1228 | }, | 1230 | }, |
| 1229 | .poisoned => {}, // Don't bother checking for cache hit. | 1231 | .poisoned => {}, // Don't bother checking for cache hit. |
| ... | @@ -1250,11 +1252,9 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { | ... | @@ -1250,11 +1252,9 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { |
| 1250 | }) }); | 1252 | }) }); |
| 1251 | } | 1253 | } |
| 1252 | 1254 | ||
| 1253 | const rand_int = randInt(io, u64); | ||
| 1254 | const tmp_dir_sub_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int); | ||
| 1255 | const config_tmp_path: Path = .{ | 1255 | const config_tmp_path: Path = .{ |
| 1256 | .root_dir = graph.local_cache_root, | 1256 | .root_dir = graph.local_cache_root, |
| 1257 | .sub_path = try arena.dupe(u8, tmp_dir_sub_path), | 1257 | .sub_path = try arena.print("tmp" ++ Dir.path.sep_str ++ "{x}", .{randInt(io, u64)}), |
| 1258 | }; | 1258 | }; |
| 1259 | const config_tmp_file: Io.File = try config_tmp_path.root_dir.handle.createFile( | 1259 | const config_tmp_file: Io.File = try config_tmp_path.root_dir.handle.createFile( |
| 1260 | io, | 1260 | io, |
| ... | @@ -1300,6 +1300,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { | ... | @@ -1300,6 +1300,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { |
| 1300 | any_errors = true; | 1300 | any_errors = true; |
| 1301 | continue; | 1301 | continue; |
| 1302 | } | 1302 | } |
| 1303 | log.info("fetching lazy dependency {s}", .{hash}); | ||
| 1303 | try unlazy_set.put(arena, .fromSlice(hash), {}); | 1304 | try unlazy_set.put(arena, .fromSlice(hash), {}); |
| 1304 | } | 1305 | } |
| 1305 | if (any_errors) return error.FailedButCacheIntact; | 1306 | if (any_errors) return error.FailedButCacheIntact; |
| ... | @@ -1328,7 +1329,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { | ... | @@ -1328,7 +1329,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { |
| 1328 | // If it is poisoned, there is no point in moving it to cached | 1329 | // If it is poisoned, there is no point in moving it to cached |
| 1329 | // location. Just leave it in the tmp directory. | 1330 | // location. Just leave it in the tmp directory. |
| 1330 | if (configuration.poisoned) { | 1331 | if (configuration.poisoned) { |
| 1331 | break :cp .{ config_tmp_path, true }; | 1332 | break :cp .{ config_tmp_path, null }; |
| 1332 | } else { | 1333 | } else { |
| 1333 | const digest = config_man.final(); | 1334 | const digest = config_man.final(); |
| 1334 | const final_path: Path = .{ | 1335 | const final_path: Path = .{ |
| ... | @@ -1362,12 +1363,10 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { | ... | @@ -1362,12 +1363,10 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { |
| 1362 | }); | 1363 | }); |
| 1363 | }; | 1364 | }; |
| 1364 | config_man.writeManifest() catch |err| log.warn("failed to write cache manifest: {t}", .{err}); | 1365 | config_man.writeManifest() catch |err| log.warn("failed to write cache manifest: {t}", .{err}); |
| 1365 | break :cp .{ final_path, false }; | 1366 | break :cp .{ final_path, config_man.toOwnedLock() }; |
| 1366 | } | 1367 | } |
| 1367 | }; | 1368 | }; |
| 1368 | |||
| 1369 | // Hang on to the configuration file lock until we finish loading the configuration file. | 1369 | // Hang on to the configuration file lock until we finish loading the configuration file. |
| 1370 | var configuration_lock = if (!poisoned) config_man.toOwnedLock() else null; | ||
| 1371 | defer if (configuration_lock) |*l| l.release(io); | 1370 | defer if (configuration_lock) |*l| l.release(io); |
| 1372 | 1371 | ||
| 1373 | switch (options.print_configuration) { | 1372 | switch (options.print_configuration) { |
lib/compiler/configurer.zig+5-1286| ... | @@ -4,16 +4,14 @@ const std = @import("std"); | ... | @@ -4,16 +4,14 @@ const std = @import("std"); |
| 4 | const Allocator = std.mem.Allocator; | 4 | const Allocator = std.mem.Allocator; |
| 5 | const Color = std.zig.Color; | 5 | const Color = std.zig.Color; |
| 6 | const Configuration = std.Build.Configuration; | 6 | const Configuration = std.Build.Configuration; |
| 7 | const File = std.Io.File; | ||
| 8 | const Io = std.Io; | 7 | const Io = std.Io; |
| 9 | const Step = std.Build.Step; | 8 | const Step = std.Build.Step; |
| 10 | const Writer = std.Io.Writer; | ||
| 11 | const assert = std.debug.assert; | 9 | const assert = std.debug.assert; |
| 12 | const fatal = std.process.fatal; | 10 | const fatal = std.process.fatal; |
| 13 | const fmt = std.fmt; | ||
| 14 | const log = std.log; | 11 | const log = std.log; |
| 15 | const mem = std.mem; | 12 | const mem = std.mem; |
| 16 | const process = std.process; | 13 | const process = std.process; |
| 14 | const Serialize = std.Build.Serialize; | ||
| 17 | 15 | ||
| 18 | pub const root = @import("@build"); | 16 | pub const root = @import("@build"); |
| 19 | pub const dependencies = @import("@dependencies"); | 17 | pub const dependencies = @import("@dependencies"); |
| ... | @@ -133,1233 +131,16 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -133,1233 +131,16 @@ pub fn main(init: process.Init.Minimal) !void { |
| 133 | .off => .no_color, | 131 | .off => .no_color, |
| 134 | }; | 132 | }; |
| 135 | 133 | ||
| 136 | builder.runBuild(root); | 134 | builder.runPackageScript(root); |
| 137 | 135 | ||
| 138 | if (builder.validateUserInputDidItFail()) { | 136 | if (builder.validateUserInputDidItFail()) { |
| 139 | fatal(" access the help menu with 'zig build -h'", .{}); | 137 | fatal(" access the help menu with 'zig build -h'", .{}); |
| 140 | } | 138 | } |
| 141 | 139 | ||
| 142 | try serializePackageOptions(builder, &graph.wip_configuration); | 140 | try Serialize.packageOptions(builder, &graph.wip_configuration); |
| 143 | try serializeSystemIntegrationOptions(&graph, &graph.wip_configuration); | 141 | try Serialize.systemIntegrationOptions(&graph, &graph.wip_configuration); |
| 144 | 142 | ||
| 145 | var stdout_buffer: [1024]u8 = undefined; | 143 | builder.serializeConfigurationExiting(); |
| 146 | var file_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); | ||
| 147 | serialize(builder, &graph.wip_configuration, &file_writer.interface) catch |err| switch (err) { | ||
| 148 | error.WriteFailed => fatal("failed to write configuration output: {t}", .{file_writer.err.?}), | ||
| 149 | error.OutOfMemory => |e| return e, | ||
| 150 | }; | ||
| 151 | file_writer.flush() catch |err| fatal("failed to write configuration output: {t}", .{err}); | ||
| 152 | |||
| 153 | // This executable is short-lived and run in Debug mode, so we'd rather | ||
| 154 | // have `zig build` run faster than catch resource leaks in the user's | ||
| 155 | // build.zig script (or, frankly, this configure runner), therefore we call | ||
| 156 | // exit directly here rather than cleanExit. | ||
| 157 | process.exit(0); | ||
| 158 | } | ||
| 159 | |||
| 160 | const Serialize = struct { | ||
| 161 | arena: Allocator, | ||
| 162 | wc: *Configuration.Wip, | ||
| 163 | module_map: std.array_hash_map.Auto(*std.Build.Module, Configuration.Module.Index) = .empty, | ||
| 164 | package_map: std.array_hash_map.Auto(*std.Build, Configuration.Package.Index) = .empty, | ||
| 165 | /// Index corresponds to `Configuration.steps` index. | ||
| 166 | step_map: std.array_hash_map.Auto(*Step, void) = .empty, | ||
| 167 | |||
| 168 | fn builderToPackage(s: *Serialize, b: *std.Build) !Configuration.Package.Index { | ||
| 169 | if (b.pkg_hash.len == 0) return .root; | ||
| 170 | const arena = s.arena; | ||
| 171 | const wc = s.wc; | ||
| 172 | const gop = try s.package_map.getOrPut(arena, b); | ||
| 173 | if (!gop.found_existing) { | ||
| 174 | gop.value_ptr.* = try wc.addExtra(Configuration.Package, .{ | ||
| 175 | .hash = try wc.addString(b.pkg_hash), | ||
| 176 | .dep_prefix = try wc.addString(b.dep_prefix), | ||
| 177 | .root_path = try wc.addString(try b.root.toString(arena)), | ||
| 178 | }); | ||
| 179 | } | ||
| 180 | return gop.value_ptr.*; | ||
| 181 | } | ||
| 182 | |||
| 183 | fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex { | ||
| 184 | const wc = s.wc; | ||
| 185 | return @enumFromInt(switch (lp orelse return .none) { | ||
| 186 | .src_path => |src_path| i: { | ||
| 187 | const sub_path = try wc.addString(src_path.sub_path); | ||
| 188 | break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{ | ||
| 189 | .owner = try s.builderToPackage(src_path.owner), | ||
| 190 | .sub_path = sub_path, | ||
| 191 | }); | ||
| 192 | }, | ||
| 193 | .generated => |generated| i: { | ||
| 194 | const sub_path = try wc.addString(generated.sub_path); | ||
| 195 | break :i try wc.addExtraErased(Configuration.LazyPath.Generated, .{ | ||
| 196 | .flags = .{ .up = @intCast(generated.up) }, | ||
| 197 | .index = generated.index, | ||
| 198 | .sub_path = sub_path, | ||
| 199 | }); | ||
| 200 | }, | ||
| 201 | .cwd_relative => |cwd_relative_sub_path| i: { | ||
| 202 | const sub_path = try wc.addString(cwd_relative_sub_path); | ||
| 203 | break :i try wc.addExtraErased(Configuration.LazyPath.Relative, .{ | ||
| 204 | .flags = .{ .base = .cwd }, | ||
| 205 | .sub_path = sub_path, | ||
| 206 | }); | ||
| 207 | }, | ||
| 208 | .relative => |relative| i: { | ||
| 209 | break :i try wc.addExtraErased(Configuration.LazyPath.Relative, .{ | ||
| 210 | .flags = .{ .base = relative.base }, | ||
| 211 | .sub_path = try wc.addString(relative.sub_path), | ||
| 212 | }); | ||
| 213 | }, | ||
| 214 | .dependency => |dependency| i: { | ||
| 215 | const sub_path = try wc.addString(dependency.sub_path); | ||
| 216 | break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{ | ||
| 217 | .owner = try s.builderToPackage(dependency.dependency.builder), | ||
| 218 | .sub_path = sub_path, | ||
| 219 | }); | ||
| 220 | }, | ||
| 221 | }); | ||
| 222 | } | ||
| 223 | |||
| 224 | fn addOptionalLazyPath(s: *Serialize, lp: ?std.Build.LazyPath) !?Configuration.LazyPath.Index { | ||
| 225 | return (try addOptionalLazyPathEnum(s, lp)).unwrap(); | ||
| 226 | } | ||
| 227 | |||
| 228 | fn addLazyPath(s: *Serialize, lp: std.Build.LazyPath) !Configuration.LazyPath.Index { | ||
| 229 | return @enumFromInt(@intFromEnum(try addOptionalLazyPathEnum(s, lp))); | ||
| 230 | } | ||
| 231 | |||
| 232 | fn addOptionalSemVer(s: *Serialize, sem_ver: ?std.SemanticVersion) !?Configuration.String { | ||
| 233 | return if (sem_ver) |sv| try s.wc.addSemVer(sv) else null; | ||
| 234 | } | ||
| 235 | |||
| 236 | fn addOptionalString(s: *Serialize, opt_slice: ?[]const u8) !?Configuration.String { | ||
| 237 | return if (opt_slice) |slice| try s.wc.addString(slice) else null; | ||
| 238 | } | ||
| 239 | |||
| 240 | fn addSystemLib(s: *Serialize, sl: *const std.Build.Module.SystemLib) !Configuration.SystemLib.Index { | ||
| 241 | const wc = s.wc; | ||
| 242 | return try wc.addDeduped(Configuration.SystemLib, .{ | ||
| 243 | .flags = .{ | ||
| 244 | .needed = sl.needed, | ||
| 245 | .weak = sl.weak, | ||
| 246 | .use_pkg_config = sl.use_pkg_config, | ||
| 247 | .preferred_link_mode = sl.preferred_link_mode, | ||
| 248 | .search_strategy = sl.search_strategy, | ||
| 249 | }, | ||
| 250 | .name = try wc.addString(sl.name), | ||
| 251 | }); | ||
| 252 | } | ||
| 253 | |||
| 254 | fn addCSourceFile(s: *Serialize, csf: *const std.Build.Module.CSourceFile) !Configuration.CSourceFile.Index { | ||
| 255 | const wc = s.wc; | ||
| 256 | const args = try initStringList(s, csf.flags); | ||
| 257 | return try wc.addExtra(Configuration.CSourceFile, .{ | ||
| 258 | .flags = .{ | ||
| 259 | .args_len = @intCast(args.len), | ||
| 260 | .lang = .init(csf.language), | ||
| 261 | }, | ||
| 262 | .file = try addLazyPath(s, csf.file), | ||
| 263 | .args = .{ .slice = args }, | ||
| 264 | }); | ||
| 265 | } | ||
| 266 | |||
| 267 | fn addCSourceFiles(s: *Serialize, csf: *const std.Build.Module.CSourceFiles) !Configuration.CSourceFiles.Index { | ||
| 268 | const wc = s.wc; | ||
| 269 | const sub_paths = try initStringList(s, csf.files); | ||
| 270 | const args = try initStringList(s, csf.flags); | ||
| 271 | return try wc.addExtra(Configuration.CSourceFiles, .{ | ||
| 272 | .flags = .{ | ||
| 273 | .args_len = @intCast(args.len), | ||
| 274 | .lang = .init(csf.language), | ||
| 275 | }, | ||
| 276 | .root = try addLazyPath(s, csf.root), | ||
| 277 | .sub_paths = .{ .slice = sub_paths }, | ||
| 278 | .args = .{ .slice = args }, | ||
| 279 | }); | ||
| 280 | } | ||
| 281 | |||
| 282 | fn addRcSourceFile(s: *Serialize, rsf: *const std.Build.Module.RcSourceFile) !Configuration.RcSourceFile.Index { | ||
| 283 | const wc = s.wc; | ||
| 284 | const include_paths = try initLazyPathList(s, rsf.include_paths); | ||
| 285 | const args = try initStringList(s, rsf.flags); | ||
| 286 | return try wc.addExtra(Configuration.RcSourceFile, .{ | ||
| 287 | .flags = .{ | ||
| 288 | .args_len = @intCast(args.len), | ||
| 289 | .include_paths = include_paths.len != 0, | ||
| 290 | }, | ||
| 291 | .file = try addLazyPath(s, rsf.file), | ||
| 292 | .include_paths = .{ .slice = include_paths }, | ||
| 293 | .args = .{ .slice = args }, | ||
| 294 | }); | ||
| 295 | } | ||
| 296 | |||
| 297 | fn addEnvironMap(s: *Serialize, opt_map: ?*std.process.Environ.Map) !?Configuration.EnvironMap.Index { | ||
| 298 | const wc = s.wc; | ||
| 299 | const map = opt_map orelse return null; | ||
| 300 | return try wc.addDeduped(Configuration.EnvironMap, .{ | ||
| 301 | .keys = try wc.addStringList(map.array_hash_map.keys()), | ||
| 302 | .values = try wc.addStringList(map.array_hash_map.values()), | ||
| 303 | }); | ||
| 304 | } | ||
| 305 | |||
| 306 | fn initArgsList(s: *Serialize, args: []const Step.Run.Arg) ![]const Configuration.Step.Run.Arg.Index { | ||
| 307 | const wc = s.wc; | ||
| 308 | const result = try s.arena.alloc(Configuration.Step.Run.Arg.Index, args.len); | ||
| 309 | for (result, args) |*dest, src| { | ||
| 310 | dest.* = try wc.addExtra(Configuration.Step.Run.Arg, switch (src) { | ||
| 311 | .artifact => |a| .{ | ||
| 312 | .flags = .{ | ||
| 313 | .tag = .artifact, | ||
| 314 | .prefix = a.prefix.len != 0, | ||
| 315 | .suffix = a.suffix.len != 0, | ||
| 316 | .basename = false, | ||
| 317 | .path = false, | ||
| 318 | .producer = true, | ||
| 319 | .generated = false, | ||
| 320 | .dep_file = false, | ||
| 321 | .make_absolute = a.make_absolute, | ||
| 322 | }, | ||
| 323 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 324 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 325 | .basename = .{ .value = null }, | ||
| 326 | .path = .{ .value = null }, | ||
| 327 | .producer = .{ .value = stepIndex(s, &a.artifact.step) }, | ||
| 328 | .generated = .{ .value = null }, | ||
| 329 | }, | ||
| 330 | .lazy_path => |a| .{ | ||
| 331 | .flags = .{ | ||
| 332 | .tag = .path_file, | ||
| 333 | .prefix = a.prefix.len != 0, | ||
| 334 | .suffix = a.suffix.len != 0, | ||
| 335 | .basename = false, | ||
| 336 | .path = true, | ||
| 337 | .producer = false, | ||
| 338 | .generated = false, | ||
| 339 | .dep_file = false, | ||
| 340 | .make_absolute = a.make_absolute, | ||
| 341 | }, | ||
| 342 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 343 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 344 | .basename = .{ .value = null }, | ||
| 345 | .path = .{ .value = try addLazyPath(s, a.lazy_path) }, | ||
| 346 | .producer = .{ .value = null }, | ||
| 347 | .generated = .{ .value = null }, | ||
| 348 | }, | ||
| 349 | .decorated_directory => |a| .{ | ||
| 350 | .flags = .{ | ||
| 351 | .tag = .path_directory, | ||
| 352 | .prefix = a.prefix.len != 0, | ||
| 353 | .suffix = a.suffix.len != 0, | ||
| 354 | .basename = false, | ||
| 355 | .path = true, | ||
| 356 | .producer = false, | ||
| 357 | .generated = false, | ||
| 358 | .dep_file = false, | ||
| 359 | .make_absolute = a.make_absolute, | ||
| 360 | }, | ||
| 361 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 362 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 363 | .basename = .{ .value = null }, | ||
| 364 | .path = .{ .value = try addLazyPath(s, a.lazy_path) }, | ||
| 365 | .producer = .{ .value = null }, | ||
| 366 | .generated = .{ .value = null }, | ||
| 367 | }, | ||
| 368 | .file_content => |a| .{ | ||
| 369 | .flags = .{ | ||
| 370 | .tag = .file_content, | ||
| 371 | .prefix = a.prefix.len != 0, | ||
| 372 | .suffix = a.suffix.len != 0, | ||
| 373 | .basename = false, | ||
| 374 | .path = true, | ||
| 375 | .producer = false, | ||
| 376 | .generated = false, | ||
| 377 | .dep_file = false, | ||
| 378 | .make_absolute = false, | ||
| 379 | }, | ||
| 380 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 381 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 382 | .basename = .{ .value = null }, | ||
| 383 | .path = .{ .value = try addLazyPath(s, a.lazy_path) }, | ||
| 384 | .producer = .{ .value = null }, | ||
| 385 | .generated = .{ .value = null }, | ||
| 386 | }, | ||
| 387 | .bytes => |a| .{ | ||
| 388 | .flags = .{ | ||
| 389 | .tag = .string, | ||
| 390 | .prefix = true, | ||
| 391 | .suffix = false, | ||
| 392 | .basename = false, | ||
| 393 | .path = false, | ||
| 394 | .producer = false, | ||
| 395 | .generated = false, | ||
| 396 | .dep_file = false, | ||
| 397 | .make_absolute = false, | ||
| 398 | }, | ||
| 399 | .prefix = .{ .value = try wc.addString(a) }, | ||
| 400 | .suffix = .{ .value = null }, | ||
| 401 | .basename = .{ .value = null }, | ||
| 402 | .path = .{ .value = null }, | ||
| 403 | .producer = .{ .value = null }, | ||
| 404 | .generated = .{ .value = null }, | ||
| 405 | }, | ||
| 406 | .output_file, .output_file_dep => |a, tag| .{ | ||
| 407 | .flags = .{ | ||
| 408 | .tag = .output_file, | ||
| 409 | .prefix = a.prefix.len != 0, | ||
| 410 | .suffix = a.suffix.len != 0, | ||
| 411 | .basename = a.basename.len != 0, | ||
| 412 | .path = false, | ||
| 413 | .producer = false, | ||
| 414 | .generated = true, | ||
| 415 | .dep_file = tag == .output_file_dep, | ||
| 416 | .make_absolute = a.make_absolute, | ||
| 417 | }, | ||
| 418 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 419 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 420 | .basename = .{ .value = if (a.basename.len != 0) try wc.addString(a.basename) else null }, | ||
| 421 | .path = .{ .value = null }, | ||
| 422 | .producer = .{ .value = null }, | ||
| 423 | .generated = .{ .value = a.generated_file }, | ||
| 424 | }, | ||
| 425 | .output_directory => |a| .{ | ||
| 426 | .flags = .{ | ||
| 427 | .tag = .output_directory, | ||
| 428 | .prefix = a.prefix.len != 0, | ||
| 429 | .suffix = a.suffix.len != 0, | ||
| 430 | .basename = a.basename.len != 0, | ||
| 431 | .path = false, | ||
| 432 | .producer = false, | ||
| 433 | .generated = true, | ||
| 434 | .dep_file = false, | ||
| 435 | .make_absolute = a.make_absolute, | ||
| 436 | }, | ||
| 437 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 438 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 439 | .basename = .{ .value = if (a.basename.len != 0) try wc.addString(a.basename) else null }, | ||
| 440 | .path = .{ .value = null }, | ||
| 441 | .producer = .{ .value = null }, | ||
| 442 | .generated = .{ .value = a.generated_file }, | ||
| 443 | }, | ||
| 444 | .passthru => .{ | ||
| 445 | .flags = .{ | ||
| 446 | .tag = .passthru, | ||
| 447 | .prefix = false, | ||
| 448 | .suffix = false, | ||
| 449 | .basename = false, | ||
| 450 | .path = false, | ||
| 451 | .producer = false, | ||
| 452 | .generated = false, | ||
| 453 | .dep_file = false, | ||
| 454 | .make_absolute = false, | ||
| 455 | }, | ||
| 456 | .prefix = .{ .value = null }, | ||
| 457 | .suffix = .{ .value = null }, | ||
| 458 | .basename = .{ .value = null }, | ||
| 459 | .path = .{ .value = null }, | ||
| 460 | .producer = .{ .value = null }, | ||
| 461 | .generated = .{ .value = null }, | ||
| 462 | }, | ||
| 463 | }); | ||
| 464 | } | ||
| 465 | return result; | ||
| 466 | } | ||
| 467 | |||
| 468 | fn initIncludeDirList( | ||
| 469 | s: *Serialize, | ||
| 470 | list: []const std.Build.Module.IncludeDir, | ||
| 471 | ) ![]const Configuration.Module.IncludeDir { | ||
| 472 | const result = try s.arena.alloc(Configuration.Module.IncludeDir, list.len); | ||
| 473 | for (result, list) |*dest, src| dest.* = switch (src) { | ||
| 474 | .path => |lp| .{ .path = try addLazyPath(s, lp) }, | ||
| 475 | .path_system => |lp| .{ .path_system = try addLazyPath(s, lp) }, | ||
| 476 | .path_after => |lp| .{ .path_after = try addLazyPath(s, lp) }, | ||
| 477 | .framework_path => |lp| .{ .framework_path = try addLazyPath(s, lp) }, | ||
| 478 | .framework_path_system => |lp| .{ .framework_path_system = try addLazyPath(s, lp) }, | ||
| 479 | .embed_path => |lp| .{ .embed_path = try addLazyPath(s, lp) }, | ||
| 480 | .other_step => |cs| .{ .path = try addLazyPath(s, cs.installed_headers_include_tree.?.getDirectory()) }, | ||
| 481 | .config_header_step => |chs| .{ .config_header_step = stepIndex(s, &chs.step) }, | ||
| 482 | }; | ||
| 483 | return result; | ||
| 484 | } | ||
| 485 | |||
| 486 | fn initLazyPathList(s: *Serialize, list: []const std.Build.LazyPath) ![]const Configuration.LazyPath.Index { | ||
| 487 | const result = try s.arena.alloc(Configuration.LazyPath.Index, list.len); | ||
| 488 | for (result, list) |*dest, src| dest.* = try addLazyPath(s, src); | ||
| 489 | return result; | ||
| 490 | } | ||
| 491 | |||
| 492 | fn initStringList(s: *Serialize, list: []const []const u8) ![]const Configuration.String { | ||
| 493 | const wc = s.wc; | ||
| 494 | const result = try s.arena.alloc(Configuration.String, list.len); | ||
| 495 | for (result, list) |*dest, src| dest.* = try wc.addString(src); | ||
| 496 | return result; | ||
| 497 | } | ||
| 498 | |||
| 499 | fn initCopyList(s: *Serialize, list: []const Step.WriteFile.Copy) ![]const Configuration.Step.WriteFile.Copy { | ||
| 500 | const result = try s.arena.alloc(Configuration.Step.WriteFile.Copy, list.len); | ||
| 501 | for (result, list) |*dest, src| dest.* = .{ | ||
| 502 | .sub_path = src.sub_path, | ||
| 503 | .src_file = try s.addLazyPath(src.src_file), | ||
| 504 | }; | ||
| 505 | return result; | ||
| 506 | } | ||
| 507 | |||
| 508 | fn initOptionalStringList(s: *Serialize, list: []const ?[]const u8) ![]const Configuration.OptionalString { | ||
| 509 | const wc = s.wc; | ||
| 510 | const result = try s.arena.alloc(Configuration.OptionalString, list.len); | ||
| 511 | for (result, list) |*dest, src| dest.* = try wc.addOptionalString(src); | ||
| 512 | return result; | ||
| 513 | } | ||
| 514 | |||
| 515 | fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index { | ||
| 516 | if (s.module_map.get(m)) |index| return index; | ||
| 517 | |||
| 518 | const wc = s.wc; | ||
| 519 | const arena = s.arena; | ||
| 520 | |||
| 521 | const rpaths = try arena.alloc(Configuration.Module.RPath, m.rpaths.items.len); | ||
| 522 | for (rpaths, m.rpaths.items) |*dest, src| dest.* = switch (src) { | ||
| 523 | .lazy_path => |lp| .{ .lazy_path = try addLazyPath(s, lp) }, | ||
| 524 | .special => |slice| .{ .special = try wc.addString(slice) }, | ||
| 525 | }; | ||
| 526 | |||
| 527 | const link_objects = try arena.alloc(Configuration.Module.LinkObject, m.link_objects.items.len); | ||
| 528 | for (link_objects, m.link_objects.items) |*dest, *src| dest.* = switch (src.*) { | ||
| 529 | .static_path => |lp| .{ .static_path = try addLazyPath(s, lp) }, | ||
| 530 | .other_step => |cs| .{ .other_step = stepIndex(s, &cs.step) }, | ||
| 531 | .system_lib => |*sl| .{ .system_lib = try addSystemLib(s, sl) }, | ||
| 532 | .assembly_file => |lp| .{ .assembly_file = try addLazyPath(s, lp) }, | ||
| 533 | .c_source_file => |csf| .{ .c_source_file = try addCSourceFile(s, csf) }, | ||
| 534 | .c_source_files => |csf| .{ .c_source_files = try addCSourceFiles(s, csf) }, | ||
| 535 | .win32_resource_file => |wrf| .{ .win32_resource_file = try addRcSourceFile(s, wrf) }, | ||
| 536 | }; | ||
| 537 | |||
| 538 | const frameworks = try arena.alloc(Configuration.Module.Framework, m.frameworks.entries.len); | ||
| 539 | for (frameworks, m.frameworks.keys(), m.frameworks.values()) |*dest, name, options| dest.* = .{ | ||
| 540 | .flags = .{ | ||
| 541 | .needed = options.needed, | ||
| 542 | .weak = options.weak, | ||
| 543 | }, | ||
| 544 | .name = try wc.addString(name), | ||
| 545 | }; | ||
| 546 | |||
| 547 | const lib_paths = try initLazyPathList(s, m.lib_paths.items); | ||
| 548 | const c_macros = try initStringList(s, m.c_macros.items); | ||
| 549 | const export_symbol_names = try initStringList(s, m.export_symbol_names); | ||
| 550 | |||
| 551 | const module_index: Configuration.Module.Index = try wc.addExtra(Configuration.Module, .{ | ||
| 552 | .flags = .{ | ||
| 553 | .optimize = .init(m.optimize), | ||
| 554 | .strip = .init(m.strip), | ||
| 555 | .unwind_tables = .init(m.unwind_tables), | ||
| 556 | .dwarf_format = .init(m.dwarf_format), | ||
| 557 | .single_threaded = .init(m.single_threaded), | ||
| 558 | .stack_protector = .init(m.stack_protector), | ||
| 559 | .stack_check = .init(m.stack_check), | ||
| 560 | .sanitize_c = .init(m.sanitize_c), | ||
| 561 | .sanitize_thread = .init(m.sanitize_thread), | ||
| 562 | .fuzz = .init(m.fuzz), | ||
| 563 | .code_model = m.code_model, | ||
| 564 | .c_macros = c_macros.len != 0, | ||
| 565 | .include_dirs = m.include_dirs.items.len != 0, | ||
| 566 | .lib_paths = lib_paths.len != 0, | ||
| 567 | .rpaths = rpaths.len != 0, | ||
| 568 | .frameworks = frameworks.len != 0, | ||
| 569 | .link_objects = link_objects.len != 0, | ||
| 570 | .export_symbol_names = export_symbol_names.len != 0, | ||
| 571 | }, | ||
| 572 | .flags2 = .{ | ||
| 573 | .valgrind = .init(m.valgrind), | ||
| 574 | .pic = .init(m.pic), | ||
| 575 | .red_zone = .init(m.red_zone), | ||
| 576 | .omit_frame_pointer = .init(m.omit_frame_pointer), | ||
| 577 | .error_tracing = .init(m.error_tracing), | ||
| 578 | .link_libc = .init(m.link_libc), | ||
| 579 | .link_libcpp = .init(m.link_libcpp), | ||
| 580 | .no_builtin = .init(m.no_builtin), | ||
| 581 | }, | ||
| 582 | .owner = try s.builderToPackage(m.owner), | ||
| 583 | .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file), | ||
| 584 | .import_table = .invalid, | ||
| 585 | .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target), | ||
| 586 | .c_macros = .{ .slice = c_macros }, | ||
| 587 | .lib_paths = .{ .slice = lib_paths }, | ||
| 588 | .export_symbol_names = .{ .slice = export_symbol_names }, | ||
| 589 | .include_dirs = .init(try s.initIncludeDirList(m.include_dirs.items)), | ||
| 590 | .rpaths = .init(rpaths), | ||
| 591 | .link_objects = .init(link_objects), | ||
| 592 | .frameworks = .{ .slice = frameworks }, | ||
| 593 | }); | ||
| 594 | |||
| 595 | // The import table is the only place that modules can form dependency | ||
| 596 | // loops. Therefore, we populate the module indexes only after adding | ||
| 597 | // the module to module_map. | ||
| 598 | try s.module_map.putNoClobber(arena, m, module_index); | ||
| 599 | |||
| 600 | var imports = try std.MultiArrayList(Configuration.ImportTable.Import).initCapacity(arena, m.import_table.entries.len); | ||
| 601 | imports.len = m.import_table.entries.len; | ||
| 602 | for ( | ||
| 603 | imports.items(.name), | ||
| 604 | imports.items(.module), | ||
| 605 | m.import_table.keys(), | ||
| 606 | m.import_table.values(), | ||
| 607 | ) |*dest_name, *dest_module, src_name, src_module| { | ||
| 608 | dest_name.* = try wc.addString(src_name); | ||
| 609 | dest_module.* = try addModule(s, src_module); | ||
| 610 | } | ||
| 611 | |||
| 612 | comptime assert(std.mem.eql(u8, @typeInfo(Configuration.Module).@"struct".field_names[2], "import_table")); | ||
| 613 | comptime assert(@typeInfo(Configuration.Module).@"struct".field_types[2] == Configuration.ImportTable.Index); | ||
| 614 | assert(wc.extra.items[@intFromEnum(module_index) + 2] == @intFromEnum(Configuration.ImportTable.Index.invalid)); | ||
| 615 | const import_table_index = try wc.addDeduped(Configuration.ImportTable, .{ | ||
| 616 | .imports = .{ .mal = imports }, | ||
| 617 | }); | ||
| 618 | wc.extra.items[@intFromEnum(module_index) + 2] = @intFromEnum(import_table_index); | ||
| 619 | |||
| 620 | return module_index; | ||
| 621 | } | ||
| 622 | |||
| 623 | fn stepIndex(s: *const Serialize, step: *Step) Configuration.Step.Index { | ||
| 624 | return @enumFromInt(s.step_map.getIndex(step).?); | ||
| 625 | } | ||
| 626 | }; | ||
| 627 | |||
| 628 | fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { | ||
| 629 | const graph = b.graph; | ||
| 630 | const arena = graph.arena; | ||
| 631 | const gpa = wc.gpa; | ||
| 632 | |||
| 633 | var s: Serialize = .{ .wc = wc, .arena = arena }; | ||
| 634 | |||
| 635 | try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len); | ||
| 636 | for ( | ||
| 637 | graph.configure_dependencies.items, | ||
| 638 | wc.path_deps.addManyAsSliceAssumeCapacity(graph.configure_dependencies.items.len), | ||
| 639 | ) |src, *dest| { | ||
| 640 | dest.* = .{ | ||
| 641 | .flags = .{ | ||
| 642 | .base = switch (src.lazy_path) { | ||
| 643 | .src_path, .dependency => .build_root, | ||
| 644 | .generated => unreachable, | ||
| 645 | .cwd_relative => .cwd, | ||
| 646 | .relative => |r| r.base, | ||
| 647 | }, | ||
| 648 | .mode = src.mode, | ||
| 649 | }, | ||
| 650 | .sub = switch (src.lazy_path) { | ||
| 651 | .src_path => |sp| try wc.addString(sp.sub_path), | ||
| 652 | .generated => unreachable, | ||
| 653 | .cwd_relative => |sub_path| try wc.addString(sub_path), | ||
| 654 | .dependency => |d| try wc.addString(d.sub_path), | ||
| 655 | .relative => |r| try wc.addString(r.sub_path), | ||
| 656 | }, | ||
| 657 | .pkg = switch (src.lazy_path) { | ||
| 658 | .src_path => |sp| .init(try s.builderToPackage(sp.owner)), | ||
| 659 | .generated => unreachable, | ||
| 660 | .cwd_relative, .relative => .none, | ||
| 661 | .dependency => |d| .init(try s.builderToPackage(d.dependency.builder)), | ||
| 662 | }, | ||
| 663 | }; | ||
| 664 | } | ||
| 665 | |||
| 666 | // Starting from all top-level steps in `b`, traverse the entire step graph | ||
| 667 | // and add all step dependencies implied by module graphs. | ||
| 668 | const top_level_steps = b.top_level_steps.values(); | ||
| 669 | try s.step_map.ensureUnusedCapacity(arena, top_level_steps.len); | ||
| 670 | for (top_level_steps) |tls| { | ||
| 671 | s.step_map.putAssumeCapacityNoClobber(&tls.step, {}); | ||
| 672 | } | ||
| 673 | { | ||
| 674 | while (wc.steps.items.len < s.step_map.count()) { | ||
| 675 | const step = s.step_map.keys()[wc.steps.items.len]; | ||
| 676 | |||
| 677 | // Set up any implied dependencies for this step. It's important that we do this first, so | ||
| 678 | // that the loop below discovers steps implied by the module graph. | ||
| 679 | try createModuleDependenciesForStep(step); | ||
| 680 | |||
| 681 | try s.step_map.ensureUnusedCapacity(arena, step.dependencies.items.len); | ||
| 682 | for (step.dependencies.items) |other_step| { | ||
| 683 | s.step_map.putAssumeCapacity(other_step, {}); | ||
| 684 | } | ||
| 685 | |||
| 686 | // Add and then de-duplicate dependencies. | ||
| 687 | const dep_steps = try arena.alloc(Configuration.Step.Index, step.dependencies.items.len); | ||
| 688 | for (dep_steps, step.dependencies.items) |*dest, src| | ||
| 689 | dest.* = @enumFromInt(s.step_map.getIndex(src).?); | ||
| 690 | |||
| 691 | const deps: Configuration.Deps.Index = try wc.addDeduped(Configuration.Deps, .{ | ||
| 692 | .steps = .{ .slice = dep_steps }, | ||
| 693 | }); | ||
| 694 | |||
| 695 | try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity); | ||
| 696 | wc.steps.appendAssumeCapacity(.{ | ||
| 697 | .name = try wc.addString(step.name), | ||
| 698 | .owner = try s.builderToPackage(step.owner), | ||
| 699 | .deps = deps, | ||
| 700 | .max_rss = .fromBytes(step.max_rss), | ||
| 701 | .extended = @enumFromInt(switch (step.tag) { | ||
| 702 | .top_level => e: { | ||
| 703 | const top_level: *Step.TopLevel = @fieldParentPtr("step", step); | ||
| 704 | break :e try wc.addExtraErased(Configuration.Step.TopLevel, .{ | ||
| 705 | .description = try wc.addString(top_level.description), | ||
| 706 | }); | ||
| 707 | }, | ||
| 708 | .compile => e: { | ||
| 709 | const c: *Step.Compile = @fieldParentPtr("step", step); | ||
| 710 | const installed_headers: []u32 = try arena.alloc(u32, c.installed_headers.items.len); | ||
| 711 | for (installed_headers, c.installed_headers.items) |*dst, src| switch (src) { | ||
| 712 | .file => |file| { | ||
| 713 | dst.* = try wc.addExtraErased(Configuration.Step.Compile.InstalledHeader.File, .{ | ||
| 714 | .source = try s.addLazyPath(file.source), | ||
| 715 | .dest_sub_path = try wc.addString(file.dest_rel_path), | ||
| 716 | }); | ||
| 717 | }, | ||
| 718 | .directory => |directory| { | ||
| 719 | const include_extensions = directory.options.include_extensions orelse &.{}; | ||
| 720 | dst.* = try wc.addExtraErased(Configuration.Step.Compile.InstalledHeader.Directory, .{ | ||
| 721 | .flags = .{ | ||
| 722 | .include_extensions = include_extensions.len != 0, | ||
| 723 | .exclude_extensions = directory.options.exclude_extensions.len != 0, | ||
| 724 | }, | ||
| 725 | .source = try s.addLazyPath(directory.source), | ||
| 726 | .dest_sub_path = try wc.addString(directory.dest_rel_path), | ||
| 727 | .exclude_extensions = .{ .slice = try s.initStringList(directory.options.exclude_extensions) }, | ||
| 728 | .include_extensions = .{ .slice = try s.initStringList(include_extensions) }, | ||
| 729 | }); | ||
| 730 | }, | ||
| 731 | }; | ||
| 732 | |||
| 733 | break :e try wc.addExtraErased(Configuration.Step.Compile, .{ | ||
| 734 | .flags = .{ | ||
| 735 | .filters_len = c.filters.len != 0, | ||
| 736 | .installed_headers_len = installed_headers.len != 0, | ||
| 737 | .force_undefined_symbols_len = c.force_undefined_symbols.entries.len != 0, | ||
| 738 | |||
| 739 | .verbose_link = c.verbose_link, | ||
| 740 | .verbose_cc = c.verbose_cc, | ||
| 741 | .rdynamic = c.rdynamic, | ||
| 742 | .import_memory = c.import_memory, | ||
| 743 | .export_memory = c.export_memory, | ||
| 744 | .import_symbols = c.import_symbols, | ||
| 745 | .import_table = c.import_table, | ||
| 746 | .export_table = c.export_table, | ||
| 747 | .shared_memory = c.shared_memory, | ||
| 748 | .link_eh_frame_hdr = c.link_eh_frame_hdr, | ||
| 749 | .link_emit_relocs = c.link_emit_relocs, | ||
| 750 | .link_function_sections = c.link_function_sections, | ||
| 751 | .link_data_sections = c.link_data_sections, | ||
| 752 | .linker_dynamicbase = c.linker_dynamicbase, | ||
| 753 | .link_z_notext = c.link_z_notext, | ||
| 754 | .link_z_relro = c.link_z_relro, | ||
| 755 | .link_z_lazy = c.link_z_lazy, | ||
| 756 | .link_z_defs = c.link_z_defs, | ||
| 757 | .headerpad_max_install_names = c.headerpad_max_install_names, | ||
| 758 | .dead_strip_dylibs = c.dead_strip_dylibs, | ||
| 759 | .force_load_objc = c.force_load_objc, | ||
| 760 | .discard_local_symbols = c.discard_local_symbols, | ||
| 761 | .mingw_unicode_entry_point = c.mingw_unicode_entry_point, | ||
| 762 | }, | ||
| 763 | .flags2 = .{ | ||
| 764 | .pie = .init(c.pie), | ||
| 765 | .formatted_panics = .init(c.formatted_panics), | ||
| 766 | .bundle_compiler_rt = .init(c.bundle_compiler_rt), | ||
| 767 | .bundle_ubsan_rt = .init(c.bundle_ubsan_rt), | ||
| 768 | .each_lib_rpath = .init(c.each_lib_rpath), | ||
| 769 | .link_gc_sections = .init(c.link_gc_sections), | ||
| 770 | .linker_allow_shlib_undefined = .init(c.linker_allow_shlib_undefined), | ||
| 771 | .linker_allow_undefined_version = .init(c.linker_allow_undefined_version), | ||
| 772 | .linker_enable_new_dtags = .init(c.linker_enable_new_dtags), | ||
| 773 | .dll_export_fns = .init(c.dll_export_fns), | ||
| 774 | .use_llvm = .init(c.use_llvm), | ||
| 775 | .use_lld = .init(c.use_lld), | ||
| 776 | .use_new_linker = .init(c.use_new_linker), | ||
| 777 | .allow_so_scripts = .init(c.allow_so_scripts), | ||
| 778 | .sanitize_coverage_trace_pc_guard = .init(c.sanitize_coverage_trace_pc_guard), | ||
| 779 | .linkage = .init(c.linkage), | ||
| 780 | }, | ||
| 781 | .flags3 = .{ | ||
| 782 | .is_linking_libc = c.is_linking_libc, | ||
| 783 | .is_linking_libcpp = c.is_linking_libcpp, | ||
| 784 | .version = c.version != null, | ||
| 785 | .compress_debug_sections = c.compress_debug_sections, | ||
| 786 | .initial_memory = c.initial_memory != null, | ||
| 787 | .max_memory = c.max_memory != null, | ||
| 788 | .kind = c.kind, | ||
| 789 | .global_base = c.global_base != null, | ||
| 790 | .test_runner = if (c.test_runner) |tr| switch (tr.mode) { | ||
| 791 | .simple => .simple, | ||
| 792 | .server => .server, | ||
| 793 | } else .default, | ||
| 794 | .wasi_exec_model = .init(c.wasi_exec_model), | ||
| 795 | .win32_manifest = c.win32_manifest != null, | ||
| 796 | .win32_module_definition = c.win32_module_definition != null, | ||
| 797 | .zig_lib_dir = c.zig_lib_dir != null, | ||
| 798 | .rc_includes = c.rc_includes, | ||
| 799 | .image_base = c.image_base != null, | ||
| 800 | .build_id = .init(c.build_id), | ||
| 801 | .entry = switch (c.entry) { | ||
| 802 | .default => .default, | ||
| 803 | .disabled => .disabled, | ||
| 804 | .enabled => .enabled, | ||
| 805 | .symbol_name => .symbol_name, | ||
| 806 | }, | ||
| 807 | .lto = .init(c.lto), | ||
| 808 | .subsystem = .init(c.subsystem), | ||
| 809 | }, | ||
| 810 | .flags4 = .{ | ||
| 811 | .libc_file = c.libc_file != null, | ||
| 812 | .link_z_common_page_size = c.link_z_common_page_size != null, | ||
| 813 | .link_z_max_page_size = c.link_z_max_page_size != null, | ||
| 814 | .pagezero_size = c.pagezero_size != null, | ||
| 815 | .stack_size = c.stack_size != null, | ||
| 816 | .headerpad_size = c.headerpad_size != null, | ||
| 817 | .error_limit = c.error_limit != null, | ||
| 818 | .install_name = c.install_name != null, | ||
| 819 | .entitlements = c.entitlements != null, | ||
| 820 | .expect_errors = if (c.expect_errors) |x| switch (x) { | ||
| 821 | .contains => .contains, | ||
| 822 | .exact => .exact, | ||
| 823 | .starts_with => .starts_with, | ||
| 824 | .stderr_contains => .stderr_contains, | ||
| 825 | } else .none, | ||
| 826 | .linker_script = c.linker_script != null, | ||
| 827 | .version_script = c.version_script != null, | ||
| 828 | .emit_directory = c.emit_directory != .none, | ||
| 829 | .generated_docs = c.generated_docs != .none, | ||
| 830 | .generated_asm = c.generated_asm != .none, | ||
| 831 | .generated_bin = c.generated_bin != .none, | ||
| 832 | .generated_pdb = c.generated_pdb != .none, | ||
| 833 | .generated_implib = c.generated_implib != .none, | ||
| 834 | .generated_llvm_bc = c.generated_llvm_bc != .none, | ||
| 835 | .generated_llvm_ir = c.generated_llvm_ir != .none, | ||
| 836 | .generated_h = c.generated_h != .none, | ||
| 837 | .incremental = .init(c.incremental), | ||
| 838 | }, | ||
| 839 | .root_module = try s.addModule(c.root_module), | ||
| 840 | .root_name = try wc.addString(c.name), | ||
| 841 | .linker_script = .{ .value = try s.addOptionalLazyPath(c.linker_script) }, | ||
| 842 | .version_script = .{ .value = try s.addOptionalLazyPath(c.version_script) }, | ||
| 843 | .zig_lib_dir = .{ .value = try s.addOptionalLazyPath(c.zig_lib_dir) }, | ||
| 844 | .libc_file = .{ .value = try s.addOptionalLazyPath(c.libc_file) }, | ||
| 845 | .win32_manifest = .{ .value = try s.addOptionalLazyPath(c.win32_manifest) }, | ||
| 846 | .win32_module_definition = .{ .value = try s.addOptionalLazyPath(c.win32_module_definition) }, | ||
| 847 | .entitlements = .{ .value = try s.addOptionalLazyPath(c.entitlements) }, | ||
| 848 | .version = .{ .value = try s.addOptionalSemVer(c.version) }, | ||
| 849 | .install_name = .{ .value = try s.addOptionalString(c.install_name) }, | ||
| 850 | .initial_memory = .{ .value = c.initial_memory }, | ||
| 851 | .max_memory = .{ .value = c.max_memory }, | ||
| 852 | .global_base = .{ .value = c.global_base }, | ||
| 853 | .image_base = .{ .value = c.image_base }, | ||
| 854 | .link_z_common_page_size = .{ .value = c.link_z_common_page_size }, | ||
| 855 | .link_z_max_page_size = .{ .value = c.link_z_max_page_size }, | ||
| 856 | .pagezero_size = .{ .value = c.pagezero_size }, | ||
| 857 | .stack_size = .{ .value = c.stack_size }, | ||
| 858 | .headerpad_size = .{ .value = c.headerpad_size }, | ||
| 859 | .error_limit = .{ .value = c.error_limit }, | ||
| 860 | .entry = .{ .value = switch (c.entry) { | ||
| 861 | .symbol_name => |name| try wc.addString(name), | ||
| 862 | .default, .disabled, .enabled => null, | ||
| 863 | } }, | ||
| 864 | .build_id = .{ .value = if (c.build_id) |id| switch (id) { | ||
| 865 | .hexstring => |*hexstring| try wc.addString(hexstring.toSlice()), | ||
| 866 | .none, .fast, .uuid, .sha1, .md5 => null, | ||
| 867 | } else null }, | ||
| 868 | .filters = .{ .slice = try s.initStringList(c.filters) }, | ||
| 869 | .installed_headers = .initErased(installed_headers), | ||
| 870 | .force_undefined_symbols = .{ .slice = try s.initStringList(c.force_undefined_symbols.keys()) }, | ||
| 871 | .expect_errors = .{ .u = if (c.expect_errors) |x| switch (x) { | ||
| 872 | .contains => |slice| .{ .contains = try wc.addString(slice) }, | ||
| 873 | .exact => |exact| .{ .exact = .{ .slice = try s.initStringList(exact) } }, | ||
| 874 | .starts_with => |slice| .{ .starts_with = try wc.addString(slice) }, | ||
| 875 | .stderr_contains => |slice| .{ .stderr_contains = try wc.addString(slice) }, | ||
| 876 | } else .none }, | ||
| 877 | .test_runner = .{ .u = if (c.test_runner) |tr| switch (tr.mode) { | ||
| 878 | .simple => .{ .simple = try s.addLazyPath(tr.path) }, | ||
| 879 | .server => .{ .server = try s.addLazyPath(tr.path) }, | ||
| 880 | } else .default }, | ||
| 881 | |||
| 882 | .emit_directory = .{ .value = c.emit_directory.unwrap() }, | ||
| 883 | .generated_docs = .{ .value = c.generated_docs.unwrap() }, | ||
| 884 | .generated_asm = .{ .value = c.generated_asm.unwrap() }, | ||
| 885 | .generated_bin = .{ .value = c.generated_bin.unwrap() }, | ||
| 886 | .generated_pdb = .{ .value = c.generated_pdb.unwrap() }, | ||
| 887 | .generated_implib = .{ .value = c.generated_implib.unwrap() }, | ||
| 888 | .generated_llvm_bc = .{ .value = c.generated_llvm_bc.unwrap() }, | ||
| 889 | .generated_llvm_ir = .{ .value = c.generated_llvm_ir.unwrap() }, | ||
| 890 | .generated_h = .{ .value = c.generated_h.unwrap() }, | ||
| 891 | }); | ||
| 892 | }, | ||
| 893 | .install_artifact => e: { | ||
| 894 | const ia: *Step.InstallArtifact = @fieldParentPtr("step", step); | ||
| 895 | break :e try wc.addExtraErased(Configuration.Step.InstallArtifact, .{ | ||
| 896 | .flags = .{ | ||
| 897 | .dylib_symlinks = ia.dylib_symlinks, | ||
| 898 | .bin_dir = ia.dest_dir != null, | ||
| 899 | .implib_dir = ia.implib_dir != null, | ||
| 900 | .pdb_dir = ia.pdb_dir != null, | ||
| 901 | .h_dir = ia.h_dir != null, | ||
| 902 | .bin_sub_path = ia.dest_sub_path != null, | ||
| 903 | }, | ||
| 904 | .bin_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.dest_dir) }, | ||
| 905 | .implib_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.implib_dir) }, | ||
| 906 | .pdb_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.pdb_dir) }, | ||
| 907 | .h_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.h_dir) }, | ||
| 908 | .bin_sub_path = .{ .value = try s.addOptionalString(ia.dest_sub_path) }, | ||
| 909 | }); | ||
| 910 | }, | ||
| 911 | .install_file => e: { | ||
| 912 | const sif: *Step.InstallFile = @fieldParentPtr("step", step); | ||
| 913 | break :e try wc.addExtraErased(Configuration.Step.InstallFile, .{ | ||
| 914 | .source = try s.addLazyPath(sif.source), | ||
| 915 | .dest_dir = try addInstallDir(wc, sif.dir), | ||
| 916 | .dest_sub_path = try wc.addString(sif.dest_rel_path), | ||
| 917 | }); | ||
| 918 | }, | ||
| 919 | .install_dir => e: { | ||
| 920 | const sid: *Step.InstallDir = @fieldParentPtr("step", step); | ||
| 921 | const dest_sub_path: ?[]const u8 = if (sid.options.install_subdir.len != 0) | ||
| 922 | sid.options.install_subdir | ||
| 923 | else | ||
| 924 | null; | ||
| 925 | const include_extensions = sid.options.include_extensions orelse &.{}; | ||
| 926 | break :e try wc.addExtraErased(Configuration.Step.InstallDir, .{ | ||
| 927 | .flags = .{ | ||
| 928 | .dest_sub_path = dest_sub_path != null, | ||
| 929 | .exclude_extensions = sid.options.exclude_extensions.len != 0, | ||
| 930 | .include_extensions = include_extensions.len != 0, | ||
| 931 | .include_extensions_active = sid.options.include_extensions != null, | ||
| 932 | .blank_extensions = sid.options.blank_extensions.len != 0, | ||
| 933 | }, | ||
| 934 | .source_dir = try s.addLazyPath(sid.options.source_dir), | ||
| 935 | .dest_dir = try addInstallDir(wc, sid.options.install_dir), | ||
| 936 | .dest_sub_path = .{ .value = try s.addOptionalString(dest_sub_path) }, | ||
| 937 | .exclude_extensions = .{ .slice = try s.initStringList(sid.options.exclude_extensions) }, | ||
| 938 | .include_extensions = .{ .slice = try s.initStringList(include_extensions) }, | ||
| 939 | .blank_extensions = .{ .slice = try s.initStringList(sid.options.blank_extensions) }, | ||
| 940 | }); | ||
| 941 | }, | ||
| 942 | .fail => e: { | ||
| 943 | const sf: *Step.Fail = @fieldParentPtr("step", step); | ||
| 944 | break :e try wc.addExtraErased(Configuration.Step.Fail, .{ | ||
| 945 | .msg = sf.error_msg, | ||
| 946 | }); | ||
| 947 | }, | ||
| 948 | .find_program => e: { | ||
| 949 | const fp: *Step.FindProgram = @fieldParentPtr("step", step); | ||
| 950 | break :e try wc.addExtraErased(Configuration.Step.FindProgram, .{ | ||
| 951 | .names = fp.names, | ||
| 952 | .found_path = fp.found_path, | ||
| 953 | }); | ||
| 954 | }, | ||
| 955 | .fmt => e: { | ||
| 956 | const sf: *Step.Fmt = @fieldParentPtr("step", step); | ||
| 957 | break :e try wc.addExtraErased(Configuration.Step.Fmt, .{ | ||
| 958 | .flags = .{ | ||
| 959 | .paths = sf.paths.len != 0, | ||
| 960 | .exclude_paths = sf.exclude_paths.len != 0, | ||
| 961 | .check = sf.check, | ||
| 962 | }, | ||
| 963 | .paths = .{ .slice = try s.initLazyPathList(sf.paths) }, | ||
| 964 | .exclude_paths = .{ .slice = try s.initLazyPathList(sf.exclude_paths) }, | ||
| 965 | }); | ||
| 966 | }, | ||
| 967 | .translate_c => e: { | ||
| 968 | const tc: *Step.TranslateC = @fieldParentPtr("step", step); | ||
| 969 | |||
| 970 | const system_libs = try arena.alloc(Configuration.SystemLib.Index, tc.system_libs.items.len); | ||
| 971 | for (system_libs, tc.system_libs.items) |*dest, *src| dest.* = try s.addSystemLib(src); | ||
| 972 | |||
| 973 | break :e try wc.addExtraErased(Configuration.Step.TranslateC, .{ | ||
| 974 | .flags = .{ | ||
| 975 | .include_dirs = tc.include_dirs.items.len != 0, | ||
| 976 | .system_libs = system_libs.len != 0, | ||
| 977 | .c_macros = tc.c_macros.items.len != 0, | ||
| 978 | .link_libc = tc.link_libc, | ||
| 979 | .optimize = .init(tc.optimize), | ||
| 980 | }, | ||
| 981 | .src_path = try s.addLazyPath(tc.source), | ||
| 982 | .output_file = tc.output_file, | ||
| 983 | .include_dirs = .init(try s.initIncludeDirList(tc.include_dirs.items)), | ||
| 984 | .system_libs = .{ .slice = system_libs }, | ||
| 985 | .c_macros = .{ .slice = tc.c_macros.items }, | ||
| 986 | .target = try addOptionalResolvedTarget(wc, tc.target), | ||
| 987 | }); | ||
| 988 | }, | ||
| 989 | .write_file => e: { | ||
| 990 | const wf: *Step.WriteFile = @fieldParentPtr("step", step); | ||
| 991 | |||
| 992 | const directories = try arena.alloc( | ||
| 993 | Configuration.Step.WriteFile.Directory, | ||
| 994 | wf.directories.items.len, | ||
| 995 | ); | ||
| 996 | for (directories, wf.directories.items) |*dest, src| dest.* = .{ | ||
| 997 | .sub_path = src.sub_path, | ||
| 998 | .src_path = try s.addLazyPath(src.src_path), | ||
| 999 | .exclude_extensions = src.exclude_extensions, | ||
| 1000 | .include_extensions = src.include_extensions, | ||
| 1001 | }; | ||
| 1002 | |||
| 1003 | break :e try wc.addExtraErased(Configuration.Step.WriteFile, .{ | ||
| 1004 | .flags = .{ | ||
| 1005 | .embeds = wf.embeds.items.len != 0, | ||
| 1006 | .copies = wf.copies.items.len != 0, | ||
| 1007 | .directories = directories.len != 0, | ||
| 1008 | .mode = switch (wf.mode) { | ||
| 1009 | .whole_cached => .whole_cached, | ||
| 1010 | .tmp => .tmp, | ||
| 1011 | .mutate => .mutate, | ||
| 1012 | }, | ||
| 1013 | }, | ||
| 1014 | .generated_directory = wf.generated_directory, | ||
| 1015 | .embeds = .{ .slice = wf.embeds.items }, | ||
| 1016 | .copies = .{ .slice = try s.initCopyList(wf.copies.items) }, | ||
| 1017 | .directories = .{ .slice = directories }, | ||
| 1018 | .mutate_path = .{ .value = switch (wf.mode) { | ||
| 1019 | .mutate => |lp| try s.addLazyPath(lp), | ||
| 1020 | .whole_cached, .tmp => null, | ||
| 1021 | } }, | ||
| 1022 | }); | ||
| 1023 | }, | ||
| 1024 | .update_source_files => e: { | ||
| 1025 | const usf: *Step.UpdateSourceFiles = @fieldParentPtr("step", step); | ||
| 1026 | break :e try wc.addExtraErased(Configuration.Step.UpdateSourceFiles, .{ | ||
| 1027 | .flags = .{ | ||
| 1028 | .embeds = usf.embeds.items.len != 0, | ||
| 1029 | .copies = usf.copies.items.len != 0, | ||
| 1030 | }, | ||
| 1031 | .embeds = .{ .slice = usf.embeds.items }, | ||
| 1032 | .copies = .{ .slice = try s.initCopyList(usf.copies.items) }, | ||
| 1033 | }); | ||
| 1034 | }, | ||
| 1035 | .run => e: { | ||
| 1036 | const run: *Step.Run = @fieldParentPtr("step", step); | ||
| 1037 | var expect_stderr_exact: ?Configuration.Bytes = null; | ||
| 1038 | var expect_stdout_exact: ?Configuration.Bytes = null; | ||
| 1039 | var expect_stderr_match: std.ArrayList(Configuration.Bytes) = .empty; | ||
| 1040 | var expect_stdout_match: std.ArrayList(Configuration.Bytes) = .empty; | ||
| 1041 | var expect_term: ?struct { | ||
| 1042 | status: Configuration.Step.Run.ExpectTermStatus, | ||
| 1043 | value: u32, | ||
| 1044 | } = null; | ||
| 1045 | var expect_stderr_snapshot: ?Configuration.LazyPath.Index = null; | ||
| 1046 | var expect_stdout_snapshot: ?Configuration.LazyPath.Index = null; | ||
| 1047 | switch (run.stdio) { | ||
| 1048 | .check => |checks| for (checks.items) |check| switch (check) { | ||
| 1049 | .expect_stderr_exact => |bytes| expect_stderr_exact = try wc.addBytes(bytes), | ||
| 1050 | .expect_stdout_exact => |bytes| expect_stdout_exact = try wc.addBytes(bytes), | ||
| 1051 | .expect_stderr_match => |bytes| { | ||
| 1052 | try expect_stderr_match.append(arena, try wc.addBytes(bytes)); | ||
| 1053 | }, | ||
| 1054 | .expect_stdout_match => |bytes| { | ||
| 1055 | try expect_stdout_match.append(arena, try wc.addBytes(bytes)); | ||
| 1056 | }, | ||
| 1057 | .expect_term => |t| expect_term = switch (t) { | ||
| 1058 | .exited => |x| .{ .status = .exited, .value = x }, | ||
| 1059 | .signal => |x| .{ .status = .signal, .value = @intFromEnum(x) }, | ||
| 1060 | .stopped => |x| .{ .status = .stopped, .value = @intFromEnum(x) }, | ||
| 1061 | .unknown => |x| .{ .status = .unknown, .value = x }, | ||
| 1062 | }, | ||
| 1063 | .expect_stderr_snapshot => |path| expect_stderr_snapshot = try s.addLazyPath(path), | ||
| 1064 | .expect_stdout_snapshot => |path| expect_stdout_snapshot = try s.addLazyPath(path), | ||
| 1065 | }, | ||
| 1066 | else => {}, | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | break :e try wc.addExtraErased(Configuration.Step.Run, .{ | ||
| 1070 | .flags = .{ | ||
| 1071 | .disable_zig_progress = run.disable_zig_progress, | ||
| 1072 | .skip_foreign_checks = run.skip_foreign_checks, | ||
| 1073 | .failing_to_execute_foreign_is_an_error = run.failing_to_execute_foreign_is_an_error, | ||
| 1074 | .has_side_effects = run.has_side_effects, | ||
| 1075 | .test_runner_mode = run.test_runner_mode, | ||
| 1076 | .color = run.color, | ||
| 1077 | .stdio = switch (run.stdio) { | ||
| 1078 | .infer_from_args => .infer_from_args, | ||
| 1079 | .inherit => .inherit, | ||
| 1080 | .check => .check, | ||
| 1081 | .zig_test => .zig_test, | ||
| 1082 | }, | ||
| 1083 | .stdin = switch (run.stdin) { | ||
| 1084 | .none => .none, | ||
| 1085 | .bytes => .bytes, | ||
| 1086 | .lazy_path => .lazy_path, | ||
| 1087 | }, | ||
| 1088 | .stdout_trim_whitespace = if (run.captured_stdout) |cs| cs.trim_whitespace else .none, | ||
| 1089 | .stderr_trim_whitespace = if (run.captured_stderr) |cs| cs.trim_whitespace else .none, | ||
| 1090 | .stdio_limit = run.stdio_limit != .unlimited, | ||
| 1091 | .producer = run.producer != null, | ||
| 1092 | .cwd = run.cwd != null, | ||
| 1093 | .captured_stdout = run.captured_stdout != null, | ||
| 1094 | .captured_stderr = run.captured_stderr != null, | ||
| 1095 | .environ_map = run.environ_map != null, | ||
| 1096 | }, | ||
| 1097 | .flags2 = .{ | ||
| 1098 | .expect_stderr_exact = expect_stderr_exact != null, | ||
| 1099 | .expect_stdout_exact = expect_stdout_exact != null, | ||
| 1100 | .expect_stderr_match = expect_stderr_match.items.len != 0, | ||
| 1101 | .expect_stdout_match = expect_stdout_match.items.len != 0, | ||
| 1102 | .expect_term = expect_term != null, | ||
| 1103 | .expect_term_status = if (expect_term) |t| t.status else .exited, | ||
| 1104 | .expect_stderr_snapshot = expect_stderr_snapshot != null, | ||
| 1105 | .expect_stdout_snapshot = expect_stdout_snapshot != null, | ||
| 1106 | }, | ||
| 1107 | .file_inputs = .{ .slice = try s.initLazyPathList(run.file_inputs.items) }, | ||
| 1108 | .args = .{ .slice = try s.initArgsList(run.argv.items) }, | ||
| 1109 | .cwd = .{ .value = try s.addOptionalLazyPath(run.cwd) }, | ||
| 1110 | .preopen_names = .{ .slice = try s.initStringList(run.preopens.keys()) }, | ||
| 1111 | .preopen_paths = .{ .slice = try s.initLazyPathList(run.preopens.values()) }, | ||
| 1112 | .captured_stdout = .{ .value = if (run.captured_stdout) |cs| .{ | ||
| 1113 | .basename = try wc.addString(cs.basename), | ||
| 1114 | .generated_file = cs.generated_file, | ||
| 1115 | } else null }, | ||
| 1116 | .captured_stderr = .{ .value = if (run.captured_stderr) |cs| .{ | ||
| 1117 | .basename = try wc.addString(cs.basename), | ||
| 1118 | .generated_file = cs.generated_file, | ||
| 1119 | } else null }, | ||
| 1120 | .environ_map = .{ .value = try s.addEnvironMap(run.environ_map) }, | ||
| 1121 | .expect_term_value = .{ .value = if (expect_term) |t| t.value else null }, | ||
| 1122 | .stdio_limit = .{ .value = run.stdio_limit.toInt64() }, | ||
| 1123 | .producer = .{ .value = if (run.producer) |cs| s.stepIndex(&cs.step) else null }, | ||
| 1124 | .expect_stderr_exact = .{ .value = if (expect_stderr_exact) |bytes| bytes else null }, | ||
| 1125 | .expect_stdout_exact = .{ .value = if (expect_stdout_exact) |bytes| bytes else null }, | ||
| 1126 | .expect_stderr_match = .{ .slice = expect_stderr_match.items }, | ||
| 1127 | .expect_stdout_match = .{ .slice = expect_stdout_match.items }, | ||
| 1128 | .expect_stderr_snapshot = .{ .value = expect_stderr_snapshot orelse null }, | ||
| 1129 | .expect_stdout_snapshot = .{ .value = expect_stdout_snapshot orelse null }, | ||
| 1130 | .stdin = .{ .u = switch (run.stdin) { | ||
| 1131 | .none => .none, | ||
| 1132 | .bytes => |bytes| .{ .bytes = try wc.addBytes(bytes) }, | ||
| 1133 | .lazy_path => |lp| .{ .lazy_path = try s.addLazyPath(lp) }, | ||
| 1134 | } }, | ||
| 1135 | }); | ||
| 1136 | }, | ||
| 1137 | .check_file => e: { | ||
| 1138 | const cf: *Step.CheckFile = @fieldParentPtr("step", step); | ||
| 1139 | break :e try wc.addExtraErased(Configuration.Step.CheckFile, .{ | ||
| 1140 | .flags = .{ | ||
| 1141 | .expected_exact = cf.expected_exact != null, | ||
| 1142 | .expected_matches = cf.expected_matches.len != 0, | ||
| 1143 | .max_bytes = cf.max_bytes != null, | ||
| 1144 | }, | ||
| 1145 | .file = try s.addLazyPath(cf.file), | ||
| 1146 | .expected_exact = .{ .value = cf.expected_exact }, | ||
| 1147 | .expected_matches = .{ .slice = cf.expected_matches }, | ||
| 1148 | .max_bytes = .{ .value = cf.max_bytes }, | ||
| 1149 | }); | ||
| 1150 | }, | ||
| 1151 | .config_header => e: { | ||
| 1152 | const ch: *Step.ConfigHeader = @fieldParentPtr("step", step); | ||
| 1153 | const lazy_path: ?std.Build.LazyPath = ch.style.getPath(); | ||
| 1154 | const pairs = try arena.alloc(Configuration.Step.ConfigHeader.Value.Pair, ch.values.count()); | ||
| 1155 | for (pairs, ch.values.keys(), ch.values.values()) |*pair, key, value| pair.* = .{ | ||
| 1156 | .key = try wc.addString(key), | ||
| 1157 | .index = switch (value) { | ||
| 1158 | .undef => .undef, | ||
| 1159 | .defined => .defined, | ||
| 1160 | .boolean => |x| switch (x) { | ||
| 1161 | false => .bool_false, | ||
| 1162 | true => .bool_true, | ||
| 1163 | }, | ||
| 1164 | .int => |x| switch (x) { | ||
| 1165 | 0 => .int_0, | ||
| 1166 | 1 => .int_1, | ||
| 1167 | else => try wc.addExtra(Configuration.Step.ConfigHeader.Value, .initSigned(x)), | ||
| 1168 | }, | ||
| 1169 | .ident => |x| try wc.addExtra(Configuration.Step.ConfigHeader.Value, .{ | ||
| 1170 | .flags = .{ | ||
| 1171 | .tag = .ident, | ||
| 1172 | .small = 0, | ||
| 1173 | }, | ||
| 1174 | .i64 = .{ .value = null }, | ||
| 1175 | .u64 = .{ .value = null }, | ||
| 1176 | .ident = .{ .value = try wc.addString(x) }, | ||
| 1177 | .string = .{ .value = null }, | ||
| 1178 | }), | ||
| 1179 | .string => |x| try wc.addExtra(Configuration.Step.ConfigHeader.Value, .{ | ||
| 1180 | .flags = .{ | ||
| 1181 | .tag = .string, | ||
| 1182 | .small = 0, | ||
| 1183 | }, | ||
| 1184 | .i64 = .{ .value = null }, | ||
| 1185 | .u64 = .{ .value = null }, | ||
| 1186 | .ident = .{ .value = null }, | ||
| 1187 | .string = .{ .value = try wc.addString(x) }, | ||
| 1188 | }), | ||
| 1189 | }, | ||
| 1190 | }; | ||
| 1191 | break :e try wc.addExtraErased(Configuration.Step.ConfigHeader, .{ | ||
| 1192 | .flags = .{ | ||
| 1193 | .template_file = lazy_path != null, | ||
| 1194 | .style = .init(ch.style), | ||
| 1195 | .input_size_limit = ch.input_size_limit != null, | ||
| 1196 | .include_guard = ch.include_guard != .none, | ||
| 1197 | }, | ||
| 1198 | .template_file = .{ .value = try s.addOptionalLazyPath(lazy_path) }, | ||
| 1199 | .generated_dir = ch.generated_dir, | ||
| 1200 | .input_size_limit = .{ .value = ch.input_size_limit }, | ||
| 1201 | .include_path = try wc.addString(ch.include_path), | ||
| 1202 | .include_guard = .{ .value = ch.include_guard.unwrap() }, | ||
| 1203 | .values = .{ .slice = pairs }, | ||
| 1204 | }); | ||
| 1205 | }, | ||
| 1206 | .obj_copy => e: { | ||
| 1207 | const oc: *Step.ObjCopy = @fieldParentPtr("step", step); | ||
| 1208 | |||
| 1209 | const debug_basename: ?Configuration.String = if (oc.debug_file) |df| | ||
| 1210 | df.basename.unwrap() | ||
| 1211 | else | ||
| 1212 | null; | ||
| 1213 | |||
| 1214 | const debug_file: ?Configuration.GeneratedFileIndex = if (oc.debug_file) |df| | ||
| 1215 | df.output_file | ||
| 1216 | else | ||
| 1217 | null; | ||
| 1218 | |||
| 1219 | const add_sections = try arena.alloc( | ||
| 1220 | Configuration.Step.ObjCopy.AddSection, | ||
| 1221 | oc.add_sections.items.len, | ||
| 1222 | ); | ||
| 1223 | for (add_sections, oc.add_sections.items) |*dest, src| dest.* = .{ | ||
| 1224 | .section_name = src.section_name, | ||
| 1225 | .file_path = try s.addLazyPath(src.file_path), | ||
| 1226 | }; | ||
| 1227 | |||
| 1228 | break :e try wc.addExtraErased(Configuration.Step.ObjCopy, .{ | ||
| 1229 | .flags = .{ | ||
| 1230 | .basename = oc.basename != .none, | ||
| 1231 | .debug_file = debug_file != null, | ||
| 1232 | .debug_basename = debug_basename != null, | ||
| 1233 | .format = .init(oc.format), | ||
| 1234 | .strip = oc.strip, | ||
| 1235 | .compress_debug = oc.compress_debug, | ||
| 1236 | .only_section = oc.only_section != .none, | ||
| 1237 | .pad_to = oc.pad_to != null, | ||
| 1238 | .add_section = add_sections.len != 0, | ||
| 1239 | .update_section = oc.update_sections.items.len != 0, | ||
| 1240 | }, | ||
| 1241 | .input_file = try s.addLazyPath(oc.input_file), | ||
| 1242 | .output_file = oc.output_file, | ||
| 1243 | .basename = .{ .value = oc.basename.unwrap() }, | ||
| 1244 | .debug_file = .{ .value = debug_file }, | ||
| 1245 | .debug_basename = .{ .value = debug_basename }, | ||
| 1246 | .only_section = .{ .value = oc.only_section.unwrap() }, | ||
| 1247 | .pad_to = .{ .value = oc.pad_to }, | ||
| 1248 | .add_section = .{ .slice = add_sections }, | ||
| 1249 | .update_section = .{ .slice = oc.update_sections.items }, | ||
| 1250 | }); | ||
| 1251 | }, | ||
| 1252 | .options => e: { | ||
| 1253 | const so: *Step.Options = @fieldParentPtr("step", step); | ||
| 1254 | |||
| 1255 | const args = try arena.alloc(Configuration.Step.Options.Arg, so.args.items.len); | ||
| 1256 | for (args, so.args.items) |*dest, src| dest.* = .{ | ||
| 1257 | .name = src.name, | ||
| 1258 | .path = try s.addLazyPath(src.path), | ||
| 1259 | }; | ||
| 1260 | |||
| 1261 | break :e try wc.addExtraErased(Configuration.Step.Options, .{ | ||
| 1262 | .flags = .{ | ||
| 1263 | .args = so.args.items.len != 0, | ||
| 1264 | }, | ||
| 1265 | .generated_file = so.generated_file, | ||
| 1266 | .contents = try wc.addBytes(so.contents.items), | ||
| 1267 | .args = .{ .slice = args }, | ||
| 1268 | }); | ||
| 1269 | }, | ||
| 1270 | }), | ||
| 1271 | }); | ||
| 1272 | } | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | try wc.unlazy_deps.ensureUnusedCapacity(gpa, graph.needed_lazy_dependencies.keys().len); | ||
| 1276 | for (graph.needed_lazy_dependencies.keys()) |k| { | ||
| 1277 | wc.unlazy_deps.appendAssumeCapacity(try wc.addString(k)); | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | try wc.write(writer, .{ | ||
| 1281 | .default_step = s.stepIndex(b.default_step), | ||
| 1282 | .generated_files_len = @intCast(graph.generated_files.items.len), | ||
| 1283 | .poisoned = switch (graph.cache_poison) { | ||
| 1284 | .pure, .disallowed, .ignored => false, | ||
| 1285 | .poisoned => true, | ||
| 1286 | }, | ||
| 1287 | }); | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | fn addOptionalResolvedTarget( | ||
| 1291 | wc: *Configuration.Wip, | ||
| 1292 | optional_resolved_target: ?std.Build.ResolvedTarget, | ||
| 1293 | ) !Configuration.ResolvedTarget.OptionalIndex { | ||
| 1294 | const resolved_target = optional_resolved_target orelse return .none; | ||
| 1295 | return .init(try wc.addDeduped(Configuration.ResolvedTarget, .{ | ||
| 1296 | .query = try wc.addTargetQuery(&resolved_target.query), | ||
| 1297 | .result = try wc.addTarget(resolved_target.result), | ||
| 1298 | })); | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | fn addInstallDir(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !Configuration.InstallDestDir { | ||
| 1302 | switch (install_dir orelse return .none) { | ||
| 1303 | .prefix => return .prefix, | ||
| 1304 | .lib => return .lib, | ||
| 1305 | .bin => return .bin, | ||
| 1306 | .header => return .header, | ||
| 1307 | .custom => |sub_path| return .initCustom(try wc.addString(sub_path)), | ||
| 1308 | } | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | fn addInstallDirDefaultNull(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !?Configuration.InstallDestDir { | ||
| 1312 | return try addInstallDir(wc, install_dir orelse return null); | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | /// If the given `Step` is a `Step.Compile`, adds any dependencies for that step which | ||
| 1316 | /// are implied by the module graph rooted at `step.cast(Step.Compile).?.root_module`. | ||
| 1317 | fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void { | ||
| 1318 | const root_module = if (step.cast(Step.Compile)) |cs| root: { | ||
| 1319 | break :root cs.root_module; | ||
| 1320 | } else return; // not a compile step so no module dependencies | ||
| 1321 | |||
| 1322 | // Starting from `root_module`, discover all modules in this graph. | ||
| 1323 | const modules = root_module.getGraph().modules; | ||
| 1324 | |||
| 1325 | // For each of those modules, set up the implied step dependencies. | ||
| 1326 | for (modules) |mod| { | ||
| 1327 | if (mod.root_source_file) |lp| lp.addStepDependencies(step); | ||
| 1328 | for (mod.include_dirs.items) |include_dir| switch (include_dir) { | ||
| 1329 | .path, | ||
| 1330 | .path_system, | ||
| 1331 | .path_after, | ||
| 1332 | .framework_path, | ||
| 1333 | .framework_path_system, | ||
| 1334 | .embed_path, | ||
| 1335 | => |lp| lp.addStepDependencies(step), | ||
| 1336 | |||
| 1337 | .other_step => |other| { | ||
| 1338 | other.getEmittedIncludeTree().addStepDependencies(step); | ||
| 1339 | step.dependOn(&other.step); | ||
| 1340 | }, | ||
| 1341 | |||
| 1342 | .config_header_step => |other| step.dependOn(&other.step), | ||
| 1343 | }; | ||
| 1344 | for (mod.lib_paths.items) |lp| lp.addStepDependencies(step); | ||
| 1345 | for (mod.rpaths.items) |rpath| switch (rpath) { | ||
| 1346 | .lazy_path => |lp| lp.addStepDependencies(step), | ||
| 1347 | .special => {}, | ||
| 1348 | }; | ||
| 1349 | for (mod.link_objects.items) |link_object| switch (link_object) { | ||
| 1350 | .static_path, | ||
| 1351 | .assembly_file, | ||
| 1352 | => |lp| lp.addStepDependencies(step), | ||
| 1353 | .other_step => |other| step.dependOn(&other.step), | ||
| 1354 | .system_lib => {}, | ||
| 1355 | .c_source_file => |source| source.file.addStepDependencies(step), | ||
| 1356 | .c_source_files => |source_files| source_files.root.addStepDependencies(step), | ||
| 1357 | .win32_resource_file => |rc_source| { | ||
| 1358 | rc_source.file.addStepDependencies(step); | ||
| 1359 | for (rc_source.include_paths) |lp| lp.addStepDependencies(step); | ||
| 1360 | }, | ||
| 1361 | }; | ||
| 1362 | } | ||
| 1363 | } | 144 | } |
| 1364 | 145 | ||
| 1365 | fn nextArg(args: []const [:0]const u8, idx: *usize) ?[:0]const u8 { | 146 | fn nextArg(args: []const [:0]const u8, idx: *usize) ?[:0]const u8 { |
| ... | @@ -1381,69 +162,7 @@ fn expectArgOrFatal(args: []const [:0]const u8, index_ptr: *usize, first: []cons | ... | @@ -1381,69 +162,7 @@ fn expectArgOrFatal(args: []const [:0]const u8, index_ptr: *usize, first: []cons |
| 1381 | return arg; | 162 | return arg; |
| 1382 | } | 163 | } |
| 1383 | 164 | ||
| 1384 | const ErrorStyle = enum { | ||
| 1385 | verbose, | ||
| 1386 | minimal, | ||
| 1387 | verbose_clear, | ||
| 1388 | minimal_clear, | ||
| 1389 | fn verboseContext(s: ErrorStyle) bool { | ||
| 1390 | return switch (s) { | ||
| 1391 | .verbose, .verbose_clear => true, | ||
| 1392 | .minimal, .minimal_clear => false, | ||
| 1393 | }; | ||
| 1394 | } | ||
| 1395 | fn clearOnUpdate(s: ErrorStyle) bool { | ||
| 1396 | return switch (s) { | ||
| 1397 | .verbose, .minimal => false, | ||
| 1398 | .verbose_clear, .minimal_clear => true, | ||
| 1399 | }; | ||
| 1400 | } | ||
| 1401 | }; | ||
| 1402 | const MultilineErrors = enum { indent, newline, none }; | ||
| 1403 | const Summary = enum { all, new, failures, line, none }; | ||
| 1404 | |||
| 1405 | fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn { | 165 | fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn { |
| 1406 | log.info("to access the help menu: zig build -h", .{}); | 166 | log.info("to access the help menu: zig build -h", .{}); |
| 1407 | fatal(f, args); | 167 | fatal(f, args); |
| 1408 | } | 168 | } |
| 1409 | |||
| 1410 | fn serializeSystemIntegrationOptions(graph: *std.Build.Graph, wc: *Configuration.Wip) Allocator.Error!void { | ||
| 1411 | const gpa = wc.gpa; | ||
| 1412 | |||
| 1413 | var bad = false; | ||
| 1414 | try wc.system_integrations.ensureTotalCapacityPrecise(gpa, graph.system_integration_options.entries.len); | ||
| 1415 | for (graph.system_integration_options.keys(), graph.system_integration_options.values()) |k, v| { | ||
| 1416 | wc.system_integrations.appendAssumeCapacity(.{ | ||
| 1417 | .name = try wc.addString(k), | ||
| 1418 | .status = switch (v) { | ||
| 1419 | .user_disabled, .user_enabled => x: { | ||
| 1420 | // The user tried to enable or disable a system library integration, but | ||
| 1421 | // the configure script did not recognize that option. | ||
| 1422 | log.err("system integration name not recognized by configure script: {s}", .{k}); | ||
| 1423 | bad = true; | ||
| 1424 | break :x .disabled; | ||
| 1425 | }, | ||
| 1426 | .declared_disabled => .disabled, | ||
| 1427 | .declared_enabled => .enabled, | ||
| 1428 | }, | ||
| 1429 | }); | ||
| 1430 | } | ||
| 1431 | if (bad) { | ||
| 1432 | log.info("help menu contains available options: zig build -h", .{}); | ||
| 1433 | process.exit(1); | ||
| 1434 | } | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | fn serializePackageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!void { | ||
| 1438 | const gpa = wc.gpa; | ||
| 1439 | |||
| 1440 | try wc.available_options.ensureTotalCapacityPrecise(gpa, b.available_options_map.count()); | ||
| 1441 | for (b.available_options_map.keys(), b.available_options_map.values()) |name, *opt| { | ||
| 1442 | wc.available_options.appendAssumeCapacity(.{ | ||
| 1443 | .name = try wc.addString(name), | ||
| 1444 | .description = try wc.addString(opt.description), | ||
| 1445 | .type = opt.type_id, | ||
| 1446 | .enum_options = if (opt.enum_options) |enum_vals| .init(try wc.addStringList(enum_vals)) else .none, | ||
| 1447 | }); | ||
| 1448 | } | ||
| 1449 | } |
lib/std/Build.zig+87-42| ... | @@ -16,6 +16,7 @@ const process = std.process; | ... | @@ -16,6 +16,7 @@ const process = std.process; |
| 16 | const File = std.Io.File; | 16 | const File = std.Io.File; |
| 17 | const Sha256 = std.crypto.hash.sha2.Sha256; | 17 | const Sha256 = std.crypto.hash.sha2.Sha256; |
| 18 | const ArrayList = std.ArrayList; | 18 | const ArrayList = std.ArrayList; |
| 19 | const fatal = std.process.fatal; | ||
| 19 | 20 | ||
| 20 | pub const Cache = @import("Build/Cache.zig"); | 21 | pub const Cache = @import("Build/Cache.zig"); |
| 21 | pub const Step = @import("Build/Step.zig"); | 22 | pub const Step = @import("Build/Step.zig"); |
| ... | @@ -23,6 +24,8 @@ pub const Module = @import("Build/Module.zig"); | ... | @@ -23,6 +24,8 @@ pub const Module = @import("Build/Module.zig"); |
| 23 | pub const abi = @import("Build/abi.zig"); | 24 | pub const abi = @import("Build/abi.zig"); |
| 24 | /// The serialized output of configure phase ingested by make phase. | 25 | /// The serialized output of configure phase ingested by make phase. |
| 25 | pub const Configuration = @import("Build/Configuration.zig"); | 26 | pub const Configuration = @import("Build/Configuration.zig"); |
| 27 | /// Logic that transforms `Build` into `Configuration`. | ||
| 28 | pub const Serialize = @import("Build/Serialize.zig"); | ||
| 26 | 29 | ||
| 27 | /// Shared state among all Build instances. | 30 | /// Shared state among all Build instances. |
| 28 | graph: *Graph, | 31 | graph: *Graph, |
| ... | @@ -1987,13 +1990,13 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 { | ... | @@ -1987,13 +1990,13 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 { |
| 1987 | .stderr_behavior = .inherit, | 1990 | .stderr_behavior = .inherit, |
| 1988 | })) { | 1991 | })) { |
| 1989 | .success => |stdout| return stdout, | 1992 | .success => |stdout| return stdout, |
| 1990 | .spawn_failed => |err| process.fatal("the following command failed with {t}:\n{s}", .{ | 1993 | .spawn_failed => |err| fatal("the following command failed with {t}:\n{s}", .{ |
| 1991 | err, std.zig.allocPrintCmd(arena, argv, .{}) catch @panic("OOM"), | 1994 | err, std.zig.allocPrintCmd(arena, argv, .{}) catch @panic("OOM"), |
| 1992 | }), | 1995 | }), |
| 1993 | .bad_exit_code => |code| process.fatal("the following command exited with code {d}:\n{s}", .{ | 1996 | .bad_exit_code => |code| fatal("the following command exited with code {d}:\n{s}", .{ |
| 1994 | code, std.zig.allocPrintCmd(arena, argv, .{}) catch @panic("OOM"), | 1997 | code, std.zig.allocPrintCmd(arena, argv, .{}) catch @panic("OOM"), |
| 1995 | }), | 1998 | }), |
| 1996 | .crashed => process.fatal("the following command crashed:\n{s}", .{ | 1999 | .crashed => fatal("the following command crashed:\n{s}", .{ |
| 1997 | std.zig.allocPrintCmd(arena, argv, .{}) catch @panic("OOM"), | 2000 | std.zig.allocPrintCmd(arena, argv, .{}) catch @panic("OOM"), |
| 1998 | }), | 2001 | }), |
| 1999 | } | 2002 | } |
| ... | @@ -2075,7 +2078,7 @@ fn findPkgHashOrFatal(b: *Build, name: []const u8) []const u8 { | ... | @@ -2075,7 +2078,7 @@ fn findPkgHashOrFatal(b: *Build, name: []const u8) []const u8 { |
| 2075 | for (b.available_deps) |dep| { | 2078 | for (b.available_deps) |dep| { |
| 2076 | if (mem.eql(u8, dep[0], name)) return dep[1]; | 2079 | if (mem.eql(u8, dep[0], name)) return dep[1]; |
| 2077 | } | 2080 | } |
| 2078 | std.log.info("all dependencies used by build.zig must be declared in corresponding build.zig.zon", .{}); | 2081 | log.info("all dependencies used by build.zig must be declared in corresponding build.zig.zon", .{}); |
| 2079 | if (b.pkg_hash.len == 0) panic("no dependency named {s}", .{name}); | 2082 | if (b.pkg_hash.len == 0) panic("no dependency named {s}", .{name}); |
| 2080 | panic("no dependency named {s} in {s} ({s})", .{ name, b.dep_prefix, b.pkg_hash }); | 2083 | panic("no dependency named {s} in {s} ({s})", .{ name, b.dep_prefix, b.pkg_hash }); |
| 2081 | } | 2084 | } |
| ... | @@ -2109,21 +2112,29 @@ fn markNeededLazyDep(b: *Build, pkg_hash: []const u8) void { | ... | @@ -2109,21 +2112,29 @@ fn markNeededLazyDep(b: *Build, pkg_hash: []const u8) void { |
| 2109 | b.graph.needed_lazy_dependencies.put(b.graph.arena, pkg_hash, {}) catch @panic("OOM"); | 2112 | b.graph.needed_lazy_dependencies.put(b.graph.arena, pkg_hash, {}) catch @panic("OOM"); |
| 2110 | } | 2113 | } |
| 2111 | 2114 | ||
| 2112 | /// When this function is called, it means that the current build does, in | 2115 | /// Deprecated in favor of `dependencyLazy`. |
| 2113 | /// fact, require this dependency. If the dependency is already fetched, it | ||
| 2114 | /// proceeds in the same manner as `dependency`. However if the dependency was | ||
| 2115 | /// not fetched, then when the build script is finished running, the build will | ||
| 2116 | /// not proceed to the make phase. Instead, the parent process will | ||
| 2117 | /// additionally fetch all the lazy dependencies that were actually required by | ||
| 2118 | /// running the build script, rebuild the build script, and then run it again. | ||
| 2119 | /// In other words, if this function returns `null` it means that the only | ||
| 2120 | /// purpose of completing the configure phase is to find out all the other lazy | ||
| 2121 | /// dependencies that are also required. | ||
| 2122 | /// | ||
| 2123 | /// It is allowed to use this function for non-lazy dependencies, in which case | ||
| 2124 | /// it will never return `null`. This allows toggling laziness via | ||
| 2125 | /// build.zig.zon without changing build.zig logic. | ||
| 2126 | pub fn lazyDependency(b: *Build, name: []const u8, args: anytype) ?*Dependency { | 2116 | pub fn lazyDependency(b: *Build, name: []const u8, args: anytype) ?*Dependency { |
| 2117 | return dependencyLazy(b, name, args) catch |err| switch (err) { | ||
| 2118 | error.LazyDependencyNeeded => null, | ||
| 2119 | }; | ||
| 2120 | } | ||
| 2121 | |||
| 2122 | /// Declares that the current configuration does in fact require a potentially | ||
| 2123 | /// lazy dependency. | ||
| 2124 | /// | ||
| 2125 | /// If the dependency is already fetched, it is returned. However if the | ||
| 2126 | /// dependency is not yet fetched, then when the build script is finished | ||
| 2127 | /// running, the toolchain will not proceed to the make phase. Instead, the | ||
| 2128 | /// parent process will additionally fetch all the lazy dependencies that were | ||
| 2129 | /// actually required by running the build script, recompile the build script, | ||
| 2130 | /// and then run it again. In other words, if this function returns | ||
| 2131 | /// `error.LazyDependencyNeeded` it means that the only purpose of completing | ||
| 2132 | /// the configure phase is to find out all the other lazy dependencies that are | ||
| 2133 | /// also required. In this case, one must propagate the error all the way up | ||
| 2134 | /// and return it from the main build function. | ||
| 2135 | /// | ||
| 2136 | /// For non-lazy dependencies, this always succeeds. | ||
| 2137 | pub fn dependencyLazy(b: *Build, name: []const u8, args: anytype) error{LazyDependencyNeeded}!*Dependency { | ||
| 2127 | const build_runner = @import("root"); | 2138 | const build_runner = @import("root"); |
| 2128 | const deps = build_runner.dependencies; | 2139 | const deps = build_runner.dependencies; |
| 2129 | const pkg_hash = findPkgHashOrFatal(b, name); | 2140 | const pkg_hash = findPkgHashOrFatal(b, name); |
| ... | @@ -2134,31 +2145,34 @@ pub fn lazyDependency(b: *Build, name: []const u8, args: anytype) ?*Dependency { | ... | @@ -2134,31 +2145,34 @@ pub fn lazyDependency(b: *Build, name: []const u8, args: anytype) ?*Dependency { |
| 2134 | const available = !@hasDecl(pkg, "available") or pkg.available; | 2145 | const available = !@hasDecl(pkg, "available") or pkg.available; |
| 2135 | if (!available) { | 2146 | if (!available) { |
| 2136 | markNeededLazyDep(b, pkg_hash); | 2147 | markNeededLazyDep(b, pkg_hash); |
| 2137 | return null; | 2148 | return error.LazyDependencyNeeded; |
| 2138 | } | 2149 | } |
| 2139 | return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg_hash, pkg.deps, args); | 2150 | return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg_hash, pkg.deps, args); |
| 2140 | } | 2151 | } |
| 2141 | } | 2152 | } |
| 2142 | 2153 | ||
| 2143 | unreachable; // Bad @dependencies source | 2154 | unreachable; // bad @dependencies source |
| 2144 | } | 2155 | } |
| 2145 | 2156 | ||
| 2157 | /// Declares that the current configuration does in fact require a potentially | ||
| 2158 | /// lazy dependency. | ||
| 2159 | /// | ||
| 2160 | /// If the dependency is already fetched, it is returned. Otherwise, exits the | ||
| 2161 | /// configuration phase with intent to fetch the lazy dependency and rerun the | ||
| 2162 | /// configuration script. | ||
| 2163 | /// | ||
| 2164 | /// If it is known to the caller at this point that additional lazy | ||
| 2165 | /// dependencies are also required, it would save time to call `dependencyLazy` | ||
| 2166 | /// instead, handling `error.LazyDependencyNeeded` in a way that marks multiple | ||
| 2167 | /// potentially lazy dependencies as required before eventually returning | ||
| 2168 | /// that error from the top level build function. | ||
| 2146 | pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency { | 2169 | pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency { |
| 2147 | const build_runner = @import("root"); | 2170 | return dependencyLazy(b, name, args) catch |err| switch (err) { |
| 2148 | const deps = build_runner.dependencies; | 2171 | error.LazyDependencyNeeded => { |
| 2149 | const pkg_hash = findPkgHashOrFatal(b, name); | 2172 | assert(b.graph.needed_lazy_dependencies.count() != 0); |
| 2150 | 2173 | serializeConfigurationExiting(b); | |
| 2151 | inline for (@typeInfo(deps.packages).@"struct".decl_names) |decl_name| { | 2174 | }, |
| 2152 | if (mem.eql(u8, decl_name, pkg_hash)) { | 2175 | }; |
| 2153 | const pkg = @field(deps.packages, decl_name); | ||
| 2154 | if (@hasDecl(pkg, "available")) { | ||
| 2155 | panic("dependency '{s}{s}' is marked as lazy in build.zig.zon which means it must use the lazyDependency function instead", .{ b.dep_prefix, name }); | ||
| 2156 | } | ||
| 2157 | return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg_hash, pkg.deps, args); | ||
| 2158 | } | ||
| 2159 | } | ||
| 2160 | |||
| 2161 | unreachable; // Bad @dependencies source | ||
| 2162 | } | 2176 | } |
| 2163 | 2177 | ||
| 2164 | /// In a build.zig file, this function is to `@import` what `lazyDependency` is to `dependency`. | 2178 | /// In a build.zig file, this function is to `@import` what `lazyDependency` is to `dependency`. |
| ... | @@ -2329,13 +2343,13 @@ fn dependencyInner( | ... | @@ -2329,13 +2343,13 @@ fn dependencyInner( |
| 2329 | .root_dir = .{ | 2343 | .root_dir = .{ |
| 2330 | .path = build_root_string, | 2344 | .path = build_root_string, |
| 2331 | .handle = Io.Dir.cwd().openDir(io, build_root_string, .{}) catch |err| | 2345 | .handle = Io.Dir.cwd().openDir(io, build_root_string, .{}) catch |err| |
| 2332 | process.fatal("failed to open {q}: {t}", .{ build_root_string, err }), | 2346 | fatal("failed to open {q}: {t}", .{ build_root_string, err }), |
| 2333 | }, | 2347 | }, |
| 2334 | }; | 2348 | }; |
| 2335 | 2349 | ||
| 2336 | const sub_builder = b.createChild(name, dep_root, pkg_hash, pkg_deps, user_input_options) catch @panic("OOM"); | 2350 | const sub_builder = b.createChild(name, dep_root, pkg_hash, pkg_deps, user_input_options) catch @panic("OOM"); |
| 2337 | if (build_zig) |bz| { | 2351 | if (build_zig) |bz| { |
| 2338 | sub_builder.runBuild(bz); | 2352 | sub_builder.runPackageScript(bz); |
| 2339 | 2353 | ||
| 2340 | if (sub_builder.validateUserInputDidItFail()) { | 2354 | if (sub_builder.validateUserInputDidItFail()) { |
| 2341 | std.debug.dumpCurrentStackTrace(.{ .first_address = @returnAddress() }); | 2355 | std.debug.dumpCurrentStackTrace(.{ .first_address = @returnAddress() }); |
| ... | @@ -2353,11 +2367,22 @@ fn dependencyInner( | ... | @@ -2353,11 +2367,22 @@ fn dependencyInner( |
| 2353 | } | 2367 | } |
| 2354 | 2368 | ||
| 2355 | /// Build system implementation detail. | 2369 | /// Build system implementation detail. |
| 2356 | pub fn runBuild(b: *Build, build_zig: anytype) void { | 2370 | pub inline fn runPackageScript(b: *Build, comptime build_zig: anytype) void { |
| 2357 | switch (@typeInfo(@typeInfo(@TypeOf(build_zig.build)).@"fn".return_type.?)) { | 2371 | const result: anyerror!void = build_zig.build(b); |
| 2358 | .error_union => return build_zig.build(b) catch unreachable, | 2372 | result catch |err| switch (err) { |
| 2359 | else => return build_zig.build(b), | 2373 | error.LazyDependencyNeeded => assert(b.graph.needed_lazy_dependencies.count() != 0), |
| 2360 | } | 2374 | else => { |
| 2375 | if (b.dep_prefix.len == 0) { | ||
| 2376 | log.err("package {q} configuration failed: {t}", .{ b.dep_prefix, err }); | ||
| 2377 | } else { | ||
| 2378 | log.err("configuration failed: {t}", .{err}); | ||
| 2379 | } | ||
| 2380 | if (@errorReturnTrace()) |trace| std.debug.dumpErrorReturnTrace(trace); | ||
| 2381 | const lazy_count = b.graph.needed_lazy_dependencies.count(); | ||
| 2382 | if (lazy_count == 0) process.exit(1); | ||
| 2383 | log.info("{d} lazy dependencies detected; fetching and retrying configuration", .{lazy_count}); | ||
| 2384 | }, | ||
| 2385 | }; | ||
| 2361 | } | 2386 | } |
| 2362 | 2387 | ||
| 2363 | // dirnameAllowEmpty is a variant of fs.path.dirname | 2388 | // dirnameAllowEmpty is a variant of fs.path.dirname |
| ... | @@ -2815,6 +2840,26 @@ fn validateConfigureDependency(lazy_path: LazyPath) void { | ... | @@ -2815,6 +2840,26 @@ fn validateConfigureDependency(lazy_path: LazyPath) void { |
| 2815 | } | 2840 | } |
| 2816 | } | 2841 | } |
| 2817 | 2842 | ||
| 2843 | /// Build system implementation detail. | ||
| 2844 | pub fn serializeConfigurationExiting(b: *Build) noreturn { | ||
| 2845 | const graph = b.graph; | ||
| 2846 | const io = graph.io; | ||
| 2847 | |||
| 2848 | var stdout_buffer: [1024]u8 = undefined; | ||
| 2849 | var file_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); | ||
| 2850 | Serialize.write(b, &graph.wip_configuration, &file_writer.interface) catch |err| switch (err) { | ||
| 2851 | error.WriteFailed => fatal("failed to write configuration output: {t}", .{file_writer.err.?}), | ||
| 2852 | error.OutOfMemory => @panic("OOM"), | ||
| 2853 | }; | ||
| 2854 | file_writer.flush() catch |err| fatal("failed to write configuration output: {t}", .{err}); | ||
| 2855 | |||
| 2856 | // This executable is short-lived and run in Debug mode, so we'd rather | ||
| 2857 | // have `zig build` run faster than catch resource leaks in the user's | ||
| 2858 | // build.zig script (or, frankly, this configure runner), therefore we call | ||
| 2859 | // exit directly here rather than cleanExit. | ||
| 2860 | process.exit(0); | ||
| 2861 | } | ||
| 2862 | |||
| 2818 | test { | 2863 | test { |
| 2819 | _ = Cache; | 2864 | _ = Cache; |
| 2820 | _ = Configuration; | 2865 | _ = Configuration; |
lib/std/Build/Serialize.zig created+1252| ... | @@ -0,0 +1,1252 @@ | ||
| 1 | const Serialize = @This(); | ||
| 2 | |||
| 3 | const std = @import("std"); | ||
| 4 | const Allocator = std.mem.Allocator; | ||
| 5 | const Configuration = std.Build.Configuration; | ||
| 6 | const Step = std.Build.Step; | ||
| 7 | const assert = std.debug.assert; | ||
| 8 | const log = std.log; | ||
| 9 | |||
| 10 | arena: Allocator, | ||
| 11 | wc: *Configuration.Wip, | ||
| 12 | module_map: std.array_hash_map.Auto(*std.Build.Module, Configuration.Module.Index) = .empty, | ||
| 13 | package_map: std.array_hash_map.Auto(*std.Build, Configuration.Package.Index) = .empty, | ||
| 14 | /// Index corresponds to `Configuration.steps` index. | ||
| 15 | step_map: std.array_hash_map.Auto(*Step, void) = .empty, | ||
| 16 | |||
| 17 | pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !void { | ||
| 18 | const graph = b.graph; | ||
| 19 | const arena = graph.arena; | ||
| 20 | const gpa = wc.gpa; | ||
| 21 | |||
| 22 | var s: Serialize = .{ .wc = wc, .arena = arena }; | ||
| 23 | |||
| 24 | try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len); | ||
| 25 | for ( | ||
| 26 | graph.configure_dependencies.items, | ||
| 27 | wc.path_deps.addManyAsSliceAssumeCapacity(graph.configure_dependencies.items.len), | ||
| 28 | ) |src, *dest| { | ||
| 29 | dest.* = .{ | ||
| 30 | .flags = .{ | ||
| 31 | .base = switch (src.lazy_path) { | ||
| 32 | .src_path, .dependency => .build_root, | ||
| 33 | .generated => unreachable, | ||
| 34 | .cwd_relative => .cwd, | ||
| 35 | .relative => |r| r.base, | ||
| 36 | }, | ||
| 37 | .mode = src.mode, | ||
| 38 | }, | ||
| 39 | .sub = switch (src.lazy_path) { | ||
| 40 | .src_path => |sp| try wc.addString(sp.sub_path), | ||
| 41 | .generated => unreachable, | ||
| 42 | .cwd_relative => |sub_path| try wc.addString(sub_path), | ||
| 43 | .dependency => |d| try wc.addString(d.sub_path), | ||
| 44 | .relative => |r| try wc.addString(r.sub_path), | ||
| 45 | }, | ||
| 46 | .pkg = switch (src.lazy_path) { | ||
| 47 | .src_path => |sp| .init(try s.builderToPackage(sp.owner)), | ||
| 48 | .generated => unreachable, | ||
| 49 | .cwd_relative, .relative => .none, | ||
| 50 | .dependency => |d| .init(try s.builderToPackage(d.dependency.builder)), | ||
| 51 | }, | ||
| 52 | }; | ||
| 53 | } | ||
| 54 | |||
| 55 | // Starting from all top-level steps in `b`, traverse the entire step graph | ||
| 56 | // and add all step dependencies implied by module graphs. | ||
| 57 | const top_level_steps = b.top_level_steps.values(); | ||
| 58 | try s.step_map.ensureUnusedCapacity(arena, top_level_steps.len); | ||
| 59 | for (top_level_steps) |tls| { | ||
| 60 | s.step_map.putAssumeCapacityNoClobber(&tls.step, {}); | ||
| 61 | } | ||
| 62 | { | ||
| 63 | while (wc.steps.items.len < s.step_map.count()) { | ||
| 64 | const step = s.step_map.keys()[wc.steps.items.len]; | ||
| 65 | |||
| 66 | // Set up any implied dependencies for this step. It's important that we do this first, so | ||
| 67 | // that the loop below discovers steps implied by the module graph. | ||
| 68 | try createModuleDependenciesForStep(step); | ||
| 69 | |||
| 70 | try s.step_map.ensureUnusedCapacity(arena, step.dependencies.items.len); | ||
| 71 | for (step.dependencies.items) |other_step| { | ||
| 72 | s.step_map.putAssumeCapacity(other_step, {}); | ||
| 73 | } | ||
| 74 | |||
| 75 | // Add and then de-duplicate dependencies. | ||
| 76 | const dep_steps = try arena.alloc(Configuration.Step.Index, step.dependencies.items.len); | ||
| 77 | for (dep_steps, step.dependencies.items) |*dest, src| | ||
| 78 | dest.* = @enumFromInt(s.step_map.getIndex(src).?); | ||
| 79 | |||
| 80 | const deps: Configuration.Deps.Index = try wc.addDeduped(Configuration.Deps, .{ | ||
| 81 | .steps = .{ .slice = dep_steps }, | ||
| 82 | }); | ||
| 83 | |||
| 84 | try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity); | ||
| 85 | wc.steps.appendAssumeCapacity(.{ | ||
| 86 | .name = try wc.addString(step.name), | ||
| 87 | .owner = try s.builderToPackage(step.owner), | ||
| 88 | .deps = deps, | ||
| 89 | .max_rss = .fromBytes(step.max_rss), | ||
| 90 | .extended = @enumFromInt(switch (step.tag) { | ||
| 91 | .top_level => e: { | ||
| 92 | const top_level: *Step.TopLevel = @fieldParentPtr("step", step); | ||
| 93 | break :e try wc.addExtraErased(Configuration.Step.TopLevel, .{ | ||
| 94 | .description = try wc.addString(top_level.description), | ||
| 95 | }); | ||
| 96 | }, | ||
| 97 | .compile => e: { | ||
| 98 | const c: *Step.Compile = @fieldParentPtr("step", step); | ||
| 99 | const installed_headers: []u32 = try arena.alloc(u32, c.installed_headers.items.len); | ||
| 100 | for (installed_headers, c.installed_headers.items) |*dst, src| switch (src) { | ||
| 101 | .file => |file| { | ||
| 102 | dst.* = try wc.addExtraErased(Configuration.Step.Compile.InstalledHeader.File, .{ | ||
| 103 | .source = try s.addLazyPath(file.source), | ||
| 104 | .dest_sub_path = try wc.addString(file.dest_rel_path), | ||
| 105 | }); | ||
| 106 | }, | ||
| 107 | .directory => |directory| { | ||
| 108 | const include_extensions = directory.options.include_extensions orelse &.{}; | ||
| 109 | dst.* = try wc.addExtraErased(Configuration.Step.Compile.InstalledHeader.Directory, .{ | ||
| 110 | .flags = .{ | ||
| 111 | .include_extensions = include_extensions.len != 0, | ||
| 112 | .exclude_extensions = directory.options.exclude_extensions.len != 0, | ||
| 113 | }, | ||
| 114 | .source = try s.addLazyPath(directory.source), | ||
| 115 | .dest_sub_path = try wc.addString(directory.dest_rel_path), | ||
| 116 | .exclude_extensions = .{ .slice = try s.initStringList(directory.options.exclude_extensions) }, | ||
| 117 | .include_extensions = .{ .slice = try s.initStringList(include_extensions) }, | ||
| 118 | }); | ||
| 119 | }, | ||
| 120 | }; | ||
| 121 | |||
| 122 | break :e try wc.addExtraErased(Configuration.Step.Compile, .{ | ||
| 123 | .flags = .{ | ||
| 124 | .filters_len = c.filters.len != 0, | ||
| 125 | .installed_headers_len = installed_headers.len != 0, | ||
| 126 | .force_undefined_symbols_len = c.force_undefined_symbols.entries.len != 0, | ||
| 127 | |||
| 128 | .verbose_link = c.verbose_link, | ||
| 129 | .verbose_cc = c.verbose_cc, | ||
| 130 | .rdynamic = c.rdynamic, | ||
| 131 | .import_memory = c.import_memory, | ||
| 132 | .export_memory = c.export_memory, | ||
| 133 | .import_symbols = c.import_symbols, | ||
| 134 | .import_table = c.import_table, | ||
| 135 | .export_table = c.export_table, | ||
| 136 | .shared_memory = c.shared_memory, | ||
| 137 | .link_eh_frame_hdr = c.link_eh_frame_hdr, | ||
| 138 | .link_emit_relocs = c.link_emit_relocs, | ||
| 139 | .link_function_sections = c.link_function_sections, | ||
| 140 | .link_data_sections = c.link_data_sections, | ||
| 141 | .linker_dynamicbase = c.linker_dynamicbase, | ||
| 142 | .link_z_notext = c.link_z_notext, | ||
| 143 | .link_z_relro = c.link_z_relro, | ||
| 144 | .link_z_lazy = c.link_z_lazy, | ||
| 145 | .link_z_defs = c.link_z_defs, | ||
| 146 | .headerpad_max_install_names = c.headerpad_max_install_names, | ||
| 147 | .dead_strip_dylibs = c.dead_strip_dylibs, | ||
| 148 | .force_load_objc = c.force_load_objc, | ||
| 149 | .discard_local_symbols = c.discard_local_symbols, | ||
| 150 | .mingw_unicode_entry_point = c.mingw_unicode_entry_point, | ||
| 151 | }, | ||
| 152 | .flags2 = .{ | ||
| 153 | .pie = .init(c.pie), | ||
| 154 | .formatted_panics = .init(c.formatted_panics), | ||
| 155 | .bundle_compiler_rt = .init(c.bundle_compiler_rt), | ||
| 156 | .bundle_ubsan_rt = .init(c.bundle_ubsan_rt), | ||
| 157 | .each_lib_rpath = .init(c.each_lib_rpath), | ||
| 158 | .link_gc_sections = .init(c.link_gc_sections), | ||
| 159 | .linker_allow_shlib_undefined = .init(c.linker_allow_shlib_undefined), | ||
| 160 | .linker_allow_undefined_version = .init(c.linker_allow_undefined_version), | ||
| 161 | .linker_enable_new_dtags = .init(c.linker_enable_new_dtags), | ||
| 162 | .dll_export_fns = .init(c.dll_export_fns), | ||
| 163 | .use_llvm = .init(c.use_llvm), | ||
| 164 | .use_lld = .init(c.use_lld), | ||
| 165 | .use_new_linker = .init(c.use_new_linker), | ||
| 166 | .allow_so_scripts = .init(c.allow_so_scripts), | ||
| 167 | .sanitize_coverage_trace_pc_guard = .init(c.sanitize_coverage_trace_pc_guard), | ||
| 168 | .linkage = .init(c.linkage), | ||
| 169 | }, | ||
| 170 | .flags3 = .{ | ||
| 171 | .is_linking_libc = c.is_linking_libc, | ||
| 172 | .is_linking_libcpp = c.is_linking_libcpp, | ||
| 173 | .version = c.version != null, | ||
| 174 | .compress_debug_sections = c.compress_debug_sections, | ||
| 175 | .initial_memory = c.initial_memory != null, | ||
| 176 | .max_memory = c.max_memory != null, | ||
| 177 | .kind = c.kind, | ||
| 178 | .global_base = c.global_base != null, | ||
| 179 | .test_runner = if (c.test_runner) |tr| switch (tr.mode) { | ||
| 180 | .simple => .simple, | ||
| 181 | .server => .server, | ||
| 182 | } else .default, | ||
| 183 | .wasi_exec_model = .init(c.wasi_exec_model), | ||
| 184 | .win32_manifest = c.win32_manifest != null, | ||
| 185 | .win32_module_definition = c.win32_module_definition != null, | ||
| 186 | .zig_lib_dir = c.zig_lib_dir != null, | ||
| 187 | .rc_includes = c.rc_includes, | ||
| 188 | .image_base = c.image_base != null, | ||
| 189 | .build_id = .init(c.build_id), | ||
| 190 | .entry = switch (c.entry) { | ||
| 191 | .default => .default, | ||
| 192 | .disabled => .disabled, | ||
| 193 | .enabled => .enabled, | ||
| 194 | .symbol_name => .symbol_name, | ||
| 195 | }, | ||
| 196 | .lto = .init(c.lto), | ||
| 197 | .subsystem = .init(c.subsystem), | ||
| 198 | }, | ||
| 199 | .flags4 = .{ | ||
| 200 | .libc_file = c.libc_file != null, | ||
| 201 | .link_z_common_page_size = c.link_z_common_page_size != null, | ||
| 202 | .link_z_max_page_size = c.link_z_max_page_size != null, | ||
| 203 | .pagezero_size = c.pagezero_size != null, | ||
| 204 | .stack_size = c.stack_size != null, | ||
| 205 | .headerpad_size = c.headerpad_size != null, | ||
| 206 | .error_limit = c.error_limit != null, | ||
| 207 | .install_name = c.install_name != null, | ||
| 208 | .entitlements = c.entitlements != null, | ||
| 209 | .expect_errors = if (c.expect_errors) |x| switch (x) { | ||
| 210 | .contains => .contains, | ||
| 211 | .exact => .exact, | ||
| 212 | .starts_with => .starts_with, | ||
| 213 | .stderr_contains => .stderr_contains, | ||
| 214 | } else .none, | ||
| 215 | .linker_script = c.linker_script != null, | ||
| 216 | .version_script = c.version_script != null, | ||
| 217 | .emit_directory = c.emit_directory != .none, | ||
| 218 | .generated_docs = c.generated_docs != .none, | ||
| 219 | .generated_asm = c.generated_asm != .none, | ||
| 220 | .generated_bin = c.generated_bin != .none, | ||
| 221 | .generated_pdb = c.generated_pdb != .none, | ||
| 222 | .generated_implib = c.generated_implib != .none, | ||
| 223 | .generated_llvm_bc = c.generated_llvm_bc != .none, | ||
| 224 | .generated_llvm_ir = c.generated_llvm_ir != .none, | ||
| 225 | .generated_h = c.generated_h != .none, | ||
| 226 | .incremental = .init(c.incremental), | ||
| 227 | }, | ||
| 228 | .root_module = try s.addModule(c.root_module), | ||
| 229 | .root_name = try wc.addString(c.name), | ||
| 230 | .linker_script = .{ .value = try s.addOptionalLazyPath(c.linker_script) }, | ||
| 231 | .version_script = .{ .value = try s.addOptionalLazyPath(c.version_script) }, | ||
| 232 | .zig_lib_dir = .{ .value = try s.addOptionalLazyPath(c.zig_lib_dir) }, | ||
| 233 | .libc_file = .{ .value = try s.addOptionalLazyPath(c.libc_file) }, | ||
| 234 | .win32_manifest = .{ .value = try s.addOptionalLazyPath(c.win32_manifest) }, | ||
| 235 | .win32_module_definition = .{ .value = try s.addOptionalLazyPath(c.win32_module_definition) }, | ||
| 236 | .entitlements = .{ .value = try s.addOptionalLazyPath(c.entitlements) }, | ||
| 237 | .version = .{ .value = try s.addOptionalSemVer(c.version) }, | ||
| 238 | .install_name = .{ .value = try s.addOptionalString(c.install_name) }, | ||
| 239 | .initial_memory = .{ .value = c.initial_memory }, | ||
| 240 | .max_memory = .{ .value = c.max_memory }, | ||
| 241 | .global_base = .{ .value = c.global_base }, | ||
| 242 | .image_base = .{ .value = c.image_base }, | ||
| 243 | .link_z_common_page_size = .{ .value = c.link_z_common_page_size }, | ||
| 244 | .link_z_max_page_size = .{ .value = c.link_z_max_page_size }, | ||
| 245 | .pagezero_size = .{ .value = c.pagezero_size }, | ||
| 246 | .stack_size = .{ .value = c.stack_size }, | ||
| 247 | .headerpad_size = .{ .value = c.headerpad_size }, | ||
| 248 | .error_limit = .{ .value = c.error_limit }, | ||
| 249 | .entry = .{ .value = switch (c.entry) { | ||
| 250 | .symbol_name => |name| try wc.addString(name), | ||
| 251 | .default, .disabled, .enabled => null, | ||
| 252 | } }, | ||
| 253 | .build_id = .{ .value = if (c.build_id) |id| switch (id) { | ||
| 254 | .hexstring => |*hexstring| try wc.addString(hexstring.toSlice()), | ||
| 255 | .none, .fast, .uuid, .sha1, .md5 => null, | ||
| 256 | } else null }, | ||
| 257 | .filters = .{ .slice = try s.initStringList(c.filters) }, | ||
| 258 | .installed_headers = .initErased(installed_headers), | ||
| 259 | .force_undefined_symbols = .{ .slice = try s.initStringList(c.force_undefined_symbols.keys()) }, | ||
| 260 | .expect_errors = .{ .u = if (c.expect_errors) |x| switch (x) { | ||
| 261 | .contains => |slice| .{ .contains = try wc.addString(slice) }, | ||
| 262 | .exact => |exact| .{ .exact = .{ .slice = try s.initStringList(exact) } }, | ||
| 263 | .starts_with => |slice| .{ .starts_with = try wc.addString(slice) }, | ||
| 264 | .stderr_contains => |slice| .{ .stderr_contains = try wc.addString(slice) }, | ||
| 265 | } else .none }, | ||
| 266 | .test_runner = .{ .u = if (c.test_runner) |tr| switch (tr.mode) { | ||
| 267 | .simple => .{ .simple = try s.addLazyPath(tr.path) }, | ||
| 268 | .server => .{ .server = try s.addLazyPath(tr.path) }, | ||
| 269 | } else .default }, | ||
| 270 | |||
| 271 | .emit_directory = .{ .value = c.emit_directory.unwrap() }, | ||
| 272 | .generated_docs = .{ .value = c.generated_docs.unwrap() }, | ||
| 273 | .generated_asm = .{ .value = c.generated_asm.unwrap() }, | ||
| 274 | .generated_bin = .{ .value = c.generated_bin.unwrap() }, | ||
| 275 | .generated_pdb = .{ .value = c.generated_pdb.unwrap() }, | ||
| 276 | .generated_implib = .{ .value = c.generated_implib.unwrap() }, | ||
| 277 | .generated_llvm_bc = .{ .value = c.generated_llvm_bc.unwrap() }, | ||
| 278 | .generated_llvm_ir = .{ .value = c.generated_llvm_ir.unwrap() }, | ||
| 279 | .generated_h = .{ .value = c.generated_h.unwrap() }, | ||
| 280 | }); | ||
| 281 | }, | ||
| 282 | .install_artifact => e: { | ||
| 283 | const ia: *Step.InstallArtifact = @fieldParentPtr("step", step); | ||
| 284 | break :e try wc.addExtraErased(Configuration.Step.InstallArtifact, .{ | ||
| 285 | .flags = .{ | ||
| 286 | .dylib_symlinks = ia.dylib_symlinks, | ||
| 287 | .bin_dir = ia.dest_dir != null, | ||
| 288 | .implib_dir = ia.implib_dir != null, | ||
| 289 | .pdb_dir = ia.pdb_dir != null, | ||
| 290 | .h_dir = ia.h_dir != null, | ||
| 291 | .bin_sub_path = ia.dest_sub_path != null, | ||
| 292 | }, | ||
| 293 | .bin_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.dest_dir) }, | ||
| 294 | .implib_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.implib_dir) }, | ||
| 295 | .pdb_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.pdb_dir) }, | ||
| 296 | .h_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.h_dir) }, | ||
| 297 | .bin_sub_path = .{ .value = try s.addOptionalString(ia.dest_sub_path) }, | ||
| 298 | }); | ||
| 299 | }, | ||
| 300 | .install_file => e: { | ||
| 301 | const sif: *Step.InstallFile = @fieldParentPtr("step", step); | ||
| 302 | break :e try wc.addExtraErased(Configuration.Step.InstallFile, .{ | ||
| 303 | .source = try s.addLazyPath(sif.source), | ||
| 304 | .dest_dir = try addInstallDir(wc, sif.dir), | ||
| 305 | .dest_sub_path = try wc.addString(sif.dest_rel_path), | ||
| 306 | }); | ||
| 307 | }, | ||
| 308 | .install_dir => e: { | ||
| 309 | const sid: *Step.InstallDir = @fieldParentPtr("step", step); | ||
| 310 | const dest_sub_path: ?[]const u8 = if (sid.options.install_subdir.len != 0) | ||
| 311 | sid.options.install_subdir | ||
| 312 | else | ||
| 313 | null; | ||
| 314 | const include_extensions = sid.options.include_extensions orelse &.{}; | ||
| 315 | break :e try wc.addExtraErased(Configuration.Step.InstallDir, .{ | ||
| 316 | .flags = .{ | ||
| 317 | .dest_sub_path = dest_sub_path != null, | ||
| 318 | .exclude_extensions = sid.options.exclude_extensions.len != 0, | ||
| 319 | .include_extensions = include_extensions.len != 0, | ||
| 320 | .include_extensions_active = sid.options.include_extensions != null, | ||
| 321 | .blank_extensions = sid.options.blank_extensions.len != 0, | ||
| 322 | }, | ||
| 323 | .source_dir = try s.addLazyPath(sid.options.source_dir), | ||
| 324 | .dest_dir = try addInstallDir(wc, sid.options.install_dir), | ||
| 325 | .dest_sub_path = .{ .value = try s.addOptionalString(dest_sub_path) }, | ||
| 326 | .exclude_extensions = .{ .slice = try s.initStringList(sid.options.exclude_extensions) }, | ||
| 327 | .include_extensions = .{ .slice = try s.initStringList(include_extensions) }, | ||
| 328 | .blank_extensions = .{ .slice = try s.initStringList(sid.options.blank_extensions) }, | ||
| 329 | }); | ||
| 330 | }, | ||
| 331 | .fail => e: { | ||
| 332 | const sf: *Step.Fail = @fieldParentPtr("step", step); | ||
| 333 | break :e try wc.addExtraErased(Configuration.Step.Fail, .{ | ||
| 334 | .msg = sf.error_msg, | ||
| 335 | }); | ||
| 336 | }, | ||
| 337 | .find_program => e: { | ||
| 338 | const fp: *Step.FindProgram = @fieldParentPtr("step", step); | ||
| 339 | break :e try wc.addExtraErased(Configuration.Step.FindProgram, .{ | ||
| 340 | .names = fp.names, | ||
| 341 | .found_path = fp.found_path, | ||
| 342 | }); | ||
| 343 | }, | ||
| 344 | .fmt => e: { | ||
| 345 | const sf: *Step.Fmt = @fieldParentPtr("step", step); | ||
| 346 | break :e try wc.addExtraErased(Configuration.Step.Fmt, .{ | ||
| 347 | .flags = .{ | ||
| 348 | .paths = sf.paths.len != 0, | ||
| 349 | .exclude_paths = sf.exclude_paths.len != 0, | ||
| 350 | .check = sf.check, | ||
| 351 | }, | ||
| 352 | .paths = .{ .slice = try s.initLazyPathList(sf.paths) }, | ||
| 353 | .exclude_paths = .{ .slice = try s.initLazyPathList(sf.exclude_paths) }, | ||
| 354 | }); | ||
| 355 | }, | ||
| 356 | .translate_c => e: { | ||
| 357 | const tc: *Step.TranslateC = @fieldParentPtr("step", step); | ||
| 358 | |||
| 359 | const system_libs = try arena.alloc(Configuration.SystemLib.Index, tc.system_libs.items.len); | ||
| 360 | for (system_libs, tc.system_libs.items) |*dest, *src| dest.* = try s.addSystemLib(src); | ||
| 361 | |||
| 362 | break :e try wc.addExtraErased(Configuration.Step.TranslateC, .{ | ||
| 363 | .flags = .{ | ||
| 364 | .include_dirs = tc.include_dirs.items.len != 0, | ||
| 365 | .system_libs = system_libs.len != 0, | ||
| 366 | .c_macros = tc.c_macros.items.len != 0, | ||
| 367 | .link_libc = tc.link_libc, | ||
| 368 | .optimize = .init(tc.optimize), | ||
| 369 | }, | ||
| 370 | .src_path = try s.addLazyPath(tc.source), | ||
| 371 | .output_file = tc.output_file, | ||
| 372 | .include_dirs = .init(try s.initIncludeDirList(tc.include_dirs.items)), | ||
| 373 | .system_libs = .{ .slice = system_libs }, | ||
| 374 | .c_macros = .{ .slice = tc.c_macros.items }, | ||
| 375 | .target = try addOptionalResolvedTarget(wc, tc.target), | ||
| 376 | }); | ||
| 377 | }, | ||
| 378 | .write_file => e: { | ||
| 379 | const wf: *Step.WriteFile = @fieldParentPtr("step", step); | ||
| 380 | |||
| 381 | const directories = try arena.alloc( | ||
| 382 | Configuration.Step.WriteFile.Directory, | ||
| 383 | wf.directories.items.len, | ||
| 384 | ); | ||
| 385 | for (directories, wf.directories.items) |*dest, src| dest.* = .{ | ||
| 386 | .sub_path = src.sub_path, | ||
| 387 | .src_path = try s.addLazyPath(src.src_path), | ||
| 388 | .exclude_extensions = src.exclude_extensions, | ||
| 389 | .include_extensions = src.include_extensions, | ||
| 390 | }; | ||
| 391 | |||
| 392 | break :e try wc.addExtraErased(Configuration.Step.WriteFile, .{ | ||
| 393 | .flags = .{ | ||
| 394 | .embeds = wf.embeds.items.len != 0, | ||
| 395 | .copies = wf.copies.items.len != 0, | ||
| 396 | .directories = directories.len != 0, | ||
| 397 | .mode = switch (wf.mode) { | ||
| 398 | .whole_cached => .whole_cached, | ||
| 399 | .tmp => .tmp, | ||
| 400 | .mutate => .mutate, | ||
| 401 | }, | ||
| 402 | }, | ||
| 403 | .generated_directory = wf.generated_directory, | ||
| 404 | .embeds = .{ .slice = wf.embeds.items }, | ||
| 405 | .copies = .{ .slice = try s.initCopyList(wf.copies.items) }, | ||
| 406 | .directories = .{ .slice = directories }, | ||
| 407 | .mutate_path = .{ .value = switch (wf.mode) { | ||
| 408 | .mutate => |lp| try s.addLazyPath(lp), | ||
| 409 | .whole_cached, .tmp => null, | ||
| 410 | } }, | ||
| 411 | }); | ||
| 412 | }, | ||
| 413 | .update_source_files => e: { | ||
| 414 | const usf: *Step.UpdateSourceFiles = @fieldParentPtr("step", step); | ||
| 415 | break :e try wc.addExtraErased(Configuration.Step.UpdateSourceFiles, .{ | ||
| 416 | .flags = .{ | ||
| 417 | .embeds = usf.embeds.items.len != 0, | ||
| 418 | .copies = usf.copies.items.len != 0, | ||
| 419 | }, | ||
| 420 | .embeds = .{ .slice = usf.embeds.items }, | ||
| 421 | .copies = .{ .slice = try s.initCopyList(usf.copies.items) }, | ||
| 422 | }); | ||
| 423 | }, | ||
| 424 | .run => e: { | ||
| 425 | const run: *Step.Run = @fieldParentPtr("step", step); | ||
| 426 | var expect_stderr_exact: ?Configuration.Bytes = null; | ||
| 427 | var expect_stdout_exact: ?Configuration.Bytes = null; | ||
| 428 | var expect_stderr_match: std.ArrayList(Configuration.Bytes) = .empty; | ||
| 429 | var expect_stdout_match: std.ArrayList(Configuration.Bytes) = .empty; | ||
| 430 | var expect_term: ?struct { | ||
| 431 | status: Configuration.Step.Run.ExpectTermStatus, | ||
| 432 | value: u32, | ||
| 433 | } = null; | ||
| 434 | var expect_stderr_snapshot: ?Configuration.LazyPath.Index = null; | ||
| 435 | var expect_stdout_snapshot: ?Configuration.LazyPath.Index = null; | ||
| 436 | switch (run.stdio) { | ||
| 437 | .check => |checks| for (checks.items) |check| switch (check) { | ||
| 438 | .expect_stderr_exact => |bytes| expect_stderr_exact = try wc.addBytes(bytes), | ||
| 439 | .expect_stdout_exact => |bytes| expect_stdout_exact = try wc.addBytes(bytes), | ||
| 440 | .expect_stderr_match => |bytes| { | ||
| 441 | try expect_stderr_match.append(arena, try wc.addBytes(bytes)); | ||
| 442 | }, | ||
| 443 | .expect_stdout_match => |bytes| { | ||
| 444 | try expect_stdout_match.append(arena, try wc.addBytes(bytes)); | ||
| 445 | }, | ||
| 446 | .expect_term => |t| expect_term = switch (t) { | ||
| 447 | .exited => |x| .{ .status = .exited, .value = x }, | ||
| 448 | .signal => |x| .{ .status = .signal, .value = @intFromEnum(x) }, | ||
| 449 | .stopped => |x| .{ .status = .stopped, .value = @intFromEnum(x) }, | ||
| 450 | .unknown => |x| .{ .status = .unknown, .value = x }, | ||
| 451 | }, | ||
| 452 | .expect_stderr_snapshot => |path| expect_stderr_snapshot = try s.addLazyPath(path), | ||
| 453 | .expect_stdout_snapshot => |path| expect_stdout_snapshot = try s.addLazyPath(path), | ||
| 454 | }, | ||
| 455 | else => {}, | ||
| 456 | } | ||
| 457 | |||
| 458 | break :e try wc.addExtraErased(Configuration.Step.Run, .{ | ||
| 459 | .flags = .{ | ||
| 460 | .disable_zig_progress = run.disable_zig_progress, | ||
| 461 | .skip_foreign_checks = run.skip_foreign_checks, | ||
| 462 | .failing_to_execute_foreign_is_an_error = run.failing_to_execute_foreign_is_an_error, | ||
| 463 | .has_side_effects = run.has_side_effects, | ||
| 464 | .test_runner_mode = run.test_runner_mode, | ||
| 465 | .color = run.color, | ||
| 466 | .stdio = switch (run.stdio) { | ||
| 467 | .infer_from_args => .infer_from_args, | ||
| 468 | .inherit => .inherit, | ||
| 469 | .check => .check, | ||
| 470 | .zig_test => .zig_test, | ||
| 471 | }, | ||
| 472 | .stdin = switch (run.stdin) { | ||
| 473 | .none => .none, | ||
| 474 | .bytes => .bytes, | ||
| 475 | .lazy_path => .lazy_path, | ||
| 476 | }, | ||
| 477 | .stdout_trim_whitespace = if (run.captured_stdout) |cs| cs.trim_whitespace else .none, | ||
| 478 | .stderr_trim_whitespace = if (run.captured_stderr) |cs| cs.trim_whitespace else .none, | ||
| 479 | .stdio_limit = run.stdio_limit != .unlimited, | ||
| 480 | .producer = run.producer != null, | ||
| 481 | .cwd = run.cwd != null, | ||
| 482 | .captured_stdout = run.captured_stdout != null, | ||
| 483 | .captured_stderr = run.captured_stderr != null, | ||
| 484 | .environ_map = run.environ_map != null, | ||
| 485 | }, | ||
| 486 | .flags2 = .{ | ||
| 487 | .expect_stderr_exact = expect_stderr_exact != null, | ||
| 488 | .expect_stdout_exact = expect_stdout_exact != null, | ||
| 489 | .expect_stderr_match = expect_stderr_match.items.len != 0, | ||
| 490 | .expect_stdout_match = expect_stdout_match.items.len != 0, | ||
| 491 | .expect_term = expect_term != null, | ||
| 492 | .expect_term_status = if (expect_term) |t| t.status else .exited, | ||
| 493 | .expect_stderr_snapshot = expect_stderr_snapshot != null, | ||
| 494 | .expect_stdout_snapshot = expect_stdout_snapshot != null, | ||
| 495 | }, | ||
| 496 | .file_inputs = .{ .slice = try s.initLazyPathList(run.file_inputs.items) }, | ||
| 497 | .args = .{ .slice = try s.initArgsList(run.argv.items) }, | ||
| 498 | .cwd = .{ .value = try s.addOptionalLazyPath(run.cwd) }, | ||
| 499 | .preopen_names = .{ .slice = try s.initStringList(run.preopens.keys()) }, | ||
| 500 | .preopen_paths = .{ .slice = try s.initLazyPathList(run.preopens.values()) }, | ||
| 501 | .captured_stdout = .{ .value = if (run.captured_stdout) |cs| .{ | ||
| 502 | .basename = try wc.addString(cs.basename), | ||
| 503 | .generated_file = cs.generated_file, | ||
| 504 | } else null }, | ||
| 505 | .captured_stderr = .{ .value = if (run.captured_stderr) |cs| .{ | ||
| 506 | .basename = try wc.addString(cs.basename), | ||
| 507 | .generated_file = cs.generated_file, | ||
| 508 | } else null }, | ||
| 509 | .environ_map = .{ .value = try s.addEnvironMap(run.environ_map) }, | ||
| 510 | .expect_term_value = .{ .value = if (expect_term) |t| t.value else null }, | ||
| 511 | .stdio_limit = .{ .value = run.stdio_limit.toInt64() }, | ||
| 512 | .producer = .{ .value = if (run.producer) |cs| s.stepIndex(&cs.step) else null }, | ||
| 513 | .expect_stderr_exact = .{ .value = if (expect_stderr_exact) |bytes| bytes else null }, | ||
| 514 | .expect_stdout_exact = .{ .value = if (expect_stdout_exact) |bytes| bytes else null }, | ||
| 515 | .expect_stderr_match = .{ .slice = expect_stderr_match.items }, | ||
| 516 | .expect_stdout_match = .{ .slice = expect_stdout_match.items }, | ||
| 517 | .expect_stderr_snapshot = .{ .value = expect_stderr_snapshot orelse null }, | ||
| 518 | .expect_stdout_snapshot = .{ .value = expect_stdout_snapshot orelse null }, | ||
| 519 | .stdin = .{ .u = switch (run.stdin) { | ||
| 520 | .none => .none, | ||
| 521 | .bytes => |bytes| .{ .bytes = try wc.addBytes(bytes) }, | ||
| 522 | .lazy_path => |lp| .{ .lazy_path = try s.addLazyPath(lp) }, | ||
| 523 | } }, | ||
| 524 | }); | ||
| 525 | }, | ||
| 526 | .check_file => e: { | ||
| 527 | const cf: *Step.CheckFile = @fieldParentPtr("step", step); | ||
| 528 | break :e try wc.addExtraErased(Configuration.Step.CheckFile, .{ | ||
| 529 | .flags = .{ | ||
| 530 | .expected_exact = cf.expected_exact != null, | ||
| 531 | .expected_matches = cf.expected_matches.len != 0, | ||
| 532 | .max_bytes = cf.max_bytes != null, | ||
| 533 | }, | ||
| 534 | .file = try s.addLazyPath(cf.file), | ||
| 535 | .expected_exact = .{ .value = cf.expected_exact }, | ||
| 536 | .expected_matches = .{ .slice = cf.expected_matches }, | ||
| 537 | .max_bytes = .{ .value = cf.max_bytes }, | ||
| 538 | }); | ||
| 539 | }, | ||
| 540 | .config_header => e: { | ||
| 541 | const ch: *Step.ConfigHeader = @fieldParentPtr("step", step); | ||
| 542 | const lazy_path: ?std.Build.LazyPath = ch.style.getPath(); | ||
| 543 | const pairs = try arena.alloc(Configuration.Step.ConfigHeader.Value.Pair, ch.values.count()); | ||
| 544 | for (pairs, ch.values.keys(), ch.values.values()) |*pair, key, value| pair.* = .{ | ||
| 545 | .key = try wc.addString(key), | ||
| 546 | .index = switch (value) { | ||
| 547 | .undef => .undef, | ||
| 548 | .defined => .defined, | ||
| 549 | .boolean => |x| switch (x) { | ||
| 550 | false => .bool_false, | ||
| 551 | true => .bool_true, | ||
| 552 | }, | ||
| 553 | .int => |x| switch (x) { | ||
| 554 | 0 => .int_0, | ||
| 555 | 1 => .int_1, | ||
| 556 | else => try wc.addExtra(Configuration.Step.ConfigHeader.Value, .initSigned(x)), | ||
| 557 | }, | ||
| 558 | .ident => |x| try wc.addExtra(Configuration.Step.ConfigHeader.Value, .{ | ||
| 559 | .flags = .{ | ||
| 560 | .tag = .ident, | ||
| 561 | .small = 0, | ||
| 562 | }, | ||
| 563 | .i64 = .{ .value = null }, | ||
| 564 | .u64 = .{ .value = null }, | ||
| 565 | .ident = .{ .value = try wc.addString(x) }, | ||
| 566 | .string = .{ .value = null }, | ||
| 567 | }), | ||
| 568 | .string => |x| try wc.addExtra(Configuration.Step.ConfigHeader.Value, .{ | ||
| 569 | .flags = .{ | ||
| 570 | .tag = .string, | ||
| 571 | .small = 0, | ||
| 572 | }, | ||
| 573 | .i64 = .{ .value = null }, | ||
| 574 | .u64 = .{ .value = null }, | ||
| 575 | .ident = .{ .value = null }, | ||
| 576 | .string = .{ .value = try wc.addString(x) }, | ||
| 577 | }), | ||
| 578 | }, | ||
| 579 | }; | ||
| 580 | break :e try wc.addExtraErased(Configuration.Step.ConfigHeader, .{ | ||
| 581 | .flags = .{ | ||
| 582 | .template_file = lazy_path != null, | ||
| 583 | .style = .init(ch.style), | ||
| 584 | .input_size_limit = ch.input_size_limit != null, | ||
| 585 | .include_guard = ch.include_guard != .none, | ||
| 586 | }, | ||
| 587 | .template_file = .{ .value = try s.addOptionalLazyPath(lazy_path) }, | ||
| 588 | .generated_dir = ch.generated_dir, | ||
| 589 | .input_size_limit = .{ .value = ch.input_size_limit }, | ||
| 590 | .include_path = try wc.addString(ch.include_path), | ||
| 591 | .include_guard = .{ .value = ch.include_guard.unwrap() }, | ||
| 592 | .values = .{ .slice = pairs }, | ||
| 593 | }); | ||
| 594 | }, | ||
| 595 | .obj_copy => e: { | ||
| 596 | const oc: *Step.ObjCopy = @fieldParentPtr("step", step); | ||
| 597 | |||
| 598 | const debug_basename: ?Configuration.String = if (oc.debug_file) |df| | ||
| 599 | df.basename.unwrap() | ||
| 600 | else | ||
| 601 | null; | ||
| 602 | |||
| 603 | const debug_file: ?Configuration.GeneratedFileIndex = if (oc.debug_file) |df| | ||
| 604 | df.output_file | ||
| 605 | else | ||
| 606 | null; | ||
| 607 | |||
| 608 | const add_sections = try arena.alloc( | ||
| 609 | Configuration.Step.ObjCopy.AddSection, | ||
| 610 | oc.add_sections.items.len, | ||
| 611 | ); | ||
| 612 | for (add_sections, oc.add_sections.items) |*dest, src| dest.* = .{ | ||
| 613 | .section_name = src.section_name, | ||
| 614 | .file_path = try s.addLazyPath(src.file_path), | ||
| 615 | }; | ||
| 616 | |||
| 617 | break :e try wc.addExtraErased(Configuration.Step.ObjCopy, .{ | ||
| 618 | .flags = .{ | ||
| 619 | .basename = oc.basename != .none, | ||
| 620 | .debug_file = debug_file != null, | ||
| 621 | .debug_basename = debug_basename != null, | ||
| 622 | .format = .init(oc.format), | ||
| 623 | .strip = oc.strip, | ||
| 624 | .compress_debug = oc.compress_debug, | ||
| 625 | .only_section = oc.only_section != .none, | ||
| 626 | .pad_to = oc.pad_to != null, | ||
| 627 | .add_section = add_sections.len != 0, | ||
| 628 | .update_section = oc.update_sections.items.len != 0, | ||
| 629 | }, | ||
| 630 | .input_file = try s.addLazyPath(oc.input_file), | ||
| 631 | .output_file = oc.output_file, | ||
| 632 | .basename = .{ .value = oc.basename.unwrap() }, | ||
| 633 | .debug_file = .{ .value = debug_file }, | ||
| 634 | .debug_basename = .{ .value = debug_basename }, | ||
| 635 | .only_section = .{ .value = oc.only_section.unwrap() }, | ||
| 636 | .pad_to = .{ .value = oc.pad_to }, | ||
| 637 | .add_section = .{ .slice = add_sections }, | ||
| 638 | .update_section = .{ .slice = oc.update_sections.items }, | ||
| 639 | }); | ||
| 640 | }, | ||
| 641 | .options => e: { | ||
| 642 | const so: *Step.Options = @fieldParentPtr("step", step); | ||
| 643 | |||
| 644 | const args = try arena.alloc(Configuration.Step.Options.Arg, so.args.items.len); | ||
| 645 | for (args, so.args.items) |*dest, src| dest.* = .{ | ||
| 646 | .name = src.name, | ||
| 647 | .path = try s.addLazyPath(src.path), | ||
| 648 | }; | ||
| 649 | |||
| 650 | break :e try wc.addExtraErased(Configuration.Step.Options, .{ | ||
| 651 | .flags = .{ | ||
| 652 | .args = so.args.items.len != 0, | ||
| 653 | }, | ||
| 654 | .generated_file = so.generated_file, | ||
| 655 | .contents = try wc.addBytes(so.contents.items), | ||
| 656 | .args = .{ .slice = args }, | ||
| 657 | }); | ||
| 658 | }, | ||
| 659 | }), | ||
| 660 | }); | ||
| 661 | } | ||
| 662 | } | ||
| 663 | |||
| 664 | try wc.unlazy_deps.ensureUnusedCapacity(gpa, graph.needed_lazy_dependencies.keys().len); | ||
| 665 | for (graph.needed_lazy_dependencies.keys()) |k| { | ||
| 666 | wc.unlazy_deps.appendAssumeCapacity(try wc.addString(k)); | ||
| 667 | } | ||
| 668 | |||
| 669 | try wc.write(writer, .{ | ||
| 670 | .default_step = s.stepIndex(b.default_step), | ||
| 671 | .generated_files_len = @intCast(graph.generated_files.items.len), | ||
| 672 | .poisoned = switch (graph.cache_poison) { | ||
| 673 | .pure, .disallowed, .ignored => false, | ||
| 674 | .poisoned => true, | ||
| 675 | }, | ||
| 676 | }); | ||
| 677 | } | ||
| 678 | |||
| 679 | pub fn systemIntegrationOptions(graph: *std.Build.Graph, wc: *Configuration.Wip) Allocator.Error!void { | ||
| 680 | const gpa = wc.gpa; | ||
| 681 | |||
| 682 | var bad = false; | ||
| 683 | try wc.system_integrations.ensureTotalCapacityPrecise(gpa, graph.system_integration_options.entries.len); | ||
| 684 | for (graph.system_integration_options.keys(), graph.system_integration_options.values()) |k, v| { | ||
| 685 | wc.system_integrations.appendAssumeCapacity(.{ | ||
| 686 | .name = try wc.addString(k), | ||
| 687 | .status = switch (v) { | ||
| 688 | .user_disabled, .user_enabled => x: { | ||
| 689 | // The user tried to enable or disable a system library integration, but | ||
| 690 | // the configure script did not recognize that option. | ||
| 691 | log.err("system integration name not recognized by configure script: {s}", .{k}); | ||
| 692 | bad = true; | ||
| 693 | break :x .disabled; | ||
| 694 | }, | ||
| 695 | .declared_disabled => .disabled, | ||
| 696 | .declared_enabled => .enabled, | ||
| 697 | }, | ||
| 698 | }); | ||
| 699 | } | ||
| 700 | if (bad) { | ||
| 701 | log.info("help menu contains available options: zig build -h", .{}); | ||
| 702 | std.process.exit(1); | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!void { | ||
| 707 | const gpa = wc.gpa; | ||
| 708 | |||
| 709 | try wc.available_options.ensureTotalCapacityPrecise(gpa, b.available_options_map.count()); | ||
| 710 | for (b.available_options_map.keys(), b.available_options_map.values()) |name, *opt| { | ||
| 711 | wc.available_options.appendAssumeCapacity(.{ | ||
| 712 | .name = try wc.addString(name), | ||
| 713 | .description = try wc.addString(opt.description), | ||
| 714 | .type = opt.type_id, | ||
| 715 | .enum_options = if (opt.enum_options) |enum_vals| .init(try wc.addStringList(enum_vals)) else .none, | ||
| 716 | }); | ||
| 717 | } | ||
| 718 | } | ||
| 719 | |||
| 720 | fn builderToPackage(s: *Serialize, b: *std.Build) !Configuration.Package.Index { | ||
| 721 | if (b.pkg_hash.len == 0) return .root; | ||
| 722 | const arena = s.arena; | ||
| 723 | const wc = s.wc; | ||
| 724 | const gop = try s.package_map.getOrPut(arena, b); | ||
| 725 | if (!gop.found_existing) { | ||
| 726 | gop.value_ptr.* = try wc.addExtra(Configuration.Package, .{ | ||
| 727 | .hash = try wc.addString(b.pkg_hash), | ||
| 728 | .dep_prefix = try wc.addString(b.dep_prefix), | ||
| 729 | .root_path = try wc.addString(try b.root.toString(arena)), | ||
| 730 | }); | ||
| 731 | } | ||
| 732 | return gop.value_ptr.*; | ||
| 733 | } | ||
| 734 | |||
| 735 | fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex { | ||
| 736 | const wc = s.wc; | ||
| 737 | return @enumFromInt(switch (lp orelse return .none) { | ||
| 738 | .src_path => |src_path| i: { | ||
| 739 | const sub_path = try wc.addString(src_path.sub_path); | ||
| 740 | break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{ | ||
| 741 | .owner = try s.builderToPackage(src_path.owner), | ||
| 742 | .sub_path = sub_path, | ||
| 743 | }); | ||
| 744 | }, | ||
| 745 | .generated => |generated| i: { | ||
| 746 | const sub_path = try wc.addString(generated.sub_path); | ||
| 747 | break :i try wc.addExtraErased(Configuration.LazyPath.Generated, .{ | ||
| 748 | .flags = .{ .up = @intCast(generated.up) }, | ||
| 749 | .index = generated.index, | ||
| 750 | .sub_path = sub_path, | ||
| 751 | }); | ||
| 752 | }, | ||
| 753 | .cwd_relative => |cwd_relative_sub_path| i: { | ||
| 754 | const sub_path = try wc.addString(cwd_relative_sub_path); | ||
| 755 | break :i try wc.addExtraErased(Configuration.LazyPath.Relative, .{ | ||
| 756 | .flags = .{ .base = .cwd }, | ||
| 757 | .sub_path = sub_path, | ||
| 758 | }); | ||
| 759 | }, | ||
| 760 | .relative => |relative| i: { | ||
| 761 | break :i try wc.addExtraErased(Configuration.LazyPath.Relative, .{ | ||
| 762 | .flags = .{ .base = relative.base }, | ||
| 763 | .sub_path = try wc.addString(relative.sub_path), | ||
| 764 | }); | ||
| 765 | }, | ||
| 766 | .dependency => |dependency| i: { | ||
| 767 | const sub_path = try wc.addString(dependency.sub_path); | ||
| 768 | break :i try wc.addExtraErased(Configuration.LazyPath.SourcePath, .{ | ||
| 769 | .owner = try s.builderToPackage(dependency.dependency.builder), | ||
| 770 | .sub_path = sub_path, | ||
| 771 | }); | ||
| 772 | }, | ||
| 773 | }); | ||
| 774 | } | ||
| 775 | |||
| 776 | fn addOptionalLazyPath(s: *Serialize, lp: ?std.Build.LazyPath) !?Configuration.LazyPath.Index { | ||
| 777 | return (try addOptionalLazyPathEnum(s, lp)).unwrap(); | ||
| 778 | } | ||
| 779 | |||
| 780 | fn addLazyPath(s: *Serialize, lp: std.Build.LazyPath) !Configuration.LazyPath.Index { | ||
| 781 | return @enumFromInt(@intFromEnum(try addOptionalLazyPathEnum(s, lp))); | ||
| 782 | } | ||
| 783 | |||
| 784 | fn addOptionalSemVer(s: *Serialize, sem_ver: ?std.SemanticVersion) !?Configuration.String { | ||
| 785 | return if (sem_ver) |sv| try s.wc.addSemVer(sv) else null; | ||
| 786 | } | ||
| 787 | |||
| 788 | fn addOptionalString(s: *Serialize, opt_slice: ?[]const u8) !?Configuration.String { | ||
| 789 | return if (opt_slice) |slice| try s.wc.addString(slice) else null; | ||
| 790 | } | ||
| 791 | |||
| 792 | fn addSystemLib(s: *Serialize, sl: *const std.Build.Module.SystemLib) !Configuration.SystemLib.Index { | ||
| 793 | const wc = s.wc; | ||
| 794 | return try wc.addDeduped(Configuration.SystemLib, .{ | ||
| 795 | .flags = .{ | ||
| 796 | .needed = sl.needed, | ||
| 797 | .weak = sl.weak, | ||
| 798 | .use_pkg_config = sl.use_pkg_config, | ||
| 799 | .preferred_link_mode = sl.preferred_link_mode, | ||
| 800 | .search_strategy = sl.search_strategy, | ||
| 801 | }, | ||
| 802 | .name = try wc.addString(sl.name), | ||
| 803 | }); | ||
| 804 | } | ||
| 805 | |||
| 806 | fn addCSourceFile(s: *Serialize, csf: *const std.Build.Module.CSourceFile) !Configuration.CSourceFile.Index { | ||
| 807 | const wc = s.wc; | ||
| 808 | const args = try initStringList(s, csf.flags); | ||
| 809 | return try wc.addExtra(Configuration.CSourceFile, .{ | ||
| 810 | .flags = .{ | ||
| 811 | .args_len = @intCast(args.len), | ||
| 812 | .lang = .init(csf.language), | ||
| 813 | }, | ||
| 814 | .file = try addLazyPath(s, csf.file), | ||
| 815 | .args = .{ .slice = args }, | ||
| 816 | }); | ||
| 817 | } | ||
| 818 | |||
| 819 | fn addCSourceFiles(s: *Serialize, csf: *const std.Build.Module.CSourceFiles) !Configuration.CSourceFiles.Index { | ||
| 820 | const wc = s.wc; | ||
| 821 | const sub_paths = try initStringList(s, csf.files); | ||
| 822 | const args = try initStringList(s, csf.flags); | ||
| 823 | return try wc.addExtra(Configuration.CSourceFiles, .{ | ||
| 824 | .flags = .{ | ||
| 825 | .args_len = @intCast(args.len), | ||
| 826 | .lang = .init(csf.language), | ||
| 827 | }, | ||
| 828 | .root = try addLazyPath(s, csf.root), | ||
| 829 | .sub_paths = .{ .slice = sub_paths }, | ||
| 830 | .args = .{ .slice = args }, | ||
| 831 | }); | ||
| 832 | } | ||
| 833 | |||
| 834 | fn addRcSourceFile(s: *Serialize, rsf: *const std.Build.Module.RcSourceFile) !Configuration.RcSourceFile.Index { | ||
| 835 | const wc = s.wc; | ||
| 836 | const include_paths = try initLazyPathList(s, rsf.include_paths); | ||
| 837 | const args = try initStringList(s, rsf.flags); | ||
| 838 | return try wc.addExtra(Configuration.RcSourceFile, .{ | ||
| 839 | .flags = .{ | ||
| 840 | .args_len = @intCast(args.len), | ||
| 841 | .include_paths = include_paths.len != 0, | ||
| 842 | }, | ||
| 843 | .file = try addLazyPath(s, rsf.file), | ||
| 844 | .include_paths = .{ .slice = include_paths }, | ||
| 845 | .args = .{ .slice = args }, | ||
| 846 | }); | ||
| 847 | } | ||
| 848 | |||
| 849 | fn addEnvironMap(s: *Serialize, opt_map: ?*std.process.Environ.Map) !?Configuration.EnvironMap.Index { | ||
| 850 | const wc = s.wc; | ||
| 851 | const map = opt_map orelse return null; | ||
| 852 | return try wc.addDeduped(Configuration.EnvironMap, .{ | ||
| 853 | .keys = try wc.addStringList(map.array_hash_map.keys()), | ||
| 854 | .values = try wc.addStringList(map.array_hash_map.values()), | ||
| 855 | }); | ||
| 856 | } | ||
| 857 | |||
| 858 | fn initArgsList(s: *Serialize, args: []const Step.Run.Arg) ![]const Configuration.Step.Run.Arg.Index { | ||
| 859 | const wc = s.wc; | ||
| 860 | const result = try s.arena.alloc(Configuration.Step.Run.Arg.Index, args.len); | ||
| 861 | for (result, args) |*dest, src| { | ||
| 862 | dest.* = try wc.addExtra(Configuration.Step.Run.Arg, switch (src) { | ||
| 863 | .artifact => |a| .{ | ||
| 864 | .flags = .{ | ||
| 865 | .tag = .artifact, | ||
| 866 | .prefix = a.prefix.len != 0, | ||
| 867 | .suffix = a.suffix.len != 0, | ||
| 868 | .basename = false, | ||
| 869 | .path = false, | ||
| 870 | .producer = true, | ||
| 871 | .generated = false, | ||
| 872 | .dep_file = false, | ||
| 873 | .make_absolute = a.make_absolute, | ||
| 874 | }, | ||
| 875 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 876 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 877 | .basename = .{ .value = null }, | ||
| 878 | .path = .{ .value = null }, | ||
| 879 | .producer = .{ .value = stepIndex(s, &a.artifact.step) }, | ||
| 880 | .generated = .{ .value = null }, | ||
| 881 | }, | ||
| 882 | .lazy_path => |a| .{ | ||
| 883 | .flags = .{ | ||
| 884 | .tag = .path_file, | ||
| 885 | .prefix = a.prefix.len != 0, | ||
| 886 | .suffix = a.suffix.len != 0, | ||
| 887 | .basename = false, | ||
| 888 | .path = true, | ||
| 889 | .producer = false, | ||
| 890 | .generated = false, | ||
| 891 | .dep_file = false, | ||
| 892 | .make_absolute = a.make_absolute, | ||
| 893 | }, | ||
| 894 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 895 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 896 | .basename = .{ .value = null }, | ||
| 897 | .path = .{ .value = try addLazyPath(s, a.lazy_path) }, | ||
| 898 | .producer = .{ .value = null }, | ||
| 899 | .generated = .{ .value = null }, | ||
| 900 | }, | ||
| 901 | .decorated_directory => |a| .{ | ||
| 902 | .flags = .{ | ||
| 903 | .tag = .path_directory, | ||
| 904 | .prefix = a.prefix.len != 0, | ||
| 905 | .suffix = a.suffix.len != 0, | ||
| 906 | .basename = false, | ||
| 907 | .path = true, | ||
| 908 | .producer = false, | ||
| 909 | .generated = false, | ||
| 910 | .dep_file = false, | ||
| 911 | .make_absolute = a.make_absolute, | ||
| 912 | }, | ||
| 913 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 914 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 915 | .basename = .{ .value = null }, | ||
| 916 | .path = .{ .value = try addLazyPath(s, a.lazy_path) }, | ||
| 917 | .producer = .{ .value = null }, | ||
| 918 | .generated = .{ .value = null }, | ||
| 919 | }, | ||
| 920 | .file_content => |a| .{ | ||
| 921 | .flags = .{ | ||
| 922 | .tag = .file_content, | ||
| 923 | .prefix = a.prefix.len != 0, | ||
| 924 | .suffix = a.suffix.len != 0, | ||
| 925 | .basename = false, | ||
| 926 | .path = true, | ||
| 927 | .producer = false, | ||
| 928 | .generated = false, | ||
| 929 | .dep_file = false, | ||
| 930 | .make_absolute = false, | ||
| 931 | }, | ||
| 932 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 933 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 934 | .basename = .{ .value = null }, | ||
| 935 | .path = .{ .value = try addLazyPath(s, a.lazy_path) }, | ||
| 936 | .producer = .{ .value = null }, | ||
| 937 | .generated = .{ .value = null }, | ||
| 938 | }, | ||
| 939 | .bytes => |a| .{ | ||
| 940 | .flags = .{ | ||
| 941 | .tag = .string, | ||
| 942 | .prefix = true, | ||
| 943 | .suffix = false, | ||
| 944 | .basename = false, | ||
| 945 | .path = false, | ||
| 946 | .producer = false, | ||
| 947 | .generated = false, | ||
| 948 | .dep_file = false, | ||
| 949 | .make_absolute = false, | ||
| 950 | }, | ||
| 951 | .prefix = .{ .value = try wc.addString(a) }, | ||
| 952 | .suffix = .{ .value = null }, | ||
| 953 | .basename = .{ .value = null }, | ||
| 954 | .path = .{ .value = null }, | ||
| 955 | .producer = .{ .value = null }, | ||
| 956 | .generated = .{ .value = null }, | ||
| 957 | }, | ||
| 958 | .output_file, .output_file_dep => |a, tag| .{ | ||
| 959 | .flags = .{ | ||
| 960 | .tag = .output_file, | ||
| 961 | .prefix = a.prefix.len != 0, | ||
| 962 | .suffix = a.suffix.len != 0, | ||
| 963 | .basename = a.basename.len != 0, | ||
| 964 | .path = false, | ||
| 965 | .producer = false, | ||
| 966 | .generated = true, | ||
| 967 | .dep_file = tag == .output_file_dep, | ||
| 968 | .make_absolute = a.make_absolute, | ||
| 969 | }, | ||
| 970 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 971 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 972 | .basename = .{ .value = if (a.basename.len != 0) try wc.addString(a.basename) else null }, | ||
| 973 | .path = .{ .value = null }, | ||
| 974 | .producer = .{ .value = null }, | ||
| 975 | .generated = .{ .value = a.generated_file }, | ||
| 976 | }, | ||
| 977 | .output_directory => |a| .{ | ||
| 978 | .flags = .{ | ||
| 979 | .tag = .output_directory, | ||
| 980 | .prefix = a.prefix.len != 0, | ||
| 981 | .suffix = a.suffix.len != 0, | ||
| 982 | .basename = a.basename.len != 0, | ||
| 983 | .path = false, | ||
| 984 | .producer = false, | ||
| 985 | .generated = true, | ||
| 986 | .dep_file = false, | ||
| 987 | .make_absolute = a.make_absolute, | ||
| 988 | }, | ||
| 989 | .prefix = .{ .value = if (a.prefix.len != 0) try wc.addString(a.prefix) else null }, | ||
| 990 | .suffix = .{ .value = if (a.suffix.len != 0) try wc.addString(a.suffix) else null }, | ||
| 991 | .basename = .{ .value = if (a.basename.len != 0) try wc.addString(a.basename) else null }, | ||
| 992 | .path = .{ .value = null }, | ||
| 993 | .producer = .{ .value = null }, | ||
| 994 | .generated = .{ .value = a.generated_file }, | ||
| 995 | }, | ||
| 996 | .passthru => .{ | ||
| 997 | .flags = .{ | ||
| 998 | .tag = .passthru, | ||
| 999 | .prefix = false, | ||
| 1000 | .suffix = false, | ||
| 1001 | .basename = false, | ||
| 1002 | .path = false, | ||
| 1003 | .producer = false, | ||
| 1004 | .generated = false, | ||
| 1005 | .dep_file = false, | ||
| 1006 | .make_absolute = false, | ||
| 1007 | }, | ||
| 1008 | .prefix = .{ .value = null }, | ||
| 1009 | .suffix = .{ .value = null }, | ||
| 1010 | .basename = .{ .value = null }, | ||
| 1011 | .path = .{ .value = null }, | ||
| 1012 | .producer = .{ .value = null }, | ||
| 1013 | .generated = .{ .value = null }, | ||
| 1014 | }, | ||
| 1015 | }); | ||
| 1016 | } | ||
| 1017 | return result; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | fn initIncludeDirList( | ||
| 1021 | s: *Serialize, | ||
| 1022 | list: []const std.Build.Module.IncludeDir, | ||
| 1023 | ) ![]const Configuration.Module.IncludeDir { | ||
| 1024 | const result = try s.arena.alloc(Configuration.Module.IncludeDir, list.len); | ||
| 1025 | for (result, list) |*dest, src| dest.* = switch (src) { | ||
| 1026 | .path => |lp| .{ .path = try addLazyPath(s, lp) }, | ||
| 1027 | .path_system => |lp| .{ .path_system = try addLazyPath(s, lp) }, | ||
| 1028 | .path_after => |lp| .{ .path_after = try addLazyPath(s, lp) }, | ||
| 1029 | .framework_path => |lp| .{ .framework_path = try addLazyPath(s, lp) }, | ||
| 1030 | .framework_path_system => |lp| .{ .framework_path_system = try addLazyPath(s, lp) }, | ||
| 1031 | .embed_path => |lp| .{ .embed_path = try addLazyPath(s, lp) }, | ||
| 1032 | .other_step => |cs| .{ .path = try addLazyPath(s, cs.installed_headers_include_tree.?.getDirectory()) }, | ||
| 1033 | .config_header_step => |chs| .{ .config_header_step = stepIndex(s, &chs.step) }, | ||
| 1034 | }; | ||
| 1035 | return result; | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | fn initLazyPathList(s: *Serialize, list: []const std.Build.LazyPath) ![]const Configuration.LazyPath.Index { | ||
| 1039 | const result = try s.arena.alloc(Configuration.LazyPath.Index, list.len); | ||
| 1040 | for (result, list) |*dest, src| dest.* = try addLazyPath(s, src); | ||
| 1041 | return result; | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | fn initStringList(s: *Serialize, list: []const []const u8) ![]const Configuration.String { | ||
| 1045 | const wc = s.wc; | ||
| 1046 | const result = try s.arena.alloc(Configuration.String, list.len); | ||
| 1047 | for (result, list) |*dest, src| dest.* = try wc.addString(src); | ||
| 1048 | return result; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | fn initCopyList(s: *Serialize, list: []const Step.WriteFile.Copy) ![]const Configuration.Step.WriteFile.Copy { | ||
| 1052 | const result = try s.arena.alloc(Configuration.Step.WriteFile.Copy, list.len); | ||
| 1053 | for (result, list) |*dest, src| dest.* = .{ | ||
| 1054 | .sub_path = src.sub_path, | ||
| 1055 | .src_file = try s.addLazyPath(src.src_file), | ||
| 1056 | }; | ||
| 1057 | return result; | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | fn initOptionalStringList(s: *Serialize, list: []const ?[]const u8) ![]const Configuration.OptionalString { | ||
| 1061 | const wc = s.wc; | ||
| 1062 | const result = try s.arena.alloc(Configuration.OptionalString, list.len); | ||
| 1063 | for (result, list) |*dest, src| dest.* = try wc.addOptionalString(src); | ||
| 1064 | return result; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index { | ||
| 1068 | if (s.module_map.get(m)) |index| return index; | ||
| 1069 | |||
| 1070 | const wc = s.wc; | ||
| 1071 | const arena = s.arena; | ||
| 1072 | |||
| 1073 | const rpaths = try arena.alloc(Configuration.Module.RPath, m.rpaths.items.len); | ||
| 1074 | for (rpaths, m.rpaths.items) |*dest, src| dest.* = switch (src) { | ||
| 1075 | .lazy_path => |lp| .{ .lazy_path = try addLazyPath(s, lp) }, | ||
| 1076 | .special => |slice| .{ .special = try wc.addString(slice) }, | ||
| 1077 | }; | ||
| 1078 | |||
| 1079 | const link_objects = try arena.alloc(Configuration.Module.LinkObject, m.link_objects.items.len); | ||
| 1080 | for (link_objects, m.link_objects.items) |*dest, *src| dest.* = switch (src.*) { | ||
| 1081 | .static_path => |lp| .{ .static_path = try addLazyPath(s, lp) }, | ||
| 1082 | .other_step => |cs| .{ .other_step = stepIndex(s, &cs.step) }, | ||
| 1083 | .system_lib => |*sl| .{ .system_lib = try addSystemLib(s, sl) }, | ||
| 1084 | .assembly_file => |lp| .{ .assembly_file = try addLazyPath(s, lp) }, | ||
| 1085 | .c_source_file => |csf| .{ .c_source_file = try addCSourceFile(s, csf) }, | ||
| 1086 | .c_source_files => |csf| .{ .c_source_files = try addCSourceFiles(s, csf) }, | ||
| 1087 | .win32_resource_file => |wrf| .{ .win32_resource_file = try addRcSourceFile(s, wrf) }, | ||
| 1088 | }; | ||
| 1089 | |||
| 1090 | const frameworks = try arena.alloc(Configuration.Module.Framework, m.frameworks.entries.len); | ||
| 1091 | for (frameworks, m.frameworks.keys(), m.frameworks.values()) |*dest, name, options| dest.* = .{ | ||
| 1092 | .flags = .{ | ||
| 1093 | .needed = options.needed, | ||
| 1094 | .weak = options.weak, | ||
| 1095 | }, | ||
| 1096 | .name = try wc.addString(name), | ||
| 1097 | }; | ||
| 1098 | |||
| 1099 | const lib_paths = try initLazyPathList(s, m.lib_paths.items); | ||
| 1100 | const c_macros = try initStringList(s, m.c_macros.items); | ||
| 1101 | const export_symbol_names = try initStringList(s, m.export_symbol_names); | ||
| 1102 | |||
| 1103 | const module_index: Configuration.Module.Index = try wc.addExtra(Configuration.Module, .{ | ||
| 1104 | .flags = .{ | ||
| 1105 | .optimize = .init(m.optimize), | ||
| 1106 | .strip = .init(m.strip), | ||
| 1107 | .unwind_tables = .init(m.unwind_tables), | ||
| 1108 | .dwarf_format = .init(m.dwarf_format), | ||
| 1109 | .single_threaded = .init(m.single_threaded), | ||
| 1110 | .stack_protector = .init(m.stack_protector), | ||
| 1111 | .stack_check = .init(m.stack_check), | ||
| 1112 | .sanitize_c = .init(m.sanitize_c), | ||
| 1113 | .sanitize_thread = .init(m.sanitize_thread), | ||
| 1114 | .fuzz = .init(m.fuzz), | ||
| 1115 | .code_model = m.code_model, | ||
| 1116 | .c_macros = c_macros.len != 0, | ||
| 1117 | .include_dirs = m.include_dirs.items.len != 0, | ||
| 1118 | .lib_paths = lib_paths.len != 0, | ||
| 1119 | .rpaths = rpaths.len != 0, | ||
| 1120 | .frameworks = frameworks.len != 0, | ||
| 1121 | .link_objects = link_objects.len != 0, | ||
| 1122 | .export_symbol_names = export_symbol_names.len != 0, | ||
| 1123 | }, | ||
| 1124 | .flags2 = .{ | ||
| 1125 | .valgrind = .init(m.valgrind), | ||
| 1126 | .pic = .init(m.pic), | ||
| 1127 | .red_zone = .init(m.red_zone), | ||
| 1128 | .omit_frame_pointer = .init(m.omit_frame_pointer), | ||
| 1129 | .error_tracing = .init(m.error_tracing), | ||
| 1130 | .link_libc = .init(m.link_libc), | ||
| 1131 | .link_libcpp = .init(m.link_libcpp), | ||
| 1132 | .no_builtin = .init(m.no_builtin), | ||
| 1133 | }, | ||
| 1134 | .owner = try s.builderToPackage(m.owner), | ||
| 1135 | .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file), | ||
| 1136 | .import_table = .invalid, | ||
| 1137 | .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target), | ||
| 1138 | .c_macros = .{ .slice = c_macros }, | ||
| 1139 | .lib_paths = .{ .slice = lib_paths }, | ||
| 1140 | .export_symbol_names = .{ .slice = export_symbol_names }, | ||
| 1141 | .include_dirs = .init(try s.initIncludeDirList(m.include_dirs.items)), | ||
| 1142 | .rpaths = .init(rpaths), | ||
| 1143 | .link_objects = .init(link_objects), | ||
| 1144 | .frameworks = .{ .slice = frameworks }, | ||
| 1145 | }); | ||
| 1146 | |||
| 1147 | // The import table is the only place that modules can form dependency | ||
| 1148 | // loops. Therefore, we populate the module indexes only after adding | ||
| 1149 | // the module to module_map. | ||
| 1150 | try s.module_map.putNoClobber(arena, m, module_index); | ||
| 1151 | |||
| 1152 | var imports = try std.MultiArrayList(Configuration.ImportTable.Import).initCapacity(arena, m.import_table.entries.len); | ||
| 1153 | imports.len = m.import_table.entries.len; | ||
| 1154 | for ( | ||
| 1155 | imports.items(.name), | ||
| 1156 | imports.items(.module), | ||
| 1157 | m.import_table.keys(), | ||
| 1158 | m.import_table.values(), | ||
| 1159 | ) |*dest_name, *dest_module, src_name, src_module| { | ||
| 1160 | dest_name.* = try wc.addString(src_name); | ||
| 1161 | dest_module.* = try addModule(s, src_module); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | comptime assert(std.mem.eql(u8, @typeInfo(Configuration.Module).@"struct".field_names[2], "import_table")); | ||
| 1165 | comptime assert(@typeInfo(Configuration.Module).@"struct".field_types[2] == Configuration.ImportTable.Index); | ||
| 1166 | assert(wc.extra.items[@intFromEnum(module_index) + 2] == @intFromEnum(Configuration.ImportTable.Index.invalid)); | ||
| 1167 | const import_table_index = try wc.addDeduped(Configuration.ImportTable, .{ | ||
| 1168 | .imports = .{ .mal = imports }, | ||
| 1169 | }); | ||
| 1170 | wc.extra.items[@intFromEnum(module_index) + 2] = @intFromEnum(import_table_index); | ||
| 1171 | |||
| 1172 | return module_index; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | fn stepIndex(s: *const Serialize, step: *Step) Configuration.Step.Index { | ||
| 1176 | return @enumFromInt(s.step_map.getIndex(step).?); | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | fn addOptionalResolvedTarget( | ||
| 1180 | wc: *Configuration.Wip, | ||
| 1181 | optional_resolved_target: ?std.Build.ResolvedTarget, | ||
| 1182 | ) !Configuration.ResolvedTarget.OptionalIndex { | ||
| 1183 | const resolved_target = optional_resolved_target orelse return .none; | ||
| 1184 | return .init(try wc.addDeduped(Configuration.ResolvedTarget, .{ | ||
| 1185 | .query = try wc.addTargetQuery(&resolved_target.query), | ||
| 1186 | .result = try wc.addTarget(resolved_target.result), | ||
| 1187 | })); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | /// If the given `Step` is a `Step.Compile`, adds any dependencies for that step which | ||
| 1191 | /// are implied by the module graph rooted at `step.cast(Step.Compile).?.root_module`. | ||
| 1192 | fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void { | ||
| 1193 | const root_module = if (step.cast(Step.Compile)) |cs| root: { | ||
| 1194 | break :root cs.root_module; | ||
| 1195 | } else return; // not a compile step so no module dependencies | ||
| 1196 | |||
| 1197 | // Starting from `root_module`, discover all modules in this graph. | ||
| 1198 | const modules = root_module.getGraph().modules; | ||
| 1199 | |||
| 1200 | // For each of those modules, set up the implied step dependencies. | ||
| 1201 | for (modules) |mod| { | ||
| 1202 | if (mod.root_source_file) |lp| lp.addStepDependencies(step); | ||
| 1203 | for (mod.include_dirs.items) |include_dir| switch (include_dir) { | ||
| 1204 | .path, | ||
| 1205 | .path_system, | ||
| 1206 | .path_after, | ||
| 1207 | .framework_path, | ||
| 1208 | .framework_path_system, | ||
| 1209 | .embed_path, | ||
| 1210 | => |lp| lp.addStepDependencies(step), | ||
| 1211 | |||
| 1212 | .other_step => |other| { | ||
| 1213 | other.getEmittedIncludeTree().addStepDependencies(step); | ||
| 1214 | step.dependOn(&other.step); | ||
| 1215 | }, | ||
| 1216 | |||
| 1217 | .config_header_step => |other| step.dependOn(&other.step), | ||
| 1218 | }; | ||
| 1219 | for (mod.lib_paths.items) |lp| lp.addStepDependencies(step); | ||
| 1220 | for (mod.rpaths.items) |rpath| switch (rpath) { | ||
| 1221 | .lazy_path => |lp| lp.addStepDependencies(step), | ||
| 1222 | .special => {}, | ||
| 1223 | }; | ||
| 1224 | for (mod.link_objects.items) |link_object| switch (link_object) { | ||
| 1225 | .static_path, | ||
| 1226 | .assembly_file, | ||
| 1227 | => |lp| lp.addStepDependencies(step), | ||
| 1228 | .other_step => |other| step.dependOn(&other.step), | ||
| 1229 | .system_lib => {}, | ||
| 1230 | .c_source_file => |source| source.file.addStepDependencies(step), | ||
| 1231 | .c_source_files => |source_files| source_files.root.addStepDependencies(step), | ||
| 1232 | .win32_resource_file => |rc_source| { | ||
| 1233 | rc_source.file.addStepDependencies(step); | ||
| 1234 | for (rc_source.include_paths) |lp| lp.addStepDependencies(step); | ||
| 1235 | }, | ||
| 1236 | }; | ||
| 1237 | } | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | fn addInstallDirDefaultNull(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !?Configuration.InstallDestDir { | ||
| 1241 | return try addInstallDir(wc, install_dir orelse return null); | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | fn addInstallDir(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !Configuration.InstallDestDir { | ||
| 1245 | switch (install_dir orelse return .none) { | ||
| 1246 | .prefix => return .prefix, | ||
| 1247 | .lib => return .lib, | ||
| 1248 | .bin => return .bin, | ||
| 1249 | .header => return .header, | ||
| 1250 | .custom => |sub_path| return .initCustom(try wc.addString(sub_path)), | ||
| 1251 | } | ||
| 1252 | } | ||