authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-05 20:23:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-12 17:30:24-07:00
log621e89a863152978834f2c2562971cca846f9b3e
treed333e1d585f8c4a8533a911ce7f87de6e911de31
parent53500a57684665e08a2e18e7a736aacfa6548062

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.

2 files changed, 197 insertions(+), 0 deletions(-)

README.md+14
......@@ -64,6 +64,20 @@ For more options, tips, and troubleshooting, please see the
6464[Building Zig From Source](https://github.com/ziglang/zig/wiki/Building-Zig-From-Source)
6565page on the wiki.
6666
67## Building from Source without LLVM
68
69If you don't need your Zig compiler to have LLVM extensions enabled, you can
70follow these instructions instead.
71
72In this case, the only system dependency is a C compiler.
73
74```
75cc -o bootstrap bootstrap.c
76./bootstrap build
77```
78
79You can pass any options to this that you would pass to `zig build`.
80
6781## Contributing
6882
6983Zig is Free and Open Source Software. We welcome bug reports and patches from
bootstrap.c created+183
......@@ -0,0 +1,183 @@
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4#include <stdbool.h>
5
6static const char *get_c_compiler(void) {
7 const char *cc = getenv("CC");
8 return (cc == NULL) ? "cc" : cc;
9}
10
11static void panic(const char *reason) {
12 fprintf(stderr, "%s\n", reason);
13 abort();
14}
15
16#if defined(__WIN32__)
17#error TODO write the functionality for executing child process into this build script
18#else
19
20#include <unistd.h>
21#include <errno.h>
22#include <sys/wait.h>
23
24static void run(char **argv) {
25 pid_t pid = fork();
26 if (pid == -1)
27 panic("fork failed");
28 if (pid == 0) {
29 // child
30 execvp(argv[0], argv);
31 exit(1);
32 }
33
34 // parent
35
36 int status;
37 waitpid(pid, &status, 0);
38
39 if (!WIFEXITED(status))
40 panic("child process crashed");
41
42 if (WEXITSTATUS(status) != 0)
43 panic("child process failed");
44}
45
46static void run_execv(char **argv) {
47 if (execv(argv[0], argv) == -1 && errno == ENOENT) return;
48 perror("execv failed");
49}
50#endif
51
52static void print_and_run(const char **argv) {
53 fprintf(stderr, "%s", argv[0]);
54 for (const char **arg = argv + 1; *arg; arg += 1) {
55 fprintf(stderr, " %s", *arg);
56 }
57 fprintf(stderr, "\n");
58 run((char **)argv);
59}
60
61static const char *get_host_os(void) {
62#if defined(__WIN32__)
63 return "windows";
64#elif defined(__APPLE__)
65 return "macos";
66#elif defined(__linux__)
67 return "linux";
68#else
69#error TODO implement get_host_os in this build script for this target
70#endif
71}
72
73static const char *get_host_arch(void) {
74#if defined(__x86_64__ )
75 return "x86_64";
76#elif defined(__aarch64__)
77 return "aarch64";
78#else
79#error TODO implement get_host_arch in this build script for this target
80#endif
81}
82
83static const char *get_host_triple(void) {
84 static char global_buffer[100];
85 sprintf(global_buffer, "%s-%s", get_host_arch(), get_host_os());
86 return global_buffer;
87}
88
89int main(int argc, char **argv) {
90 argv[0] = "./zig2";
91 run_execv(argv);
92
93 const char *cc = get_c_compiler();
94 const char *host_triple = get_host_triple();
95
96 {
97 const char *child_argv[] = {
98 cc, "-o", "zig-wasm2c", "stage1/wasm2c.c", "-O2", "-std=c99", NULL,
99 };
100 print_and_run(child_argv);
101 }
102 {
103 const char *child_argv[] = {
104 "./zig-wasm2c", "stage1/zig1.wasm", "zig1.c", NULL,
105 };
106 print_and_run(child_argv);
107 }
108 {
109 const char *child_argv[] = {
110 cc, "-o", "zig1", "zig1.c", "stage1/wasi.c", "-std=c99", "-Os", "-lm", NULL,
111 };
112 print_and_run(child_argv);
113 }
114 {
115 FILE *f = fopen("config.zig", "wb");
116 if (f == NULL)
117 panic("unable to open config.zig for writing");
118
119 const char *zig_version = "0.12.0-dev.bootstrap";
120
121 int written = fprintf(f,
122 "pub const have_llvm = false;\n"
123 "pub const llvm_has_m68k = false;\n"
124 "pub const llvm_has_csky = false;\n"
125 "pub const llvm_has_arc = false;\n"
126 "pub const llvm_has_xtensa = false;\n"
127 "pub const version: [:0]const u8 = \"%s\";\n"
128 "pub const semver = @import(\"std\").SemanticVersion.parse(version) catch unreachable;\n"
129 "pub const enable_logging: bool = false;\n"
130 "pub const enable_link_snapshots: bool = false;\n"
131 "pub const enable_tracy = false;\n"
132 "pub const value_tracing = false;\n"
133 "pub const skip_non_native = false;\n"
134 "pub const only_c = false;\n"
135 "pub const force_gpa = false;\n"
136 "pub const only_core_functionality = true;\n"
137 "pub const only_reduce = false;\n"
138 , zig_version);
139 if (written < 100)
140 panic("unable to write to config.zig file");
141 if (fclose(f) != 0)
142 panic("unable to finish writing to config.zig file");
143 }
144
145 {
146 const char *child_argv[] = {
147 "./zig1", "lib", "build-exe", "src/main.zig",
148 "-ofmt=c", "-lc", "-OReleaseSmall",
149 "--name", "zig2", "-femit-bin=zig2.c",
150 "--mod", "build_options::config.zig",
151 "--mod", "aro::deps/aro/lib.zig",
152 "--deps", "build_options,aro",
153 "-target", host_triple,
154 NULL,
155 };
156 print_and_run(child_argv);
157 }
158
159 {
160 const char *child_argv[] = {
161 "./zig1", "lib", "build-obj", "lib/compiler_rt.zig",
162 "-ofmt=c", "-OReleaseSmall",
163 "--name", "compiler_rt", "-femit-bin=compiler_rt.c",
164 "--mod", "build_options::config.zig",
165 "--deps", "build_options",
166 "-target", host_triple,
167 NULL,
168 };
169 print_and_run(child_argv);
170 }
171
172 {
173 const char *child_argv[] = {
174 cc, "-o", "zig2", "zig2.c", "compiler_rt.c",
175 "-std=c99", "-O2", "-fno-stack-protector",
176 "-Wl,-z,stack-size=0x10000000", "-Istage1", NULL,
177 };
178 print_and_run(child_argv);
179 }
180
181 run_execv(argv);
182 panic("build script failed to create valid zig2 executable");
183}