Commit 7eb0a3edce

Andrew Kelley <andrew@ziglang.org>
2020-02-17 00:57:34
remove libc dependency of zig0 building libstage2
Rather than `zig0 build ...` the build now does `zig0 build-lib ...`, avoiding the requirement of linking the build script, and thus avoiding the requirement of finding native libc, for systems where libc is the system ABI.
1 parent 39ee46a
cmake/install.cmake
@@ -1,16 +1,16 @@
 message("-- Installing: ${CMAKE_INSTALL_PREFIX}/lib")
 
-if(NOT EXISTS ${zig0_EXE})
+if(NOT EXISTS ${zig_EXE})
     message("::")
     message(":: ERROR: Executable not found")
     message(":: (execute_process)")
     message("::")
-    message(":: executable: ${zig0_EXE}")
+    message(":: executable: ${zig_EXE}")
     message("::")
     message(FATAL_ERROR)
 endif()
 
-execute_process(COMMAND ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS}
+execute_process(COMMAND ${zig_EXE} ${ZIG_INSTALL_ARGS}
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
     RESULT_VARIABLE _result
 )
@@ -19,11 +19,11 @@ if(_result)
     message(":: ERROR: ${_result}")
     message(":: (execute_process)")
 
-    string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${INSTALL_LIBUSERLAND_ARGS}")
+    string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${ZIG_INSTALL_ARGS}")
     message("::")
-    message(":: argv: ${zig0_EXE} ${s_INSTALL_LIBUSERLAND_ARGS} install")
+    message(":: argv: ${zig_EXE} ${s_INSTALL_LIBUSERLAND_ARGS}")
 
-    set(_args ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS})
+    set(_args ${zig_EXE} ${ZIG_INSTALL_ARGS})
     list(LENGTH _args _len)
     math(EXPR _len "${_len} - 1")
     message("::")
src/main.cpp
@@ -1003,9 +1003,22 @@ static int main0(int argc, char **argv) {
         return main_exit(root_progress_node, EXIT_FAILURE);
     }
 
+    // If both output_dir and enable_cache are provided, and doing build-lib, we
+    // will just do a file copy at the end. This helps when bootstrapping zig from zig0
+    // because we want to pass something like this:
+    // zig0 build-lib --cache on --output-dir ${CMAKE_BINARY_DIR}
+    // And we don't have access to `zig0 build` because that would require detecting native libc
+    // on systems where we are not able to build a libc from source for them.
+    // But that's the only reason this works, so otherwise we give an error here.
+    Buf *final_output_dir_step = nullptr;
     if (output_dir != nullptr && enable_cache == CacheOptOn) {
-        fprintf(stderr, "`--output-dir` is incompatible with --cache on.\n");
-        return print_error_usage(arg0);
+        if (cmd == CmdBuild && out_type == OutTypeLib) {
+            final_output_dir_step = output_dir;
+            output_dir = nullptr;
+        } else {
+            fprintf(stderr, "`--output-dir` is incompatible with --cache on.\n");
+            return print_error_usage(arg0);
+        }
     }
 
     if (target_requires_pic(&target, have_libc) && want_pic == WantPICDisabled) {
@@ -1290,8 +1303,21 @@ static int main0(int argc, char **argv) {
 #if defined(ZIG_OS_WINDOWS)
                         buf_replace(&g->output_file_path, '/', '\\');
 #endif
-                        if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0)
-                            return main_exit(root_progress_node, EXIT_FAILURE);
+                        if (final_output_dir_step != nullptr) {
+                            Buf *dest_basename = buf_alloc();
+                            os_path_split(&g->output_file_path, nullptr, dest_basename);
+                            Buf *dest_path = buf_alloc();
+                            os_path_join(final_output_dir_step, dest_basename, dest_path);
+
+                            if ((err = os_copy_file(&g->output_file_path, dest_path))) {
+                                fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->output_file_path),
+                                        buf_ptr(dest_path), err_str(err));
+                                return main_exit(root_progress_node, EXIT_FAILURE);
+                            }
+                        } else {
+                            if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0)
+                                return main_exit(root_progress_node, EXIT_FAILURE);
+                        }
                     }
                     return main_exit(root_progress_node, EXIT_SUCCESS);
                 } else {
src/userland.cpp
@@ -146,19 +146,8 @@ int stage2_cmd_targets(const char *zig_triple) {
 }
 
 enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) {
-    libc->include_dir = "/dummy/include";
-    libc->include_dir_len = strlen(libc->include_dir);
-    libc->sys_include_dir = "/dummy/sys/include";
-    libc->sys_include_dir_len = strlen(libc->sys_include_dir);
-    libc->crt_dir = "";
-    libc->crt_dir_len = strlen(libc->crt_dir);
-    libc->static_crt_dir = "";
-    libc->static_crt_dir_len = strlen(libc->static_crt_dir);
-    libc->msvc_lib_dir = "";
-    libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir);
-    libc->kernel32_lib_dir = "";
-    libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir);
-    return ErrorNone;
+    const char *msg = "stage0 called stage2_libc_parse";
+    stage2_panic(msg, strlen(msg));
 }
 
 enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) {
src-self-hosted/libc_installation.zig
@@ -204,14 +204,17 @@ pub const LibCInstallation = struct {
                 }
             }
         } else {
-            var batch = Batch(FindError!void, 2, .auto_async).init();
-            batch.add(&async self.findNativeIncludeDirPosix(allocator));
-            if (is_freebsd or is_netbsd) {
-                self.crt_dir = try std.mem.dupeZ(allocator, u8, "/usr/lib");
-            } else if (is_linux or is_dragonfly) {
-                batch.add(&async self.findNativeCrtDirPosix(allocator));
-            }
-            try batch.wait();
+            try blk: {
+                var batch = Batch(FindError!void, 2, .auto_async).init();
+                errdefer batch.wait() catch {};
+                batch.add(&async self.findNativeIncludeDirPosix(allocator));
+                if (is_freebsd or is_netbsd) {
+                    self.crt_dir = try std.mem.dupeZ(allocator, u8, "/usr/lib");
+                } else if (is_linux or is_dragonfly) {
+                    batch.add(&async self.findNativeCrtDirPosix(allocator));
+                }
+                break :blk batch.wait();
+            };
         }
         return self;
     }
