buninu-linux 0.9.56 → 0.10.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/LICENSES/MIT-ZilchOS-bootstrap-from-tcc.txt +21 -0
  2. package/NOTICE.md +34 -0
  3. package/README.md +3 -0
  4. package/initramfs/usr/lib/bootstrap/1.prepare-rootfs.js +106 -0
  5. package/initramfs/usr/lib/bootstrap/10.build-m4.js +40 -0
  6. package/initramfs/usr/lib/bootstrap/11.build-flex.js +50 -0
  7. package/initramfs/usr/lib/bootstrap/12.build-gcc.js +261 -0
  8. package/initramfs/usr/lib/bootstrap/2.enter-rootfs.js +49 -0
  9. package/initramfs/usr/lib/bootstrap/3.gen-musl-dev.js +141 -0
  10. package/initramfs/usr/lib/bootstrap/4.build-tcc.js +61 -0
  11. package/initramfs/usr/lib/bootstrap/5.build-make.js +58 -0
  12. package/initramfs/usr/lib/bootstrap/6.build-binutils.js +77 -0
  13. package/initramfs/usr/lib/bootstrap/7.build-gmp.js +68 -0
  14. package/initramfs/usr/lib/bootstrap/8.build-mpfr.js +59 -0
  15. package/initramfs/usr/lib/bootstrap/9.build-mpc.js +55 -0
  16. package/initramfs/usr/lib/bootstrap/LICENSE +21 -0
  17. package/initramfs/usr/lib/bootstrap/LICENSES/MIT-ZilchOS-bootstrap-from-tcc.txt +21 -0
  18. package/initramfs/usr/lib/bootstrap/NOTICE.md +65 -0
  19. package/initramfs/usr/lib/bootstrap/README.md +204 -0
  20. package/initramfs/usr/lib/bootstrap/downloads.md +49 -0
  21. package/initramfs/usr/lib/bootstrap/lib/build.js +155 -0
  22. package/initramfs/usr/lib/bootstrap/lib/common.js +134 -0
  23. package/initramfs/usr/lib/bootstrap/lib/compile-object.c +14 -0
  24. package/initramfs/usr/lib/bootstrap/lib/musl-headers.js +59 -0
  25. package/initramfs/usr/lib/bootstrap/lib/seed.js +148 -0
  26. package/initramfs/usr/lib/bootstrap/lib/startup-check.c +14 -0
  27. package/initramfs/usr/lib/bootstrap/lib/tcc-build.js +53 -0
  28. package/initramfs/usr/lib/bootstrap/sources/musl-1.2.6.tar.gz +0 -0
  29. package/initramfs/usr/lib/bootstrap/sources/tinycc-05f0faf-upstream.tar.gz +0 -0
  30. package/initramfs/usr/lib/bootstrap/sources/tinycc-local-bootstrap-files.tar.gz +0 -0
  31. package/package.json +1 -1
  32. package/test/bootstrap.test.js +65 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Alexander Sosedkin.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE.md CHANGED
@@ -18,6 +18,40 @@ Alpine's CDN serves only the current pkgrel of each branch, so the package
18
18
  URLs below stop working once a build is superseded. The pinned aports commits
19
19
  are permanent and are the Corresponding Source for each exact build.
20
20
 
