blob a364982c (50691B) - Raw
1 const std = @import("std"); 2 const builtin = std.builtin; 3 const tests = @import("test/tests.zig"); 4 const BufMap = std.BufMap; 5 const mem = std.mem; 6 const ArrayList = std.ArrayList; 7 const io = std.io; 8 const fs = std.fs; 9 const InstallDirectoryOptions = std.Build.InstallDirectoryOptions; 10 const assert = std.debug.assert; 11 12 const zig_version: std.SemanticVersion = .{ .major = 0, .minor = 14, .patch = 0 }; 13 const stack_size = 32 * 1024 * 1024; 14 15 pub fn build(b: *std.Build) !void { 16 const only_c = b.option(bool, "only-c", "Translate the Zig compiler to C code, with only the C backend enabled") orelse false; 17 const target = t: { 18 var default_target: std.Target.Query = .{}; 19 default_target.ofmt = b.option(std.Target.ObjectFormat, "ofmt", "Object format to target") orelse if (only_c) .c else null; 20 break :t b.standardTargetOptions(.{ .default_target = default_target }); 21 }; 22 23 const optimize = b.standardOptimizeOption(.{}); 24 25 const flat = b.option(bool, "flat", "Put files into the installation prefix in a manner suited for upstream distribution rather than a posix file system hierarchy standard") orelse false; 26 const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode"); 27 const use_zig_libcxx = b.option(bool, "use-zig-libcxx", "If libc++ is needed, use zig's bundled version, don't try to integrate with the system") orelse false; 28 29 const test_step = b.step("test", "Run all the tests"); 30 const skip_install_lib_files = b.option(bool, "no-lib", "skip copying of lib/ files and langref to installation prefix. Useful for development") orelse false; 31 const skip_install_langref = b.option(bool, "no-langref", "skip copying of langref to the installation prefix") orelse skip_install_lib_files; 32 const std_docs = b.option(bool, "std-docs", "include standard library autodocs") orelse false; 33 const no_bin = b.option(bool, "no-bin", "skip emitting compiler binary") orelse false; 34 const enable_tidy = b.option(bool, "enable-tidy", "Check langref output HTML validity") orelse false; 35 36 const langref_file = generateLangRef(b); 37 const install_langref = b.addInstallFileWithDir(langref_file, .prefix, "doc/langref.html"); 38 const check_langref = tidyCheck(b, langref_file); 39 if (enable_tidy) install_langref.step.dependOn(check_langref); 40 // Checking autodocs is disabled because tidy gives a false positive: 41 // line 304 column 9 - Warning: moved <style> tag to <head>! fix-style-tags: no to avoid. 42 // I noticed that `--show-warnings no` still incorrectly causes exit code 1. 43 // I was unable to find an alternative to tidy. 44 //const check_autodocs = tidyCheck(b, b.path("lib/docs/index.html")); 45 if (enable_tidy) { 46 test_step.dependOn(check_langref); 47 //test_step.dependOn(check_autodocs); 48 } 49 if (!skip_install_langref) { 50 b.getInstallStep().dependOn(&install_langref.step); 51 } 52 53 const autodoc_test = b.addObject(.{ 54 .name = "std", 55 .root_source_file = b.path("lib/std/std.zig"), 56 .target = target, 57 .zig_lib_dir = b.path("lib"), 58 .optimize = .Debug, 59 }); 60 const install_std_docs = b.addInstallDirectory(.{ 61 .source_dir = autodoc_test.getEmittedDocs(), 62 .install_dir = .prefix, 63 .install_subdir = "doc/std", 64 }); 65 //if (enable_tidy) install_std_docs.step.dependOn(check_autodocs); 66 if (std_docs) { 67 b.getInstallStep().dependOn(&install_std_docs.step); 68 } 69 70 if (flat) { 71 b.installFile("LICENSE", "LICENSE"); 72 b.installFile("README.md", "README.md"); 73 } 74 75 const langref_step = b.step("langref", "Build and install the language reference"); 76 langref_step.dependOn(&install_langref.step); 77 78 const std_docs_step = b.step("std-docs", "Build and install the standard library documentation"); 79 std_docs_step.dependOn(&install_std_docs.step); 80 81 const docs_step = b.step("docs", "Build and install documentation"); 82 docs_step.dependOn(langref_step); 83 docs_step.dependOn(std_docs_step); 84 85 const skip_debug = b.option(bool, "skip-debug", "Main test suite skips debug builds") orelse false; 86 const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false; 87 const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release; 88 const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release; 89 const skip_release_safe = b.option(bool, "skip-release-safe", "Main test suite skips release-safe builds") orelse skip_release; 90 const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false; 91 const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false; 92 const skip_single_threaded = b.option(bool, "skip-single-threaded", "Main test suite skips tests that are single-threaded") orelse false; 93 const skip_translate_c = b.option(bool, "skip-translate-c", "Main test suite skips translate-c tests") orelse false; 94 const skip_run_translated_c = b.option(bool, "skip-run-translated-c", "Main test suite skips run-translated-c tests") orelse false; 95 96 const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false; 97 98 const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false; 99 const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse static_llvm; 100 const llvm_has_m68k = b.option( 101 bool, 102 "llvm-has-m68k", 103 "Whether LLVM has the experimental target m68k enabled", 104 ) orelse false; 105 const llvm_has_csky = b.option( 106 bool, 107 "llvm-has-csky", 108 "Whether LLVM has the experimental target csky enabled", 109 ) orelse false; 110 const llvm_has_arc = b.option( 111 bool, 112 "llvm-has-arc", 113 "Whether LLVM has the experimental target arc enabled", 114 ) orelse false; 115 const llvm_has_xtensa = b.option( 116 bool, 117 "llvm-has-xtensa", 118 "Whether LLVM has the experimental target xtensa enabled", 119 ) orelse false; 120 const enable_ios_sdk = b.option(bool, "enable-ios-sdk", "Run tests requiring presence of iOS SDK and frameworks") orelse false; 121 const enable_macos_sdk = b.option(bool, "enable-macos-sdk", "Run tests requiring presence of macOS SDK and frameworks") orelse enable_ios_sdk; 122 const enable_symlinks_windows = b.option(bool, "enable-symlinks-windows", "Run tests requiring presence of symlinks on Windows") orelse false; 123 const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h"); 124 125 if (!skip_install_lib_files) { 126 b.installDirectory(.{ 127 .source_dir = b.path("lib"), 128 .install_dir = if (flat) .prefix else .lib, 129 .install_subdir = if (flat) "lib" else "zig", 130 .exclude_extensions = &[_][]const u8{ 131 // exclude files from lib/std/compress/testdata 132 ".gz", 133 ".z.0", 134 ".z.9", 135 ".zst.3", 136 ".zst.19", 137 "rfc1951.txt", 138 "rfc1952.txt", 139 "rfc8478.txt", 140 // exclude files from lib/std/compress/flate/testdata 141 ".expect", 142 ".expect-noinput", 143 ".golden", 144 ".input", 145 "compress-e.txt", 146 "compress-gettysburg.txt", 147 "compress-pi.txt", 148 "rfc1951.txt", 149 // exclude files from lib/std/compress/lzma/testdata 150 ".lzma", 151 // exclude files from lib/std/compress/xz/testdata 152 ".xz", 153 // exclude files from lib/std/tz/ 154 ".tzif", 155 // exclude files from lib/std/tar/testdata 156 ".tar", 157 // others 158 "README.md", 159 }, 160 .blank_extensions = &[_][]const u8{ 161 "test.zig", 162 }, 163 }); 164 } 165 166 if (only_install_lib_files) 167 return; 168 169 const entitlements = b.option([]const u8, "entitlements", "Path to entitlements file for hot-code swapping without sudo on macOS"); 170 const tracy = b.option([]const u8, "tracy", "Enable Tracy integration. Supply path to Tracy source"); 171 const tracy_callstack = b.option(bool, "tracy-callstack", "Include callstack information with Tracy data. Does nothing if -Dtracy is not provided") orelse (tracy != null); 172 const tracy_allocation = b.option(bool, "tracy-allocation", "Include allocation information with Tracy data. Does nothing if -Dtracy is not provided") orelse (tracy != null); 173 const force_gpa = b.option(bool, "force-gpa", "Force the compiler to use GeneralPurposeAllocator") orelse false; 174 const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse (enable_llvm or only_c); 175 const sanitize_thread = b.option(bool, "sanitize-thread", "Enable thread-sanitization") orelse false; 176 const strip = b.option(bool, "strip", "Omit debug information"); 177 const pie = b.option(bool, "pie", "Produce a Position Independent Executable"); 178 const value_tracing = b.option(bool, "value-tracing", "Enable extra state tracking to help troubleshoot bugs in the compiler (using the std.debug.Trace API)") orelse false; 179 180 const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: { 181 if (strip == true) break :blk @as(u32, 0); 182 if (optimize != .Debug) break :blk 0; 183 break :blk 4; 184 }; 185 186 const exe = addCompilerStep(b, .{ 187 .optimize = optimize, 188 .target = target, 189 .strip = strip, 190 .sanitize_thread = sanitize_thread, 191 .single_threaded = single_threaded, 192 }); 193 exe.pie = pie; 194 exe.entitlements = entitlements; 195 196 exe.build_id = b.option( 197 std.zig.BuildId, 198 "build-id", 199 "Request creation of '.note.gnu.build-id' section", 200 ); 201 202 if (no_bin) { 203 b.getInstallStep().dependOn(&exe.step); 204 } else { 205 const install_exe = b.addInstallArtifact(exe, .{ 206 .dest_dir = if (flat) .{ .override = .prefix } else .default, 207 }); 208 b.getInstallStep().dependOn(&install_exe.step); 209 } 210 211 test_step.dependOn(&exe.step); 212 213 if (target.result.os.tag == .windows and target.result.abi == .gnu) { 214 // LTO is currently broken on mingw, this can be removed when it's fixed. 215 exe.want_lto = false; 216 } 217 218 const use_llvm = b.option(bool, "use-llvm", "Use the llvm backend"); 219 exe.use_llvm = use_llvm; 220 exe.use_lld = use_llvm; 221 222 const exe_options = b.addOptions(); 223 exe.root_module.addOptions("build_options", exe_options); 224 225 exe_options.addOption(u32, "mem_leak_frames", mem_leak_frames); 226 exe_options.addOption(bool, "skip_non_native", skip_non_native); 227 exe_options.addOption(bool, "have_llvm", enable_llvm); 228 exe_options.addOption(bool, "llvm_has_m68k", llvm_has_m68k); 229 exe_options.addOption(bool, "llvm_has_csky", llvm_has_csky); 230 exe_options.addOption(bool, "llvm_has_arc", llvm_has_arc); 231 exe_options.addOption(bool, "llvm_has_xtensa", llvm_has_xtensa); 232 exe_options.addOption(bool, "force_gpa", force_gpa); 233 exe_options.addOption(bool, "only_c", only_c); 234 exe_options.addOption(bool, "only_core_functionality", only_c); 235 236 if (link_libc) { 237 exe.linkLibC(); 238 } 239 240 const is_debug = optimize == .Debug; 241 const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug; 242 const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug; 243 const enable_link_snapshots = b.option(bool, "link-snapshot", "Whether to enable linker state snapshots") orelse false; 244 245 const opt_version_string = b.option([]const u8, "version-string", "Override Zig version string. Default is to find out with git."); 246 const version_slice = if (opt_version_string) |version| version else v: { 247 if (!std.process.can_spawn) { 248 std.debug.print("error: version info cannot be retrieved from git. Zig version must be provided using -Dversion-string\n", .{}); 249 std.process.exit(1); 250 } 251 const version_string = b.fmt("{d}.{d}.{d}", .{ zig_version.major, zig_version.minor, zig_version.patch }); 252 253 var code: u8 = undefined; 254 const git_describe_untrimmed = b.runAllowFail(&[_][]const u8{ 255 "git", 256 "-C", 257 b.build_root.path orelse ".", 258 "describe", 259 "--match", 260 "*.*.*", 261 "--tags", 262 "--abbrev=9", 263 }, &code, .Ignore) catch { 264 break :v version_string; 265 }; 266 const git_describe = mem.trim(u8, git_describe_untrimmed, " \n\r"); 267 268 switch (mem.count(u8, git_describe, "-")) { 269 0 => { 270 // Tagged release version (e.g. 0.10.0). 271 if (!mem.eql(u8, git_describe, version_string)) { 272 std.debug.print("Zig version '{s}' does not match Git tag '{s}'\n", .{ version_string, git_describe }); 273 std.process.exit(1); 274 } 275 break :v version_string; 276 }, 277 2 => { 278 // Untagged development build (e.g. 0.10.0-dev.2025+ecf0050a9). 279 var it = mem.splitScalar(u8, git_describe, '-'); 280 const tagged_ancestor = it.first(); 281 const commit_height = it.next().?; 282 const commit_id = it.next().?; 283 284 const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor); 285 if (zig_version.order(ancestor_ver) != .gt) { 286 std.debug.print("Zig version '{}' must be greater than tagged ancestor '{}'\n", .{ zig_version, ancestor_ver }); 287 std.process.exit(1); 288 } 289 290 // Check that the commit hash is prefixed with a 'g' (a Git convention). 291 if (commit_id.len < 1 or commit_id[0] != 'g') { 292 std.debug.print("Unexpected `git describe` output: {s}\n", .{git_describe}); 293 break :v version_string; 294 } 295 296 // The version is reformatted in accordance with the https://semver.org specification. 297 break :v b.fmt("{s}-dev.{s}+{s}", .{ version_string, commit_height, commit_id[1..] }); 298 }, 299 else => { 300 std.debug.print("Unexpected `git describe` output: {s}\n", .{git_describe}); 301 break :v version_string; 302 }, 303 } 304 }; 305 const version = try b.allocator.dupeZ(u8, version_slice); 306 exe_options.addOption([:0]const u8, "version", version); 307 308 if (enable_llvm) { 309 const cmake_cfg = if (static_llvm) null else blk: { 310 if (findConfigH(b, config_h_path_option)) |config_h_path| { 311 const file_contents = fs.cwd().readFileAlloc(b.allocator, config_h_path, max_config_h_bytes) catch unreachable; 312 break :blk parseConfigH(b, file_contents); 313 } else { 314 std.log.warn("config.h could not be located automatically. Consider providing it explicitly via \"-Dconfig_h\"", .{}); 315 break :blk null; 316 } 317 }; 318 319 if (cmake_cfg) |cfg| { 320 // Inside this code path, we have to coordinate with system packaged LLVM, Clang, and LLD. 321 // That means we also have to rely on stage1 compiled c++ files. We parse config.h to find 322 // the information passed on to us from cmake. 323 if (cfg.cmake_prefix_path.len > 0) { 324 var it = mem.tokenizeScalar(u8, cfg.cmake_prefix_path, ';'); 325 while (it.next()) |path| { 326 b.addSearchPrefix(path); 327 } 328 } 329 330 try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx); 331 } else { 332 // Here we are -Denable-llvm but no cmake integration. 333 try addStaticLlvmOptionsToExe(exe); 334 } 335 if (target.result.os.tag == .windows) { 336 // LLVM depends on networking as of version 18. 337 exe.linkSystemLibrary("ws2_32"); 338 339 exe.linkSystemLibrary("version"); 340 exe.linkSystemLibrary("uuid"); 341 exe.linkSystemLibrary("ole32"); 342 } 343 } 344 345 const semver = try std.SemanticVersion.parse(version); 346 exe_options.addOption(std.SemanticVersion, "semver", semver); 347 348 exe_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions); 349 exe_options.addOption(bool, "enable_logging", enable_logging); 350 exe_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots); 351 exe_options.addOption(bool, "enable_tracy", tracy != null); 352 exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack); 353 exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation); 354 exe_options.addOption(bool, "value_tracing", value_tracing); 355 if (tracy) |tracy_path| { 356 const client_cpp = b.pathJoin( 357 &[_][]const u8{ tracy_path, "public", "TracyClient.cpp" }, 358 ); 359 360 // On mingw, we need to opt into windows 7+ to get some features required by tracy. 361 const tracy_c_flags: []const []const u8 = if (target.result.os.tag == .windows and target.result.abi == .gnu) 362 &[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined", "-D_WIN32_WINNT=0x601" } 363 else 364 &[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined" }; 365 366 exe.addIncludePath(.{ .cwd_relative = tracy_path }); 367 exe.addCSourceFile(.{ .file = .{ .cwd_relative = client_cpp }, .flags = tracy_c_flags }); 368 if (!enable_llvm) { 369 exe.root_module.linkSystemLibrary("c++", .{ .use_pkg_config = .no }); 370 } 371 exe.linkLibC(); 372 373 if (target.result.os.tag == .windows) { 374 exe.linkSystemLibrary("dbghelp"); 375 exe.linkSystemLibrary("ws2_32"); 376 } 377 } 378 379 const test_filters = b.option([]const []const u8, "test-filter", "Skip tests that do not match any filter") orelse &[0][]const u8{}; 380 381 const test_cases_options = b.addOptions(); 382 383 test_cases_options.addOption(bool, "enable_tracy", false); 384 test_cases_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions); 385 test_cases_options.addOption(bool, "enable_logging", enable_logging); 386 test_cases_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots); 387 test_cases_options.addOption(bool, "skip_non_native", skip_non_native); 388 test_cases_options.addOption(bool, "have_llvm", enable_llvm); 389 test_cases_options.addOption(bool, "llvm_has_m68k", llvm_has_m68k); 390 test_cases_options.addOption(bool, "llvm_has_csky", llvm_has_csky); 391 test_cases_options.addOption(bool, "llvm_has_arc", llvm_has_arc); 392 test_cases_options.addOption(bool, "llvm_has_xtensa", llvm_has_xtensa); 393 test_cases_options.addOption(bool, "force_gpa", force_gpa); 394 test_cases_options.addOption(bool, "only_c", only_c); 395 test_cases_options.addOption(bool, "only_core_functionality", true); 396 test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu); 397 test_cases_options.addOption(bool, "enable_wine", b.enable_wine); 398 test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime); 399 test_cases_options.addOption(bool, "enable_rosetta", b.enable_rosetta); 400 test_cases_options.addOption(bool, "enable_darling", b.enable_darling); 401 test_cases_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2); 402 test_cases_options.addOption(bool, "value_tracing", value_tracing); 403 test_cases_options.addOption(?[]const u8, "glibc_runtimes_dir", b.glibc_runtimes_dir); 404 test_cases_options.addOption([:0]const u8, "version", version); 405 test_cases_options.addOption(std.SemanticVersion, "semver", semver); 406 test_cases_options.addOption([]const []const u8, "test_filters", test_filters); 407 408 var chosen_opt_modes_buf: [4]builtin.OptimizeMode = undefined; 409 var chosen_mode_index: usize = 0; 410 if (!skip_debug) { 411 chosen_opt_modes_buf[chosen_mode_index] = builtin.OptimizeMode.Debug; 412 chosen_mode_index += 1; 413 } 414 if (!skip_release_safe) { 415 chosen_opt_modes_buf[chosen_mode_index] = builtin.OptimizeMode.ReleaseSafe; 416 chosen_mode_index += 1; 417 } 418 if (!skip_release_fast) { 419 chosen_opt_modes_buf[chosen_mode_index] = builtin.OptimizeMode.ReleaseFast; 420 chosen_mode_index += 1; 421 } 422 if (!skip_release_small) { 423 chosen_opt_modes_buf[chosen_mode_index] = builtin.OptimizeMode.ReleaseSmall; 424 chosen_mode_index += 1; 425 } 426 const optimization_modes = chosen_opt_modes_buf[0..chosen_mode_index]; 427 428 const fmt_include_paths = &.{ "lib", "src", "test", "tools", "build.zig", "build.zig.zon" }; 429 const fmt_exclude_paths = &.{"test/cases"}; 430 const do_fmt = b.addFmt(.{ 431 .paths = fmt_include_paths, 432 .exclude_paths = fmt_exclude_paths, 433 }); 434 b.step("fmt", "Modify source files in place to have conforming formatting").dependOn(&do_fmt.step); 435 436 const check_fmt = b.step("test-fmt", "Check source files having conforming formatting"); 437 check_fmt.dependOn(&b.addFmt(.{ 438 .paths = fmt_include_paths, 439 .exclude_paths = fmt_exclude_paths, 440 .check = true, 441 }).step); 442 test_step.dependOn(check_fmt); 443 444 const test_cases_step = b.step("test-cases", "Run the main compiler test cases"); 445 try tests.addCases(b, test_cases_step, test_filters, target, .{ 446 .skip_translate_c = skip_translate_c, 447 .skip_run_translated_c = skip_run_translated_c, 448 }, .{ 449 .enable_llvm = enable_llvm, 450 .llvm_has_m68k = llvm_has_m68k, 451 .llvm_has_csky = llvm_has_csky, 452 .llvm_has_arc = llvm_has_arc, 453 .llvm_has_xtensa = llvm_has_xtensa, 454 }); 455 test_step.dependOn(test_cases_step); 456 457 test_step.dependOn(tests.addModuleTests(b, .{ 458 .test_filters = test_filters, 459 .root_src = "test/behavior.zig", 460 .name = "behavior", 461 .desc = "Run the behavior tests", 462 .optimize_modes = optimization_modes, 463 .include_paths = &.{}, 464 .skip_single_threaded = skip_single_threaded, 465 .skip_non_native = skip_non_native, 466 .skip_libc = skip_libc, 467 .max_rss = 1 * 1024 * 1024 * 1024, 468 })); 469 470 test_step.dependOn(tests.addModuleTests(b, .{ 471 .test_filters = test_filters, 472 .root_src = "test/c_import.zig", 473 .name = "c-import", 474 .desc = "Run the @cImport tests", 475 .optimize_modes = optimization_modes, 476 .include_paths = &.{"test/c_import"}, 477 .skip_single_threaded = true, 478 .skip_non_native = skip_non_native, 479 .skip_libc = skip_libc, 480 })); 481 482 test_step.dependOn(tests.addModuleTests(b, .{ 483 .test_filters = test_filters, 484 .root_src = "lib/compiler_rt.zig", 485 .name = "compiler-rt", 486 .desc = "Run the compiler_rt tests", 487 .optimize_modes = optimization_modes, 488 .include_paths = &.{}, 489 .skip_single_threaded = true, 490 .skip_non_native = skip_non_native, 491 .skip_libc = true, 492 .no_builtin = true, 493 })); 494 495 test_step.dependOn(tests.addModuleTests(b, .{ 496 .test_filters = test_filters, 497 .root_src = "lib/c.zig", 498 .name = "universal-libc", 499 .desc = "Run the universal libc tests", 500 .optimize_modes = optimization_modes, 501 .include_paths = &.{}, 502 .skip_single_threaded = true, 503 .skip_non_native = skip_non_native, 504 .skip_libc = true, 505 .no_builtin = true, 506 })); 507 508 test_step.dependOn(tests.addCompareOutputTests(b, test_filters, optimization_modes)); 509 test_step.dependOn(tests.addStandaloneTests( 510 b, 511 optimization_modes, 512 enable_macos_sdk, 513 enable_ios_sdk, 514 enable_symlinks_windows, 515 )); 516 test_step.dependOn(tests.addCAbiTests(b, skip_non_native, skip_release)); 517 test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, enable_symlinks_windows)); 518 test_step.dependOn(tests.addStackTraceTests(b, test_filters, optimization_modes)); 519 test_step.dependOn(tests.addCliTests(b)); 520 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filters, optimization_modes)); 521 test_step.dependOn(tests.addModuleTests(b, .{ 522 .test_filters = test_filters, 523 .root_src = "lib/std/std.zig", 524 .name = "std", 525 .desc = "Run the standard library tests", 526 .optimize_modes = optimization_modes, 527 .include_paths = &.{}, 528 .skip_single_threaded = skip_single_threaded, 529 .skip_non_native = skip_non_native, 530 .skip_libc = skip_libc, 531 // I observed a value of 4572626944 on the M2 CI. 532 .max_rss = 5029889638, 533 })); 534 535 try addWasiUpdateStep(b, version); 536 537 const update_mingw_step = b.step("update-mingw", "Update zig's bundled mingw"); 538 const opt_mingw_src_path = b.option([]const u8, "mingw-src", "path to mingw-w64 source directory"); 539 const update_mingw_exe = b.addExecutable(.{ 540 .name = "update_mingw", 541 .target = b.graph.host, 542 .root_source_file = b.path("tools/update_mingw.zig"), 543 }); 544 const update_mingw_run = b.addRunArtifact(update_mingw_exe); 545 update_mingw_run.addDirectoryArg(b.path("lib")); 546 if (opt_mingw_src_path) |mingw_src_path| { 547 update_mingw_run.addDirectoryArg(.{ .cwd_relative = mingw_src_path }); 548 } else { 549 // Intentionally cause an error if this build step is requested. 550 update_mingw_run.addArg("--missing-mingw-source-directory"); 551 } 552 553 update_mingw_step.dependOn(&update_mingw_run.step); 554 } 555 556 fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { 557 const semver = try std.SemanticVersion.parse(version); 558 559 var target_query: std.Target.Query = .{ 560 .cpu_arch = .wasm32, 561 .os_tag = .wasi, 562 }; 563 target_query.cpu_features_add.addFeature(@intFromEnum(std.Target.wasm.Feature.bulk_memory)); 564 565 const exe = addCompilerStep(b, .{ 566 .optimize = .ReleaseSmall, 567 .target = b.resolveTargetQuery(target_query), 568 }); 569 570 const exe_options = b.addOptions(); 571 exe.root_module.addOptions("build_options", exe_options); 572 573 exe_options.addOption(u32, "mem_leak_frames", 0); 574 exe_options.addOption(bool, "have_llvm", false); 575 exe_options.addOption(bool, "force_gpa", false); 576 exe_options.addOption(bool, "only_c", true); 577 exe_options.addOption([:0]const u8, "version", version); 578 exe_options.addOption(std.SemanticVersion, "semver", semver); 579 exe_options.addOption(bool, "enable_debug_extensions", false); 580 exe_options.addOption(bool, "enable_logging", false); 581 exe_options.addOption(bool, "enable_link_snapshots", false); 582 exe_options.addOption(bool, "enable_tracy", false); 583 exe_options.addOption(bool, "enable_tracy_callstack", false); 584 exe_options.addOption(bool, "enable_tracy_allocation", false); 585 exe_options.addOption(bool, "value_tracing", false); 586 exe_options.addOption(bool, "only_core_functionality", true); 587 588 const run_opt = b.addSystemCommand(&.{ 589 "wasm-opt", 590 "-Oz", 591 "--enable-bulk-memory", 592 "--enable-sign-ext", 593 }); 594 run_opt.addArtifactArg(exe); 595 run_opt.addArg("-o"); 596 run_opt.addFileArg(b.path("stage1/zig1.wasm")); 597 598 const copy_zig_h = b.addUpdateSourceFiles(); 599 copy_zig_h.addCopyFileToSource(b.path("lib/zig.h"), "stage1/zig.h"); 600 601 const update_zig1_step = b.step("update-zig1", "Update stage1/zig1.wasm"); 602 update_zig1_step.dependOn(&run_opt.step); 603 update_zig1_step.dependOn(©_zig_h.step); 604 } 605 606 const AddCompilerStepOptions = struct { 607 optimize: std.builtin.OptimizeMode, 608 target: std.Build.ResolvedTarget, 609 strip: ?bool = null, 610 sanitize_thread: ?bool = null, 611 single_threaded: ?bool = null, 612 }; 613 614 fn addCompilerStep(b: *std.Build, options: AddCompilerStepOptions) *std.Build.Step.Compile { 615 const exe = b.addExecutable(.{ 616 .name = "zig", 617 .root_source_file = b.path("src/main.zig"), 618 .target = options.target, 619 .optimize = options.optimize, 620 .max_rss = 7_000_000_000, 621 .strip = options.strip, 622 .sanitize_thread = options.sanitize_thread, 623 .single_threaded = options.single_threaded, 624 }); 625 exe.stack_size = stack_size; 626 627 const aro_module = b.createModule(.{ 628 .root_source_file = b.path("lib/compiler/aro/aro.zig"), 629 }); 630 631 const aro_translate_c_module = b.createModule(.{ 632 .root_source_file = b.path("lib/compiler/aro_translate_c.zig"), 633 .imports = &.{ 634 .{ 635 .name = "aro", 636 .module = aro_module, 637 }, 638 }, 639 }); 640 641 exe.root_module.addImport("aro", aro_module); 642 exe.root_module.addImport("aro_translate_c", aro_translate_c_module); 643 return exe; 644 } 645 646 const exe_cflags = [_][]const u8{ 647 "-std=c++17", 648 "-D__STDC_CONSTANT_MACROS", 649 "-D__STDC_FORMAT_MACROS", 650 "-D__STDC_LIMIT_MACROS", 651 "-D_GNU_SOURCE", 652 "-fno-exceptions", 653 "-fno-rtti", 654 "-fno-stack-protector", 655 "-fvisibility-inlines-hidden", 656 "-Wno-type-limits", 657 "-Wno-missing-braces", 658 "-Wno-comment", 659 }; 660 661 fn addCmakeCfgOptionsToExe( 662 b: *std.Build, 663 cfg: CMakeConfig, 664 exe: *std.Build.Step.Compile, 665 use_zig_libcxx: bool, 666 ) !void { 667 if (exe.rootModuleTarget().isDarwin()) { 668 // useful for package maintainers 669 exe.headerpad_max_install_names = true; 670 } 671 exe.addObjectFile(.{ .cwd_relative = b.pathJoin(&[_][]const u8{ 672 cfg.cmake_binary_dir, 673 "zigcpp", 674 b.fmt("{s}{s}{s}", .{ 675 cfg.cmake_static_library_prefix, 676 "zigcpp", 677 cfg.cmake_static_library_suffix, 678 }), 679 }) }); 680 assert(cfg.lld_include_dir.len != 0); 681 exe.addIncludePath(.{ .cwd_relative = cfg.lld_include_dir }); 682 exe.addIncludePath(.{ .cwd_relative = cfg.llvm_include_dir }); 683 exe.addLibraryPath(.{ .cwd_relative = cfg.llvm_lib_dir }); 684 addCMakeLibraryList(exe, cfg.clang_libraries); 685 addCMakeLibraryList(exe, cfg.lld_libraries); 686 addCMakeLibraryList(exe, cfg.llvm_libraries); 687 688 if (use_zig_libcxx) { 689 exe.linkLibCpp(); 690 } else { 691 // System -lc++ must be used because in this code path we are attempting to link 692 // against system-provided LLVM, Clang, LLD. 693 const need_cpp_includes = true; 694 const static = cfg.llvm_linkage == .static; 695 const lib_suffix = if (static) exe.rootModuleTarget().staticLibSuffix()[1..] else exe.rootModuleTarget().dynamicLibSuffix()[1..]; 696 switch (exe.rootModuleTarget().os.tag) { 697 .linux => { 698 // First we try to link against the detected libcxx name. If that doesn't work, we fall 699 // back to -lc++ and cross our fingers. 700 addCxxKnownPath(b, cfg, exe, b.fmt("lib{s}.{s}", .{ cfg.system_libcxx, lib_suffix }), "", need_cpp_includes) catch |err| switch (err) { 701 error.RequiredLibraryNotFound => { 702 exe.linkLibCpp(); 703 }, 704 else => |e| return e, 705 }; 706 exe.linkSystemLibrary("unwind"); 707 }, 708 .ios, .macos, .watchos, .tvos, .visionos => { 709 exe.linkLibCpp(); 710 }, 711 .windows => { 712 if (exe.rootModuleTarget().abi != .msvc) exe.linkLibCpp(); 713 }, 714 .freebsd => { 715 if (static) { 716 try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{lib_suffix}), null, need_cpp_includes); 717 try addCxxKnownPath(b, cfg, exe, b.fmt("libgcc_eh.{s}", .{lib_suffix}), null, need_cpp_includes); 718 } else { 719 try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{lib_suffix}), null, need_cpp_includes); 720 } 721 }, 722 .openbsd => { 723 try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{lib_suffix}), null, need_cpp_includes); 724 try addCxxKnownPath(b, cfg, exe, b.fmt("libc++abi.{s}", .{lib_suffix}), null, need_cpp_includes); 725 }, 726 .netbsd, .dragonfly => { 727 if (static) { 728 try addCxxKnownPath(b, cfg, exe, b.fmt("libstdc++.{s}", .{lib_suffix}), null, need_cpp_includes); 729 try addCxxKnownPath(b, cfg, exe, b.fmt("libgcc_eh.{s}", .{lib_suffix}), null, need_cpp_includes); 730 } else { 731 try addCxxKnownPath(b, cfg, exe, b.fmt("libstdc++.{s}", .{lib_suffix}), null, need_cpp_includes); 732 } 733 }, 734 .solaris, .illumos => { 735 try addCxxKnownPath(b, cfg, exe, b.fmt("libstdc++.{s}", .{lib_suffix}), null, need_cpp_includes); 736 try addCxxKnownPath(b, cfg, exe, b.fmt("libgcc_eh.{s}", .{lib_suffix}), null, need_cpp_includes); 737 }, 738 .haiku => { 739 try addCxxKnownPath(b, cfg, exe, b.fmt("libstdc++.{s}", .{lib_suffix}), null, need_cpp_includes); 740 }, 741 else => {}, 742 } 743 } 744 745 if (cfg.dia_guids_lib.len != 0) { 746 exe.addObjectFile(.{ .cwd_relative = cfg.dia_guids_lib }); 747 } 748 } 749 750 fn addStaticLlvmOptionsToExe(exe: *std.Build.Step.Compile) !void { 751 // Adds the Zig C++ sources which both stage1 and stage2 need. 752 // 753 // We need this because otherwise zig_clang_cc1_main.cpp ends up pulling 754 // in a dependency on llvm::cfg::Update<llvm::BasicBlock*>::dump() which is 755 // unavailable when LLVM is compiled in Release mode. 756 const zig_cpp_cflags = exe_cflags ++ [_][]const u8{"-DNDEBUG=1"}; 757 exe.addCSourceFiles(.{ 758 .files = &zig_cpp_sources, 759 .flags = &zig_cpp_cflags, 760 }); 761 762 for (clang_libs) |lib_name| { 763 exe.linkSystemLibrary(lib_name); 764 } 765 766 for (lld_libs) |lib_name| { 767 exe.linkSystemLibrary(lib_name); 768 } 769 770 for (llvm_libs) |lib_name| { 771 exe.linkSystemLibrary(lib_name); 772 } 773 774 exe.linkSystemLibrary("z"); 775 exe.linkSystemLibrary("zstd"); 776 777 if (exe.rootModuleTarget().os.tag != .windows or exe.rootModuleTarget().abi != .msvc) { 778 // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries. 779 exe.linkSystemLibrary("c++"); 780 } 781 782 if (exe.rootModuleTarget().os.tag == .windows) { 783 exe.linkSystemLibrary("version"); 784 exe.linkSystemLibrary("uuid"); 785 exe.linkSystemLibrary("ole32"); 786 } 787 } 788 789 fn addCxxKnownPath( 790 b: *std.Build, 791 ctx: CMakeConfig, 792 exe: *std.Build.Step.Compile, 793 objname: []const u8, 794 errtxt: ?[]const u8, 795 need_cpp_includes: bool, 796 ) !void { 797 if (!std.process.can_spawn) 798 return error.RequiredLibraryNotFound; 799 800 const path_padded = run: { 801 var args = std.ArrayList([]const u8).init(b.allocator); 802 try args.append(ctx.cxx_compiler); 803 var it = std.mem.tokenizeAny(u8, ctx.cxx_compiler_arg1, &std.ascii.whitespace); 804 while (it.next()) |arg| try args.append(arg); 805 try args.append(b.fmt("-print-file-name={s}", .{objname})); 806 break :run b.run(args.items); 807 }; 808 var tokenizer = mem.tokenizeAny(u8, path_padded, "\r\n"); 809 const path_unpadded = tokenizer.next().?; 810 if (mem.eql(u8, path_unpadded, objname)) { 811 if (errtxt) |msg| { 812 std.debug.print("{s}", .{msg}); 813 } else { 814 std.debug.print("Unable to determine path to {s}\n", .{objname}); 815 } 816 return error.RequiredLibraryNotFound; 817 } 818 exe.addObjectFile(.{ .cwd_relative = path_unpadded }); 819 820 // TODO a way to integrate with system c++ include files here 821 // c++ -E -Wp,-v -xc++ /dev/null 822 if (need_cpp_includes) { 823 // I used these temporarily for testing something but we obviously need a 824 // more general purpose solution here. 825 //exe.addIncludePath("/nix/store/2lr0fc0ak8rwj0k8n3shcyz1hz63wzma-gcc-11.3.0/include/c++/11.3.0"); 826 //exe.addIncludePath("/nix/store/2lr0fc0ak8rwj0k8n3shcyz1hz63wzma-gcc-11.3.0/include/c++/11.3.0/x86_64-unknown-linux-gnu"); 827 } 828 } 829 830 fn addCMakeLibraryList(exe: *std.Build.Step.Compile, list: []const u8) void { 831 var it = mem.tokenizeScalar(u8, list, ';'); 832 while (it.next()) |lib| { 833 if (mem.startsWith(u8, lib, "-l")) { 834 exe.linkSystemLibrary(lib["-l".len..]); 835 } else if (exe.rootModuleTarget().os.tag == .windows and 836 mem.endsWith(u8, lib, ".lib") and !fs.path.isAbsolute(lib)) 837 { 838 exe.linkSystemLibrary(lib[0 .. lib.len - ".lib".len]); 839 } else { 840 exe.addObjectFile(.{ .cwd_relative = lib }); 841 } 842 } 843 } 844 845 const CMakeConfig = struct { 846 llvm_linkage: std.builtin.LinkMode, 847 cmake_binary_dir: []const u8, 848 cmake_prefix_path: []const u8, 849 cmake_static_library_prefix: []const u8, 850 cmake_static_library_suffix: []const u8, 851 cxx_compiler: []const u8, 852 cxx_compiler_arg1: []const u8, 853 lld_include_dir: []const u8, 854 lld_libraries: []const u8, 855 clang_libraries: []const u8, 856 llvm_lib_dir: []const u8, 857 llvm_include_dir: []const u8, 858 llvm_libraries: []const u8, 859 dia_guids_lib: []const u8, 860 system_libcxx: []const u8, 861 }; 862 863 const max_config_h_bytes = 1 * 1024 * 1024; 864 865 fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 { 866 if (config_h_path_option) |path| { 867 var config_h_or_err = fs.cwd().openFile(path, .{}); 868 if (config_h_or_err) |*file| { 869 file.close(); 870 return path; 871 } else |_| { 872 std.log.err("Could not open provided config.h: \"{s}\"", .{path}); 873 std.process.exit(1); 874 } 875 } 876 877 var check_dir = fs.path.dirname(b.graph.zig_exe).?; 878 while (true) { 879 var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable; 880 defer dir.close(); 881 882 // Check if config.h is present in dir 883 var config_h_or_err = dir.openFile("config.h", .{}); 884 if (config_h_or_err) |*file| { 885 file.close(); 886 return fs.path.join( 887 b.allocator, 888 &[_][]const u8{ check_dir, "config.h" }, 889 ) catch unreachable; 890 } else |e| switch (e) { 891 error.FileNotFound => {}, 892 else => unreachable, 893 } 894 895 // Check if we reached the source root by looking for .git, and bail if so 896 var git_dir_or_err = dir.openDir(".git", .{}); 897 if (git_dir_or_err) |*git_dir| { 898 git_dir.close(); 899 return null; 900 } else |_| {} 901 902 // Otherwise, continue search in the parent directory 903 const new_check_dir = fs.path.dirname(check_dir); 904 if (new_check_dir == null or mem.eql(u8, new_check_dir.?, check_dir)) { 905 return null; 906 } 907 check_dir = new_check_dir.?; 908 } 909 } 910 911 fn parseConfigH(b: *std.Build, config_h_text: []const u8) ?CMakeConfig { 912 var ctx: CMakeConfig = .{ 913 .llvm_linkage = undefined, 914 .cmake_binary_dir = undefined, 915 .cmake_prefix_path = undefined, 916 .cmake_static_library_prefix = undefined, 917 .cmake_static_library_suffix = undefined, 918 .cxx_compiler = undefined, 919 .cxx_compiler_arg1 = "", 920 .lld_include_dir = undefined, 921 .lld_libraries = undefined, 922 .clang_libraries = undefined, 923 .llvm_lib_dir = undefined, 924 .llvm_include_dir = undefined, 925 .llvm_libraries = undefined, 926 .dia_guids_lib = undefined, 927 .system_libcxx = undefined, 928 }; 929 930 const mappings = [_]struct { prefix: []const u8, field: []const u8 }{ 931 .{ 932 .prefix = "#define ZIG_CMAKE_BINARY_DIR ", 933 .field = "cmake_binary_dir", 934 }, 935 .{ 936 .prefix = "#define ZIG_CMAKE_PREFIX_PATH ", 937 .field = "cmake_prefix_path", 938 }, 939 .{ 940 .prefix = "#define ZIG_CMAKE_STATIC_LIBRARY_PREFIX ", 941 .field = "cmake_static_library_prefix", 942 }, 943 .{ 944 .prefix = "#define ZIG_CMAKE_STATIC_LIBRARY_SUFFIX ", 945 .field = "cmake_static_library_suffix", 946 }, 947 .{ 948 .prefix = "#define ZIG_CXX_COMPILER ", 949 .field = "cxx_compiler", 950 }, 951 .{ 952 .prefix = "#define ZIG_CXX_COMPILER_ARG1 ", 953 .field = "cxx_compiler_arg1", 954 }, 955 .{ 956 .prefix = "#define ZIG_LLD_INCLUDE_PATH ", 957 .field = "lld_include_dir", 958 }, 959 .{ 960 .prefix = "#define ZIG_LLD_LIBRARIES ", 961 .field = "lld_libraries", 962 }, 963 .{ 964 .prefix = "#define ZIG_CLANG_LIBRARIES ", 965 .field = "clang_libraries", 966 }, 967 .{ 968 .prefix = "#define ZIG_LLVM_LIBRARIES ", 969 .field = "llvm_libraries", 970 }, 971 .{ 972 .prefix = "#define ZIG_DIA_GUIDS_LIB ", 973 .field = "dia_guids_lib", 974 }, 975 .{ 976 .prefix = "#define ZIG_LLVM_INCLUDE_PATH ", 977 .field = "llvm_include_dir", 978 }, 979 .{ 980 .prefix = "#define ZIG_LLVM_LIB_PATH ", 981 .field = "llvm_lib_dir", 982 }, 983 .{ 984 .prefix = "#define ZIG_SYSTEM_LIBCXX", 985 .field = "system_libcxx", 986 }, 987 // .prefix = ZIG_LLVM_LINK_MODE parsed manually below 988 }; 989 990 var lines_it = mem.tokenizeAny(u8, config_h_text, "\r\n"); 991 while (lines_it.next()) |line| { 992 inline for (mappings) |mapping| { 993 if (mem.startsWith(u8, line, mapping.prefix)) { 994 var it = mem.splitScalar(u8, line, '"'); 995 _ = it.first(); // skip the stuff before the quote 996 const quoted = it.next().?; // the stuff inside the quote 997 const trimmed = mem.trim(u8, quoted, " "); 998 @field(ctx, mapping.field) = toNativePathSep(b, trimmed); 999 } 1000 } 1001 if (mem.startsWith(u8, line, "#define ZIG_LLVM_LINK_MODE ")) { 1002 var it = mem.splitScalar(u8, line, '"'); 1003 _ = it.next().?; // skip the stuff before the quote 1004 const quoted = it.next().?; // the stuff inside the quote 1005 ctx.llvm_linkage = if (mem.eql(u8, quoted, "shared")) .dynamic else .static; 1006 } 1007 } 1008 return ctx; 1009 } 1010 1011 fn toNativePathSep(b: *std.Build, s: []const u8) []u8 { 1012 const duplicated = b.allocator.dupe(u8, s) catch unreachable; 1013 for (duplicated) |*byte| switch (byte.*) { 1014 '/' => byte.* = fs.path.sep, 1015 else => {}, 1016 }; 1017 return duplicated; 1018 } 1019 1020 const zig_cpp_sources = [_][]const u8{ 1021 // These are planned to stay even when we are self-hosted. 1022 "src/zig_llvm.cpp", 1023 "src/zig_clang.cpp", 1024 "src/zig_llvm-ar.cpp", 1025 "src/zig_clang_driver.cpp", 1026 "src/zig_clang_cc1_main.cpp", 1027 "src/zig_clang_cc1as_main.cpp", 1028 }; 1029 1030 const clang_libs = [_][]const u8{ 1031 "clangFrontendTool", 1032 "clangCodeGen", 1033 "clangFrontend", 1034 "clangDriver", 1035 "clangSerialization", 1036 "clangSema", 1037 "clangStaticAnalyzerFrontend", 1038 "clangStaticAnalyzerCheckers", 1039 "clangStaticAnalyzerCore", 1040 "clangAnalysis", 1041 "clangASTMatchers", 1042 "clangAST", 1043 "clangParse", 1044 "clangSema", 1045 "clangAPINotes", 1046 "clangBasic", 1047 "clangEdit", 1048 "clangLex", 1049 "clangARCMigrate", 1050 "clangRewriteFrontend", 1051 "clangRewrite", 1052 "clangCrossTU", 1053 "clangIndex", 1054 "clangToolingCore", 1055 "clangExtractAPI", 1056 "clangSupport", 1057 }; 1058 const lld_libs = [_][]const u8{ 1059 "lldMinGW", 1060 "lldELF", 1061 "lldCOFF", 1062 "lldWasm", 1063 "lldMachO", 1064 "lldCommon", 1065 }; 1066 // This list can be re-generated with `llvm-config --libfiles` and then 1067 // reformatting using your favorite text editor. Note we do not execute 1068 // `llvm-config` here because we are cross compiling. Also omit LLVMTableGen 1069 // from these libs. 1070 const llvm_libs = [_][]const u8{ 1071 "LLVMWindowsManifest", 1072 "LLVMXRay", 1073 "LLVMLibDriver", 1074 "LLVMDlltoolDriver", 1075 "LLVMTextAPIBinaryReader", 1076 "LLVMCoverage", 1077 "LLVMLineEditor", 1078 "LLVMXCoreDisassembler", 1079 "LLVMXCoreCodeGen", 1080 "LLVMXCoreDesc", 1081 "LLVMXCoreInfo", 1082 "LLVMX86TargetMCA", 1083 "LLVMX86Disassembler", 1084 "LLVMX86AsmParser", 1085 "LLVMX86CodeGen", 1086 "LLVMX86Desc", 1087 "LLVMX86Info", 1088 "LLVMWebAssemblyDisassembler", 1089 "LLVMWebAssemblyAsmParser", 1090 "LLVMWebAssemblyCodeGen", 1091 "LLVMWebAssemblyUtils", 1092 "LLVMWebAssemblyDesc", 1093 "LLVMWebAssemblyInfo", 1094 "LLVMVEDisassembler", 1095 "LLVMVEAsmParser", 1096 "LLVMVECodeGen", 1097 "LLVMVEDesc", 1098 "LLVMVEInfo", 1099 "LLVMSystemZDisassembler", 1100 "LLVMSystemZAsmParser", 1101 "LLVMSystemZCodeGen", 1102 "LLVMSystemZDesc", 1103 "LLVMSystemZInfo", 1104 "LLVMSparcDisassembler", 1105 "LLVMSparcAsmParser", 1106 "LLVMSparcCodeGen", 1107 "LLVMSparcDesc", 1108 "LLVMSparcInfo", 1109 "LLVMRISCVTargetMCA", 1110 "LLVMRISCVDisassembler", 1111 "LLVMRISCVAsmParser", 1112 "LLVMRISCVCodeGen", 1113 "LLVMRISCVDesc", 1114 "LLVMRISCVInfo", 1115 "LLVMPowerPCDisassembler", 1116 "LLVMPowerPCAsmParser", 1117 "LLVMPowerPCCodeGen", 1118 "LLVMPowerPCDesc", 1119 "LLVMPowerPCInfo", 1120 "LLVMNVPTXCodeGen", 1121 "LLVMNVPTXDesc", 1122 "LLVMNVPTXInfo", 1123 "LLVMMSP430Disassembler", 1124 "LLVMMSP430AsmParser", 1125 "LLVMMSP430CodeGen", 1126 "LLVMMSP430Desc", 1127 "LLVMMSP430Info", 1128 "LLVMMipsDisassembler", 1129 "LLVMMipsAsmParser", 1130 "LLVMMipsCodeGen", 1131 "LLVMMipsDesc", 1132 "LLVMMipsInfo", 1133 "LLVMLoongArchDisassembler", 1134 "LLVMLoongArchAsmParser", 1135 "LLVMLoongArchCodeGen", 1136 "LLVMLoongArchDesc", 1137 "LLVMLoongArchInfo", 1138 "LLVMLanaiDisassembler", 1139 "LLVMLanaiCodeGen", 1140 "LLVMLanaiAsmParser", 1141 "LLVMLanaiDesc", 1142 "LLVMLanaiInfo", 1143 "LLVMHexagonDisassembler", 1144 "LLVMHexagonCodeGen", 1145 "LLVMHexagonAsmParser", 1146 "LLVMHexagonDesc", 1147 "LLVMHexagonInfo", 1148 "LLVMBPFDisassembler", 1149 "LLVMBPFAsmParser", 1150 "LLVMBPFCodeGen", 1151 "LLVMBPFDesc", 1152 "LLVMBPFInfo", 1153 "LLVMAVRDisassembler", 1154 "LLVMAVRAsmParser", 1155 "LLVMAVRCodeGen", 1156 "LLVMAVRDesc", 1157 "LLVMAVRInfo", 1158 "LLVMARMDisassembler", 1159 "LLVMARMAsmParser", 1160 "LLVMARMCodeGen", 1161 "LLVMARMDesc", 1162 "LLVMARMUtils", 1163 "LLVMARMInfo", 1164 "LLVMAMDGPUTargetMCA", 1165 "LLVMAMDGPUDisassembler", 1166 "LLVMAMDGPUAsmParser", 1167 "LLVMAMDGPUCodeGen", 1168 "LLVMAMDGPUDesc", 1169 "LLVMAMDGPUUtils", 1170 "LLVMAMDGPUInfo", 1171 "LLVMAArch64Disassembler", 1172 "LLVMAArch64AsmParser", 1173 "LLVMAArch64CodeGen", 1174 "LLVMAArch64Desc", 1175 "LLVMAArch64Utils", 1176 "LLVMAArch64Info", 1177 "LLVMOrcDebugging", 1178 "LLVMOrcJIT", 1179 "LLVMWindowsDriver", 1180 "LLVMMCJIT", 1181 "LLVMJITLink", 1182 "LLVMInterpreter", 1183 "LLVMExecutionEngine", 1184 "LLVMRuntimeDyld", 1185 "LLVMOrcTargetProcess", 1186 "LLVMOrcShared", 1187 "LLVMDWP", 1188 "LLVMDebugInfoLogicalView", 1189 "LLVMDebugInfoGSYM", 1190 "LLVMOption", 1191 "LLVMObjectYAML", 1192 "LLVMObjCopy", 1193 "LLVMMCA", 1194 "LLVMMCDisassembler", 1195 "LLVMLTO", 1196 "LLVMPasses", 1197 "LLVMHipStdPar", 1198 "LLVMCFGuard", 1199 "LLVMCoroutines", 1200 "LLVMipo", 1201 "LLVMVectorize", 1202 "LLVMLinker", 1203 "LLVMInstrumentation", 1204 "LLVMFrontendOpenMP", 1205 "LLVMFrontendOffloading", 1206 "LLVMFrontendOpenACC", 1207 "LLVMFrontendHLSL", 1208 "LLVMFrontendDriver", 1209 "LLVMExtensions", 1210 "LLVMDWARFLinkerParallel", 1211 "LLVMDWARFLinkerClassic", 1212 "LLVMDWARFLinker", 1213 "LLVMGlobalISel", 1214 "LLVMMIRParser", 1215 "LLVMAsmPrinter", 1216 "LLVMSelectionDAG", 1217 "LLVMCodeGen", 1218 "LLVMTarget", 1219 "LLVMObjCARCOpts", 1220 "LLVMCodeGenTypes", 1221 "LLVMIRPrinter", 1222 "LLVMInterfaceStub", 1223 "LLVMFileCheck", 1224 "LLVMFuzzMutate", 1225 "LLVMScalarOpts", 1226 "LLVMInstCombine", 1227 "LLVMAggressiveInstCombine", 1228 "LLVMTransformUtils", 1229 "LLVMBitWriter", 1230 "LLVMAnalysis", 1231 "LLVMProfileData", 1232 "LLVMSymbolize", 1233 "LLVMDebugInfoBTF", 1234 "LLVMDebugInfoPDB", 1235 "LLVMDebugInfoMSF", 1236 "LLVMDebugInfoDWARF", 1237 "LLVMObject", 1238 "LLVMTextAPI", 1239 "LLVMMCParser", 1240 "LLVMIRReader", 1241 "LLVMAsmParser", 1242 "LLVMMC", 1243 "LLVMDebugInfoCodeView", 1244 "LLVMBitReader", 1245 "LLVMFuzzerCLI", 1246 "LLVMCore", 1247 "LLVMRemarks", 1248 "LLVMBitstreamReader", 1249 "LLVMBinaryFormat", 1250 "LLVMTargetParser", 1251 "LLVMSupport", 1252 "LLVMDemangle", 1253 }; 1254 1255 fn generateLangRef(b: *std.Build) std.Build.LazyPath { 1256 const doctest_exe = b.addExecutable(.{ 1257 .name = "doctest", 1258 .root_source_file = b.path("tools/doctest.zig"), 1259 .target = b.graph.host, 1260 .optimize = .Debug, 1261 }); 1262 1263 var dir = b.build_root.handle.openDir("doc/langref", .{ .iterate = true }) catch |err| { 1264 std.debug.panic("unable to open 'doc/langref' directory: {s}", .{@errorName(err)}); 1265 }; 1266 defer dir.close(); 1267 1268 var wf = b.addWriteFiles(); 1269 1270 var it = dir.iterateAssumeFirstIteration(); 1271 while (it.next() catch @panic("failed to read dir")) |entry| { 1272 if (std.mem.startsWith(u8, entry.name, ".") or entry.kind != .file) 1273 continue; 1274 1275 const out_basename = b.fmt("{s}.out", .{std.fs.path.stem(entry.name)}); 1276 const cmd = b.addRunArtifact(doctest_exe); 1277 cmd.addArgs(&.{ 1278 "--zig", b.graph.zig_exe, 1279 // TODO: enhance doctest to use "--listen=-" rather than operating 1280 // in a temporary directory 1281 "--cache-root", b.cache_root.path orelse ".", 1282 }); 1283 if (b.zig_lib_dir) |p| { 1284 cmd.addArg("--zig-lib-dir"); 1285 cmd.addDirectoryArg(p); 1286 } 1287 cmd.addArgs(&.{"-i"}); 1288 cmd.addFileArg(b.path(b.fmt("doc/langref/{s}", .{entry.name}))); 1289 1290 cmd.addArgs(&.{"-o"}); 1291 _ = wf.addCopyFile(cmd.addOutputFileArg(out_basename), out_basename); 1292 } 1293 1294 const docgen_exe = b.addExecutable(.{ 1295 .name = "docgen", 1296 .root_source_file = b.path("tools/docgen.zig"), 1297 .target = b.graph.host, 1298 .optimize = .Debug, 1299 }); 1300 1301 const docgen_cmd = b.addRunArtifact(docgen_exe); 1302 docgen_cmd.addArgs(&.{"--code-dir"}); 1303 docgen_cmd.addDirectoryArg(wf.getDirectory()); 1304 1305 docgen_cmd.addFileArg(b.path("doc/langref.html.in")); 1306 return docgen_cmd.addOutputFileArg("langref.html"); 1307 } 1308 1309 fn tidyCheck(b: *std.Build, html_file: std.Build.LazyPath) *std.Build.Step { 1310 const run_tidy = b.addSystemCommand(&.{ 1311 "tidy", "--drop-empty-elements", "no", "-qe", 1312 }); 1313 run_tidy.addFileArg(html_file); 1314 run_tidy.expectExitCode(0); 1315 return &run_tidy.step; 1316 }