build.zig
@@ -64,8 +64,6 @@ pub fn build(b: *Builder) !void {
     try configureStage2(b, test_stage2, ctx);
     try configureStage2(b, exe, ctx);
 
-    addLibUserlandStep(b, mode);
-
     const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;
     const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;
     const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release;
@@ -366,28 +364,3 @@ const Context = struct {
     dia_guids_lib: []const u8,
     llvm: LibraryDep,
 };
-
-fn addLibUserlandStep(b: *Builder, mode: builtin.Mode) void {
-    const artifact = b.addStaticLibrary("userland", "src-self-hosted/stage1.zig");
-    artifact.disable_gen_h = true;
-    artifact.bundle_compiler_rt = true;
-    artifact.setTarget(builtin.arch, builtin.os, builtin.abi);
-    artifact.setBuildMode(mode);
-    artifact.force_pic = true;
-    if (mode != .Debug) {
-        artifact.strip = true;
-    }
-    artifact.linkSystemLibrary("c");
-    if (builtin.os == .windows) {
-        artifact.linkSystemLibrary("ntdll");
-    }
-    const libuserland_step = b.step("libuserland", "Build the userland compiler library for use in stage1");
-    libuserland_step.dependOn(&artifact.step);
-
-    const output_dir = b.option(
-        []const u8,
-        "output-dir",
-        "For libuserland step, where to put the output",
-    ) orelse return;
-    artifact.setOutputDir(output_dir);
-}
CMakeLists.txt
@@ -604,28 +604,29 @@ else()
     set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a")
 endif()
 if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
-    set(LIBUSERLAND_RELEASE_MODE "false")
+    set(LIBUSERLAND_RELEASE_ARG "")
 else()
-    set(LIBUSERLAND_RELEASE_MODE "true")
+    set(LIBUSERLAND_RELEASE_ARG "--release-fast --strip")
+endif()
+if(WIN32)
+    set(LIBUSERLAND_WINDOWS_ARGS "-lntdll")
+else()
+    set(LIBUSERLAND_WINDOWS_ARGS "")
 endif()
 
-set(BUILD_LIBUSERLAND_ARGS "build"
+set(BUILD_LIBUSERLAND_ARGS "build-lib"
     --override-lib-dir "${CMAKE_SOURCE_DIR}/lib"
-    "-Doutput-dir=${CMAKE_BINARY_DIR}"
-    "-Drelease=${LIBUSERLAND_RELEASE_MODE}"
-    "-Dlib-files-only"
-    --prefix "${CMAKE_INSTALL_PREFIX}"
-    libuserland
+    --cache on
+    --output-dir "${CMAKE_BINARY_DIR}"
+    ${LIBUSERLAND_RELEASE_ARG}
+    "src-self-hosted/stage1.zig"
+    --disable-gen-h
+    --bundle-compiler-rt
+    -fPIC
+    -lc
+    ${LIBUSERLAND_WINDOWS_ARGS}
 )
 
-# When using Visual Studio build system generator we default to libuserland install.
-if(MSVC)
-    set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix")
-    if(NOT ZIG_SKIP_INSTALL_LIB_FILES)
-        set(BUILD_LIBUSERLAND_ARGS ${BUILD_LIBUSERLAND_ARGS} install)
-    endif()
-endif()
-
 add_custom_target(zig_build_libuserland ALL
     COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS}
     DEPENDS zig0
@@ -648,12 +649,30 @@ add_dependencies(zig zig_build_libuserland)
 
 install(TARGETS zig DESTINATION bin)
 
-# CODE has no effect with Visual Studio build system generator.
-if(NOT MSVC)
-    get_target_property(zig0_BINARY_DIR zig0 BINARY_DIR)
-    install(CODE "set(zig0_EXE \"${zig0_BINARY_DIR}/zig0\")")
-    install(CODE "set(INSTALL_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\" install)")
-    install(CODE "set(BUILD_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\")")
+set(ZIG_INSTALL_ARGS "build"
+    --override-lib-dir "${CMAKE_SOURCE_DIR}/lib"
+    "-Dlib-files-only"
+    --prefix "${CMAKE_INSTALL_PREFIX}"
+    install
+)
+
+# CODE has no effect with Visual Studio build system generator, therefore
+# when using Visual Studio build system generator we resort to running
+# `zig build install` during the build phase.
+if(MSVC)
+    set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL
+        "Windows-only: Disable copying lib/ files to install prefix during the build phase")
+    if(NOT ZIG_SKIP_INSTALL_LIB_FILES)
+        add_custom_target(zig_install_lib_files ALL
+            COMMAND zig ${ZIG_INSTALL_ARGS}
+            DEPENDS zig
+            WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
+        )
+    endif()
+else()
+    get_target_property(zig_BINARY_DIR zig BINARY_DIR)
+    install(CODE "set(zig_EXE \"${zig_BINARY_DIR}/zig\")")
+    install(CODE "set(ZIG_INSTALL_ARGS \"${ZIG_INSTALL_ARGS}\")")
     install(CODE "set(CMAKE_SOURCE_DIR \"${CMAKE_SOURCE_DIR}\")")
     install(SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/cmake/install.cmake)
 endif()