Commit 621e89a863

Andrew Kelley <andrew@ziglang.org>
2023-11-06 04:23:52
add bootstrap.c for building from source without LLVM
When a zig compiler without LLVM extensions is satisfactory, this greatly simplified build-from-source process can be used. This could be useful for users who only want to contribute to the standard library, for example.
1 parent 53500a5
Changed files (2)
bootstrap.c
@@ -0,0 +1,183 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+static const char *get_c_compiler(void) {
+    const char *cc = getenv("CC");
+    return (cc == NULL) ? "cc" : cc;
+}
+
+static void panic(const char *reason) {
+    fprintf(stderr, "%s\n", reason);
+    abort();
+}
+
+#if defined(__WIN32__)
+#error TODO write the functionality for executing child process into this build script
+#else
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+static void run(char **argv) {
+    pid_t pid = fork();
+    if (pid == -1)
+        panic("fork failed");
+    if (pid == 0) {
+        // child
+        execvp(argv[0], argv);
+        exit(1);
+    }
+
+    // parent
+
+    int status;
+    waitpid(pid, &status, 0);
+
+    if (!WIFEXITED(status))
+        panic("child process crashed");
+
+    if (WEXITSTATUS(status) != 0)
+        panic("child process failed");
+}
+
+static void run_execv(char **argv) {
+    if (execv(argv[0], argv) == -1 && errno == ENOENT) return;
+    perror("execv failed");
+}
+#endif
+
+static void print_and_run(const char **argv) {
+    fprintf(stderr, "%s", argv[0]);
+    for (const char **arg = argv + 1; *arg; arg += 1) {
+        fprintf(stderr, " %s", *arg);
+    }
+    fprintf(stderr, "\n");
+    run((char **)argv);
+}
+
+static const char *get_host_os(void) {
+#if defined(__WIN32__)
+    return "windows";
+#elif defined(__APPLE__)
+    return "macos";
+#elif defined(__linux__)
+    return "linux";
+#else
+#error TODO implement get_host_os in this build script for this target
+#endif
+}
+
+static const char *get_host_arch(void) {
+#if defined(__x86_64__ )
+    return "x86_64";
+#elif defined(__aarch64__)
+    return "aarch64";
+#else
+#error TODO implement get_host_arch in this build script for this target
+#endif
+}
+
+static const char *get_host_triple(void) {
+    static char global_buffer[100];
+    sprintf(global_buffer, "%s-%s", get_host_arch(), get_host_os());
+    return global_buffer;
+}
+
+int main(int argc, char **argv) {
+    argv[0] = "./zig2";
+    run_execv(argv);
+
+    const char *cc = get_c_compiler();
+    const char *host_triple = get_host_triple();
+
+    {
+        const char *child_argv[] = {
+            cc, "-o", "zig-wasm2c", "stage1/wasm2c.c", "-O2", "-std=c99", NULL,
+        };
+        print_and_run(child_argv);
+    }
+    {
+        const char *child_argv[] = {
+            "./zig-wasm2c", "stage1/zig1.wasm", "zig1.c", NULL,
+        };
+        print_and_run(child_argv);
+    }
+    {
+        const char *child_argv[] = {
+            cc, "-o", "zig1", "zig1.c", "stage1/wasi.c", "-std=c99", "-Os", "-lm", NULL,
+        };
+        print_and_run(child_argv);
+    }
+    {
+        FILE *f = fopen("config.zig", "wb");
+        if (f == NULL)
+            panic("unable to open config.zig for writing");
+
+        const char *zig_version = "0.12.0-dev.bootstrap";
+
+        int written = fprintf(f,
+            "pub const have_llvm = false;\n"
+            "pub const llvm_has_m68k = false;\n"
+            "pub const llvm_has_csky = false;\n"
+            "pub const llvm_has_arc = false;\n"
+            "pub const llvm_has_xtensa = false;\n"
+            "pub const version: [:0]const u8 = \"%s\";\n"
+            "pub const semver = @import(\"std\").SemanticVersion.parse(version) catch unreachable;\n"
+            "pub const enable_logging: bool = false;\n"
+            "pub const enable_link_snapshots: bool = false;\n"
+            "pub const enable_tracy = false;\n"
+            "pub const value_tracing = false;\n"
+            "pub const skip_non_native = false;\n"
+            "pub const only_c = false;\n"
+            "pub const force_gpa = false;\n"
+            "pub const only_core_functionality = true;\n"
+            "pub const only_reduce = false;\n"
+        , zig_version);
+        if (written < 100)
+            panic("unable to write to config.zig file");
+        if (fclose(f) != 0)
+            panic("unable to finish writing to config.zig file");
+    }
+
+    {
+        const char *child_argv[] = {
+            "./zig1", "lib", "build-exe", "src/main.zig",
+            "-ofmt=c", "-lc", "-OReleaseSmall",
+            "--name", "zig2", "-femit-bin=zig2.c",
+            "--mod", "build_options::config.zig",
+            "--mod", "aro::deps/aro/lib.zig",
+            "--deps", "build_options,aro",
+            "-target", host_triple,
+            NULL,
+        };
+        print_and_run(child_argv);
+    }
+
+    {
+        const char *child_argv[] = {
+            "./zig1", "lib", "build-obj", "lib/compiler_rt.zig",
+            "-ofmt=c", "-OReleaseSmall",
+            "--name", "compiler_rt", "-femit-bin=compiler_rt.c",
+            "--mod", "build_options::config.zig",
+            "--deps", "build_options",
+            "-target", host_triple,
+            NULL,
+        };
+        print_and_run(child_argv);
+    }
+
+    {
+        const char *child_argv[] = {
+            cc, "-o", "zig2", "zig2.c", "compiler_rt.c",
+            "-std=c99", "-O2", "-fno-stack-protector",
+            "-Wl,-z,stack-size=0x10000000", "-Istage1", NULL,
+        };
+        print_and_run(child_argv);
+    }
+
+    run_execv(argv);
+    panic("build script failed to create valid zig2 executable");
+}
README.md
@@ -64,6 +64,20 @@ For more options, tips, and troubleshooting, please see the
 [Building Zig From Source](https://github.com/ziglang/zig/wiki/Building-Zig-From-Source)
 page on the wiki.
 
+## Building from Source without LLVM
+
+If you don't need your Zig compiler to have LLVM extensions enabled, you can
+follow these instructions instead.
+
+In this case, the only system dependency is a C compiler.
+
+```
+cc -o bootstrap bootstrap.c
+./bootstrap build
+```
+
+You can pass any options to this that you would pass to `zig build`.
+
 ## Contributing
 
 Zig is Free and Open Source Software. We welcome bug reports and patches from