feat: add mes, mes-libs, and nyacc

This commit is contained in:
Jake Hamilton 2024-06-05 15:16:52 -07:00
parent 84633e1eb8
commit 0ff2902587
Signed by: jakehamilton
GPG key ID: 9762169A1B35EA68
11 changed files with 1589 additions and 23 deletions

View file

@ -19,6 +19,14 @@
# "aarch64-darwin"
];
in {
extras = let
result = lib.modules.run {
modules =
builtins.attrValues modules;
};
in
result.config.exports.resolved.extras;
packages = forEachSystem (
system: let
result = lib.modules.run {

View file

@ -24,7 +24,6 @@ in {
extras ? {},
...
}: let
source = builtins.toFile "source" contents;
script =
''
target=''${out}''${destination}
@ -33,17 +32,19 @@ in {
mkdir -p ''${out}''${destinationDir}
''
+ ''
cp ${source} ''${target}
cp ''${contentsPath} ''${target}
''
+ lib.strings.when isExecutable ''
chmod 555 ''${target}
'';
package = builtins.derivation (
(builtins.removeAttrs settings ["meta" "extras" "contents" "executable" "isExecutable"])
(builtins.removeAttrs settings ["meta" "extras" "executable" "isExecutable"])
// {
inherit name system destination;
inherit name system destination contents;
destinationDir = builtins.dirOf destination;
passAsFile = ["contents"];
builder = "${stage0.kaem.package}/bin/kaem";
args = [

View file

@ -8,31 +8,40 @@
type = lib.types.attrs.of lib.types.package;
};
extras = lib.options.create {
default.value = {};
type = lib.types.attrs.any;
};
};
in {
options = {
exports = {
inherit (options) packages;
inherit (options) packages extras;
resolved = {
inherit (options) packages;
inherit (options) packages extras;
};
};
};
config = {
exports.resolved =
builtins.mapAttrs (
name: value:
lib.attrs.filter
(
name: value:
if value ? meta && value.meta ? platforms
then builtins.elem config.aux.system value.meta.platforms
else true
)
value
)
(builtins.removeAttrs config.exports ["resolved"]);
exports.resolved = {
packages =
builtins.mapAttrs (
name: value:
lib.attrs.filter
(
name: value:
if value ? meta && value.meta ? platforms
then builtins.elem config.aux.system value.meta.platforms
else true
)
value
)
config.exports.packages;
extras = config.exports.extras;
};
};
}

View file

@ -3,16 +3,31 @@
config,
}: let
cfg = config.aux.foundation.stages.stage1;
stage1 = config.aux.foundation.stages.stage1;
in {
includes = [
./nyacc
# ./mes
./mes
];
config = {
exports = {
packages = {
stage1-nyacc = config.aux.foundation.stages.stage1.nyacc.package;
stage1-nyacc = stage1.nyacc.package;
stage1-mes = stage1.mes.compiler.package;
stage1-mes-libs = stage1.mes.libs.package;
};
extras = {
stage1 = {
mes = {
src = stage1.mes.src;
libs = {
prefix = stage1.mes.libs.prefix;
};
};
};
};
};
};

View file

@ -0,0 +1,109 @@
{
lib,
config,
}: let
cfg = config.aux.foundation.stages.stage1.mes.compiler;
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.stages.stage1.mes.compiler = {
package = lib.options.create {
type = lib.types.package;
description = "The package to use for the mes compiler.";
};
meta = {
description = lib.options.create {
type = lib.types.string;
description = "Description for the package.";
default.value = "Scheme interpreter and C compiler for bootstrapping.";
};
homepage = lib.options.create {
type = lib.types.string;
description = "Homepage for the package.";
default.value = "https://www.gnu.org/software/mes";
};
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 = ["i686-linux"];
};
};
};
config = {
aux.foundation.stages.stage1.mes.compiler = {
package = let
compile = path: let
file = builtins.baseNameOf path;
fileWithoutExtension = builtins.replaceStrings [".c"] [""] file;
cc = builtins.concatStringsSep " " [
"${stage1.mes.libs.src.bin}/bin/mes-m2"
"-e"
"main"
"${stage1.mes.libs.src.bin}/bin/mescc.scm"
"--"
"-D"
"HAVE_CONFIG_H=1"
"-I"
"${stage1.mes.libs.prefix}/include"
"-I"
"${stage1.mes.libs.prefix}/include/linux/x86"
];
in
builders.kaem.build {
name = fileWithoutExtension;
script = ''
mkdir ''${out}
cd ''${out}
${cc} -c ${stage1.mes.libs.prefix}/${path}
'';
};
getSourcePath = suffix: source: "${source}/${source.name}${suffix}";
sources = import ./sources.nix;
files =
lib.strings.concatMapSep
" "
(getSourcePath ".o")
(builtins.map compile sources.x86.linux.mescc.mes);
in
builders.kaem.build {
name = "mes-${stage1.mes.version}";
meta = cfg.meta;
script = ''
mkdir -p ''${out}/bin
${stage1.mes.libs.src.bin}/bin/mes-m2 -e main ${stage1.mes.libs.src.bin}/bin/mescc.scm -- \
-L ${stage1.mes.libs.prefix}/lib \
-L ${stage1.mes.libs.package}/lib \
-lc \
-lmescc \
-nostdlib \
-o ''${out}/bin/mes \
${stage1.mes.libs.package}/lib/x86-mes/crt1.o \
${files}
'';
};
};
};
}

View file

@ -0,0 +1,99 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash coreutils gnutar
# Generate a sources.nix for a version of GNU mes. Creates lists of source files
# from build-aux/configure-lib.sh.
#
# You may point this tool at a manually downloaded tarball, but more ideal is
# using the source tarball from Nixpkgs. For example:
#
# MES_TARBALL="$(nix eval --raw .#extras.stage1.mes.src)"
# ./create-sources.sh "$MES_TARBALL" > ./sources.nix
#
# Alternatively, here is a one-liner:
#
# ./create-sources.sh "$(nix eval --raw .#extras.stage1.mes.src)" > ./sources.nix
set -eu
# Supported platforms
ARCHS="x86"
KERNELS="linux"
COMPILERS="mescc gcc"
format() {
echo "["
echo $* | xargs printf ' "%s"\n'
echo " ]"
}
gen_sources() {
# Configuration variables used by configure-lib.sh
export mes_libc=mes
export mes_cpu=$1
export mes_kernel=$2
export compiler=$3
# Populate source file lists
source $CONFIGURE_LIB_SH
cat <<EOF
$mes_cpu.$mes_kernel.$compiler = {
libc_mini = $(format $libc_mini_SOURCES);
libmescc = $(format $libmescc_SOURCES);
libtcc1 = $(format $libtcc1_SOURCES);
libc = $(format $libc_SOURCES);
libc_tcc = $(format $libc_tcc_SOURCES);
libc_gnu = $(format $libc_gnu_SOURCES);
mes = $(format $mes_SOURCES);
};
EOF
}
MES_TARBALL=$1
if [ ! -f $MES_TARBALL ]; then
echo "Provide path to mes-x.x.x.tar.gz as first argument" >&2
exit 1
fi
echo "Generating sources.nix from $MES_TARBALL" >&2
TMP=$(mktemp -d)
cd $TMP
echo "Workdir: $TMP" >&2
echo "Extracting $MES_TARBALL" >&2
tar --strip-components 1 -xf $MES_TARBALL
CONFIGURE_LIB_SH="$TMP/build-aux/configure-lib.sh"
if [ ! -f $CONFIGURE_LIB_SH ]; then
echo "Could not find mes's configure-lib.sh script at $CONFIGURE_LIB_SH" >&2
exit 1
fi
# Create dummy config expected by configure-lib.sh
touch config.sh
chmod +x config.sh
echo "Configuring with $CONFIGURE_LIB_SH" >&2
cat <<EOF
# This file is generated by ./create-sources.sh.
# Do not edit!
{
EOF
for arch in $ARCHS; do
for kernel in $KERNELS; do
for compiler in $COMPILERS; do
gen_sources $arch $kernel $compiler
done
done
done
cat <<EOF
}
EOF

View file

@ -2,11 +2,36 @@
lib,
config,
}: let
cfg = config.aux.foundation.stages.stage1.mes;
system = config.aux.system;
builders = config.aux.foundation.builders;
in {
includes = [
./compiler.nix
./libs.nix
];
options.aux.foundation.stages.stage1.mes = {
src = lib.options.create {
type = lib.types.package;
description = "Source for the package.";
};
version = lib.options.create {
type = lib.types.string;
description = "Version of the package.";
};
};
config = {
aux.foundation.stages.stage0.mes = {
aux.foundation.stages.stage1.mes = {
version = "0.25";
src = builtins.fetchurl {
url = "https://ftpmirror.gnu.org/mes/mes-${cfg.version}.tar.gz";
sha256 = "MlJQs1Z+2SA7pwFhyDWvAQeec+vtl7S1u3fKUAuCiUA=";
};
};
};
}

View file

@ -0,0 +1,238 @@
{
lib,
config,
}: let
cfg = config.aux.foundation.stages.stage1.mes.libs;
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.stages.stage1.mes.libs = {
package = lib.options.create {
type = lib.types.package;
description = "The package to use for mes libs.";
};
meta = {
description = lib.options.create {
type = lib.types.string;
description = "Description for the package.";
default.value = "Scheme interpreter and C compiler for bootstrapping.";
};
homepage = lib.options.create {
type = lib.types.string;
description = "Homepage for the package.";
default.value = "https://www.gnu.org/software/mes";
};
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 = ["i686-linux"];
};
};
src = lib.options.create {
type = lib.types.package;
description = "Source for the package.";
};
prefix = lib.options.create {
type = lib.types.string;
description = "Prefix for the package.";
};
};
config = {
aux.foundation.stages.stage1.mes.libs = {
prefix = "${cfg.src.out}/mes-${stage1.mes.version}";
src = let
config_h = builtins.toFile "config.h" ''
#undef SYSTEM_LIBC
#define MES_VERSION "${stage1.mes.version}"
'';
in
builders.kaem.build {
name = "mes-src-${stage1.mes.version}";
meta = cfg.meta;
outputs = [
"out"
"bin"
];
script = ''
# Unpack source
ungz --file ${stage1.mes.src} --output mes.tar
mkdir ''${out}
cd ''${out}
untar --non-strict --file ''${NIX_BUILD_TOP}/mes.tar # ignore symlinks
MES_PREFIX=''${out}/mes-${stage1.mes.version}
cd ''${MES_PREFIX}
cp ${config_h} include/mes/config.h
mkdir include/arch
cp include/linux/x86/syscall.h include/arch/syscall.h
cp include/linux/x86/kernel-stat.h include/arch/kernel-stat.h
# Remove pregenerated files
rm mes/module/mes/psyntax.pp mes/module/mes/psyntax.pp.header
# These files are symlinked in the repo
cp mes/module/srfi/srfi-9-struct.mes mes/module/srfi/srfi-9.mes
cp mes/module/srfi/srfi-9/gnu-struct.mes mes/module/srfi/srfi-9/gnu.mes
# Remove environment impurities
__GUILE_LOAD_PATH="\"''${MES_PREFIX}/mes/module:''${MES_PREFIX}/module:${stage1.nyacc.package.extras.guileModule}\""
boot0_scm=mes/module/mes/boot-0.scm
guile_mes=mes/module/mes/guile.mes
replace --file ''${boot0_scm} --output ''${boot0_scm} --match-on "(getenv \"GUILE_LOAD_PATH\")" --replace-with ''${__GUILE_LOAD_PATH}
replace --file ''${guile_mes} --output ''${guile_mes} --match-on "(getenv \"GUILE_LOAD_PATH\")" --replace-with ''${__GUILE_LOAD_PATH}
module_mescc_scm=module/mescc/mescc.scm
replace --file ''${module_mescc_scm} --output ''${module_mescc_scm} --match-on "(getenv \"M1\")" --replace-with "\"${stage0.mescc-tools.package}/bin/M1\""
replace --file ''${module_mescc_scm} --output ''${module_mescc_scm} --match-on "(getenv \"HEX2\")" --replace-with "\"${stage0.mescc-tools.package}/bin/hex2\""
replace --file ''${module_mescc_scm} --output ''${module_mescc_scm} --match-on "(getenv \"BLOOD_ELF\")" --replace-with "\"${stage0.mescc-tools.package}/bin/blood-elf\""
replace --file ''${module_mescc_scm} --output ''${module_mescc_scm} --match-on "(getenv \"srcdest\")" --replace-with "\"''${MES_PREFIX}\""
mes_c=src/mes.c
replace --file ''${mes_c} --output ''${mes_c} --match-on "getenv (\"MES_PREFIX\")" --replace-with "\"''${MES_PREFIX}\""
replace --file ''${mes_c} --output ''${mes_c} --match-on "getenv (\"srcdest\")" --replace-with "\"''${MES_PREFIX}\""
# Increase runtime resource limits
gc_c=src/gc.c
replace --file ''${gc_c} --output ''${gc_c} --match-on "getenv (\"MES_ARENA\")" --replace-with "\"100000000\""
replace --file ''${gc_c} --output ''${gc_c} --match-on "getenv (\"MES_MAX_ARENA\")" --replace-with "\"100000000\""
replace --file ''${gc_c} --output ''${gc_c} --match-on "getenv (\"MES_STACK\")" --replace-with "\"6000000\""
# Create mescc.scm
mescc_in=scripts/mescc.scm.in
replace --file ''${mescc_in} --output ''${mescc_in} --match-on "(getenv \"MES_PREFIX\")" --replace-with "\"''${MES_PREFIX}\""
replace --file ''${mescc_in} --output ''${mescc_in} --match-on "(getenv \"includedir\")" --replace-with "\"''${MES_PREFIX}/include\""
replace --file ''${mescc_in} --output ''${mescc_in} --match-on "(getenv \"libdir\")" --replace-with "\"''${MES_PREFIX}/lib\""
replace --file ''${mescc_in} --output ''${mescc_in} --match-on @prefix@ --replace-with ''${MES_PREFIX}
replace --file ''${mescc_in} --output ''${mescc_in} --match-on @VERSION@ --replace-with ${stage1.mes.version}
replace --file ''${mescc_in} --output ''${mescc_in} --match-on @mes_cpu@ --replace-with x86
replace --file ''${mescc_in} --output ''${mescc_in} --match-on @mes_kernel@ --replace-with linux
mkdir -p ''${bin}/bin
cp ''${mescc_in} ''${bin}/bin/mescc.scm
# Build mes-m2
kaem --verbose --strict --file kaem.x86
cp bin/mes-m2 ''${bin}/bin/mes-m2
chmod 555 ''${bin}/bin/mes-m2
'';
};
package = let
compile = path: let
file = builtins.baseNameOf path;
fileWithoutExtension = builtins.replaceStrings [".c"] [""] file;
cc = builtins.concatStringsSep " " [
"${cfg.src.bin}/bin/mes-m2"
"-e"
"main"
"${cfg.src.bin}/bin/mescc.scm"
"--"
"-D"
"HAVE_CONFIG_H=1"
"-I"
"${cfg.prefix}/include"
"-I"
"${cfg.prefix}/include/linux/x86"
];
in
builders.kaem.build {
name = fileWithoutExtension;
script = ''
mkdir ''${out}
cd ''${out}
${cc} -c ${cfg.prefix}/${path}
'';
};
getSourcePath = suffix: source: "${source}/${source.name}${suffix}";
archive = destination: sources: "catm ${destination} ${lib.strings.concatMapSep " " (getSourcePath ".o") sources}";
source = destination: sources: "catm ${destination} ${lib.strings.concatMapSep " " (getSourcePath ".s") sources}";
createLib = name: sources: let
compiled = builtins.map compile sources;
in
builders.kaem.build {
name = "mes-${name}-${stage1.mes.version}";
meta = cfg.meta;
script = ''
LIBDIR=''${out}/lib
mkdir -p ''${LIBDIR}
cd ''${LIBDIR}
${archive "${name}.a" compiled}
${source "${name}.s" compiled}
'';
};
sources = import ./sources.nix;
crt1 = compile "lib/linux/x86-mes-mescc/crt1.c";
libc-mini = createLib "libc-mini" sources.x86.linux.mescc.libc_mini;
libmescc = createLib "libmescc" sources.x86.linux.mescc.libmescc;
libc = createLib "libc" sources.x86.linux.mescc.libc;
libc_tcc = createLib "libc+tcc" (sources.x86.linux.mescc.libc_tcc ++ ["lib/linux/symlink.c"]);
in
builders.kaem.build {
name = "mes-m2-libs-${stage1.mes.version}";
meta = cfg.meta;
script = ''
LIBDIR=''${out}/lib
mkdir -p ''${out} ''${LIBDIR}
mkdir -p ''${LIBDIR}/x86-mes
# crt1.o
cp ${crt1}/crt1.o ''${LIBDIR}/x86-mes
cp ${crt1}/crt1.s ''${LIBDIR}/x86-mes
# libc-mini.a
cp ${libc-mini}/lib/libc-mini.a ''${LIBDIR}/x86-mes
cp ${libc-mini}/lib/libc-mini.s ''${LIBDIR}/x86-mes
# libmescc.a
cp ${libmescc}/lib/libmescc.a ''${LIBDIR}/x86-mes
cp ${libmescc}/lib/libmescc.s ''${LIBDIR}/x86-mes
# libc.a
cp ${libc}/lib/libc.a ''${LIBDIR}/x86-mes
cp ${libc}/lib/libc.s ''${LIBDIR}/x86-mes
# libc+tcc.a
cp ${libc_tcc}/lib/libc+tcc.a ''${LIBDIR}/x86-mes
cp ${libc_tcc}/lib/libc+tcc.s ''${LIBDIR}/x86-mes
'';
};
};
};
}

File diff suppressed because it is too large Load diff

View file

@ -45,7 +45,7 @@ in {
};
src = lib.options.create {
type = lib.types.string;
type = lib.types.package;
description = "Source for the package.";
};
};
@ -60,6 +60,7 @@ in {
package = builders.kaem.build {
name = "${pname}-${version}";
meta = cfg.meta;
src = cfg.src;
script = ''
ungz --file ${cfg.src} --output nyacc.tar

View file

@ -2,6 +2,7 @@
options.aux = {
system = lib.options.create {
type = lib.types.string;
default.value = "x86_64-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.