buninu-linux 0.8.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.
- package/LICENSES/MIT-ZilchOS-bootstrap-from-tcc.txt +21 -0
- package/NOTICE.md +34 -0
- package/README.md +3 -0
- package/initramfs/bin/tar +34 -46
- package/initramfs/buninu/apps/bunmsh/CHANGELOG.md +103 -0
- package/initramfs/buninu/apps/bunmsh/PORTING.md +133 -15
- package/initramfs/buninu/apps/bunmsh/help/awk.md +38 -0
- package/initramfs/buninu/apps/bunmsh/help/break.md +21 -0
- package/initramfs/buninu/apps/bunmsh/help/chmod.md +8 -2
- package/initramfs/buninu/apps/bunmsh/help/cmp.md +29 -0
- package/initramfs/buninu/apps/bunmsh/help/continue.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/cp.md +4 -0
- package/initramfs/buninu/apps/bunmsh/help/diff.md +30 -0
- package/initramfs/buninu/apps/bunmsh/help/egrep.md +26 -0
- package/initramfs/buninu/apps/bunmsh/help/export.md +2 -2
- package/initramfs/buninu/apps/bunmsh/help/expr.md +30 -0
- package/initramfs/buninu/apps/bunmsh/help/fgrep.md +25 -0
- package/initramfs/buninu/apps/bunmsh/help/grep.md +4 -0
- package/initramfs/buninu/apps/bunmsh/help/ls.md +4 -2
- package/initramfs/buninu/apps/bunmsh/help/mkdir.md +1 -1
- package/initramfs/buninu/apps/bunmsh/help/print.md +3 -0
- package/initramfs/buninu/apps/bunmsh/help/return.md +23 -0
- package/initramfs/buninu/apps/bunmsh/help/sed.md +8 -3
- package/initramfs/buninu/apps/bunmsh/help/set.md +12 -3
- package/initramfs/buninu/apps/bunmsh/help/tr.md +4 -0
- package/initramfs/buninu/apps/bunmsh/help/trap.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/uniq.md +27 -0
- package/initramfs/buninu/apps/bunmsh/package.json +1 -1
- package/initramfs/buninu/apps/bunmsh/src/awk.js +203 -0
- package/initramfs/buninu/apps/bunmsh/src/diff.js +222 -0
- package/initramfs/buninu/apps/bunmsh/src/fancy-ls.js +15 -4
- package/initramfs/buninu/apps/bunmsh/src/main.js +21 -5
- package/initramfs/buninu/apps/bunmsh/src/sed.js +159 -0
- package/initramfs/buninu/apps/bunmsh/src/shell.js +1283 -540
- package/initramfs/buninu/apps/bunmsh/test/awk-reference.test.js +35 -0
- package/initramfs/buninu/apps/bunmsh/test/awk.test.js +62 -0
- package/initramfs/buninu/apps/bunmsh/test/posix-bootstrap.test.js +595 -0
- package/initramfs/buninu/apps/bunmsh/test/utility-reference-cases.mjs +98 -0
- package/initramfs/buninu/apps/bunmsh/test/utility-reference.test.js +23 -0
- package/initramfs/buninu/apps/jsgotty/client-kitty.mjs +61 -0
- package/initramfs/buninu/apps/jsgotty/client.mjs +16 -0
- package/initramfs/buninu/apps/jsgotty/package-lock.json +2 -2
- package/initramfs/buninu/apps/jsgotty/package.json +1 -1
- package/initramfs/buninu/apps/jsgotty/tests/client-kitty.test.mjs +43 -0
- package/initramfs/etc/resolv.conf +2 -1
- package/initramfs/usr/lib/bootstrap/1.prepare-rootfs.js +106 -0
- package/initramfs/usr/lib/bootstrap/10.build-m4.js +40 -0
- package/initramfs/usr/lib/bootstrap/11.build-flex.js +50 -0
- package/initramfs/usr/lib/bootstrap/12.build-gcc.js +261 -0
- package/initramfs/usr/lib/bootstrap/2.enter-rootfs.js +49 -0
- package/initramfs/usr/lib/bootstrap/3.gen-musl-dev.js +141 -0
- package/initramfs/usr/lib/bootstrap/4.build-tcc.js +61 -0
- package/initramfs/usr/lib/bootstrap/5.build-make.js +58 -0
- package/initramfs/usr/lib/bootstrap/6.build-binutils.js +77 -0
- package/initramfs/usr/lib/bootstrap/7.build-gmp.js +68 -0
- package/initramfs/usr/lib/bootstrap/8.build-mpfr.js +59 -0
- package/initramfs/usr/lib/bootstrap/9.build-mpc.js +55 -0
- package/initramfs/usr/lib/bootstrap/LICENSE +21 -0
- package/initramfs/usr/lib/bootstrap/LICENSES/MIT-ZilchOS-bootstrap-from-tcc.txt +21 -0
- package/initramfs/usr/lib/bootstrap/NOTICE.md +65 -0
- package/initramfs/usr/lib/bootstrap/README.md +204 -0
- package/initramfs/usr/lib/bootstrap/downloads.md +49 -0
- package/initramfs/usr/lib/bootstrap/lib/build.js +155 -0
- package/initramfs/usr/lib/bootstrap/lib/common.js +134 -0
- package/initramfs/usr/lib/bootstrap/lib/compile-object.c +14 -0
- package/initramfs/usr/lib/bootstrap/lib/musl-headers.js +59 -0
- package/initramfs/usr/lib/bootstrap/lib/seed.js +148 -0
- package/initramfs/usr/lib/bootstrap/lib/startup-check.c +14 -0
- package/initramfs/usr/lib/bootstrap/lib/tcc-build.js +53 -0
- package/initramfs/usr/lib/bootstrap/sources/musl-1.2.6.tar.gz +0 -0
- package/initramfs/usr/lib/bootstrap/sources/tinycc-05f0faf-upstream.tar.gz +0 -0
- package/initramfs/usr/lib/bootstrap/sources/tinycc-local-bootstrap-files.tar.gz +0 -0
- package/initramfs/usr/share/doc/buninu-linux/tar.md +11 -0
- package/package.json +1 -1
- package/scripts/fetch.js +2 -0
- package/test/bootstrap.test.js +65 -0
- package/test/tar-strip.test.js +36 -0
|
@@ -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);
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { cc } from "bun:ffi";
|
|
3
|
+
import {
|
|
4
|
+
mkdtempSync, readFileSync, renameSync,
|
|
5
|
+
rmSync, writeFileSync,
|
|
6
|
+
} from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import {
|
|
9
|
+
assertAbsent, bootstrap, cli,
|
|
10
|
+
requireRootfs, validateElf,
|
|
11
|
+
} from "./lib/common.js";
|
|
12
|
+
import {
|
|
13
|
+
generateHeaders,
|
|
14
|
+
} from "./lib/musl-headers.js";
|
|
15
|
+
|
|
16
|
+
async function main(args) {
|
|
17
|
+
// Run inside the prepared rootfs.
|
|
18
|
+
// This generates public headers
|
|
19
|
+
// and ordinary dynamic-link CRT.
|
|
20
|
+
// It does not build libc or rcrt1.
|
|
21
|
+
if (args.length) throw new Error(
|
|
22
|
+
"Usage: bun 3.gen-musl-dev.js"
|
|
23
|
+
);
|
|
24
|
+
const { arch } = requireRootfs();
|
|
25
|
+
const names = [
|
|
26
|
+
"crt1.o", "crti.o", "crtn.o",
|
|
27
|
+
];
|
|
28
|
+
assertAbsent("/usr/include");
|
|
29
|
+
for (const name of names) {
|
|
30
|
+
assertAbsent(`/usr/lib/${name}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Follow musl's Makefile rules in
|
|
34
|
+
// JS: public headers, arch bits,
|
|
35
|
+
// alltypes.h and syscall.h.
|
|
36
|
+
console.log(
|
|
37
|
+
"① Generating musl headers"
|
|
38
|
+
);
|
|
39
|
+
generateHeaders(
|
|
40
|
+
arch,
|
|
41
|
+
"/bootstrap/src/musl",
|
|
42
|
+
"/usr/include"
|
|
43
|
+
);
|
|
44
|
+
// chroot mounts /tmp separately;
|
|
45
|
+
// stage objects on the same FS as
|
|
46
|
+
// /usr/lib for the final rename.
|
|
47
|
+
const work = mkdtempSync(
|
|
48
|
+
"/usr/lib/.musl-crt-"
|
|
49
|
+
);
|
|
50
|
+
let compiler;
|
|
51
|
+
try {
|
|
52
|
+
// ARM64 TCC does not handle adrp.
|
|
53
|
+
// Ordinary crt1's _start_c uses
|
|
54
|
+
// x0, not x1 (_DYNAMIC). Omit just
|
|
55
|
+
// that unused argument in a
|
|
56
|
+
// temporary header override.
|
|
57
|
+
// Keep musl sources untouched.
|
|
58
|
+
if (arch === "aarch64") {
|
|
59
|
+
prepareArm64Startup(work);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Bun.cc builds libtcc.c in memory
|
|
63
|
+
// without standalone cc or CRT.
|
|
64
|
+
// TCC_OUTPUT_OBJ emits the three
|
|
65
|
+
// relocatable startup objects.
|
|
66
|
+
console.log(
|
|
67
|
+
"② Building CRT with Bun.cc"
|
|
68
|
+
);
|
|
69
|
+
compiler = cc({
|
|
70
|
+
source: join(
|
|
71
|
+
bootstrap,
|
|
72
|
+
"lib/compile-object.c"
|
|
73
|
+
),
|
|
74
|
+
library: ["gcc_s"],
|
|
75
|
+
flags: ["-L/usr/lib", "-L/lib"],
|
|
76
|
+
include: [
|
|
77
|
+
"/bootstrap/src/tinycc",
|
|
78
|
+
"/bootstrap/src/tinycc/include",
|
|
79
|
+
"/usr/include",
|
|
80
|
+
],
|
|
81
|
+
symbols: {
|
|
82
|
+
compile_object: {
|
|
83
|
+
args: [
|
|
84
|
+
"cstring", "cstring",
|
|
85
|
+
"cstring",
|
|
86
|
+
],
|
|
87
|
+
returns: "int",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
compileCrt(
|
|
92
|
+
compiler, arch, work, names
|
|
93
|
+
);
|
|
94
|
+
for (const name of names) {
|
|
95
|
+
renameSync(
|
|
96
|
+
join(work, name),
|
|
97
|
+
`/usr/lib/${name}`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
console.log(
|
|
101
|
+
"Ready: musl headers and CRT."
|
|
102
|
+
);
|
|
103
|
+
console.log(
|
|
104
|
+
"Next: bun " +
|
|
105
|
+
"/bootstrap/" +
|
|
106
|
+
"4.build-tcc.js"
|
|
107
|
+
);
|
|
108
|
+
} finally {
|
|
109
|
+
compiler?.close();
|
|
110
|
+
rmSync(work, {
|
|
111
|
+
recursive: true, force: true,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function prepareArm64Startup(work) {
|
|
117
|
+
const original = readFileSync("/bootstrap/src/musl/arch/aarch64/crt_arch.h", "utf8");
|
|
118
|
+
const lines = original.split("\n");
|
|
119
|
+
const removed = lines.filter(line => line.includes("_DYNAMIC"));
|
|
120
|
+
if (removed.length !== 4 || !removed.some(line => line.includes("adrp x1"))) {
|
|
121
|
+
throw new Error("Unexpected musl ARM64 startup code; refusing compatibility edit");
|
|
122
|
+
}
|
|
123
|
+
writeFileSync(join(work, "crt_arch.h"), lines.filter(line => !line.includes("_DYNAMIC")).join("\n"));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function compileCrt(compiler, arch, work, names) {
|
|
127
|
+
const z = text => Buffer.from(text + "\0");
|
|
128
|
+
const flags = `-nostdinc -DCRT -D_XOPEN_SOURCE=700 -I${work} -I/bootstrap/src/musl/arch/${arch} -I/bootstrap/src/musl/arch/generic -I/bootstrap/src/musl/src/include -I/bootstrap/src/musl/src/internal -I/usr/include -I/bootstrap/src/tinycc/include`;
|
|
129
|
+
for (const name of names) {
|
|
130
|
+
const source = name === "crt1.o" ? "/bootstrap/src/musl/crt/crt1.c" : `/bootstrap/src/musl/crt/${arch}/${name.slice(0, -2)}.s`;
|
|
131
|
+
const output = join(work, name);
|
|
132
|
+
console.log(`${source} -> /usr/lib/${name}`);
|
|
133
|
+
const result = compiler.symbols.compile_object(z(source), z(output), z(flags));
|
|
134
|
+
if (result) throw new Error(`${name}: TinyCC returned ${result}`);
|
|
135
|
+
const bytes = readFileSync(output);
|
|
136
|
+
validateElf(name, bytes, arch);
|
|
137
|
+
if (bytes.readUInt16LE(16) !== 1) throw new Error(`${name} is not a relocatable ELF object`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (import.meta.main) await cli(main);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
bootstrap, cli, requireRootfs, run,
|
|
6
|
+
validateElf,
|
|
7
|
+
} from "./lib/common.js";
|
|
8
|
+
import {
|
|
9
|
+
buildTcc,
|
|
10
|
+
} from "./lib/tcc-build.js";
|
|
11
|
+
|
|
12
|
+
async function main(args) {
|
|
13
|
+
// Stage 3 must have generated
|
|
14
|
+
// headers and the three CRT files.
|
|
15
|
+
if (args.length) throw new Error(
|
|
16
|
+
"Usage: bun 4.build-tcc.js"
|
|
17
|
+
);
|
|
18
|
+
const { arch } = requireRootfs();
|
|
19
|
+
for (const name of [
|
|
20
|
+
"crt1.o", "crti.o", "crtn.o",
|
|
21
|
+
]) {
|
|
22
|
+
validateElf(
|
|
23
|
+
name,
|
|
24
|
+
readFileSync(`/usr/lib/${name}`),
|
|
25
|
+
arch
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Bun.cc -> standalone stage1 ->
|
|
30
|
+
// stage2, then compare bytes.
|
|
31
|
+
// Build x64 runtime helpers when
|
|
32
|
+
// needed and test /bin/cc.
|
|
33
|
+
await buildTcc();
|
|
34
|
+
|
|
35
|
+
// Exercise the generated CRT:
|
|
36
|
+
// argv, env, constructors,
|
|
37
|
+
// destructors and exit status.
|
|
38
|
+
await verifyStartup();
|
|
39
|
+
console.log(
|
|
40
|
+
"Ready: cc source.c -o program"
|
|
41
|
+
);
|
|
42
|
+
console.log(
|
|
43
|
+
"Next: bun /bootstrap/" +
|
|
44
|
+
"5.build-make.js"
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function verifyStartup() {
|
|
49
|
+
const output = "/bootstrap/build/tinycc/startup-check";
|
|
50
|
+
await run(["/bin/cc", join(bootstrap, "lib/startup-check.c"), "-o", output]);
|
|
51
|
+
const child = Bun.spawn([output, "hello", "two words"], {
|
|
52
|
+
env: { PATH: "/bin:/usr/bin", CRT_TEST: "seed-free" }, stdout: "pipe", stderr: "inherit",
|
|
53
|
+
});
|
|
54
|
+
const stdout = await new Response(child.stdout).text();
|
|
55
|
+
if (await child.exited !== 42 || stdout !== "argc/argv, environment, constructor OK\ndestructor OK\n") {
|
|
56
|
+
throw new Error(`CRT startup check failed: ${stdout}`);
|
|
57
|
+
}
|
|
58
|
+
console.log(stdout + "exit status 42: OK");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (import.meta.main) await cli(main);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import {
|
|
3
|
+
chmodSync, copyFileSync,
|
|
4
|
+
} from "node:fs";
|
|
5
|
+
import { cli } from "./lib/common.js";
|
|
6
|
+
import {
|
|
7
|
+
buildRoot, command, configure,
|
|
8
|
+
installAdapters, makeIn, patch,
|
|
9
|
+
ready, shell, source, stage, tools,
|
|
10
|
+
} from "./lib/build.js";
|
|
11
|
+
|
|
12
|
+
async function main(args) {
|
|
13
|
+
const { triple } = stage(
|
|
14
|
+
5, "make", args
|
|
15
|
+
);
|
|
16
|
+
installAdapters();
|
|
17
|
+
const src = await source(
|
|
18
|
+
"make@4.4.1", "make-4.4.1"
|
|
19
|
+
);
|
|
20
|
+
const build = buildRoot + "/make";
|
|
21
|
+
prepareMake(src);
|
|
22
|
+
await configure(src, build, [
|
|
23
|
+
"--build=" + triple,
|
|
24
|
+
"--prefix=/bootstrap/toolchain",
|
|
25
|
+
"--disable-dependency-tracking",
|
|
26
|
+
"--without-guile", "--disable-nls",
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
// GNU Make provides its own
|
|
30
|
+
// no-make shell bootstrap builder.
|
|
31
|
+
await command(
|
|
32
|
+
[shell, src + "/build.sh"],
|
|
33
|
+
build
|
|
34
|
+
);
|
|
35
|
+
copyFileSync(
|
|
36
|
+
build + "/make", tools + "/make"
|
|
37
|
+
);
|
|
38
|
+
chmodSync(tools + "/make", 0o755);
|
|
39
|
+
await makeIn(build, ["clean"]);
|
|
40
|
+
await makeIn(build);
|
|
41
|
+
copyFileSync(
|
|
42
|
+
build + "/make", tools + "/make"
|
|
43
|
+
);
|
|
44
|
+
await command(
|
|
45
|
+
[tools + "/make", "--version"]
|
|
46
|
+
);
|
|
47
|
+
ready(5, "GNU Make self-rebuild");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function prepareMake(src) {
|
|
51
|
+
patch(src + "/build.sh", ' LIBOBJS="${LIBOBJS:+$LIBOBJS }lib/$lo"',
|
|
52
|
+
' lo=${lo#\'${LIBOBJDIR}\'}\n LIBOBJS="${LIBOBJS:+$LIBOBJS }lib/$lo"');
|
|
53
|
+
patch(src + "/src/mkcustom.h", "char *alloca ();", "void *alloca ();");
|
|
54
|
+
patch(src + "/lib/glob.c", "extern char *alloca ();", "extern void *alloca ();");
|
|
55
|
+
patch(src + "/lib/alloca.c", "memory_full ();", "abort ();");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (import.meta.main) await cli(main);
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import {
|
|
3
|
+
existsSync, readdirSync,
|
|
4
|
+
readFileSync, statSync,
|
|
5
|
+
copyFileSync, writeFileSync,
|
|
6
|
+
} from "node:fs";
|
|
7
|
+
import { cli } from "./lib/common.js";
|
|
8
|
+
import {
|
|
9
|
+
buildRoot, command, configure,
|
|
10
|
+
makeIn, ready, source, stage,
|
|
11
|
+
toolchain, tools,
|
|
12
|
+
} from "./lib/build.js";
|
|
13
|
+
|
|
14
|
+
async function main(args) {
|
|
15
|
+
const { arch, triple } = stage(
|
|
16
|
+
6, "binutils", args
|
|
17
|
+
);
|
|
18
|
+
const src = await source(
|
|
19
|
+
"binutils@2.39", "binutils-2.39"
|
|
20
|
+
);
|
|
21
|
+
const build = buildRoot + "/binutils";
|
|
22
|
+
const env = {
|
|
23
|
+
CFLAGS: "-O2 -D__LITTLE_ENDIAN__=1",
|
|
24
|
+
};
|
|
25
|
+
await configure(src, build, [
|
|
26
|
+
"--build=" + triple,
|
|
27
|
+
"--host=" + triple,
|
|
28
|
+
"--target=" + triple,
|
|
29
|
+
"--prefix=" + toolchain,
|
|
30
|
+
"--disable-nls", "--disable-werror",
|
|
31
|
+
"--disable-gprofng",
|
|
32
|
+
"--disable-gold", "--disable-gdb",
|
|
33
|
+
"--disable-sim", "--disable-libctf",
|
|
34
|
+
"--disable-shared",
|
|
35
|
+
"--disable-multilib",
|
|
36
|
+
"--disable-dependency-tracking",
|
|
37
|
+
"--without-debuginfod",
|
|
38
|
+
"--without-zstd",
|
|
39
|
+
], env);
|
|
40
|
+
await makeIn(build, ["all"], env);
|
|
41
|
+
restoreManpages(src, build);
|
|
42
|
+
await makeIn(build, ["install"], env);
|
|
43
|
+
await runtime(arch);
|
|
44
|
+
await command([
|
|
45
|
+
toolchain + "/bin/as", "--version",
|
|
46
|
+
]);
|
|
47
|
+
await command([
|
|
48
|
+
toolchain + "/bin/ld", "--version",
|
|
49
|
+
]);
|
|
50
|
+
ready(6, "Binutils and TCC runtime");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function restoreManpages(src, build) {
|
|
54
|
+
for (const dir of ["gas/doc", "binutils/doc", "ld", "gprof"]) {
|
|
55
|
+
for (const name of readdirSync(src + "/" + dir).filter(n => n.endsWith(".1"))) {
|
|
56
|
+
const target = `${build}/${dir}/${name}`;
|
|
57
|
+
if (existsSync(target) && statSync(target).size === 0) copyFileSync(`${src}/${dir}/${name}`, target);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function runtime(arch) {
|
|
63
|
+
const cwd = buildRoot + "/tcc-runtime";
|
|
64
|
+
if (arch === "aarch64") {
|
|
65
|
+
await command([tools + "/cc", "-c", "/bootstrap/src/tinycc/lib/lib-arm64.c", "-o", "lib-arm64.o"], cwd);
|
|
66
|
+
await command([toolchain + "/bin/ar", "rcs", toolchain + "/lib/tcc/libbootstrap-tcc-arm64.a", "lib-arm64.o"], cwd);
|
|
67
|
+
}
|
|
68
|
+
const code = `static volatile long double a=1.5L,b=2.0L;
|
|
69
|
+
int main(void){long double x=a,y=b;return x*y!=3.0L||x/y!=0.75L||x+y!=3.5L||x-y!=-0.5L||!(x<y)||(double)(x*y)!=3.0;}`;
|
|
70
|
+
// command() creates the working directory before compilation.
|
|
71
|
+
await command([toolchain + "/bin/ar", "--version"], cwd);
|
|
72
|
+
writeFileSync(cwd + "/quad.c", code);
|
|
73
|
+
await command([tools + "/cc", "quad.c", "-o", "quad"], cwd);
|
|
74
|
+
await command([cwd + "/quad"], cwd);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (import.meta.main) await cli(main);
|