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.
- package/LICENSES/MIT-ZilchOS-bootstrap-from-tcc.txt +21 -0
- package/NOTICE.md +34 -0
- package/README.md +3 -0
- 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/package.json +1 -1
- 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);
|