From 8e27d6d87e9b385d5bd00b3ad3197d75fcce590b Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Thu, 6 Jun 2024 22:49:52 -0700 Subject: [PATCH] feat: musl boot --- foundation/flake.nix | 5 +- foundation/src/builders/bash/boot.nix | 77 ++++++++++ foundation/src/builders/bash/default.nix | 22 +++ foundation/src/default.nix | 1 + foundation/src/platform/default.nix | 29 +++- .../src/stages/stage0/phases/phase11.nix | 23 +-- .../src/stages/stage0/phases/phase12.nix | 23 +-- foundation/src/stages/stage1/default.nix | 14 ++ .../src/stages/stage1/gnugrep/default.nix | 106 +++++++++++++ foundation/src/stages/stage1/gnused/boot.nix | 77 ++++++++++ .../src/stages/stage1/gnused/default.nix | 49 ++++++ foundation/src/stages/stage1/gnutar/boot.nix | 76 ++++++++++ .../src/stages/stage1/gnutar/default.nix | 49 ++++++ foundation/src/stages/stage1/gzip/default.nix | 104 +++++++++++++ foundation/src/stages/stage1/musl/boot.nix | 139 ++++++++++++++++++ foundation/src/stages/stage1/musl/default.nix | 44 ++++++ .../stage1/musl/patches/always-flush.patch | 13 ++ foundation/src/system/default.nix | 2 +- 18 files changed, 826 insertions(+), 27 deletions(-) create mode 100644 foundation/src/builders/bash/boot.nix create mode 100644 foundation/src/builders/bash/default.nix create mode 100644 foundation/src/stages/stage1/gnugrep/default.nix create mode 100644 foundation/src/stages/stage1/gnused/boot.nix create mode 100644 foundation/src/stages/stage1/gnused/default.nix create mode 100644 foundation/src/stages/stage1/gnutar/boot.nix create mode 100644 foundation/src/stages/stage1/gnutar/default.nix create mode 100644 foundation/src/stages/stage1/gzip/default.nix create mode 100644 foundation/src/stages/stage1/musl/boot.nix create mode 100644 foundation/src/stages/stage1/musl/default.nix create mode 100644 foundation/src/stages/stage1/musl/patches/always-flush.patch diff --git a/foundation/flake.nix b/foundation/flake.nix index 16e5550..3ed9ec4 100644 --- a/foundation/flake.nix +++ b/foundation/flake.nix @@ -13,8 +13,9 @@ modules = import ./src; forEachSystem = lib.attrs.generate [ - "x86_64-linux" - "aarch64-linux" + # "x86_64-linux" + # "aarch64-linux" + "i686-linux" # "x86_64-darwin" # "aarch64-darwin" ]; diff --git a/foundation/src/builders/bash/boot.nix b/foundation/src/builders/bash/boot.nix new file mode 100644 index 0000000..c108d14 --- /dev/null +++ b/foundation/src/builders/bash/boot.nix @@ -0,0 +1,77 @@ +{ + lib, + config, +}: let + system = config.aux.system; + builders = config.aux.foundation.builders; + + stage0 = config.aux.foundation.stages.stage0; + stage1 = config.aux.foundation.stages.stage1; +in { + options.aux.foundation.builders.bash.boot = { + build = lib.options.create { + type = lib.types.function lib.types.package; + description = "Builds a package using the kaem builder."; + }; + }; + + config = { + aux.foundation.builders.bash.boot = { + build = lib.modules.overrides.default (settings @ { + name, + script, + meta ? {}, + extras ? {}, + env ? {}, + deps ? {}, + ... + }: let + package = builtins.derivation ( + (builtins.removeAttrs settings ["meta" "extras" "executable" "env" "deps" "script"]) + // env + // { + inherit name system script; + + passAsFile = ["script"]; + + builder = "${stage1.bash.boot.package}/bin/bash"; + + args = [ + "-e" + (builtins.toFile "bash-builder.sh" '' + export CONFIG_SHELL=$SHELL + + # Normalize the NIX_BUILD_CORES variable. The value might be 0, which + # means that we're supposed to try and auto-detect the number of + # available CPU cores at run-time. We don't have nproc to detect the + # number of available CPU cores so default to 1 if not set. + NIX_BUILD_CORES="''${NIX_BUILD_CORES:-1}" + if [ $NIX_BUILD_CORES -le 0 ]; then + NIX_BUILD_CORES=1 + fi + export NIX_BUILD_CORES + + bash -eux $scriptPath + '') + ]; + + SHELL = "${stage1.bash.boot.package}/bin/bash"; + + PATH = lib.paths.bin ( + (deps.build.host or []) + ++ [ + stage1.bash.boot.package + stage1.coreutils.boot.package + stage0.mescc-tools-extra.package + ] + ); + } + ); + in + package + // { + inherit meta extras; + }); + }; + }; +} diff --git a/foundation/src/builders/bash/default.nix b/foundation/src/builders/bash/default.nix new file mode 100644 index 0000000..1909ea0 --- /dev/null +++ b/foundation/src/builders/bash/default.nix @@ -0,0 +1,22 @@ +{ + lib, + config, +}: let + system = config.aux.system; + builders = config.aux.foundation.builders; + + stage0 = config.aux.foundation.stages.stage0; +in { + includes = [ + ./boot.nix + ]; + + options.aux.foundation.builders.bash = { + # TODO: Bash builder that isn't boot. + }; + + config = { + aux.foundation.builders.bash = { + }; + }; +} diff --git a/foundation/src/default.nix b/foundation/src/default.nix index c8efde9..cd7df84 100644 --- a/foundation/src/default.nix +++ b/foundation/src/default.nix @@ -1,5 +1,6 @@ let modules = { + builderBash = builders/bash; builderFileText = ./builders/file/text; builderKaem = ./builders/kaem; builderRaw = ./builders/raw; diff --git a/foundation/src/platform/default.nix b/foundation/src/platform/default.nix index 8ef4bd5..d5114f8 100644 --- a/foundation/src/platform/default.nix +++ b/foundation/src/platform/default.nix @@ -287,6 +287,11 @@ }; in { options.aux.platform = { + name = lib.options.create { + type = lib.types.string; + description = "Name of the platform"; + }; + family = lib.options.create { type = lib.types.string; description = "Family of the platform"; @@ -314,11 +319,31 @@ in { default.value = null; description = "Version of the platform"; }; + + build = lib.options.create { + type = lib.types.string; + description = "The build entry, such as x86-unknown-linux-gnu."; + }; + + host = lib.options.create { + type = lib.types.string; + description = "The host entry, such as x86-unknown-linux-gnu."; + }; }; config = { aux.platform = - platforms.${platform} - or (builtins.throw "Unsupported platform: ${system}"); + ( + platforms.${platform} + or (builtins.throw "Unsupported platform: ${system}") + ) + // { + name = platform; + + # These will only ever have `linux` as the target since we + # do not support darwin bootstrapping. + build = "${platform}-unknown-${target}-gnu"; + host = "${platform}-unknown-${target}-gnu"; + }; }; } diff --git a/foundation/src/stages/stage0/phases/phase11.nix b/foundation/src/stages/stage0/phases/phase11.nix index 2f2920d..97f04f5 100644 --- a/foundation/src/stages/stage0/phases/phase11.nix +++ b/foundation/src/stages/stage0/phases/phase11.nix @@ -114,18 +114,19 @@ in { executable = blood-elf.package; - args = [ + args = (lib.lists.when (config.aux.platform.bits == 64) "--64") - "-f" - hex2_linker_M1 - ( - if config.aux.platform.endian == "little" - then "--little-endian" - else "--big-endian" - ) - "-o" - (builtins.placeholder "out") - ]; + ++ [ + "-f" + hex2_linker_M1 + ( + if config.aux.platform.endian == "little" + then "--little-endian" + else "--big-endian" + ) + "-o" + (builtins.placeholder "out") + ]; }; hex2_linker_hex2 = builders.raw.build { pname = "hex2_linker_hex2"; diff --git a/foundation/src/stages/stage0/phases/phase12.nix b/foundation/src/stages/stage0/phases/phase12.nix index 57dff75..0ee6b94 100644 --- a/foundation/src/stages/stage0/phases/phase12.nix +++ b/foundation/src/stages/stage0/phases/phase12.nix @@ -116,18 +116,19 @@ in { executable = blood-elf.package; - args = [ + args = (lib.lists.when (config.aux.platform.bits == 64) "--64") - "-f" - kaem_M1 - ( - if config.aux.platform.endian == "little" - then "--little-endian" - else "--big-endian" - ) - "-o" - (builtins.placeholder "out") - ]; + ++ [ + "-f" + kaem_M1 + ( + if config.aux.platform.endian == "little" + then "--little-endian" + else "--big-endian" + ) + "-o" + (builtins.placeholder "out") + ]; }; kaem_hex2 = builders.raw.build { pname = "kaem_hex2"; diff --git a/foundation/src/stages/stage1/default.nix b/foundation/src/stages/stage1/default.nix index b97be73..a8065d7 100644 --- a/foundation/src/stages/stage1/default.nix +++ b/foundation/src/stages/stage1/default.nix @@ -7,6 +7,7 @@ stage1 = config.aux.foundation.stages.stage1; in { includes = [ + # These packages are built using Kaem. ./nyacc ./mes ./ln-boot @@ -15,6 +16,13 @@ in { ./gnumake ./coreutils ./bash + + # These packages are built using Bash v2. + ./gnused + ./gnugrep + ./gnutar + ./gzip + ./musl ]; config = { @@ -33,6 +41,12 @@ in { stage1-gnumake = stage1.gnumake.package; stage1-coreutils-boot = stage1.coreutils.boot.package; stage1-bash-boot = stage1.bash.boot.package; + + stage1-gnused-boot = stage1.gnused.boot.package; + stage1-gnugrep = stage1.gnugrep.package; + stage1-gnutar-boot = stage1.gnutar.boot.package; + stage1-gzip = stage1.gzip.package; + stage1-musl-boot = stage1.musl.boot.package; }; extras = { diff --git a/foundation/src/stages/stage1/gnugrep/default.nix b/foundation/src/stages/stage1/gnugrep/default.nix new file mode 100644 index 0000000..a5af8d4 --- /dev/null +++ b/foundation/src/stages/stage1/gnugrep/default.nix @@ -0,0 +1,106 @@ +{ + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.gnugrep; + + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.stage1; +in { + options.aux.foundation.stages.stage1.gnugrep = { + package = lib.options.create { + type = lib.types.package; + description = "The package to use for gnugrep."; + }; + + version = lib.options.create { + type = lib.types.string; + description = "Version of the package."; + }; + + src = lib.options.create { + type = lib.types.package; + description = "Source for the package."; + }; + + meta = { + description = lib.options.create { + type = lib.types.string; + description = "Description for the package."; + default.value = "GNU implementation of the Unix grep command"; + }; + + homepage = lib.options.create { + type = lib.types.string; + description = "Homepage for the package."; + default.value = "https://www.gnu.org/software/grep"; + }; + + license = lib.options.create { + # TODO: Add a proper type for licenses. + type = lib.types.attrs.any; + description = "License for the package."; + default.value = lib.licenses.gpl3Plus; + }; + + platforms = lib.options.create { + type = lib.types.list.of lib.types.string; + description = "Platforms the package supports."; + default.value = ["x86_64-linux" "aarch64-linux" "i686-linux"]; + }; + + mainProgram = lib.options.create { + type = lib.types.string; + description = "The main program of the package."; + default.value = "grep"; + }; + }; + }; + + config = { + aux.foundation.stages.stage1.gnugrep = { + version = "2.4"; + + src = builtins.fetchurl { + url = "https://ftpmirror.gnu.org/grep/grep-${cfg.version}.tar.gz"; + sha256 = "05iayw5sfclc476vpviz67hdy03na0pz2kb5csa50232nfx34853"; + }; + + package = let + # Thanks to the live-bootstrap project! + # See https://github.com/fosslinux/live-bootstrap/blob/1bc4296091c51f53a5598050c8956d16e945b0f5/sysa/grep-2.4 + makefile = builtins.fetchurl { + url = "https://github.com/fosslinux/live-bootstrap/raw/1bc4296091c51f53a5598050c8956d16e945b0f5/sysa/grep-2.4/mk/main.mk"; + sha256 = "08an9ljlqry3p15w28hahm6swnd3jxizsd2188przvvsj093j91k"; + }; + in + builders.bash.boot.build { + name = "gnused-boot-${cfg.version}"; + meta = cfg.meta; + + deps.build.host = [ + stage1.tinycc.mes.compiler.package + stage1.gnumake.package + ]; + + script = '' + # Unpack + ungz --file ${cfg.src} --output grep.tar + untar --file grep.tar + rm grep.tar + cd grep-${cfg.version} + + # Configure + cp ${makefile} Makefile + + # Build + make CC="tcc -B ${stage1.tinycc.mes.libs.package}/lib" + + # Install + make install PREFIX=$out + ''; + }; + }; + }; +} diff --git a/foundation/src/stages/stage1/gnused/boot.nix b/foundation/src/stages/stage1/gnused/boot.nix new file mode 100644 index 0000000..575ec39 --- /dev/null +++ b/foundation/src/stages/stage1/gnused/boot.nix @@ -0,0 +1,77 @@ +{ + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.gnused.boot; + + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.stage1; +in { + options.aux.foundation.stages.stage1.gnused.boot = { + package = lib.options.create { + type = lib.types.package; + description = "The package to use for gnused-boot."; + }; + + version = lib.options.create { + type = lib.types.string; + description = "Version of the package."; + }; + + src = lib.options.create { + type = lib.types.package; + description = "Source for the package."; + }; + }; + + config = { + aux.foundation.stages.stage1.gnused.boot = { + version = "4.0.9"; + + src = builtins.fetchurl { + url = "https://ftpmirror.gnu.org/sed/sed-${cfg.version}.tar.gz"; + sha256 = "0006gk1dw2582xsvgx6y6rzs9zw8b36rhafjwm288zqqji3qfrf3"; + }; + + package = let + # Thanks to the live-bootstrap project! + # See https://github.com/fosslinux/live-bootstrap/blob/1bc4296091c51f53a5598050c8956d16e945b0f5/sysa/sed-4.0.9/sed-4.0.9.kaem + makefile = builtins.fetchurl { + url = "https://github.com/fosslinux/live-bootstrap/raw/1bc4296091c51f53a5598050c8956d16e945b0f5/sysa/sed-4.0.9/mk/main.mk"; + sha256 = "0w1f5ri0g5zla31m6l6xyzbqwdvandqfnzrsw90dd6ak126w3mya"; + }; + in + builders.bash.boot.build { + name = "gnused-boot-${cfg.version}"; + + meta = stage1.gnused.meta; + + deps.build.host = [ + stage1.tinycc.mes.compiler.package + stage1.gnumake.package + ]; + + script = '' + # Unpack + ungz --file ${cfg.src} --output sed.tar + untar --file sed.tar + rm sed.tar + cd sed-${cfg.version} + + # Configure + cp ${makefile} Makefile + catm config.h + + # Build + make \ + CC="tcc -B ${stage1.tinycc.mes.libs.package}/lib" \ + LIBC=mes + + # Install + make install PREFIX=$out + ''; + }; + }; + }; +} diff --git a/foundation/src/stages/stage1/gnused/default.nix b/foundation/src/stages/stage1/gnused/default.nix new file mode 100644 index 0000000..60b564f --- /dev/null +++ b/foundation/src/stages/stage1/gnused/default.nix @@ -0,0 +1,49 @@ +{ + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.gnused; + + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.gnused; +in { + includes = [ + ./boot.nix + ]; + + options.aux.foundation.stages.stage1.gnused = { + meta = { + description = lib.options.create { + type = lib.types.string; + description = "Description for the package."; + default.value = "GNU sed, a batch stream editor."; + }; + + homepage = lib.options.create { + type = lib.types.string; + description = "Homepage for the package."; + default.value = "https://www.gnu.org/software/sed"; + }; + + license = lib.options.create { + # TODO: Add a proper type for licenses. + type = lib.types.attrs.any; + description = "License for the package."; + default.value = lib.licenses.gpl3Plus; + }; + + platforms = lib.options.create { + type = lib.types.list.of lib.types.string; + description = "Platforms the package supports."; + default.value = ["x86_64-linux" "aarch64-linux" "i686-linux"]; + }; + + mainProgram = lib.options.create { + type = lib.types.string; + description = "The main program of the package."; + default.value = "sed"; + }; + }; + }; +} diff --git a/foundation/src/stages/stage1/gnutar/boot.nix b/foundation/src/stages/stage1/gnutar/boot.nix new file mode 100644 index 0000000..945c47c --- /dev/null +++ b/foundation/src/stages/stage1/gnutar/boot.nix @@ -0,0 +1,76 @@ +{ + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.gnutar.boot; + + platform = config.aux.platform; + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.stage1; +in { + options.aux.foundation.stages.stage1.gnutar.boot = { + package = lib.options.create { + type = lib.types.package; + description = "The package to use for gnutar-boot."; + }; + + version = lib.options.create { + type = lib.types.string; + description = "Version of the package."; + }; + + src = lib.options.create { + type = lib.types.package; + description = "Source for the package."; + }; + }; + + config = { + aux.foundation.stages.stage1.gnutar.boot = { + version = "1.12"; + + src = builtins.fetchurl { + url = "https://ftpmirror.gnu.org/tar/tar-${cfg.version}.tar.gz"; + sha256 = "02m6gajm647n8l9a5bnld6fnbgdpyi4i3i83p7xcwv0kif47xhy6"; + }; + + package = let + in + builders.bash.boot.build { + name = "gnutar-boot-${cfg.version}"; + + meta = stage1.gnutar.meta; + + deps.build.host = [ + stage1.tinycc.mes.compiler.package + stage1.gnumake.package + stage1.gnused.boot.package + stage1.gnugrep.package + ]; + + script = '' + # Unpack + ungz --file ${cfg.src} --output tar.tar + untar --file tar.tar + rm tar.tar + cd tar-${cfg.version} + + # Configure + export CC="tcc -B ${stage1.tinycc.mes.libs.package}/lib" + bash ./configure \ + --build=${platform.build} \ + --host=${platform.host} \ + --disable-nls \ + --prefix=$out + + # Build + make AR="tcc -ar" + + # Install + make install + ''; + }; + }; + }; +} diff --git a/foundation/src/stages/stage1/gnutar/default.nix b/foundation/src/stages/stage1/gnutar/default.nix new file mode 100644 index 0000000..e577b8f --- /dev/null +++ b/foundation/src/stages/stage1/gnutar/default.nix @@ -0,0 +1,49 @@ +{ + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.gnutar; + + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.gnutar; +in { + includes = [ + ./boot.nix + ]; + + options.aux.foundation.stages.stage1.gnutar = { + meta = { + description = lib.options.create { + type = lib.types.string; + description = "Description for the package."; + default.value = "GNU implementation of the `tar' archiver"; + }; + + homepage = lib.options.create { + type = lib.types.string; + description = "Homepage for the package."; + default.value = "https://www.gnu.org/software/tar"; + }; + + license = lib.options.create { + # TODO: Add a proper type for licenses. + type = lib.types.attrs.any; + description = "License for the package."; + default.value = lib.licenses.gpl3Plus; + }; + + platforms = lib.options.create { + type = lib.types.list.of lib.types.string; + description = "Platforms the package supports."; + default.value = ["x86_64-linux" "aarch64-linux" "i686-linux"]; + }; + + mainProgram = lib.options.create { + type = lib.types.string; + description = "The main program of the package."; + default.value = "tar"; + }; + }; + }; +} diff --git a/foundation/src/stages/stage1/gzip/default.nix b/foundation/src/stages/stage1/gzip/default.nix new file mode 100644 index 0000000..ef34fd1 --- /dev/null +++ b/foundation/src/stages/stage1/gzip/default.nix @@ -0,0 +1,104 @@ +{ + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.gzip; + + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.stage1; +in { + options.aux.foundation.stages.stage1.gzip = { + package = lib.options.create { + type = lib.types.package; + description = "The package to use for gnugrep."; + }; + + version = lib.options.create { + type = lib.types.string; + description = "Version of the package."; + }; + + src = lib.options.create { + type = lib.types.package; + description = "Source for the package."; + }; + + meta = { + description = lib.options.create { + type = lib.types.string; + description = "Description for the package."; + default.value = "GNU implementation of the Unix grep command"; + }; + + homepage = lib.options.create { + type = lib.types.string; + description = "Homepage for the package."; + default.value = "https://www.gnu.org/software/grep"; + }; + + license = lib.options.create { + # TODO: Add a proper type for licenses. + type = lib.types.attrs.any; + description = "License for the package."; + default.value = lib.licenses.gpl3Plus; + }; + + platforms = lib.options.create { + type = lib.types.list.of lib.types.string; + description = "Platforms the package supports."; + default.value = ["x86_64-linux" "aarch64-linux" "i686-linux"]; + }; + + mainProgram = lib.options.create { + type = lib.types.string; + description = "The main program of the package."; + default.value = "grep"; + }; + }; + }; + + config = { + aux.foundation.stages.stage1.gzip = { + version = "1.2.4"; + + src = builtins.fetchurl { + url = "https://ftpmirror.gnu.org/gzip/gzip-${cfg.version}.tar.gz"; + sha256 = "0ryr5b00qz3xcdcv03qwjdfji8pasp0007ay3ppmk71wl8c1i90w"; + }; + + package = let + in + builders.bash.boot.build { + name = "gnused-boot-${cfg.version}"; + meta = cfg.meta; + + deps.build.host = [ + stage1.tinycc.mes.compiler.package + stage1.gnumake.package + stage1.gnused.boot.package + stage1.gnugrep.package + ]; + + script = '' + # Unpack + ungz --file ${cfg.src} --output gzip.tar + untar --file gzip.tar + rm gzip.tar + cd gzip-${cfg.version} + + # Configure + export CC="tcc -B ${stage1.tinycc.mes.libs.package}/lib -Dstrlwr=unused" + bash ./configure --prefix=$out + + # Build + make + + # Install + mkdir $out + make install + ''; + }; + }; + }; +} diff --git a/foundation/src/stages/stage1/musl/boot.nix b/foundation/src/stages/stage1/musl/boot.nix new file mode 100644 index 0000000..aa2c5a6 --- /dev/null +++ b/foundation/src/stages/stage1/musl/boot.nix @@ -0,0 +1,139 @@ +{ + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.musl.boot; + + platform = config.aux.platform; + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.stage1; +in { + options.aux.foundation.stages.stage1.musl.boot = { + package = lib.options.create { + type = lib.types.package; + description = "The package to use for musl-boot."; + }; + + version = lib.options.create { + type = lib.types.string; + description = "Version of the package."; + }; + + src = lib.options.create { + type = lib.types.package; + description = "Source for the package."; + }; + }; + + config = { + aux.foundation.stages.stage1.musl.boot = { + version = "1.1.24"; + + src = builtins.fetchurl { + url = "https://musl.libc.org/releases/musl-${cfg.version}.tar.gz"; + sha256 = "E3DJqBKyzyp9koAlEMygBYzDfmanvt1wBR8KNAFQIqM="; + }; + + package = let + # Thanks to the live-bootstrap project! + # See https://github.com/fosslinux/live-bootstrap/blob/d98f97e21413efc32c770d0356f1feda66025686/sysa/musl-1.1.24/musl-1.1.24.sh + liveBootstrap = "https://github.com/fosslinux/live-bootstrap/raw/d98f97e21413efc32c770d0356f1feda66025686/sysa/musl-1.1.24"; + patches = [ + (builtins.fetchurl { + url = "${liveBootstrap}/patches/avoid_set_thread_area.patch"; + sha256 = "TsbBZXk4/KMZG9EKi7cF+sullVXrxlizLNH0UHGXsPs="; + }) + (builtins.fetchurl { + url = "${liveBootstrap}/patches/avoid_sys_clone.patch"; + sha256 = "/ZmH64J57MmbxdfQ4RNjamAiBdkImMTlHsHdgV4gMj4="; + }) + (builtins.fetchurl { + url = "${liveBootstrap}/patches/fenv.patch"; + sha256 = "vMVGjoN4deAJW5gsSqA207SJqAbvhrnOsGK49DdEiTI="; + }) + (builtins.fetchurl { + url = "${liveBootstrap}/patches/makefile.patch"; + sha256 = "03iYBAUnsrEdLIIhhhq5mM6BGnPn2EfUmIHu51opxbw="; + }) + (builtins.fetchurl { + url = "${liveBootstrap}/patches/musl_weak_symbols.patch"; + sha256 = "/d9a2eUkpe9uyi1ye6T4CiYc9MR3FZ9na0Gb90+g4v0="; + }) + (builtins.fetchurl { + url = "${liveBootstrap}/patches/set_thread_area.patch"; + sha256 = "RIZYqbbRSx4X/0iFUhriwwBRmoXVR295GNBUjf2UrM0="; + }) + (builtins.fetchurl { + url = "${liveBootstrap}/patches/sigsetjmp.patch"; + sha256 = "wd2Aev1zPJXy3q933aiup5p1IMKzVJBquAyl3gbK4PU="; + }) + # FIXME: this patch causes the build to fail + # (builtins.fetchurl { + # url = "${liveBootstrap}/patches/stdio_flush_on_exit.patch"; + # sha256 = "/z5ze3h3QTysay8nRvyvwPv3pmTcKptdkBIaMCoeLDg="; + # }) + # HACK: always flush stdio immediately + ./patches/always-flush.patch + (builtins.fetchurl { + url = "${liveBootstrap}/patches/va_list.patch"; + sha256 = "UmcMIl+YCi3wIeVvjbsCyqFlkyYsM4ECNwTfXP+s7vg="; + }) + ]; + in + builders.bash.boot.build { + name = "musl-boot-${cfg.version}"; + + meta = stage1.musl.meta; + + deps.build.host = [ + stage1.tinycc.mes.compiler.package + stage1.gnumake.package + stage1.gnused.boot.package + stage1.gnugrep.package + stage1.gnupatch.package + stage1.gnutar.boot.package + stage1.gzip.package + ]; + + script = '' + # Unpack + tar xzf ${cfg.src} + cd musl-${cfg.version} + + # Patch + ${lib.strings.concatMapSep "\n" (file: "patch -Np0 -i ${file}") patches} + # tcc does not support complex types + rm -rf src/complex + # Configure fails without this + mkdir -p /dev + # https://github.com/ZilchOS/bootstrap-from-tcc/blob/2e0c68c36b3437386f786d619bc9a16177f2e149/using-nix/2a3-intermediate-musl.nix + sed -i 's|/bin/sh|${stage1.bash.boot.package}/bin/bash|' \ + tools/*.sh + chmod 755 tools/*.sh + # patch popen/system to search in PATH instead of hardcoding /bin/sh + sed -i 's|posix_spawn(&pid, "/bin/sh",|posix_spawnp(\&pid, "sh",|' \ + src/stdio/popen.c src/process/system.c + sed -i 's|execl("/bin/sh", "sh", "-c",|execlp("sh", "-c",|'\ + src/misc/wordexp.c + + # Configure + bash ./configure \ + --prefix=$out \ + --build=${(builtins.trace platform.build) platform.build} \ + --host=${platform.host} \ + --disable-shared \ + CC=tcc + + # Build + make AR="tcc -ar" RANLIB=true CFLAGS="-DSYSCALL_NO_TLS" + + # Install + make install + cp ${stage1.tinycc.mes.libs.package}/lib/libtcc1.a $out/lib + + ''; + }; + }; + }; +} diff --git a/foundation/src/stages/stage1/musl/default.nix b/foundation/src/stages/stage1/musl/default.nix new file mode 100644 index 0000000..54c1017 --- /dev/null +++ b/foundation/src/stages/stage1/musl/default.nix @@ -0,0 +1,44 @@ +{ + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.musl; + + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.musl; +in { + includes = [ + ./boot.nix + ]; + + options.aux.foundation.stages.stage1.musl = { + meta = { + description = lib.options.create { + type = lib.types.string; + description = "Description for the package."; + default.value = "An efficient, small, quality libc implementation"; + }; + + homepage = lib.options.create { + type = lib.types.string; + description = "Homepage for the package."; + default.value = "https://musl.libc.org"; + }; + + license = lib.options.create { + # TODO: Add a proper type for licenses. + type = lib.types.attrs.any; + description = "License for the package."; + default.value = lib.licenses.mit; + }; + + platforms = lib.options.create { + type = lib.types.list.of lib.types.string; + description = "Platforms the package supports."; + # TODO: Support more platforms. + default.value = ["i686-linux"]; + }; + }; + }; +} diff --git a/foundation/src/stages/stage1/musl/patches/always-flush.patch b/foundation/src/stages/stage1/musl/patches/always-flush.patch new file mode 100644 index 0000000..e01a7ee --- /dev/null +++ b/foundation/src/stages/stage1/musl/patches/always-flush.patch @@ -0,0 +1,13 @@ +diff --git src/env/__libc_start_main.c src/env/__libc_start_main.c +index 8fbe526..9476c22 100644 +--- src/env/__libc_start_main.c ++++ src/env/__libc_start_main.c +@@ -91,6 +91,7 @@ static int libc_start_main_stage2(int (*main)(int,char **,char **), int argc, ch + __libc_start_init(); + + /* Pass control to the application */ ++ setbuf(stdout, NULL); + exit(main(argc, argv, envp)); + return 0; + } + diff --git a/foundation/src/system/default.nix b/foundation/src/system/default.nix index d0946f1..aae1d96 100644 --- a/foundation/src/system/default.nix +++ b/foundation/src/system/default.nix @@ -2,7 +2,7 @@ options.aux = { system = lib.options.create { type = lib.types.string; - default.value = "x86_64-linux"; + default.value = "i686-linux"; description = '' The system to build packages for. This value can be provided as either `config.aux.system` or by setting the `system` argument for modules.