21
+ ## Bootstrap source archives
22
+
23
+ `initramfs/usr/lib/bootstrap/sources/` additionally carries uncompiled source:
24
+
25
+ - musl 1.2.6, from https://musl.libc.org/releases/musl-1.2.6.tar.gz;
26
+ its full `COPYRIGHT` is preserved inside the archive.
27
+ - TinyCC commit `05f0faf`, with `COPYING` and per-file license notices preserved
28
+ in `tinycc-05f0faf-upstream.tar.gz`.
29
+ - Local TinyCC bootstrap recipes in `tinycc-local-bootstrap-files.tar.gz`.
30
+
31
+ ### Bootstrap route credit and build-time downloads
32
+
33
+ Credit to [ZilchOS/bootstrap-from-tcc](https://github.com/ZilchOS/bootstrap-from-tcc)
34
+ by Alexander Sosedkin (Copyright (c) 2021 Alexander Sosedkin), whose bootstrap
35
+ route and recipes informed Buninu's TinyCC-to-GCC stages. The complete MIT
36
+ notice is preserved in `LICENSES/MIT-ZilchOS-bootstrap-from-tcc.txt` and in
37
+ the bootstrap payload. Reference checkout:
38
+ `d2f9454b34fef570cfb32cf5b17d85a90dba81bf`.
39
+
40
+ Stages 5–12 additionally fetch GNU Make 4.4.1, Binutils 2.39, GMP 4.3.2,
41
+ MPFR 2.4.2, MPC 0.8.1, GNU m4 1.4.18, Flex 2.6.4 and the pinned GCC 4.7
42
+ vendor snapshot. These source archives and compiled results are not bundled
43
+ in the npm package. Their own licenses apply, independently of Buninu's and
44
+ ZilchOS's MIT licenses.
45
+
46
+ See [the bootstrap-specific notices](initramfs/usr/lib/bootstrap/NOTICE.md)
47
+ for component licenses, provenance, runtime-helper exceptions and where
48
+ upstream license texts are retained. The credit and MIT license are copied
49
+ into each prepared rootfs and the final result's license directory.
50
+
51
+ The numbered bootstrap scripts extract these sources into the new rootfs.
52
+ See `initramfs/usr/lib/bootstrap/README.md` for the source-generation steps
53
+ and the ARM64 ordinary-CRT compatibility adjustment.
54
+
21
55
  ## Components tracked in this repository
22
56
 
23
57
  These files are committed under `native/x86_64/lib/` and
package/README.md CHANGED
@@ -47,6 +47,9 @@
47
47
  + Simplified browser works: buninu-browser natively or casty in chroot debian
48
48
  + Playing YouTube with sound (experimental); see [Playing YouTube with sound](#playing-youtube-with-sound-experimental)
49
49
  + See [Buninu Browser](#buninu-browser-early-stage-experimental) for the built-in browser, or [Debian and Chromium with casty](#debian-and-chromium-with-casty) for the optional chroot setup
50
+ * [Bootstrap a C compiler from Bun](initramfs/usr/lib/bootstrap/README.md):
51
+ + numbered scripts generate musl headers/CRT,
52
+ + build TinyCC and download the sources needed to continue through GCC 4.7, starting with `bun /usr/lib/bootstrap/1.prepare-rootfs.js`.
50
53
 
51
54
  ---
52
55
 
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env bun
2
+ import { mkdtempSync, rmSync, statSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ import {
6
+ assertAbsent, cli, isBuninuLinux,
7
+ normalizeArch, options,
8
+ } from "./lib/common.js";
9
+ import {
10
+ installSources, localSeed,
11
+ releaseSeed, sourceArchives,
12
+ validateSeed, writeSeed,
13
+ } from "./lib/seed.js";
14
+ import { printEntry } from "./2.enter-rootfs.js";
15
+
16
+ async function main(args) {
17
+ // Optional arguments: ARCH ROOTFS.
18
+ // ARCH defaults to this Bun's CPU.
19
+ // ROOTFS defaults to roota / rootx
20
+ // in the current working directory.
21
+ const selected = options(args);
22
+ if (!selected) return;
23
+ const { arch, rootfs } = selected;
24
+ assertAbsent(rootfs);
25
+ const parent = statSync(
26
+ dirname(rootfs)
27
+ );
28
+ if (!parent.isDirectory()) {
29
+ throw new Error(
30
+ "ROOTFS parent must exist"
31
+ );
32
+ }
33
+
34
+ // Bundled musl 1.2.6 + TinyCC +
35
+ // overlay; verify before any writes.
36
+ // No musl-dev APK is required.
37
+ const archives = sourceArchives();
38
+ const work = mkdtempSync(
39
+ join(tmpdir(), "buninu-bootstrap-")
40
+ );
41
+ try {
42
+ // Local mode reads /etc/os-release
43
+ // ID=buninu-linux, then copies:
44
+ // /bin/bun, /lib/ld-musl-*.so.1,
45
+ // libgcc_s.so.1, libstdc++.so.6,
46
+ // resolv.conf, tar, unzip, env,
47
+ // their JS helpers and bunmsh.
48
+ // Resolve links to copy real data.
49
+ const local = isBuninuLinux()
50
+ && arch === normalizeArch(
51
+ process.arch
52
+ );
53
+ console.log(
54
+ "① Preparing runtime and tools " +
55
+ (local ? "from this Buninu Linux"
56
+ : "from buninu-linux@0.9.56")
57
+ );
58
+
59
+ // Otherwise fetch npm 0.9.56:
60
+ // native/<arch>/lib -> rootfs libs
61
+ // initramfs tools -> same paths.
62
+ // Fetch musl Bun 1.4.2 ZIP for
63
+ // the selected arch -> /bin/bun.
64
+ // URLs + SHA-256: downloads.md,
65
+ // parsed as YAML, like the repo's
66
+ // scripts/npm-packages.md.
67
+ const files = local
68
+ ? localSeed(arch)
69
+ : await releaseSeed(arch, work);
70
+ if (local) console.log(
71
+ "② Reusing system musl-bun"
72
+ );
73
+ validateSeed(files, arch);
74
+ writeSeed(
75
+ rootfs, arch, files,
76
+ local ? "local" : "npm@0.9.56"
77
+ );
78
+
79
+ // Extract musl and TinyCC into
80
+ // /bootstrap/src. The overlay
81
+ // adds build recipes and /bin/cc.
82
+ // Stage 3 already needs TinyCC
83
+ // source to generate CRT objects.
84
+ // Copy stages 1–12 and helpers to
85
+ // /bootstrap in rootfs.
86
+ console.log(
87
+ "③ Extracting musl, TinyCC " +
88
+ "and bootstrap overlay sources"
89
+ );
90
+ await installSources(
91
+ rootfs, archives
92
+ );
93
+ console.log(
94
+ `Prepared ${arch}: ${rootfs}`
95
+ );
96
+ printEntry(rootfs);
97
+ } finally {
98
+ // Preserve a partially written
99
+ // rootfs for inspection on error.
100
+ rmSync(work, {
101
+ recursive: true, force: true,
102
+ });
103
+ }
104
+ }
105
+
106
+ if (import.meta.main) await cli(main);
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bun
2
+ import { writeFileSync } from "node:fs";
3
+ import { cli } from "./lib/common.js";
4
+ import {
5
+ buildRoot, command, configure,
6
+ makeIn, ready, source, stage, tools,
7
+ } from "./lib/build.js";
8
+
9
+ async function main(args) {
10
+ const { triple } = stage(
11
+ 10, "m4", args
12
+ );
13
+ const src = await source(
14
+ "m4@1.4.18", "m4-1.4.18"
15
+ );
16
+ const build = buildRoot + "/m4";
17
+ await configure(src, build, [
18
+ "--build=" + triple,
19
+ "--host=" + triple,
20
+ "--prefix=/bootstrap/toolchain",
21
+ "--disable-dependency-tracking",
22
+ ]);
23
+ await makeIn(build);
24
+ await makeIn(build, ["install"]);
25
+ writeFileSync(
26
+ build + "/verify.m4",
27
+ "define(`square',`eval($1*$1)')" +
28
+ "square(12)\n"
29
+ );
30
+ const output = await command(
31
+ [tools + "/m4", "verify.m4"],
32
+ build, {}, true
33
+ );
34
+ if (output.trim() !== "144") {
35
+ throw new Error("m4 check failed");
36
+ }
37
+ ready(10, "GNU m4 expansion");
38
+ }
39
+
40
+ if (import.meta.main) await cli(main);
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bun
2
+ import { writeFileSync } from "node:fs";
3
+ import { cli } from "./lib/common.js";
4
+ import {
5
+ buildRoot, command, configure,
6
+ makeIn, ready, source, stage, tools,
7
+ } from "./lib/build.js";
8
+
9
+ async function main(args) {
10
+ const { triple } = stage(
11
+ 11, "flex", args
12
+ );
13
+ const src = await source(
14
+ "flex@2.6.4", "flex-2.6.4"
15
+ );
16
+ const build = buildRoot + "/flex";
17
+ const env = { M4: tools + "/m4" };
18
+ await configure(src, build, [
19
+ "--build=" + triple,
20
+ "--host=" + triple,
21
+ "--prefix=/bootstrap/toolchain",
22
+ "--disable-nls",
23
+ "--disable-dependency-tracking",
24
+ "--disable-shared",
25
+ ], env);
26
+ await makeIn(
27
+ build, ["-C", "src"], env
28
+ );
29
+ await makeIn(
30
+ build, ["-C", "src", "install"],
31
+ env
32
+ );
33
+ await verifyLexer(build, env);
34
+ ready(11, "Flex generated lexer");
35
+ }
36
+
37
+ async function verifyLexer(build, env) {
38
+ writeFileSync(build + "/verify.l", `%option noyywrap
39
+ %%
40
+ [0-9]+ return 7;
41
+ . return 1;
42
+ %%
43
+ int main(void){yy_scan_string("123");return yylex()!=7;}
44
+ `);
45
+ await command([tools + "/flex", "-o", "verify.c", "verify.l"], build, env);
46
+ await command([tools + "/cc", "verify.c", "-o", "verify-flex"], build, env);
47
+ await command([build + "/verify-flex"], build, env);
48
+ }
49
+
50
+ if (import.meta.main) await cli(main);
@@ -0,0 +1,261 @@
1
+ #!/usr/bin/env bun
2
+ import {
3
+ chmodSync, copyFileSync, cpSync, existsSync, mkdirSync, mkdtempSync,
4
+ readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync,
5
+ } from "node:fs";
6
+ import {
7
+ bootstrap, cli, sha256,
8
+ } from "./lib/common.js";
9
+ import {
10
+ buildRoot, command, configure,
11
+ makeIn, patch, deps, ready,
12
+ resultRoot, source, sourceRoot, stage, useLog,
13
+ toolchain, tools,
14
+ } from "./lib/build.js";
15
+
16
+ const gccCommit = "9d2b63d100ae7c99ee8b128fb41086fd85c8f57d";
17
+ // GCC clears MAKEOVERRIDES. Preserve its normal explicit submake flags
18
+ // and append our header-install selection to that forwarding list.
19
+ const headerInstallFlags =
20
+ "FLAGS_TO_PASS=$(BASE_FLAGS_TO_PASS) $(EXTRA_HOST_FLAGS) " +
21
+ "INSTALL_HEADERS_DIR=install-include-dir";
22
+
23
+ async function main(args) {
24
+ const { arch, triple } = stage(
25
+ 12, "gcc", args
26
+ );
27
+ // GCC's ARM vendor 4.7 branch has
28
+ // both the ARM64 and x64 backends.
29
+ // Pin the full commit, not a branch.
30
+ const src = await source(
31
+ "gcc@4.7-9d2b63d",
32
+ "gcc-" + gccCommit
33
+ );
34
+ const build = buildRoot + "/gcc-4.7";
35
+ prepareGcc(src, arch);
36
+ // Install native assembler/linker
37
+ // before building target libgcc.
38
+ installBinutils();
39
+ await configure(src, build, [
40
+ "--build=" + triple,
41
+ "--host=" + triple,
42
+ "--target=" + triple,
43
+ "--prefix=" + resultRoot,
44
+ "--enable-languages=c",
45
+ "--disable-build-with-cxx",
46
+ "--disable-bootstrap",
47
+ "--disable-libquadmath",
48
+ "--disable-decimal-float",
49
+ "--disable-fixed-point",
50
+ "--disable-lto",
51
+ "--disable-libgomp",
52
+ "--disable-multilib",
53
+ "--disable-multiarch",
54
+ "--disable-libmudflap",
55
+ "--disable-libssp",
56
+ "--disable-libitm", "--disable-nls",
57
+ "--disable-werror",
58
+ "--with-gmp=" + deps,
59
+ "--with-mpfr=" + deps,
60
+ "--with-mpc=" + deps,
61
+ "--with-build-time-tools=" +
62
+ toolchain + "/bin",
63
+ "--with-as=" +
64
+ resultRoot + "/bin/as",
65
+ "--with-ld=" +
66
+ resultRoot + "/bin/ld",
67
+ "--with-native-system-header-dir=" +
68
+ "/usr/include",
69
+ ]);
70
+
71
+ // Explicit make assignments avoid
72
+ // cached missing-tool commands.
73
+ await makeIn(build, [
74
+ "M4=" + tools + "/m4",
75
+ "FLEX=" + tools + "/flex", "all",
76
+ ]);
77
+ // Install compiler, headers, CRT
78
+ // support and libgcc into result.
79
+ // Create include directories via
80
+ // Make; copy headers with JS below.
81
+ // No tar pipe or cp -p -r needed.
82
+ await makeIn(build, [
83
+ headerInstallFlags, "install-gcc",
84
+ ]);
85
+ await makeIn(build, [
86
+ "install-target-libgcc",
87
+ ]);
88
+ // libgcc installs unwind.h too.
89
+ // Copy headers last to remove links
90
+ // back into the source tree.
91
+ installCompilerHeaders(
92
+ src, build, triple
93
+ );
94
+ // Test with all intermediate trees
95
+ // hidden, then restore them.
96
+ await verifyGcc(arch, triple);
97
+ ready(
98
+ 12, "GCC 4.7 C compiler + libgcc"
99
+ );
100
+ console.log(
101
+ "Compiler: " +
102
+ resultRoot + "/bin/gcc"
103
+ );
104
+ console.log(
105
+ "Stop: GCC 4.7 milestone reached."
106
+ );
107
+ }
108
+
109
+ function prepareGcc(src, arch) {
110
+ const header = "bootstrap-musl.h";
111
+ const text = `/* Local ordinary Linux-musl bootstrap target settings. */
112
+ #undef GNU_USER_DYNAMIC_LINKER
113
+ #define GNU_USER_DYNAMIC_LINKER "/lib/ld-musl-${arch}.so.1"
114
+ #undef GNU_USER_DYNAMIC_LINKER64
115
+ #define GNU_USER_DYNAMIC_LINKER64 "/lib/ld-musl-${arch}.so.1"
116
+ #undef OPTION_GLIBC
117
+ #define OPTION_GLIBC 0
118
+ #undef TARGET_C99_FUNCTIONS
119
+ #define TARGET_C99_FUNCTIONS 1
120
+ #undef TARGET_HAS_SINCOS
121
+ #define TARGET_HAS_SINCOS 1
122
+ #undef INT_FAST16_TYPE
123
+ #define INT_FAST16_TYPE "int"
124
+ #undef INT_FAST32_TYPE
125
+ #define INT_FAST32_TYPE "int"
126
+ #undef UINT_FAST16_TYPE
127
+ #define UINT_FAST16_TYPE "unsigned int"
128
+ #undef UINT_FAST32_TYPE
129
+ #define UINT_FAST32_TYPE "unsigned int"
130
+ `;
131
+ writeFileSync(src + "/gcc/config/" + header, text);
132
+ const path = src + "/gcc/config.gcc";
133
+ const config = readFileSync(path, "utf8");
134
+ const marker = "# Buninu native musl bootstrap";
135
+ if (!config.includes(marker)) writeFileSync(path, config + `\n${marker}\ncase $target in\n aarch64-*-linux-musl*|x86_64-*-linux-musl*) tm_file="$tm_file ${header}" ;;\nesac\n`);
136
+ patch(src + "/libiberty/regex.c", "# ifdef REGEX_MALLOC\n", "/* TinyCC: use the existing heap allocation path. */\n# if defined __TINYC__ && !defined REGEX_MALLOC\n# define REGEX_MALLOC 1\n# endif\n# ifdef REGEX_MALLOC\n");
137
+ patch(src + "/libiberty/argv.c", '#include "libiberty.h"', '#include <stdlib.h>\n#include "libiberty.h"');
138
+ }
139
+
140
+ function verificationSource(arch) {
141
+ return `#include <stdint.h>
142
+ #include <stdio.h>
143
+ #include <unwind.h>
144
+ #ifdef __gnu_linux__
145
+ #error musl must not claim glibc
146
+ #endif
147
+ #if !defined(__linux__) || !defined(${arch === "aarch64" ? "__aarch64__" : "__x86_64__"})
148
+ #error unexpected target
149
+ #endif
150
+ typedef char fast16[__builtin_types_compatible_p(__INT_FAST16_TYPE__,int_fast16_t)?1:-1];
151
+ typedef char fast32[__builtin_types_compatible_p(__UINT_FAST32_TYPE__,uint_fast32_t)?1:-1];
152
+ static volatile unsigned __int128 large=((unsigned __int128)1<<100)+123,divisor=7;
153
+ int main(void){unsigned __int128 a=large,b=divisor,q=a/b,r=a%b;
154
+ if(q*b+r!=a||r>=b)return 1;
155
+ puts("GCC 4.7 C and libgcc runtime verified");return 0;}
156
+ `;
157
+ }
158
+
159
+ function installCompilerHeaders(src, build, triple) {
160
+ const version = readFileSync(src + "/gcc/BASE-VER", "utf8").trim();
161
+ if (!/^4\.7\.\d+$/.test(version)) throw new Error(`Unexpected GCC version: ${version}`);
162
+ const destination = `${resultRoot}/lib/gcc/${triple}/${version}`;
163
+ for (const name of ["include", "include-fixed"]) {
164
+ const source = `${build}/gcc/${name}`;
165
+ if (!statSync(source).isDirectory()) throw new Error(`Missing GCC headers: ${source}`);
166
+ const target = `${destination}/${name}`;
167
+ // Replace only the generated private header directory. Dereference
168
+ // unwind.h and other source/build links so result survives their removal.
169
+ rmSync(target, { recursive: true, force: true });
170
+ cpSync(source, target, { recursive: true, dereference: true, preserveTimestamps: true });
171
+ }
172
+ }
173
+
174
+ function installBinutils() {
175
+ mkdirSync(resultRoot + "/bin", { recursive: true });
176
+ rmSync(resultRoot + "/verified.json", { force: true });
177
+ for (const name of ["as", "ld", "ar", "ranlib", "nm", "objcopy", "objdump", "readelf", "strip", "size", "strings", "addr2line", "c++filt"]) {
178
+ // Copy bytes, not symlinks into the intermediate toolchain tree.
179
+ const target = resultRoot + "/bin/" + name;
180
+ copyFileSync(toolchain + "/bin/" + name, target);
181
+ chmodSync(target, 0o755);
182
+ }
183
+ const notices = resultRoot + "/share/licenses/bootstrap";
184
+ mkdirSync(notices, { recursive: true });
185
+ copyFileSync(bootstrap + "/NOTICE.md", notices + "/NOTICE.md");
186
+ copyFileSync(bootstrap + "/LICENSE", notices + "/LICENSE");
187
+ cpSync(bootstrap + "/LICENSES", notices + "/LICENSES", { recursive: true });
188
+ // Keep notices with the installed binaries, including static dependencies.
189
+ for (const directory of ["gcc-" + gccCommit, "binutils-2.39", "gmp-4.3.2", "mpfr-2.4.2", "mpc-0.8.1"]) {
190
+ const target = resultRoot + "/share/licenses/" + directory;
191
+ mkdirSync(target, { recursive: true });
192
+ for (const name of readdirSync(sourceRoot + "/" + directory)) {
193
+ if (/^(COPYING|COPYRIGHT|LICENSE)/.test(name) && statSync(sourceRoot + "/" + directory + "/" + name).isFile()) {
194
+ copyFileSync(sourceRoot + "/" + directory + "/" + name, target + "/" + name);
195
+ }
196
+ }
197
+ }
198
+ }
199
+
200
+ async function verifyGcc(arch, triple) {
201
+ const gcc = resultRoot + "/bin/gcc";
202
+ const work = mkdtempSync("/tmp/bootstrap-result-check-");
203
+ const hidden = [];
204
+ // No compiler search-path overrides: exercise the installed defaults.
205
+ const env = {
206
+ PATH: resultRoot + "/bin:/bin:/usr/bin",
207
+ SHELL: "/bin/sh", CONFIG_SHELL: "/bin/sh", CC: gcc,
208
+ LD_LIBRARY_PATH: resultRoot + "/lib:" + resultRoot + "/lib64",
209
+ };
210
+ useLog(resultRoot + "/verification.log");
211
+ try {
212
+ for (const path of [sourceRoot, deps, toolchain, buildRoot]) {
213
+ const backup = path + ".verification-hidden";
214
+ if (existsSync(backup)) throw new Error(`Restore interrupted verification directory first: ${backup} -> ${path}`);
215
+ renameSync(path, backup);
216
+ hidden.push([path, backup]);
217
+ }
218
+ const version = (await command([gcc, "-dumpversion"], work, env, true)).trim();
219
+ if (!/^4\.7\./.test(version)) throw new Error(`Unexpected GCC version: ${version}`);
220
+ for (const name of ["libgcc.a", "libgcc_s.so.1", "crtbegin.o", "crtend.o", "crtbeginS.o", "crtendS.o"]) {
221
+ const path = (await command([gcc, "-print-file-name=" + name], work, env, true)).trim();
222
+ if (!path.startsWith(resultRoot + "/") || !existsSync(path)) throw new Error(`Missing installed support file: ${name}: ${path}`);
223
+ if (name === "libgcc_s.so.1") env.LD_LIBRARY_PATH = path.slice(0, path.lastIndexOf("/")) + ":" + env.LD_LIBRARY_PATH;
224
+ }
225
+ writeFileSync(work + "/verify.c", verificationSource(arch));
226
+ for (const optimization of ["-O0", "-O2"]) {
227
+ await command([gcc, optimization, "verify.c", "-o", "verify-gcc"], work, env);
228
+ const headers = await command([resultRoot + "/bin/readelf", "-l", "verify-gcc"], work, env, true);
229
+ if (!headers.includes(`/lib/ld-musl-${arch}.so.1`)) throw new Error("Wrong musl interpreter");
230
+ await command([work + "/verify-gcc"], work, env);
231
+ }
232
+ // Exercise installed crtbeginS/crtendS and shared libgcc, too.
233
+ writeFileSync(work + "/shared.c", "__int128 divide(__int128 a,__int128 b){return a/b;}\n");
234
+ writeFileSync(work + "/shared-main.c", "extern __int128 divide(__int128,__int128);int main(void){return divide(((__int128)1<<100)+1,7)!=(((__int128)1<<100)+1)/7;}\n");
235
+ await command([gcc, "-shared", "-fPIC", "-shared-libgcc", "shared.c", "-o", "libverify.so"], work, env);
236
+ await command([gcc, "shared-main.c", "-L.", "-lverify", "-Wl,-rpath,$ORIGIN", "-o", "verify-shared"], work, env);
237
+ await command([work + "/verify-shared"], work, env);
238
+ const files = [];
239
+ function inventory(directory, prefix = "") {
240
+ for (const entry of readdirSync(directory, { withFileTypes: true })) {
241
+ const path = prefix + entry.name;
242
+ if (entry.isDirectory()) inventory(directory + "/" + entry.name, path + "/");
243
+ else if (statSync(directory + "/" + entry.name).isFile() && !["verified.json", "verification.log"].includes(path)) {
244
+ const bytes = readFileSync(directory + "/" + entry.name);
245
+ files.push({ path, bytes: bytes.length, sha256: sha256(bytes) });
246
+ }
247
+ }
248
+ }
249
+ inventory(resultRoot);
250
+ writeFileSync(resultRoot + "/verified.json", JSON.stringify({
251
+ version, arch, triple, compiler: gcc, independentOf: hidden.map(([path]) => path),
252
+ requires: ["/usr/include", "/usr/lib", "/lib"], files,
253
+ }, null, 2) + "\n");
254
+ } finally {
255
+ // Restore in reverse order even when a compiler check fails.
256
+ for (const [path, backup] of hidden.reverse()) renameSync(backup, path);
257
+ rmSync(work, { recursive: true, force: true });
258
+ }
259
+ }
260
+
261
+ if (import.meta.main) await cli(main);
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env bun
2
+ import {
3
+ cli, isBuninuLinux, options, quote,
4
+ } from "./lib/common.js";
5
+
6
+ const archAlias = /^(x|x64|x86_64|x86-64|a|arm64|aarch64)$/;
7
+
8
+ export function printEntry(rootfs = "/path/to/your/rootfs") {
9
+ console.log("\nEnter the rootfs:");
10
+ console.log(isBuninuLinux()
11
+ ? ` chroot ${quote(rootfs)} /bin/sh`
12
+ : ` bun x bunproot -koe -r ${quote(rootfs)}`);
13
+ console.log("Then run inside it:");
14
+ console.log(" cd /bootstrap");
15
+ console.log(" bun 3.gen-musl-dev.js");
16
+ console.log(" bun 4.build-tcc.js");
17
+ }
18
+
19
+ async function main(args) {
20
+ // Print instructions only. No
21
+ // rootfs or marker file is read.
22
+ if (!args.length) {
23
+ printEntry();
24
+ return;
25
+ }
26
+ if (args.includes("--help") ||
27
+ args.includes("-h")) {
28
+ console.log(
29
+ "Usage: bun 2.enter-rootfs.js " +
30
+ "[ARCH] [ROOTFS]"
31
+ );
32
+ console.log(
33
+ "No ROOTFS: print commands " +
34
+ "using /path/to/your/rootfs."
35
+ );
36
+ return;
37
+ }
38
+ // Keep stage 1's argument aliases,
39
+ // but never infer roota or rootx.
40
+ const archOnly = args.length === 1
41
+ && archAlias.test(args[0]);
42
+ const selected = options(archOnly
43
+ ? [...args, "/path/to/your/rootfs"]
44
+ : args);
45
+ if (!selected) return;
46
+ printEntry(selected.rootfs);
47
+ }
48
+
49
+ if (import.meta.main) await cli(main);