From 3a6d4526a62349d2ca8e75e999a710c20a4849cb Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Thu, 6 Jun 2024 23:14:11 -0700 Subject: [PATCH] feat: tinycc-musl --- foundation/src/stages/stage1/default.nix | 4 +- foundation/src/stages/stage1/musl/boot.nix | 2 +- .../src/stages/stage1/tinycc/default.nix | 1 + foundation/src/stages/stage1/tinycc/mes.nix | 6 +- foundation/src/stages/stage1/tinycc/musl.nix | 177 ++++++++++++++++++ .../patches/ignore-duplicate-symbols.patch | 14 ++ .../patches/ignore-static-inside-array.patch | 22 +++ .../stage1/tinycc/patches/static-link.patch | 11 ++ lib/src/numbers/default.test.nix | 4 +- 9 files changed, 233 insertions(+), 8 deletions(-) create mode 100644 foundation/src/stages/stage1/tinycc/musl.nix create mode 100644 foundation/src/stages/stage1/tinycc/patches/ignore-duplicate-symbols.patch create mode 100644 foundation/src/stages/stage1/tinycc/patches/ignore-static-inside-array.patch create mode 100644 foundation/src/stages/stage1/tinycc/patches/static-link.patch diff --git a/foundation/src/stages/stage1/default.nix b/foundation/src/stages/stage1/default.nix index a8065d7..0bfe6cf 100644 --- a/foundation/src/stages/stage1/default.nix +++ b/foundation/src/stages/stage1/default.nix @@ -11,7 +11,7 @@ in { ./nyacc ./mes ./ln-boot - ./tinycc + ./tinycc # With the exception of `tinycc-musl` which uses Bash. ./gnupatch ./gnumake ./coreutils @@ -47,6 +47,8 @@ in { stage1-gnutar-boot = stage1.gnutar.boot.package; stage1-gzip = stage1.gzip.package; stage1-musl-boot = stage1.musl.boot.package; + stage1-tinycc-musl = stage1.tinycc.musl.compiler.package; + stage1-tinycc-musl-libs = stage1.tinycc.musl.libs.package; }; extras = { diff --git a/foundation/src/stages/stage1/musl/boot.nix b/foundation/src/stages/stage1/musl/boot.nix index aa2c5a6..ee56243 100644 --- a/foundation/src/stages/stage1/musl/boot.nix +++ b/foundation/src/stages/stage1/musl/boot.nix @@ -120,7 +120,7 @@ in { # Configure bash ./configure \ --prefix=$out \ - --build=${(builtins.trace platform.build) platform.build} \ + --build=${platform.build} \ --host=${platform.host} \ --disable-shared \ CC=tcc diff --git a/foundation/src/stages/stage1/tinycc/default.nix b/foundation/src/stages/stage1/tinycc/default.nix index 3a41a6c..b85ccd0 100644 --- a/foundation/src/stages/stage1/tinycc/default.nix +++ b/foundation/src/stages/stage1/tinycc/default.nix @@ -11,6 +11,7 @@ in { includes = [ ./boot.nix ./mes.nix + ./musl.nix ]; options.aux.foundation.stages.stage1.tinycc = { diff --git a/foundation/src/stages/stage1/tinycc/mes.nix b/foundation/src/stages/stage1/tinycc/mes.nix index 1aae609..4f377db 100644 --- a/foundation/src/stages/stage1/tinycc/mes.nix +++ b/foundation/src/stages/stage1/tinycc/mes.nix @@ -8,7 +8,7 @@ args @ { stage1 = config.aux.foundation.stages.stage1; - pname = "tinycc-boot"; + pname = "tinycc-mes"; helpers = lib.fp.withDynamicArgs (import ./helpers.nix) args; in { @@ -56,7 +56,7 @@ in { }; tinycc-mes-boot = helpers.createTinyccMes { - pname = "tinycc-mes-boot"; + pname = "${pname}-boot"; version = stage1.tinycc.version; src = cfg.src; args = [ @@ -83,7 +83,7 @@ in { }; in helpers.createTinyccMes { - pname = "tinycc-mes"; + inherit pname; version = stage1.tinycc.version; src = cfg.src; args = [ diff --git a/foundation/src/stages/stage1/tinycc/musl.nix b/foundation/src/stages/stage1/tinycc/musl.nix new file mode 100644 index 0000000..e8822a7 --- /dev/null +++ b/foundation/src/stages/stage1/tinycc/musl.nix @@ -0,0 +1,177 @@ +args @ { + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.tinycc.musl; + + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.stage1; + + pname = "tinycc-musl"; + + helpers = lib.fp.withDynamicArgs (import ./helpers.nix) args; +in { + options.aux.foundation.stages.stage1.tinycc.musl = { + compiler = { + package = lib.options.create { + type = lib.types.package; + description = "The package to use for the tinycc-musl compiler."; + }; + }; + + libs = { + package = lib.options.create { + type = lib.types.package; + description = "The package to use for the tinycc-musl libs."; + }; + }; + + src = lib.options.create { + type = lib.types.string; + description = "Source for the package."; + }; + + revision = lib.options.create { + type = lib.types.string; + description = "Revision of the package."; + }; + }; + + config = { + aux.foundation.stages.stage1.tinycc.musl = let + patches = [ + ./patches/ignore-duplicate-symbols.patch + ./patches/ignore-static-inside-array.patch + ./patches/static-link.patch + ]; + + tinycc-musl = builders.bash.boot.build { + name = "${pname}-${stage1.tinycc.version}"; + + meta = stage1.tinycc.meta; + + deps.build.host = [ + stage1.tinycc.boot.compiler.package + stage1.gnupatch.package + stage1.gnutar.boot.package + stage1.gzip.package + ]; + + script = '' + # Unpack + tar xzf ${cfg.src} + cd tinycc-${builtins.substring 0 7 cfg.revision} + + # Patch + ${lib.strings.concatMapSep "\n" (file: "patch -Np0 -i ${file}") patches} + + # Configure + touch config.h + + # Build + # We first have to recompile using tcc-0.9.26 as tcc-0.9.27 is not self-hosting, + # but when linked with musl it is. + ln -s ${stage1.musl.boot.package}/lib/libtcc1.a ./libtcc1.a + + tcc \ + -B ${stage1.tinycc.boot.libs.package}/lib \ + -DC2STR \ + -o c2str \ + conftest.c + ./c2str include/tccdefs.h tccdefs_.h + + tcc -v \ + -static \ + -o tcc-musl \ + -D TCC_TARGET_I386=1 \ + -D CONFIG_TCCDIR=\"\" \ + -D CONFIG_TCC_CRTPREFIX=\"{B}\" \ + -D CONFIG_TCC_ELFINTERP=\"/musl/loader\" \ + -D CONFIG_TCC_LIBPATHS=\"{B}\" \ + -D CONFIG_TCC_SYSINCLUDEPATHS=\"${stage1.musl.boot.package}/include\" \ + -D TCC_LIBGCC=\"libc.a\" \ + -D TCC_LIBTCC1=\"libtcc1.a\" \ + -D CONFIG_TCC_STATIC=1 \ + -D CONFIG_USE_LIBGCC=1 \ + -D TCC_VERSION=\"0.9.27\" \ + -D ONE_SOURCE=1 \ + -D TCC_MUSL=1 \ + -D CONFIG_TCC_PREDEFS=1 \ + -D CONFIG_TCC_SEMLOCK=0 \ + -B . \ + -B ${stage1.tinycc.boot.libs.package}/lib \ + tcc.c + # libtcc1.a + rm -f libtcc1.a + tcc -c -D HAVE_CONFIG_H=1 lib/libtcc1.c + tcc -ar cr libtcc1.a libtcc1.o + + # Rebuild tcc-musl with itself + ./tcc-musl \ + -v \ + -static \ + -o tcc-musl \ + -D TCC_TARGET_I386=1 \ + -D CONFIG_TCCDIR=\"\" \ + -D CONFIG_TCC_CRTPREFIX=\"{B}\" \ + -D CONFIG_TCC_ELFINTERP=\"/musl/loader\" \ + -D CONFIG_TCC_LIBPATHS=\"{B}\" \ + -D CONFIG_TCC_SYSINCLUDEPATHS=\"${stage1.musl.boot.package}/include\" \ + -D TCC_LIBGCC=\"libc.a\" \ + -D TCC_LIBTCC1=\"libtcc1.a\" \ + -D CONFIG_TCC_STATIC=1 \ + -D CONFIG_USE_LIBGCC=1 \ + -D TCC_VERSION=\"0.9.27\" \ + -D ONE_SOURCE=1 \ + -D TCC_MUSL=1 \ + -D CONFIG_TCC_PREDEFS=1 \ + -D CONFIG_TCC_SEMLOCK=0 \ + -B . \ + -B ${stage1.musl.boot.package}/lib \ + tcc.c + # libtcc1.a + rm -f libtcc1.a + ./tcc-musl -c -D HAVE_CONFIG_H=1 lib/libtcc1.c + ./tcc-musl -c -D HAVE_CONFIG_H=1 lib/alloca.S + ./tcc-musl -ar cr libtcc1.a libtcc1.o alloca.o + + # Install + install -D tcc-musl $out/bin/tcc + install -Dm444 libtcc1.a $out/lib/libtcc1.a + ''; + }; + in { + revision = "fd6d2180c5c801bb0b4c5dde27d61503059fc97d"; + + src = builtins.fetchurl { + url = "https://repo.or.cz/tinycc.git/snapshot/${cfg.revision}.tar.gz"; + sha256 = "R81SNbEmh4s9FNQxCWZwUiMCYRkkwOHAdRf0aMnnRiA="; + }; + + compiler.package = builders.bash.boot.build { + name = "${pname}-${stage1.tinycc.version}-compiler"; + + meta = stage1.tinycc.meta; + + script = '' + install -D ${tinycc-musl}/bin/tcc $out/bin/tcc + ''; + }; + + libs.package = builders.bash.boot.build { + name = "${pname}-${stage1.tinycc.version}-libs"; + + meta = stage1.tinycc.meta; + + script = '' + mkdir $out + cp -r ${stage1.musl.boot.package}/* $out + chmod +w $out/lib/libtcc1.a + cp ${tinycc-musl}/lib/libtcc1.a $out/lib/libtcc1.a + + ''; + }; + }; + }; +} diff --git a/foundation/src/stages/stage1/tinycc/patches/ignore-duplicate-symbols.patch b/foundation/src/stages/stage1/tinycc/patches/ignore-duplicate-symbols.patch new file mode 100644 index 0000000..2e5255e --- /dev/null +++ b/foundation/src/stages/stage1/tinycc/patches/ignore-duplicate-symbols.patch @@ -0,0 +1,14 @@ +--- tccelf.c ++++ tccelf.c +@@ -710,8 +710,9 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, + #if 0 + printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n", + sym_bind, shndx, new_vis, esym_bind, esym->st_shndx, esym_vis); +-#endif + tcc_error_noabort("'%s' defined twice", name); ++#endif ++ goto do_patch; + } + } else { + esym->st_other = other; + diff --git a/foundation/src/stages/stage1/tinycc/patches/ignore-static-inside-array.patch b/foundation/src/stages/stage1/tinycc/patches/ignore-static-inside-array.patch new file mode 100644 index 0000000..f03b991 --- /dev/null +++ b/foundation/src/stages/stage1/tinycc/patches/ignore-static-inside-array.patch @@ -0,0 +1,22 @@ +--- tccgen.c ++++ tccgen.c +@@ -4941,7 +4941,7 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) + next(); + n = -1; + t1 = 0; +- if (td & TYPE_PARAM) while (1) { ++ while (1) { + /* XXX The optional type-quals and static should only be accepted + in parameter decls. The '*' as well, and then even only + in prototypes (not function defs). */ +@@ -4972,7 +4972,8 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) + } + break; + +- } else if (tok != ']') { ++ } ++ if (tok != ']') { + if (!local_stack || (storage & VT_STATIC)) + vpushi(expr_const()); + else { + diff --git a/foundation/src/stages/stage1/tinycc/patches/static-link.patch b/foundation/src/stages/stage1/tinycc/patches/static-link.patch new file mode 100644 index 0000000..8478a44 --- /dev/null +++ b/foundation/src/stages/stage1/tinycc/patches/static-link.patch @@ -0,0 +1,11 @@ +--- libtcc.c ++++ libtcc.c +@@ -793,6 +793,7 @@ LIBTCCAPI TCCState *tcc_new(void) + + s->gnu_ext = 1; + s->tcc_ext = 1; ++ s->static_link = 1; + s->nocommon = 1; + s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/ + s->cversion = 199901; /* default unless -std=c11 is supplied */ + diff --git a/lib/src/numbers/default.test.nix b/lib/src/numbers/default.test.nix index 45ba2b8..78ea058 100644 --- a/lib/src/numbers/default.test.nix +++ b/lib/src/numbers/default.test.nix @@ -29,9 +29,7 @@ in { expected = "64"; actual = lib.numbers.into.hex 100; in - (builtins.trace actual) - actual - == expected; + actual == expected; }; };