diff --git a/build.zig b/build.zig index fc8e6dced1..5896ab1a8c 100644 --- a/build.zig +++ b/build.zig @@ -129,6 +129,7 @@ pub fn build(b: *Builder) !void { const force_gpa = b.option(bool, "force-gpa", "Force the compiler to use GeneralPurposeAllocator") orelse false; const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm; const strip = b.option(bool, "strip", "Omit debug information") orelse false; + const use_zig0 = b.option(bool, "zig0", "Bootstrap using zig0") orelse false; 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: { if (strip) break :blk @as(u32, 0); @@ -136,7 +137,11 @@ pub fn build(b: *Builder) !void { break :blk 4; }; - const main_file: ?[]const u8 = if (is_stage1) null else "src/main.zig"; + const main_file: ?[]const u8 = mf: { + if (!is_stage1) break :mf "src/main.zig"; + if (use_zig0) break :mf null; + break :mf "src/stage1.zig"; + }; const exe = b.addExecutable("zig", main_file); exe.strip = strip; @@ -311,8 +316,10 @@ pub fn build(b: *Builder) !void { zig1_obj.addArg("-fsingle-threaded"); } - exe.step.dependOn(&zig1_obj.step); - exe.addObjectFile(zig1_obj_path); + if (use_zig0) { + exe.step.dependOn(&zig1_obj.step); + exe.addObjectFile(zig1_obj_path); + } // This is intentionally a dummy path. stage1.zig tries to @import("compiler_rt") in case // of being built by cmake. But when built by zig it's gonna get a compiler_rt so that @@ -559,9 +566,7 @@ fn addCmakeCfgOptionsToExe( } } -fn addStaticLlvmOptionsToExe( - exe: *std.build.LibExeObjStep, -) !void { +fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep) !void { // Adds the Zig C++ sources which both stage1 and stage2 need. // // We need this because otherwise zig_clang_cc1_main.cpp ends up pulling diff --git a/ci/azure/macos_script b/ci/azure/macos_script index 446ad37bb5..160ce5fe03 100755 --- a/ci/azure/macos_script +++ b/ci/azure/macos_script @@ -55,8 +55,11 @@ make $JOBS install cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig" make $JOBS install -# TODO figure out why this causes a segmentation fault -# release/bin/zig test ../test/behavior.zig -fno-stage1 -fLLVM -I ../test +# Build stage2 standalone so that we can test stage2 against stage2 compiler-rt. +release/bin/zig build -p stage2 -Denable-llvm + +stage2/bin/zig test ../test/behavior.zig -I../test -fLLVM +stage2/bin/zig test ../test/behavior.zig -I../test release/bin/zig build test-toolchain -Denable-macos-sdk release/bin/zig build test-std diff --git a/ci/azure/windows_script.bat b/ci/azure/windows_script.bat deleted file mode 100644 index 5002fce24b..0000000000 --- a/ci/azure/windows_script.bat +++ /dev/null @@ -1,8 +0,0 @@ -@echo on -SET "SRCROOT=%cd%" -SET "PREVPATH=%PATH%" -SET "PREVMSYSTEM=%MSYSTEM%" - -set "PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem" -SET "MSYSTEM=MINGW64" -bash -lc "cd ${SRCROOT} && ci/azure/windows_script" || exit /b diff --git a/ci/zinc/drone.yml b/ci/zinc/drone.yml index d6fac279e1..cb105381ae 100644 --- a/ci/zinc/drone.yml +++ b/ci/zinc/drone.yml @@ -9,19 +9,7 @@ workspace: path: /workspace steps: -- name: probe - image: ci/debian-amd64:11.1-3 - commands: - - ./ci/zinc/linux_probe.sh - -- name: build - image: ci/debian-amd64:11.1-3 - commands: - - ./ci/zinc/linux_build.sh - - name: test - depends_on: - - build image: ci/debian-amd64:11.1-3 commands: - ./ci/zinc/linux_test.sh diff --git a/ci/zinc/linux_base.sh b/ci/zinc/linux_base.sh index 5d33e19e67..f1e9924258 100755 --- a/ci/zinc/linux_base.sh +++ b/ci/zinc/linux_base.sh @@ -17,7 +17,6 @@ set -x set -e ARCH="$(uname -m)" -JOBS="-j$(nproc)" DEPS_LOCAL="/deps/local" WORKSPACE="$DRONE_WORKSPACE" diff --git a/ci/zinc/linux_build.sh b/ci/zinc/linux_build.sh deleted file mode 100755 index 1d468bbd25..0000000000 --- a/ci/zinc/linux_build.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/sh - -. ./ci/zinc/linux_base.sh - -ZIG="$DEPS_LOCAL/bin/zig" -TARGET="${ARCH}-linux-musl" -MCPU="baseline" - -# Make the `zig version` number consistent. -# This will affect the cmake command below. -git config core.abbrev 9 - -# Build debug zig. -echo "BUILD debug zig with zig:$($ZIG version)" - -export CC="$ZIG cc -target $TARGET -mcpu=$MCPU" -export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU" - -mkdir _debug -cd _debug -cmake .. \ - -DCMAKE_INSTALL_PREFIX="$DEBUG_STAGING" \ - -DCMAKE_PREFIX_PATH="$DEPS_LOCAL" \ - -DCMAKE_BUILD_TYPE=Debug \ - -DZIG_TARGET_TRIPLE="$TARGET" \ - -DZIG_TARGET_MCPU="$MCPU" \ - -DZIG_STATIC=ON \ - -GNinja - -# Now cmake will use zig as the C/C++ compiler. We reset the environment variables -# so that installation and testing do not get affected by them. -unset CC -unset CXX - -ninja $JOBS install - -ZIG=$DEBUG_STAGING/bin/zig - -# Here we rebuild zig but this time using the Zig binary we just now produced to -# build zig1.o rather than relying on the one built with stage0. See -# https://github.com/ziglang/zig/issues/6830 for more details. -cmake .. -DZIG_EXECUTABLE="$ZIG" -ninja $JOBS install - -cd $WORKSPACE - -# Build release zig. -echo "BUILD release zig with zig:$($ZIG version)" -export CC="$ZIG cc -target $TARGET -mcpu=$MCPU" -export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU" -mkdir _release -cd _release -cmake .. \ - -DCMAKE_INSTALL_PREFIX="$RELEASE_STAGING" \ - -DCMAKE_PREFIX_PATH="$DEPS_LOCAL" \ - -DCMAKE_BUILD_TYPE=Release \ - -DZIG_TARGET_TRIPLE="$TARGET" \ - -DZIG_TARGET_MCPU="$MCPU" \ - -DZIG_STATIC=ON \ - -GNinja -unset CC -unset CXX -ninja $JOBS install - -cd $WORKSPACE - -# Look for non-conforming code formatting. -# Formatting errors can be fixed by running `zig fmt` on the files printed here. -$ZIG fmt --check . - -# Explicit exit helps show last command duration. -exit diff --git a/ci/zinc/linux_probe.sh b/ci/zinc/linux_probe.sh deleted file mode 100755 index 7c7d6c52fe..0000000000 --- a/ci/zinc/linux_probe.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -. ./ci/zinc/linux_base.sh - -# Probe CPU/brand details. -echo "lscpu:" -(lscpu | sed 's,^, : ,') 1>&2 - -# Explicit exit helps show last command duration. -exit diff --git a/ci/zinc/linux_test.sh b/ci/zinc/linux_test.sh index 453269029d..969e19312e 100755 --- a/ci/zinc/linux_test.sh +++ b/ci/zinc/linux_test.sh @@ -2,15 +2,65 @@ . ./ci/zinc/linux_base.sh -ZIG=$DEBUG_STAGING/bin/zig +ZIG="$DEPS_LOCAL/bin/zig" +TARGET="${ARCH}-linux-musl" +MCPU="baseline" -$ZIG test test/behavior.zig -fno-stage1 -I test -fLLVM -$ZIG test test/behavior.zig -fno-stage1 -I test -fLLVM -target aarch64-linux --test-cmd qemu-aarch64 --test-cmd-bin -$ZIG test test/behavior.zig -fno-stage1 -I test -ofmt=c -$ZIG test test/behavior.zig -fno-stage1 -I test -target wasm32-wasi --test-cmd wasmtime --test-cmd-bin -$ZIG test test/behavior.zig -fno-stage1 -I test -target arm-linux --test-cmd qemu-arm --test-cmd-bin -$ZIG test test/behavior.zig -fno-stage1 -I test -target aarch64-linux --test-cmd qemu-aarch64 --test-cmd-bin -$ZIG test test/behavior.zig -fno-stage1 -I test +# Make the `zig version` number consistent. +# This will affect the cmake command below. +git config core.abbrev 9 + +echo "BUILD debug zig with zig:$($ZIG version)" + +export CC="$ZIG cc -target $TARGET -mcpu=$MCPU" +export CXX="$ZIG c++ -target $TARGET -mcpu=$MCPU" + +mkdir _debug +cd _debug +cmake .. \ + -DCMAKE_INSTALL_PREFIX="$DEBUG_STAGING" \ + -DCMAKE_PREFIX_PATH="$DEPS_LOCAL" \ + -DCMAKE_BUILD_TYPE=Debug \ + -DZIG_TARGET_TRIPLE="$TARGET" \ + -DZIG_TARGET_MCPU="$MCPU" \ + -DZIG_STATIC=ON \ + -GNinja + +# Now cmake will use zig as the C/C++ compiler. We reset the environment variables +# so that installation and testing do not get affected by them. +unset CC +unset CXX + +ninja install + +ZIG="$DEBUG_STAGING/bin/zig" + +# Here we rebuild zig but this time using the Zig binary we just now produced to +# build zig1.o rather than relying on the one built with stage0. See +# https://github.com/ziglang/zig/issues/6830 for more details. +cmake .. -DZIG_EXECUTABLE="$ZIG" +ninja install + +cd $WORKSPACE + +# Look for non-conforming code formatting. +# Formatting errors can be fixed by running `zig fmt` on the files printed here. +$ZIG fmt --check . + +# Build stage2 standalone so that we can test stage2 against stage2 compiler-rt. +$ZIG build -p stage2 -Denable-llvm -Duse-zig-libcxx + +stage2/bin/zig test test/behavior.zig -I test -fLLVM +stage2/bin/zig test test/behavior.zig -I test +stage2/bin/zig test test/behavior.zig -I test -fLLVM -target aarch64-linux --test-cmd qemu-aarch64 --test-cmd-bin +stage2/bin/zig test test/behavior.zig -I test -target aarch64-linux --test-cmd qemu-aarch64 --test-cmd-bin +stage2/bin/zig test test/behavior.zig -I test -ofmt=c +stage2/bin/zig test test/behavior.zig -I test -target wasm32-wasi --test-cmd wasmtime --test-cmd-bin +stage2/bin/zig test test/behavior.zig -I test -target arm-linux --test-cmd qemu-arm --test-cmd-bin +stage2/bin/zig test test/behavior.zig -I test -fLLVM -target aarch64-macos --test-no-exec +stage2/bin/zig test test/behavior.zig -I test -target aarch64-macos --test-no-exec +stage2/bin/zig test test/behavior.zig -I test -fLLVM -target x86_64-macos --test-no-exec +stage2/bin/zig test test/behavior.zig -I test -target x86_64-macos --test-no-exec $ZIG build test-behavior -fqemu -fwasmtime $ZIG build test-compiler-rt -fqemu -fwasmtime @@ -31,7 +81,7 @@ $ZIG build test-fmt -fqemu -fwasmtime $ZIG build test-stage2 -fqemu -fwasmtime # Produce the experimental std lib documentation. -mkdir -p $RELEASE_STAGING/docs/std +mkdir -p "$RELEASE_STAGING/docs/std" $ZIG test lib/std/std.zig \ --zig-lib-dir lib \ -femit-docs=$RELEASE_STAGING/docs/std \ @@ -40,5 +90,16 @@ $ZIG test lib/std/std.zig \ # Look for HTML errors. tidy --drop-empty-elements no -qe zig-cache/langref.html +# Build release zig. +$ZIG build \ + --prefix "$RELEASE_STAGING" \ + --search-prefix "$DEPS_LOCAL" \ + -Denable-llvm \ + -Duse-zig-libcxx \ + -Drelease \ + -Dstrip \ + -Dtarget="$TARGET" \ + -Dstage1 + # Explicit exit helps show last command duration. exit diff --git a/src/main.zig b/src/main.zig index 05afc2b166..248ae2dd76 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2008,28 +2008,34 @@ fn buildOutputType( // are part of libc or libc++. We remove them from the list and communicate their // existence via flags instead. { + // Similarly, if any libs in this list are statically provided, we remove + // them from this list and populate the link_objects array instead. + const sep = fs.path.sep_str; + var test_path = std.ArrayList(u8).init(gpa); + defer test_path.deinit(); + var i: usize = 0; - while (i < system_libs.count()) { + syslib: while (i < system_libs.count()) { const lib_name = system_libs.keys()[i]; if (target_util.is_libc_lib_name(target_info.target, lib_name)) { link_libc = true; - _ = system_libs.orderedRemove(lib_name); + system_libs.orderedRemoveAt(i); continue; } if (target_util.is_libcpp_lib_name(target_info.target, lib_name)) { link_libcpp = true; - _ = system_libs.orderedRemove(lib_name); + system_libs.orderedRemoveAt(i); continue; } if (mem.eql(u8, lib_name, "unwind")) { link_libunwind = true; - _ = system_libs.orderedRemove(lib_name); + system_libs.orderedRemoveAt(i); continue; } if (target_util.is_compiler_rt_lib_name(target_info.target, lib_name)) { std.log.warn("ignoring superfluous library '{s}': this dependency is fulfilled instead by compiler-rt which zig unconditionally provides", .{lib_name}); - _ = system_libs.orderedRemove(lib_name); + system_libs.orderedRemoveAt(i); continue; } if (std.fs.path.isAbsolute(lib_name)) { @@ -2038,10 +2044,32 @@ fn buildOutputType( if (target_info.target.os.tag == .wasi) { if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { try wasi_emulated_libs.append(crt_file); - _ = system_libs.orderedRemove(lib_name); + system_libs.orderedRemoveAt(i); continue; } } + + for (lib_dirs.items) |lib_dir_path| { + test_path.clearRetainingCapacity(); + try test_path.writer().print("{s}" ++ sep ++ "{s}{s}{s}", .{ + lib_dir_path, + target_info.target.libPrefix(), + lib_name, + target_info.target.staticLibSuffix(), + }); + fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { + error.FileNotFound => continue, + else => |e| fatal("unable to search for static library '{s}': {s}", .{ + test_path.items, @errorName(e), + }), + }; + try link_objects.append(.{ .path = try arena.dupe(u8, test_path.items) }); + system_libs.orderedRemoveAt(i); + continue :syslib; + } + + std.log.scoped(.cli).debug("depending on system for -l{s}", .{lib_name}); + i += 1; } } @@ -2068,7 +2096,9 @@ fn buildOutputType( want_native_include_dirs = true; } - if (sysroot == null and cross_target.isNativeOs() and (system_libs.count() != 0 or want_native_include_dirs)) { + if (sysroot == null and cross_target.isNativeOs() and + (system_libs.count() != 0 or want_native_include_dirs)) + { const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| { fatal("unable to detect native system paths: {s}", .{@errorName(err)}); };