diff --git a/README.md b/README.md index 8fb01b711c..699cf9a025 100644 --- a/README.md +++ b/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 diff --git a/bootstrap.c b/bootstrap.c new file mode 100644 index 0000000000..da8b10064f --- /dev/null +++ b/bootstrap.c @@ -0,0 +1,183 @@ +#include +#include +#include +#include + +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 +#include +#include + +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"); +}