╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ build.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
353 const cmake_cfg = if (static_llvm) null else blk: { 354 const io = b.graph.io; 355 const cwd: Io.Dir = .cwd(); 356 if (findConfigH(b, config_h_path_option)) |config_h_path| { 357 const file_contents = cwd.readFileAlloc(io, config_h_path, arena, .limited(max_config_h_bytes)) catch unreachable; 358 break :blk parseConfigH(b, file_contents); 359 } else { 360 std.log.warn("config.h could not be located automatically", .{}); 361 std.log.info("config.h can be provided explicitly via \"-Dconfig_h\"", .{}); 362 break :blk null; 363 } 364 }; 365 366 if (cmake_cfg) |cfg| { 367 // Inside this code path, we have to coordinate with system packaged LLVM, Clang, and LLD. 368 // That means we also have to rely on stage1 compiled c++ files. We parse config.h to find 369 // the information passed on to us from cmake. 370 if (cfg.cmake_prefix_path.len > 0) { 371 var it = mem.tokenizeScalar(u8, cfg.cmake_prefix_path, ';'); 372 while (it.next()) |path| { 373 b.addSearchPrefix(path); 374 } 375 } 376 377 try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx); 378 } else { 379 // Here we are -Denable-llvm but no cmake integration. 380 try addStaticLlvmOptionsToModule(exe.root_module, .{ 381 .llvm_has_m68k = llvm_has_m68k, 382 .llvm_has_csky = llvm_has_csky, 383 .llvm_has_arc = llvm_has_arc, 384 .llvm_has_xtensa = llvm_has_xtensa, 385 }); 386 } 387 if (target.result.os.tag == .windows) { 388 // LLVM depends on networking as of version 18. 389 exe.root_module.linkSystemLibrary("ws2_32", .{}); 390 391 exe.root_module.linkSystemLibrary("version", .{}); 392 exe.root_module.linkSystemLibrary("uuid", .{}); 393 exe.root_module.linkSystemLibrary("ole32", .{}); 394 } 395 } 396 397 const semver = try std.SemanticVersion.parse(version); 398 exe_options.addOption(std.SemanticVersion, "semver", semver); 399 400 exe_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions); 401 exe_options.addOption(bool, "enable_logging", enable_logging); 402 exe_options.addOption(bool, "enable_tracy", tracy != null); 403 exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack); 404 exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation); 405 exe_options.addOption(u32, "tracy_callstack_depth", tracy_callstack_depth); 406 exe_options.addOption(bool, "value_tracing", value_tracing); 407 if (tracy) |tracy_dir| { 408 const tracy_mod = b.createModule(.{ 409 .target = target, 410 // Always build Tracy in ReleaseFast so that it doesn't make -Odebug compiler builds unusable. 411 .optimize = .fast, 412 .root_source_file = null, 413 .link_libc = true, 414 .link_libcpp = true, 415 }); 416 417 tracy_mod.addCMacro("TRACY_ENABLE", "1"); 418 419 if (!tracy_callstack) { 420 tracy_mod.addCMacro("TRACY_NO_CALLSTACK", "1"); 421 } 422 423 tracy_mod.addIncludePath(tracy_dir); 424 tracy_mod.addCSourceFile(.{ .file = tracy_dir.path(b, "public/TracyClient.cpp") }); 425 426 if (target.result.os.tag == .windows) { 427 tracy_mod.linkSystemLibrary("dbghelp", .{}); 428 tracy_mod.linkSystemLibrary("ws2_32", .{}); 429 } 430 431 exe.root_module.addImport("tracy", tracy_mod); 432 } 433 434 const test_filters = b.option([]const []const u8, "test-filter", "Skip tests that do not match any filter") orelse &[0][]const u8{}; 435 const test_target_filters = b.option([]const []const u8, "test-target-filter", "Skip tests whose target triple do not match any filter") orelse &[0][]const u8{}; 436 const test_extra_targets = b.option(bool, "test-extra-targets", "Enable running module tests for additional targets") orelse false; 437 438 var chosen_opt_modes_buf: [4]std.lang.Optimize = undefined; 439 var chosen_mode_index: usize = 0; 440 if (!skip_debug) { 441 chosen_opt_modes_buf[chosen_mode_index] = .debug; 442 chosen_mode_index += 1; 443 } 444 if (!skip_release_safe) { 445 chosen_opt_modes_buf[chosen_mode_index] = .safe; 446 chosen_mode_index += 1; 447 } 448 if (!skip_release_fast) { 449 chosen_opt_modes_buf[chosen_mode_index] = .fast; 450 chosen_mode_index += 1; 451 } 452 if (!skip_release_small) { 453 chosen_opt_modes_buf[chosen_mode_index] = .small; 454 chosen_mode_index += 1; 455 } 456 const optimize_modes = chosen_opt_modes_buf[0..chosen_mode_index]; 457 458 const test_only: ?tests.ModuleTestOptions.TestOnly = if (no_matrix) 459 .default 460 else if (fuzz_only) 461 .{ .fuzz = optimize } 462 else 463 null; 464 465 const fmt_include_paths = b.pathList(&.{ "lib", "src", "test", "tools", "build.zig", "build.zig.zon" }); 466 const fmt_exclude_paths = b.pathList(&.{ "test/cases", "test/behavior/zon" }); 467 const do_fmt = b.addFmt(.{ 468 .paths = fmt_include_paths, 469 .exclude_paths = fmt_exclude_paths, 470 }); 471 b.step("fmt", "Modify source files in place to have conforming formatting").dependOn(&do_fmt.step); 472 473 const check_fmt = b.step("test-fmt", "Check source files having conforming formatting"); 474 check_fmt.dependOn(&b.addFmt(.{ 475 .paths = fmt_include_paths, 476 .exclude_paths = fmt_exclude_paths, 477 .check = true, 478 }).step); 479 test_step.dependOn(check_fmt); 480 481 const test_cases_step = b.step("test-cases", "Run the main compiler test cases"); 482 try tests.addCases(b, test_cases_step, .{ 483 .test_filters = test_filters, 484 .test_target_filters = test_target_filters, 485 .skip_compile_errors = skip_compile_errors, 486 .skip_non_native = skip_non_native, 487 .skip_spirv = skip_spirv, 488 .skip_wasm = skip_wasm, 489 .skip_freebsd = skip_freebsd, 490 .skip_netbsd = skip_netbsd, 491 .skip_openbsd = skip_openbsd, 492 .skip_windows = skip_windows, 493 .skip_darwin = skip_darwin, 494 .skip_linux = skip_linux, 495 .skip_llvm = skip_llvm, 496 .skip_libc = skip_libc, 497 }, .{ 498 .enable_llvm = enable_llvm, 499 .llvm_has_m68k = llvm_has_m68k, 500 .llvm_has_csky = llvm_has_csky, 501 .llvm_has_arc = llvm_has_arc, 502 .llvm_has_xtensa = llvm_has_xtensa, 503 }); 504 test_step.dependOn(test_cases_step); 505 506 const test_modules_step = b.step("test-modules", "Run the per-target module tests"); 507 test_step.dependOn(test_modules_step); 508 509 test_modules_step.dependOn(tests.addModuleTests(b, .{ 510 .test_filters = test_filters, 511 .test_target_filters = test_target_filters, 512 .test_extra_targets = test_extra_targets, 513 .root_src = "test/behavior.zig", 514 .name = "behavior", 515 .desc = "Run the behavior tests", 516 .optimize_modes = optimize_modes, 517 .include_paths = &.{}, 518 .sanitize_thread = sanitize_thread, 519 .skip_single_threaded = skip_single_threaded, 520 .skip_non_native = skip_non_native, 521 .test_only = test_only, 522 .skip_spirv = skip_spirv, 523 .skip_wasm = skip_wasm, 524 .skip_freebsd = skip_freebsd, 525 .skip_netbsd = skip_netbsd, 526 .skip_openbsd = skip_openbsd, 527 .skip_windows = skip_windows, 528 .skip_darwin = skip_darwin, 529 .skip_linux = skip_linux, 530 .skip_llvm = skip_llvm, 531 .skip_libc = skip_libc, 532 .max_rss = 4_000_000_000, 533 })); 534 535 test_modules_step.dependOn(tests.addModuleTests(b, .{ 536 .test_filters = test_filters, 537 .test_target_filters = test_target_filters, 538 .test_extra_targets = test_extra_targets, 539 .root_src = "lib/compiler_rt.zig", 540 .name = "compiler-rt", 541 .desc = "Run the compiler_rt tests", 542 .optimize_modes = optimize_modes, 543 .include_paths = &.{}, 544 .sanitize_thread = sanitize_thread, 545 .skip_single_threaded = true, 546 .skip_non_native = skip_non_native, 547 .test_only = test_only, 548 .skip_spirv = skip_spirv, 549 .skip_wasm = skip_wasm, 550 .skip_freebsd = skip_freebsd, 551 .skip_netbsd = skip_netbsd, 552 .skip_openbsd = skip_openbsd, 553 .skip_windows = skip_windows, 554 .skip_darwin = skip_darwin, 555 .skip_linux = skip_linux, 556 .skip_llvm = skip_llvm, 557 .skip_libc = true, 558 .no_builtin = true, 559 .max_rss = 4_000_000_000, 560 })); 561 562 test_modules_step.dependOn(tests.addModuleTests(b, .{ 563 .test_filters = test_filters, 564 .test_target_filters = test_target_filters, 565 .test_extra_targets = test_extra_targets, 566 .root_src = "lib/std/std.zig", 567 .name = "std", 568 .desc = "Run the standard library tests", 569 .optimize_modes = optimize_modes, 570 .include_paths = &.{}, 571 .sanitize_thread = sanitize_thread, 572 .skip_single_threaded = skip_single_threaded, 573 .skip_non_native = skip_non_native, 574 .test_only = test_only, 575 .skip_spirv = true, 576 .skip_wasm = skip_wasm, 577 .skip_freebsd = skip_freebsd, 578 .skip_netbsd = skip_netbsd, 579 .skip_openbsd = skip_openbsd, 580 .skip_windows = skip_windows, 581 .skip_darwin = skip_darwin, 582 .skip_linux = skip_linux, 583 .skip_llvm = skip_llvm, 584 .skip_libc = skip_libc, 585 .max_rss = 9_600_000_000, 586 })); 587 588 test_modules_step.dependOn(tests.addModuleTests(b, .{ 589 .test_filters = test_filters, 590 .test_target_filters = test_target_filters, 591 .test_extra_targets = test_extra_targets, 592 .root_src = "test/c.zig", 593 .name = "libc", 594 .desc = "Run the libc API tests", 595 .optimize_modes = optimize_modes, 596 .include_paths = &.{}, 597 .sanitize_thread = sanitize_thread, 598 .skip_single_threaded = true, 599 .skip_non_native = skip_non_native, 600 .test_only = test_only, 601 .skip_spirv = true, 602 .skip_wasm = skip_wasm, 603 .skip_freebsd = skip_freebsd, 604 .skip_netbsd = skip_netbsd, 605 .skip_openbsd = skip_openbsd, 606 .skip_windows = skip_windows, 607 .skip_darwin = skip_darwin, 608 .skip_linux = skip_linux, 609 .skip_llvm = skip_llvm, 610 .skip_libc = skip_libc, 611 .no_builtin = true, 612 .max_rss = 4_000_000_000, 613 })); 614 615 const unit_tests_step = b.step("test-unit", "Run the compiler source unit tests"); 616 test_step.dependOn(unit_tests_step); 617 618 const unit_tests = b.addTest(.{ 619 .root_module = addCompilerMod(b, .{ 620 .optimize = optimize, 621 .target = target, 622 .sanitize_thread = sanitize_thread, 623 .single_threaded = single_threaded, 624 }), 625 .filters = test_filters, 626 .use_llvm = use_llvm, 627 .use_lld = use_llvm, 628 .zig_lib_dir = b.path("lib"), 629 .max_rss = 3_000_000_000, 630 }); 631 if (link_libc) { 632 unit_tests.root_module.link_libc = true; 633 } 634 unit_tests.root_module.addOptions("build_options", exe_options); 635 unit_tests_step.dependOn(&b.addRunArtifact(unit_tests).step); 636 637 test_step.dependOn(tests.addStandaloneTests( 638 b, 639 optimize_modes, 640 enable_macos_sdk, 641 enable_ios_sdk, 642 enable_symlinks_windows, 643 )); 644 test_step.dependOn(tests.addCAbiTests(b, .{ 645 .test_target_filters = test_target_filters, 646 .optimize_modes = optimize_modes, 647 .skip_non_native = skip_non_native, 648 .skip_wasm = skip_wasm, 649 .skip_freebsd = skip_freebsd, 650 .skip_netbsd = skip_netbsd, 651 .skip_openbsd = skip_openbsd, 652 .skip_windows = skip_windows, 653 .skip_darwin = skip_darwin, 654 .skip_linux = skip_linux, 655 .skip_llvm = skip_llvm, 656 .max_rss = 4_300_000_000, 657 })); 658 test_step.dependOn(tests.addLinkTests(b, .{ 659 .test_target_filters = test_target_filters, 660 .test_filters = test_filters, 661 .optimize_modes = optimize_modes, 662 .skip_non_native = skip_non_native, 663 .skip_freebsd = skip_freebsd, 664 .skip_netbsd = skip_netbsd, 665 .skip_openbsd = skip_openbsd, 666 .skip_windows = skip_windows, 667 .skip_darwin = skip_darwin, 668 .skip_linux = skip_linux, 669 .skip_llvm = skip_llvm, 670 .skip_libc = skip_libc, 671 .max_rss = 100_000_000, 672 })); 673 test_step.dependOn(tests.addStackTraceTests(b, .{ 674 .test_filters = test_filters, 675 .test_target_filters = test_target_filters, 676 .test_extra_targets = test_extra_targets, 677 .optimize_modes = optimize_modes, 678 .skip_non_native = skip_non_native, 679 .skip_freebsd = skip_freebsd, 680 .skip_netbsd = skip_netbsd, 681 .skip_openbsd = skip_openbsd, 682 .skip_windows = skip_windows, 683 .skip_darwin = skip_darwin, 684 .skip_linux = skip_linux, 685 .skip_llvm = skip_llvm, 686 .skip_libc = skip_libc, 687 })); 688 test_step.dependOn(tests.addErrorTraceTests(b, .{ 689 .test_filters = test_filters, 690 .test_target_filters = test_target_filters, 691 .test_extra_targets = test_extra_targets, 692 .optimize_modes = optimize_modes, 693 .skip_non_native = skip_non_native, 694 .skip_freebsd = skip_freebsd, 695 .skip_netbsd = skip_netbsd, 696 .skip_openbsd = skip_openbsd, 697 .skip_windows = skip_windows, 698 .skip_darwin = skip_darwin, 699 .skip_linux = skip_linux, 700 .skip_llvm = skip_llvm, 701 .skip_libc = skip_libc, 702 })); 703 test_step.dependOn(tests.addCliTests(b)); 704 if (tests.addDebuggerTests(b, .{ 705 .test_filters = test_filters, 706 .test_target_filters = test_target_filters, 707 .gdb = b.option([]const u8, "gdb", "path to gdb binary"), 708 .lldb = b.option([]const u8, "lldb", "path to lldb binary"), 709 .optimize_modes = optimize_modes, 710 .skip_single_threaded = skip_single_threaded, 711 .skip_libc = skip_libc, 712 })) |test_debugger_step| test_step.dependOn(test_debugger_step); 713 if (tests.addLlvmIrTests(b, .{ 714 .enable_llvm = enable_llvm, 715 .test_filters = test_filters, 716 .test_target_filters = test_target_filters, 717 })) |test_llvm_ir_step| test_step.dependOn(test_llvm_ir_step); 718 719 try addWasiUpdateStep(b, version); 720 721 const update_mingw_step = b.step("update-mingw", "Update zig's bundled mingw"); 722 const opt_mingw_src_path = b.option([]const u8, "mingw-src", "path to mingw-w64 source directory"); 723 if (opt_mingw_src_path) |mingw_src_path| { 724 const update_mingw_exe = b.addExecutable(.{ 725 .name = "update_mingw", 726 .root_module = b.createModule(.{ 727 .target = b.graph.host, 728 .root_source_file = b.path("tools/update_mingw.zig"), 729 }), 730 }); 731 const update_mingw_run = b.addRunArtifact(update_mingw_exe); 732 update_mingw_run.addDirectoryArg(b.path("lib")); 733 update_mingw_run.addDirectoryArg(.{ .cwd_relative = mingw_src_path }); 734 735 update_mingw_step.dependOn(&update_mingw_run.step); 736 } else { 737 update_mingw_step.dependOn(&b.addFail("The -Dmingw-src=... option is required for this step").step); 738 } 739 740 const check_mingw_step = b.step("check-mingw", "Checks for mingw preprocessor regressions"); 741 const mingw_preprocessor_mod = b.createModule(.{ 742 .root_source_file = b.path("src/libs/mingw/Preprocessor.zig"), 743 .target = target, 744 }); 745 746 const check_mingw_exe = b.addExecutable(.{ 747 .name = "check_mingw", 748 .root_module = b.createModule(.{ 749 .target = b.graph.host, 750 .root_source_file = b.path("tools/check_mingw.zig"), 751 .imports = &.{ 752 .{ .name = "preprocessor", .module = mingw_preprocessor_mod }, 753 }, 754 }), 755 }); 756 const check_mingw_run = b.addRunArtifact(check_mingw_exe); 757 check_mingw_run.addDirectoryArg(b.path("lib/libc/mingw")); 758 check_mingw_step.dependOn(&check_mingw_run.step); 759 760 { 761 const gen_oracle_exe = b.addExecutable(.{ 762 .name = "gen_parser_oracle", 763 .root_module = b.createModule(.{ 764 .root_source_file = b.path("tools/gen_parser_oracle.zig"), 765 .target = b.graph.host, 766 }), 767 }); 768 769 const gen_oracle_step = b.step("gen-parser-oracle", "Regenerate lib/std/zig/parser_generated_oracle.zig from doc/langref/grammar.peg"); 770 const gen_oracle_run = b.addRunArtifact(gen_oracle_exe); 771 gen_oracle_run.addFileArg(b.path("doc/langref/grammar.peg")); 772 gen_oracle_run.addFileArg(b.path("lib/std/zig/parser_generated_oracle.zig")); 773 gen_oracle_step.dependOn(&gen_oracle_run.step); 774 775 const check_oracle_step = b.step("check-parser-oracle", "Check if doc/langref/grammar.peg was modified without regenerating the oracle"); 776 const check_oracle_run = b.addRunArtifact(gen_oracle_exe); 777 check_oracle_run.addFileArg(b.path("doc/langref/grammar.peg")); 778 check_oracle_run.addFileArg(b.path("lib/std/zig/parser_generated_oracle.zig")); 779 check_oracle_run.addArg("--check"); 780 check_oracle_step.dependOn(&check_oracle_run.step); 781 test_step.dependOn(check_oracle_step); 782 } 783 784 const test_incremental_step = b.step("test-incremental", "Run the incremental compilation test cases"); 785 try tests.addIncrementalTests(b, test_incremental_step, .{ 786 .test_filters = test_filters, 787 .test_target_filters = test_target_filters, 788 .skip_non_native = skip_non_native, 789 .skip_wasm = skip_wasm, 790 .skip_freebsd = skip_freebsd, 791 .skip_netbsd = skip_netbsd, 792 .skip_openbsd = skip_openbsd, 793 .skip_windows = skip_windows, 794 .skip_darwin = skip_darwin, 795 .skip_linux = skip_linux, 796 .skip_llvm = skip_llvm, 797 }); 798 if (!skip_test_incremental) test_step.dependOn(test_incremental_step); 799 800 if (tests.addLibcTestNszTests(b, .{ 801 .optimize_modes = optimize_modes, 802 .test_filters = test_filters, 803 .test_target_filters = test_target_filters, 804 .skip_wasm = skip_wasm, 805 .max_rss = 4_300_000_000, 806 })) |test_libc_nsz_step| test_step.dependOn(test_libc_nsz_step); 807 } 808 809 fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { 810 const semver = try std.SemanticVersion.parse(version); 811 812 const exe = addCompilerStep(b, .{ 813 .optimize = .small, 814 .target = b.resolveTargetQuery(std.Target.Query.parse(.{ 815 .arch_os_abi = "wasm32-wasi", 816 // * `nontrapping_bulk_memory_len0` is supported by `wasm2c`. 817 .cpu_features = "baseline+nontrapping_bulk_memory_len0", 818 }) catch unreachable), 819 }); 820 821 const exe_options = b.addOptions(); 822 exe.root_module.addOptions("build_options", exe_options); 823 824 exe_options.addOption(u32, "mem_leak_frames", 0); 825 exe_options.addOption(bool, "have_llvm", false); 826 exe_options.addOption(bool, "debug_gpa", false); 827 exe_options.addOption([:0]const u8, "version", version); 828 exe_options.addOption(std.SemanticVersion, "semver", semver); 829 exe_options.addOption(bool, "enable_debug_extensions", false); 830 exe_options.addOption(bool, "enable_logging", false); 831 exe_options.addOption(bool, "enable_tracy", false); 832 exe_options.addOption(bool, "enable_tracy_callstack", false); 833 exe_options.addOption(bool, "enable_tracy_allocation", false); 834 exe_options.addOption(u32, "tracy_callstack_depth", 0); 835 exe_options.addOption(bool, "value_tracing", false); 836 exe_options.addOption(DevEnv, "dev", .bootstrap); 837 exe_options.addOption(IoMode, "io_mode", .threaded); 838 839 // zig1 chooses to interpret values by name. The tradeoff is as follows: 840 // 841 // * We lose a small amount of performance. This is essentially irrelevant for zig1. 842 // 843 // * We lose the ability to perform trivial renames on certain `std.lang` types without 844 // zig1.wasm updates. For instance, we cannot rename an enum from PascalCase fields to 845 // snake_case fields without an update. 846 // 847 // * We gain the ability to add and remove fields to and from `std.lang` types without 848 // zig1.wasm updates. For instance, we can add a new tag to `CallingConvention` without 849 // an update. 850 // 851 // Because field renames only happen when we apply a breaking change to the language (which 852 // is becoming progressively rarer), but tags may be added to or removed from target-dependent 853 // types over time in response to new targets coming into use, we gain more than we lose here. 854 exe_options.addOption(ValueInterpretMode, "value_interpret_mode", .by_name); 855 856 const run_opt = b.addSystemCommand(&.{ 857 "wasm-opt", 858 "-Oz", 859 "--enable-bulk-memory", 860 "--enable-mutable-globals", 861 "--enable-extended-const", 862 "--enable-nontrapping-float-to-int", 863 "--enable-sign-ext", 864 }); 865 run_opt.addArtifactArg(exe); 866 run_opt.addArg("-o"); 867 const optimized_wasm = run_opt.addOutputFileArg("zig1.wasm"); 868 869 const update_zig1 = b.addUpdateSourceFiles(); 870 update_zig1.addCopyFileToSource(optimized_wasm, "stage1/zig1.wasm"); 871 update_zig1.addCopyFileToSource(b.path("lib/zig.h"), "stage1/zig.h"); 872 873 const update_zig1_step = b.step("update-zig1", "Update stage1/zig1.wasm"); 874 update_zig1_step.dependOn(&update_zig1.step); 875 } 876 877 const AddCompilerModOptions = struct { 878 optimize: std.lang.Optimize, 879 target: std.Build.ResolvedTarget, 880 strip: ?bool = null, 881 valgrind: ?bool = null, 882 sanitize_thread: ?bool = null, 883 single_threaded: ?bool = null, 884 }; 885 886 fn addCompilerMod(b: *std.Build, options: AddCompilerModOptions) *std.Build.Module { 887 const compiler_mod = b.createModule(.{ 888 .root_source_file = b.path("src/main.zig"), 889 .target = options.target, 890 .optimize = options.optimize, 891 .strip = options.strip, 892 .sanitize_thread = options.sanitize_thread, 893 .single_threaded = options.single_threaded, 894 .valgrind = options.valgrind, 895 }); 896 897 return compiler_mod; 898 } 899 900 fn addCompilerStep(b: *std.Build, options: AddCompilerModOptions) *std.Build.Step.Compile { 901 const exe = b.addExecutable(.{ 902 .name = "zig", 903 // This number should never be raised. If the value is exceeded, then 904 // it is considered a bug in the Zig project that building the 905 // compiler takes more than 8G of memory. 906 .max_rss = 8_000_000_000, 907 .root_module = addCompilerMod(b, options), 908 }); 909 exe.stack_size = stack_size; 910 911 // Must match the condition in CMakeLists.txt. 912 const function_data_sections = switch (options.target.result.cpu.arch) { 913 .arm, 914 .armeb, 915 .thumb, 916 .thumbeb, 917 .hexagon, 918 .powerpc, 919 .powerpcle, 920 .powerpc64, 921 .powerpc64le, 922 => true, 923 else => false, 924 }; 925 926 exe.link_function_sections = function_data_sections; 927 exe.link_data_sections = function_data_sections; 928 929 return exe; 930 } 931 932 const exe_cflags = [_][]const u8{ 933 "-std=c++17", 934 "-D__STDC_CONSTANT_MACROS", 935 "-D__STDC_FORMAT_MACROS", 936 "-D__STDC_LIMIT_MACROS", 937 "-D_GNU_SOURCE", 938 "-fno-exceptions", 939 "-fno-rtti", 940 "-fno-stack-protector", 941 "-fvisibility-inlines-hidden", 942 "-Wno-type-limits", 943 "-Wno-missing-braces", 944 "-Wno-comment", 945 // `exe_cflags` is only used for static linking. 946 "-DLLVM_BUILD_STATIC", 947 "-DCLANG_BUILD_STATIC", 948 }; 949 950 fn addCmakeCfgOptionsToExe( 951 b: *std.Build, 952 cfg: CMakeConfig, 953 exe: *std.Build.Step.Compile, 954 use_zig_libcxx: bool, 955 ) !void { 956 const mod = exe.root_module; 957 const target = &mod.resolved_target.?.result; 958 959 if (target.os.tag.isDarwin()) { 960 // useful for package maintainers 961 exe.headerpad_max_install_names = true; 962 } 963 964 mod.addObjectFile(.{ .cwd_relative = b.pathJoin(&.{ 965 cfg.cmake_binary_dir, 966 "zigcpp", 967 b.fmt("{s}{s}{s}", .{ 968 cfg.cmake_static_library_prefix, 969 "zigcpp", 970 cfg.cmake_static_library_suffix, 971 }), 972 }) }); 973 assert(cfg.lld_include_dir.len != 0); 974 mod.addIncludePath(.{ .cwd_relative = cfg.lld_include_dir }); 975 mod.addIncludePath(.{ .cwd_relative = cfg.llvm_include_dir }); 976 mod.addLibraryPath(.{ .cwd_relative = cfg.llvm_lib_dir }); 977 addCMakeLibraryList(mod, cfg.clang_libraries); 978 addCMakeLibraryList(mod, cfg.lld_libraries); 979 addCMakeLibraryList(mod, cfg.llvm_libraries); 980 981 if (use_zig_libcxx) { 982 mod.link_libcpp = true; 983 } else { 984 // System -lc++ must be used because in this code path we are attempting to link 985 // against system-provided LLVM, Clang, LLD. 986 const need_cpp_includes = true; 987 const static = cfg.llvm_linkage == .static; 988 const lib_suffix = if (static) target.staticLibSuffix()[1..] else target.dynamicLibSuffix()[1..]; 989 switch (target.os.tag) { 990 .linux => { 991 // First we try to link against the detected libcxx name. If that doesn't work, we fall 992 // back to -lc++ and cross our fingers. 993 addCxxKnownPath(b, cfg, exe, b.fmt("lib{s}.{s}", .{ cfg.system_libcxx, lib_suffix }), "", need_cpp_includes) catch |err| switch (err) { 994 error.RequiredLibraryNotFound => { 995 mod.link_libcpp = true; 996 }, 997 else => |e| return e, 998 }; 999 mod.linkSystemLibrary("unwind", .{}); 1000 }, 1001 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { 1002 mod.link_libcpp = true; 1003 }, 1004 .windows => { 1005 if (target.abi != .msvc) mod.link_libcpp = true; 1006 }, 1007 .freebsd => { 1008 try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{lib_suffix}), null, need_cpp_includes); 1009 if (static) try addCxxKnownPath(b, cfg, exe, b.fmt("libgcc_eh.{s}", .{lib_suffix}), null, need_cpp_includes); 1010 }, 1011 .openbsd => { 1012 // - llvm requires libexecinfo which has conflicting symbols with libc++abi 1013 // - only an issue with .a linking 1014 // - workaround is to link c++abi dynamically 1015 try addCxxKnownPath(b, cfg, exe, b.fmt("libc++.{s}", .{target.dynamicLibSuffix()[1..]}), null, need_cpp_includes); 1016 try addCxxKnownPath(b, cfg, exe, b.fmt("libc++abi.{s}", .{target.dynamicLibSuffix()[1..]}), null, need_cpp_includes); 1017 }, 1018 .netbsd, .dragonfly => { 1019 try addCxxKnownPath(b, cfg, exe, b.fmt("libstdc++.{s}", .{lib_suffix}), null, need_cpp_includes); 1020 if (static) try addCxxKnownPath(b, cfg, exe, b.fmt("libgcc_eh.{s}", .{lib_suffix}), null, need_cpp_includes); 1021 }, 1022 .illumos => { 1023 try addCxxKnownPath(b, cfg, exe, b.fmt("libstdc++.{s}", .{lib_suffix}), null, need_cpp_includes); 1024 try addCxxKnownPath(b, cfg, exe, b.fmt("libgcc_eh.{s}", .{lib_suffix}), null, need_cpp_includes); 1025 }, 1026 .haiku => { 1027 try addCxxKnownPath(b, cfg, exe, b.fmt("libstdc++.{s}", .{lib_suffix}), null, need_cpp_includes); 1028 }, 1029 else => {}, 1030 } 1031 } 1032 1033 if (cfg.dia_guids_lib.len != 0) { 1034 mod.addObjectFile(.{ .cwd_relative = cfg.dia_guids_lib }); 1035 } 1036 } 1037 1038 fn addStaticLlvmOptionsToModule(mod: *std.Build.Module, options: struct { 1039 llvm_has_m68k: bool, 1040 llvm_has_csky: bool, 1041 llvm_has_arc: bool, 1042 llvm_has_xtensa: bool, 1043 }) !void { 1044 // Adds the Zig C++ sources which both stage1 and stage2 need. 1045 // 1046 // We need this because otherwise zig_clang_cc1_main.cpp ends up pulling 1047 // in a dependency on llvm::cfg::Update<llvm::BasicBlock*>::dump() which is 1048 // unavailable when LLVM is compiled in Release mode. 1049 const zig_cpp_cflags = exe_cflags ++ [_][]const u8{"-DNDEBUG=1"}; 1050 mod.addCSourceFiles(.{ 1051 .files = &zig_cpp_sources, 1052 .flags = &zig_cpp_cflags, 1053 }); 1054 1055 const lsl_options: std.Build.Module.LinkSystemLibraryOptions = .{ .use_pkg_config = .no }; 1056 1057 for (clang_libs) |lib_name| { 1058 mod.linkSystemLibrary(lib_name, lsl_options); 1059 } 1060 1061 for (lld_libs) |lib_name| { 1062 mod.linkSystemLibrary(lib_name, lsl_options); 1063 } 1064 1065 for (llvm_libs) |lib_name| { 1066 mod.linkSystemLibrary(lib_name, lsl_options); 1067 } 1068 1069 if (options.llvm_has_m68k) for (llvm_libs_m68k) |lib_name| { 1070 mod.linkSystemLibrary(lib_name, lsl_options); 1071 }; 1072 1073 if (options.llvm_has_csky) for (llvm_libs_csky) |lib_name| { 1074 mod.linkSystemLibrary(lib_name, lsl_options); 1075 }; 1076 1077 if (options.llvm_has_arc) for (llvm_libs_arc) |lib_name| { 1078 mod.linkSystemLibrary(lib_name, lsl_options); 1079 }; 1080 1081 if (options.llvm_has_xtensa) for (llvm_libs_xtensa) |lib_name| { 1082 mod.linkSystemLibrary(lib_name, lsl_options); 1083 }; 1084 1085 mod.linkSystemLibrary("z", lsl_options); 1086 mod.linkSystemLibrary("zstd", lsl_options); 1087 1088 if (mod.resolved_target.?.result.os.tag != .windows or mod.resolved_target.?.result.abi != .msvc) { 1089 // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries. 1090 mod.linkSystemLibrary("c++", lsl_options); 1091 } 1092 1093 if (mod.resolved_target.?.result.os.tag == .windows) { 1094 mod.linkSystemLibrary("version", lsl_options); 1095 mod.linkSystemLibrary("uuid", lsl_options); 1096 mod.linkSystemLibrary("ole32", lsl_options); 1097 } 1098 } 1099 1100 fn addCxxKnownPath( 1101 b: *std.Build, 1102 ctx: CMakeConfig, 1103 exe: *std.Build.Step.Compile, 1104 objname: []const u8, 1105 errtxt: ?[]const u8, 1106 need_cpp_includes: bool, 1107 ) !void { 1108 if (!std.process.can_spawn) return error.RequiredLibraryNotFound; 1109 1110 const arena = b.graph.arena; 1111 1112 const path_padded = run: { 1113 var args = std.array_list.Managed([]const u8).init(arena); 1114 try args.append(ctx.cxx_compiler); 1115 var it = std.mem.tokenizeAny(u8, ctx.cxx_compiler_arg1, &std.ascii.whitespace); 1116 while (it.next()) |arg| try args.append(arg); 1117 try args.append(b.fmt("-print-file-name={s}", .{objname})); 1118 break :run b.run(args.items); 1119 }; 1120 var tokenizer = mem.tokenizeAny(u8, path_padded, "\r\n"); 1121 const path_unpadded = tokenizer.next().?; 1122 if (mem.eql(u8, path_unpadded, objname)) { 1123 if (errtxt) |msg| { 1124 std.debug.print("{s}", .{msg}); 1125 } else { 1126 std.debug.print("Unable to determine path to {s}\n", .{objname}); 1127 } 1128 return error.RequiredLibraryNotFound; 1129 } 1130 // By default, explicit library paths are not checked for being linker scripts, 1131 // but libc++ may very well be one, so force all inputs to be checked when passing 1132 // an explicit path to libc++. 1133 exe.allow_so_scripts = true; 1134 exe.root_module.addObjectFile(.{ .cwd_relative = path_unpadded }); 1135 1136 // TODO a way to integrate with system c++ include files here 1137 // c++ -E -Wp,-v -xc++ /dev/null 1138 if (need_cpp_includes) { 1139 // I used these temporarily for testing something but we obviously need a 1140 // more general purpose solution here. 1141 //exe.root_module.addIncludePath("/nix/store/2lr0fc0ak8rwj0k8n3shcyz1hz63wzma-gcc-11.3.0/include/c++/11.3.0"); 1142 //exe.root_module.addIncludePath("/nix/store/2lr0fc0ak8rwj0k8n3shcyz1hz63wzma-gcc-11.3.0/include/c++/11.3.0/x86_64-unknown-linux-gnu"); 1143 } 1144 } 1145 1146 fn addCMakeLibraryList(mod: *std.Build.Module, list: []const u8) void { 1147 var it = mem.tokenizeScalar(u8, list, ';'); 1148 while (it.next()) |lib| { 1149 if (mem.startsWith(u8, lib, "-l")) { 1150 mod.linkSystemLibrary(lib["-l".len..], .{}); 1151 } else if (mod.resolved_target.?.result.os.tag == .windows and 1152 mem.endsWith(u8, lib, ".lib") and !fs.path.isAbsolute(lib)) 1153 { 1154 mod.linkSystemLibrary(lib[0 .. lib.len - ".lib".len], .{}); 1155 } else { 1156 mod.addObjectFile(.{ .cwd_relative = lib }); 1157 } 1158 } 1159 } 1160 1161 const CMakeConfig = struct { 1162 llvm_linkage: std.lang.LinkMode, 1163 cmake_binary_dir: []const u8, 1164 cmake_prefix_path: []const u8, 1165 cmake_static_library_prefix: []const u8, 1166 cmake_static_library_suffix: []const u8, 1167 cxx_compiler: []const u8, 1168 cxx_compiler_arg1: []const u8, 1169 lld_include_dir: []const u8, 1170 lld_libraries: []const u8, 1171 clang_libraries: []const u8, 1172 llvm_lib_dir: []const u8, 1173 llvm_include_dir: []const u8, 1174 llvm_libraries: []const u8, 1175 dia_guids_lib: []const u8, 1176 system_libcxx: []const u8, 1177 }; 1178 1179 const max_config_h_bytes = 1 * 1024 * 1024; 1180 1181 fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 { 1182 const arena = b.graph.arena; 1183 const io = b.graph.io; 1184 const cwd: Io.Dir = .cwd(); 1185 1186 if (config_h_path_option) |path| { 1187 var config_h_or_err = cwd.openFile(io, path, .{}); 1188 if (config_h_or_err) |*file| { 1189 file.close(io); 1190 return path; 1191 } else |_| { 1192 std.log.err("Could not open provided config.h: \"{s}\"", .{path}); 1193 std.process.exit(1); 1194 } 1195 } 1196 1197 var check_dir = fs.path.dirname(b.graph.zig_exe).?; 1198 while (true) { 1199 var dir = cwd.openDir(io, check_dir, .{}) catch unreachable; 1200 defer dir.close(io); 1201 1202 // Check if config.h is present in dir 1203 var config_h_or_err = dir.openFile(io, "config.h", .{}); 1204 if (config_h_or_err) |*file| { 1205 file.close(io); 1206 return fs.path.join( 1207 arena, 1208 &[_][]const u8{ check_dir, "config.h" }, 1209 ) catch unreachable; 1210 } else |e| switch (e) { 1211 error.FileNotFound => {}, 1212 else => unreachable, 1213 } 1214 1215 // Check if we reached the source root by looking for .git, and bail if so 1216 var git_dir_or_err = dir.openDir(io, ".git", .{}); 1217 if (git_dir_or_err) |*git_dir| { 1218 git_dir.close(io); 1219 return null; 1220 } else |_| {} 1221 1222 // Otherwise, continue search in the parent directory 1223 const new_check_dir = fs.path.dirname(check_dir); 1224 if (new_check_dir == null or mem.eql(u8, new_check_dir.?, check_dir)) { 1225 return null; 1226 } 1227 check_dir = new_check_dir.?; 1228 } 1229 } 1230 1231 fn parseConfigH(b: *std.Build, config_h_text: []const u8) ?CMakeConfig { 1232 var ctx: CMakeConfig = .{ 1233 .llvm_linkage = undefined, 1234 .cmake_binary_dir = undefined, 1235 .cmake_prefix_path = undefined, 1236 .cmake_static_library_prefix = undefined, 1237 .cmake_static_library_suffix = undefined, 1238 .cxx_compiler = undefined, 1239 .cxx_compiler_arg1 = "", 1240 .lld_include_dir = undefined, 1241 .lld_libraries = undefined, 1242 .clang_libraries = undefined, 1243 .llvm_lib_dir = undefined, 1244 .llvm_include_dir = undefined, 1245 .llvm_libraries = undefined, 1246 .dia_guids_lib = undefined, 1247 .system_libcxx = undefined, 1248 }; 1249 1250 const mappings = [_]struct { prefix: []const u8, field: []const u8 }{ 1251 .{ 1252 .prefix = "#define ZIG_CMAKE_BINARY_DIR ", 1253 .field = "cmake_binary_dir", 1254 }, 1255 .{ 1256 .prefix = "#define ZIG_CMAKE_PREFIX_PATH ", 1257 .field = "cmake_prefix_path", 1258 }, 1259 .{ 1260 .prefix = "#define ZIG_CMAKE_STATIC_LIBRARY_PREFIX ", 1261 .field = "cmake_static_library_prefix", 1262 }, 1263 .{ 1264 .prefix = "#define ZIG_CMAKE_STATIC_LIBRARY_SUFFIX ", 1265 .field = "cmake_static_library_suffix", 1266 }, 1267 .{ 1268 .prefix = "#define ZIG_CXX_COMPILER ", 1269 .field = "cxx_compiler", 1270 }, 1271 .{ 1272 .prefix = "#define ZIG_CXX_COMPILER_ARG1 ", 1273 .field = "cxx_compiler_arg1", 1274 }, 1275 .{ 1276 .prefix = "#define ZIG_LLD_INCLUDE_PATH ", 1277 .field = "lld_include_dir", 1278 }, 1279 .{ 1280 .prefix = "#define ZIG_LLD_LIBRARIES ", 1281 .field = "lld_libraries", 1282 }, 1283 .{ 1284 .prefix = "#define ZIG_CLANG_LIBRARIES ", 1285 .field = "clang_libraries", 1286 }, 1287 .{ 1288 .prefix = "#define ZIG_LLVM_LIBRARIES ", 1289 .field = "llvm_libraries", 1290 }, 1291 .{ 1292 .prefix = "#define ZIG_DIA_GUIDS_LIB ", 1293 .field = "dia_guids_lib", 1294 }, 1295 .{ 1296 .prefix = "#define ZIG_LLVM_INCLUDE_PATH ", 1297 .field = "llvm_include_dir", 1298 }, 1299 .{ 1300 .prefix = "#define ZIG_LLVM_LIB_PATH ", 1301 .field = "llvm_lib_dir", 1302 }, 1303 .{ 1304 .prefix = "#define ZIG_SYSTEM_LIBCXX", 1305 .field = "system_libcxx", 1306 }, 1307 // .prefix = ZIG_LLVM_LINK_MODE parsed manually below 1308 }; 1309 1310 var lines_it = mem.tokenizeAny(u8, config_h_text, "\r\n"); 1311 while (lines_it.next()) |line| { 1312 inline for (mappings) |mapping| { 1313 if (mem.startsWith(u8, line, mapping.prefix)) { 1314 var it = mem.splitScalar(u8, line, '"'); 1315 _ = it.first(); // skip the stuff before the quote 1316 const quoted = it.next().?; // the stuff inside the quote 1317 const trimmed = mem.trim(u8, quoted, " "); 1318 @field(ctx, mapping.field) = toNativePathSep(b, trimmed); 1319 } 1320 } 1321 if (mem.startsWith(u8, line, "#define ZIG_LLVM_LINK_MODE ")) { 1322 var it = mem.splitScalar(u8, line, '"'); 1323 _ = it.next().?; // skip the stuff before the quote 1324 const quoted = it.next().?; // the stuff inside the quote 1325 ctx.llvm_linkage = if (mem.eql(u8, quoted, "shared")) .dynamic else .static; 1326 } 1327 } 1328 return ctx; 1329 } 1330 1331 fn toNativePathSep(b: *std.Build, s: []const u8) []u8 { 1332 const arena = b.graph.arena; 1333 const duplicated = arena.dupe(u8, s) catch unreachable; 1334 for (duplicated) |*byte| switch (byte.*) { 1335 '/' => byte.* = fs.path.sep, 1336 else => {}, 1337 }; 1338 return duplicated; 1339 } 1340 1341 const zig_cpp_sources = [_][]const u8{ 1342 // These are planned to stay even when we are self-hosted. 1343 "src/zig_llvm.cpp", 1344 "src/zig_llvm-ar.cpp", 1345 "src/zig_clang_driver.cpp", 1346 "src/zig_clang_cc1_main.cpp", 1347 "src/zig_clang_cc1as_main.cpp", 1348 }; 1349 1350 const clang_libs = [_][]const u8{ 1351 "clangFrontendTool", 1352 "clangCodeGen", 1353 "clangStaticAnalyzerFrontend", 1354 "clangStaticAnalyzerCheckers", 1355 "clangStaticAnalyzerCore", 1356 "clangCrossTU", 1357 "clangFrontend", 1358 "clangDriver", 1359 "clangOptions", 1360 "clangSerialization", 1361 "clangSema", 1362 "clangAnalysisLifetimeSafety", 1363 "clangAnalysis", 1364 "clangASTMatchers", 1365 "clangAST", 1366 "clangParse", 1367 "clangSema", 1368 "clangAPINotes", 1369 "clangBasic", 1370 "clangEdit", 1371 "clangLex", 1372 "clangRewriteFrontend", 1373 "clangRewrite", 1374 "clangIndex", 1375 "clangFormat", 1376 "clangToolingInclusions", 1377 "clangToolingCore", 1378 "clangExtractAPI", 1379 "clangSupport", 1380 "clangInstallAPI", 1381 "clangAST", 1382 }; 1383 const lld_libs = [_][]const u8{ 1384 "lldMinGW", 1385 "lldELF", 1386 "lldCOFF", 1387 "lldWasm", 1388 "lldMachO", 1389 "lldCommon", 1390 }; 1391 // This list can be re-generated with `llvm-config --libfiles` and then 1392 // reformatting using your favorite text editor. Note we do not execute 1393 // `llvm-config` here because we are cross compiling. Also omit LLVMTableGen 1394 // from these libs. 1395 const llvm_libs = [_][]const u8{ 1396 "LLVMWindowsManifest", 1397 "LLVMXRay", 1398 "LLVMLibDriver", 1399 "LLVMDlltoolDriver", 1400 "LLVMTelemetry", 1401 "LLVMTextAPIBinaryReader", 1402 "LLVMCoverage", 1403 "LLVMLineEditor", 1404 "LLVMXCoreDisassembler", 1405 "LLVMXCoreCodeGen", 1406 "LLVMXCoreDesc", 1407 "LLVMXCoreInfo", 1408 "LLVMX86TargetMCA", 1409 "LLVMX86Disassembler", 1410 "LLVMX86AsmParser", 1411 "LLVMX86CodeGen", 1412 "LLVMX86Desc", 1413 "LLVMX86Info", 1414 "LLVMWebAssemblyDisassembler", 1415 "LLVMWebAssemblyAsmParser", 1416 "LLVMWebAssemblyCodeGen", 1417 "LLVMWebAssemblyUtils", 1418 "LLVMWebAssemblyDesc", 1419 "LLVMWebAssemblyInfo", 1420 "LLVMVEDisassembler", 1421 "LLVMVEAsmParser", 1422 "LLVMVECodeGen", 1423 "LLVMVEDesc", 1424 "LLVMVEInfo", 1425 "LLVMSystemZDisassembler", 1426 "LLVMSystemZAsmParser", 1427 "LLVMSystemZCodeGen", 1428 "LLVMSystemZDesc", 1429 "LLVMSystemZInfo", 1430 "LLVMSPIRVCodeGen", 1431 "LLVMSPIRVDesc", 1432 "LLVMSPIRVInfo", 1433 "LLVMSPIRVAnalysis", 1434 "LLVMSparcDisassembler", 1435 "LLVMSparcAsmParser", 1436 "LLVMSparcCodeGen", 1437 "LLVMSparcDesc", 1438 "LLVMSparcInfo", 1439 "LLVMRISCVTargetMCA", 1440 "LLVMRISCVDisassembler", 1441 "LLVMRISCVAsmParser", 1442 "LLVMRISCVCodeGen", 1443 "LLVMRISCVDesc", 1444 "LLVMRISCVInfo", 1445 "LLVMPowerPCDisassembler", 1446 "LLVMPowerPCAsmParser", 1447 "LLVMPowerPCCodeGen", 1448 "LLVMPowerPCDesc", 1449 "LLVMPowerPCInfo", 1450 "LLVMNVPTXCodeGen", 1451 "LLVMNVPTXDesc", 1452 "LLVMNVPTXInfo", 1453 "LLVMMSP430Disassembler", 1454 "LLVMMSP430AsmParser", 1455 "LLVMMSP430CodeGen", 1456 "LLVMMSP430Desc", 1457 "LLVMMSP430Info", 1458 "LLVMMipsDisassembler", 1459 "LLVMMipsAsmParser", 1460 "LLVMMipsCodeGen", 1461 "LLVMMipsDesc", 1462 "LLVMMipsInfo", 1463 "LLVMLoongArchDisassembler", 1464 "LLVMLoongArchAsmParser", 1465 "LLVMLoongArchCodeGen", 1466 "LLVMLoongArchDesc", 1467 "LLVMLoongArchInfo", 1468 "LLVMLanaiDisassembler", 1469 "LLVMLanaiCodeGen", 1470 "LLVMLanaiAsmParser", 1471 "LLVMLanaiDesc", 1472 "LLVMLanaiInfo", 1473 "LLVMHexagonDisassembler", 1474 "LLVMHexagonCodeGen", 1475 "LLVMHexagonAsmParser", 1476 "LLVMHexagonDesc", 1477 "LLVMHexagonInfo", 1478 "LLVMBPFDisassembler", 1479 "LLVMBPFAsmParser", 1480 "LLVMBPFCodeGen", 1481 "LLVMBPFDesc", 1482 "LLVMBPFInfo", 1483 "LLVMAVRDisassembler", 1484 "LLVMAVRAsmParser", 1485 "LLVMAVRCodeGen", 1486 "LLVMAVRDesc", 1487 "LLVMAVRInfo", 1488 "LLVMARMDisassembler", 1489 "LLVMARMAsmParser", 1490 "LLVMARMCodeGen", 1491 "LLVMARMDesc", 1492 "LLVMARMUtils", 1493 "LLVMARMInfo", 1494 "LLVMAMDGPUTargetMCA", 1495 "LLVMAMDGPUDisassembler", 1496 "LLVMAMDGPUAsmParser", 1497 "LLVMAMDGPUCodeGen", 1498 "LLVMAMDGPUDesc", 1499 "LLVMAMDGPUUtils", 1500 "LLVMAMDGPUInfo", 1501 "LLVMAArch64Disassembler", 1502 "LLVMAArch64AsmParser", 1503 "LLVMAArch64CodeGen", 1504 "LLVMAArch64Desc", 1505 "LLVMAArch64Utils", 1506 "LLVMAArch64Info", 1507 "LLVMOrcDebugging", 1508 "LLVMOrcJIT", 1509 "LLVMWindowsDriver", 1510 "LLVMMCJIT", 1511 "LLVMJITLink", 1512 "LLVMInterpreter", 1513 "LLVMExecutionEngine", 1514 "LLVMRuntimeDyld", 1515 "LLVMOrcTargetProcess", 1516 "LLVMOrcShared", 1517 "LLVMDWP", 1518 "LLVMDWARFCFIChecker", 1519 "LLVMDebugInfoLogicalView", 1520 "LLVMOption", 1521 "LLVMObjCopy", 1522 "LLVMMCA", 1523 "LLVMMCDisassembler", 1524 "LLVMDTLTO", 1525 "LLVMLTO", 1526 "LLVMFrontendOpenACC", 1527 "LLVMFrontendDriver", 1528 "LLVMExtensions", 1529 "LLVMPlugins", 1530 "LLVMPasses", 1531 "LLVMHipStdPar", 1532 "LLVMCoroutines", 1533 "LLVMCFGuard", 1534 "LLVMipo", 1535 "LLVMInstrumentation", 1536 "LLVMVectorize", 1537 "LLVMSandboxIR", 1538 "LLVMLinker", 1539 "LLVMFrontendOpenMP", 1540 "LLVMFrontendDirective", 1541 "LLVMFrontendAtomic", 1542 "LLVMFrontendOffloading", 1543 "LLVMObjectYAML", 1544 "LLVMDWARFLinkerParallel", 1545 "LLVMDWARFLinkerClassic", 1546 "LLVMDWARFLinker", 1547 "LLVMGlobalISel", 1548 "LLVMMIRParser", 1549 "LLVMAsmPrinter", 1550 "LLVMSelectionDAG", 1551 "LLVMCodeGen", 1552 "LLVMTarget", 1553 "LLVMObjCARCOpts", 1554 "LLVMCodeGenTypes", 1555 "LLVMCGData", 1556 "LLVMCAS", 1557 "LLVMIRPrinter", 1558 "LLVMInterfaceStub", 1559 "LLVMFileCheck", 1560 "LLVMFuzzMutate", 1561 "LLVMScalarOpts", 1562 "LLVMInstCombine", 1563 "LLVMAggressiveInstCombine", 1564 "LLVMTransformUtils", 1565 "LLVMBitWriter", 1566 "LLVMAnalysis", 1567 "LLVMProfileData", 1568 "LLVMSymbolize", 1569 "LLVMDebugInfoBTF", 1570 "LLVMDebugInfoPDB", 1571 "LLVMDebugInfoMSF", 1572 "LLVMDebugInfoCodeView", 1573 "LLVMDebugInfoGSYM", 1574 "LLVMDebugInfoDWARF", 1575 "LLVMObject", 1576 "LLVMTextAPI", 1577 "LLVMMCParser", 1578 "LLVMIRReader", 1579 "LLVMAsmParser", 1580 "LLVMMC", 1581 "LLVMDebugInfoDWARFLowLevel", 1582 "LLVMBitReader", 1583 "LLVMFrontendHLSL", 1584 "LLVMFuzzerCLI", 1585 "LLVMABI", 1586 "LLVMCore", 1587 "LLVMRemarks", 1588 "LLVMBitstreamReader", 1589 "LLVMBinaryFormat", 1590 "LLVMTargetParser", 1591 "LLVMSupport", 1592 "LLVMDemangle", 1593 }; 1594 const llvm_libs_m68k = [_][]const u8{ 1595 "LLVMM68kDisassembler", 1596 "LLVMM68kAsmParser", 1597 "LLVMM68kCodeGen", 1598 "LLVMM68kDesc", 1599 "LLVMM68kInfo", 1600 }; 1601 const llvm_libs_csky = [_][]const u8{ 1602 "LLVMCSKYDisassembler", 1603 "LLVMCSKYAsmParser", 1604 "LLVMCSKYCodeGen", 1605 "LLVMCSKYDesc", 1606 "LLVMCSKYInfo", 1607 }; 1608 const llvm_libs_arc = [_][]const u8{ 1609 "LLVMARCDisassembler", 1610 "LLVMARCCodeGen", 1611 "LLVMARCDesc", 1612 "LLVMARCInfo", 1613 }; 1614 const llvm_libs_xtensa = [_][]const u8{ 1615 "LLVMXtensaDisassembler", 1616 "LLVMXtensaAsmParser", 1617 "LLVMXtensaCodeGen", 1618 "LLVMXtensaDesc", 1619 "LLVMXtensaInfo", 1620 }; 1621 1622 fn generateLangRef(b: *std.Build) !std.Build.LazyPath { 1623 const io = b.graph.io; 1624 const arena = b.graph.arena; 1625 1626 const doctest_exe = b.addExecutable(.{ 1627 .name = "doctest", 1628 .root_module = b.createModule(.{ 1629 .root_source_file = b.path("tools/doctest.zig"), 1630 .target = b.graph.host, 1631 .optimize = .debug, 1632 }), 1633 }); 1634 1635 const langref_path = try b.root.join(arena, "doc/langref"); 1636 1637 var dir = langref_path.root_dir.handle.openDir(io, langref_path.sub_path, .{ .iterate = true }) catch |err| 1638 std.debug.panic("unable to open directory {f}: {t}", .{ langref_path, err }); 1639 defer dir.close(io); 1640 1641 var wf = b.addWriteFiles(); 1642 b.step("test-docs", "Test code snippets from the docs").dependOn(&wf.step); 1643 1644 var it = dir.iterateAssumeFirstIteration(); 1645 while (it.next(io) catch @panic("failed to read dir")) |entry| { 1646 if (entry.kind != .file) continue; 1647 if (std.mem.startsWith(u8, entry.name, ".")) continue; 1648 if (!std.mem.endsWith(u8, entry.name, ".zig")) continue; 1649 1650 const out_basename = b.fmt("{s}.out", .{std.fs.path.stem(entry.name)}); 1651 const cmd = b.addRunArtifact(doctest_exe); 1652 1653 cmd.addArg("--zig"); 1654 cmd.addFileArg(.zig_exe); 1655 1656 cmd.addArg("--cache-root"); 1657 cmd.addDirectoryArg(.cache_root); 1658 1659 cmd.addArg("--zig-lib-dir"); 1660 cmd.addDirectoryArg(.zig_lib); 1661 1662 cmd.addArg("-i"); 1663 cmd.addFileArg(b.path(b.fmt("doc/langref/{s}", .{entry.name}))); 1664 1665 cmd.addArg("-o"); 1666 _ = wf.addCopyFile(cmd.addOutputFileArg(out_basename), out_basename); 1667 } 1668 1669 const docgen_exe = b.addExecutable(.{ 1670 .name = "docgen", 1671 .root_module = b.createModule(.{ 1672 .root_source_file = b.path("tools/docgen.zig"), 1673 .target = b.graph.host, 1674 .optimize = .debug, 1675 }), 1676 }); 1677 1678 const docgen_cmd = b.addRunArtifact(docgen_exe); 1679 docgen_cmd.addArgs(&.{"--code-dir"}); 1680 docgen_cmd.addDirectoryArg(wf.getDirectory()); 1681 docgen_cmd.addArgs(&.{"--grammar"}); 1682 docgen_cmd.addFileArg(b.path("doc/langref/grammar.peg")); 1683 1684 docgen_cmd.addFileArg(b.path("doc/langref.html.in")); 1685 return docgen_cmd.addOutputFileArg("langref.html"); 1686 } 1687 1688 fn superHtmlCheck(b: *std.Build, html_file: std.Build.LazyPath) *std.Build.Step { 1689 const run_superhtml = b.addSystemCommand(&.{ 1690 "superhtml", "check", 1691 }); 1692 run_superhtml.addFileArg(html_file); 1693 run_superhtml.expectExitCode(0); 1694 return &run_superhtml.step; 1695 } 1696