From 4a771e2f60a114bfa6e50dc8003e2f579cee216a Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Thu, 6 Jun 2024 17:45:06 -0700 Subject: [PATCH] feat: add gnumake and gnupatch --- foundation/src/stages/stage1/default.nix | 13 +- .../src/stages/stage1/gnumake/default.nix | 262 ++++++++++++++++++ .../patches/0001-No-impure-bin-sh.patch | 36 +++ .../patches/0002-remove-impure-dirs.patch | 41 +++ .../gnumake/patches/0003-tinycc-support.patch | 59 ++++ .../src/stages/stage1/gnupatch/default.nix | 169 +++++++++++ 6 files changed, 571 insertions(+), 9 deletions(-) create mode 100644 foundation/src/stages/stage1/gnumake/default.nix create mode 100644 foundation/src/stages/stage1/gnumake/patches/0001-No-impure-bin-sh.patch create mode 100644 foundation/src/stages/stage1/gnumake/patches/0002-remove-impure-dirs.patch create mode 100644 foundation/src/stages/stage1/gnumake/patches/0003-tinycc-support.patch create mode 100644 foundation/src/stages/stage1/gnupatch/default.nix diff --git a/foundation/src/stages/stage1/default.nix b/foundation/src/stages/stage1/default.nix index 101b21e..b136e05 100644 --- a/foundation/src/stages/stage1/default.nix +++ b/foundation/src/stages/stage1/default.nix @@ -11,6 +11,8 @@ in { ./mes ./ln-boot ./tinycc + ./gnupatch + ./gnumake ]; config = { @@ -25,6 +27,8 @@ in { stage1-tinycc-boot-libs = stage1.tinycc.boot.libs.package; stage1-tinycc-mes = stage1.tinycc.mes.compiler.package; stage1-tinycc-mes-libs = stage1.tinycc.mes.libs.package; + stage1-gnupatch = stage1.gnupatch.package; + stage1-gnumake = stage1.gnumake.package; }; extras = { @@ -35,15 +39,6 @@ in { prefix = stage1.mes.libs.prefix; }; }; - tinycc = { - boot = { - src = stage1.tinycc.boot.src; - tarball = builtins.fetchurl { - url = "https://gitlab.com/janneke/tinycc/-/archive/${stage1.tinycc.boot.revision}/tinycc-${stage1.tinycc.boot.revision}.tar.gz"; - sha256 = "1a0cw9a62qc76qqn5sjmp3xrbbvsz2dxrw21lrnx9q0s74mwaxbq"; - }; - }; - }; }; }; }; diff --git a/foundation/src/stages/stage1/gnumake/default.nix b/foundation/src/stages/stage1/gnumake/default.nix new file mode 100644 index 0000000..a173050 --- /dev/null +++ b/foundation/src/stages/stage1/gnumake/default.nix @@ -0,0 +1,262 @@ +{ + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.gnumake; + + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.stage1; +in { + options.aux.foundation.stages.stage1.gnumake = { + package = lib.options.create { + type = lib.types.package; + description = "The package to use for gnumake."; + }; + + meta = { + description = lib.options.create { + type = lib.types.string; + description = "Description for the package."; + default.value = "A tool to control the generation of non-source files from sources"; + }; + + homepage = lib.options.create { + type = lib.types.string; + description = "Homepage for the package."; + default.value = "https://www.gnu.org/software/make"; + }; + + 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"]; + }; + }; + + 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.gnumake = { + version = "4.4.1"; + + src = builtins.fetchurl { + url = "https://ftpmirror.gnu.org/make/make-${cfg.version}.tar.gz"; + sha256 = "1cwgcmwdn7gqn5da2ia91gkyiqs9birr10sy5ykpkaxzcwfzn5nx"; + }; + + package = let + patches = [ + # Replaces /bin/sh with sh, see patch file for reasoning + ./patches/0001-No-impure-bin-sh.patch + # Purity: don't look for library dependencies (of the form `-lfoo') in /lib + # and /usr/lib. It's a stupid feature anyway. Likewise, when searching for + # included Makefiles, don't look in /usr/include and friends. + ./patches/0002-remove-impure-dirs.patch + # Fixes for tinycc. See comments in patch file for reasoning + ./patches/0003-tinycc-support.patch + ]; + + /* + Maintenance notes: + + Generated by + ./configure \ + --build i686-pc-linux-gnu \ + --host i686-pc-linux-gnu \ + CC="${tinycc.compiler}/bin/tcc -B ${tinycc.libs}/lib" \ + ac_cv_func_dup=no + - `ac_cv_func_dup` disabled as mes-libc doesn't implement tmpfile() + + The output src/config.h was then manually filtered, removing definitions that + didn't have uses in the source code + */ + config = [ + "-DFILE_TIMESTAMP_HI_RES=0" + "-DHAVE_ALLOCA" + "-DHAVE_ALLOCA_H" + "-DHAVE_ATEXIT" + "-DHAVE_DECL_BSD_SIGNAL=0" + "-DHAVE_DECL_GETLOADAVG=0" + "-DHAVE_DECL_SYS_SIGLIST=0" + "-DHAVE_DECL__SYS_SIGLIST=0" + "-DHAVE_DECL___SYS_SIGLIST=0" + "-DHAVE_DIRENT_H" + "-DHAVE_DUP2" + "-DHAVE_FCNTL_H" + "-DHAVE_FDOPEN" + "-DHAVE_GETCWD" + "-DHAVE_GETTIMEOFDAY" + "-DHAVE_INTTYPES_H" + "-DHAVE_ISATTY" + "-DHAVE_LIMITS_H" + "-DHAVE_LOCALE_H" + "-DHAVE_MEMORY_H" + "-DHAVE_MKTEMP" + "-DHAVE_SA_RESTART" + "-DHAVE_SETVBUF" + "-DHAVE_SIGACTION" + "-DHAVE_SIGSETMASK" + "-DHAVE_STDINT_H" + "-DHAVE_STDLIB_H" + "-DHAVE_STRDUP" + "-DHAVE_STRERROR" + "-DHAVE_STRINGS_H" + "-DHAVE_STRING_H" + "-DHAVE_STRTOLL" + "-DHAVE_SYS_FILE_H" + "-DHAVE_SYS_PARAM_H" + "-DHAVE_SYS_RESOURCE_H" + "-DHAVE_SYS_SELECT_H" + "-DHAVE_SYS_STAT_H" + "-DHAVE_SYS_TIMEB_H" + "-DHAVE_SYS_TIME_H" + "-DHAVE_SYS_WAIT_H" + "-DHAVE_TTYNAME" + "-DHAVE_UMASK" + "-DHAVE_UNISTD_H" + "-DHAVE_WAITPID" + "-DMAKE_JOBSERVER" + "-DMAKE_SYMLINKS" + "-DPATH_SEPARATOR_CHAR=':'" + "-DSCCS_GET=\\\"get\\\"" + "-DSTDC_HEADERS" + "-Dsig_atomic_t=int" + "-Dvfork=fork" + ]; + + cflags = + [ + "-I./src" + "-I./lib" + "-DHAVE_CONFIG_H" + "-DMAKE_MAINTAINER_MODE" + "-DLIBDIR=\\\"${builtins.placeholder "out"}/lib\\\"" + "-DLOCALEDIR=\\\"/fake-locale\\\"" + "-DPOSIX=1" + # mes-libc doesn't implement osync_* methods + "-DNO_OUTPUT_SYNC=1" + # mes-libc doesn't define O_TMPFILE + "-DO_TMPFILE=020000000" + ] + ++ config; + + sources = { + # Maintenance note: list of source files derived from Basic.mk + make = [ + "src/ar.c" + "src/arscan.c" + "src/commands.c" + "src/default.c" + "src/dir.c" + "src/expand.c" + "src/file.c" + "src/function.c" + "src/getopt.c" + "src/getopt1.c" + "src/guile.c" + "src/hash.c" + "src/implicit.c" + "src/job.c" + "src/load.c" + "src/loadapi.c" + "src/main.c" + "src/misc.c" + "src/output.c" + "src/read.c" + "src/remake.c" + "src/rule.c" + "src/shuffle.c" + "src/signame.c" + "src/strcache.c" + "src/variable.c" + "src/version.c" + "src/vpath.c" + ]; + glob = [ + "lib/fnmatch.c" + "lib/glob.c" + ]; + remote = [ + "src/remote-stub.c" + ]; + }; + + files = + sources.make + ++ sources.glob + ++ sources.remote + ++ [ + "src/posixos.c" + ]; + + objects = + builtins.map + ( + value: + builtins.replaceStrings [".c"] [".o"] + (builtins.baseNameOf value) + ) + files; + in + builders.kaem.build { + name = "gnumake-${cfg.version}"; + + meta = cfg.meta; + src = cfg.src; + + deps.build.host = [ + stage1.tinycc.mes.compiler.package + stage1.gnupatch.package + ]; + + script = '' + # Unpack + ungz --file ${cfg.src} --output make.tar + untar --file make.tar + rm make.tar + cd make-${cfg.version} + + # Patch + ${lib.strings.concatMapSep "\n" (file: "patch -Np1 -i ${file}") patches} + + # Configure + catm src/config.h src/mkconfig.h src/mkcustom.h + cp lib/glob.in.h lib/glob.h + cp lib/fnmatch.in.h lib/fnmatch.h + + # Compile + alias CC="tcc -B ${stage1.tinycc.mes.libs.package}/lib ${builtins.concatStringsSep " " cflags}" + ${lib.strings.concatMapSep "\n" (file: "CC -c ${file}") files} + + # Link + CC -o make ${builtins.concatStringsSep " " objects} + + # Check + ./make --version + + # Install + mkdir -p ''${out}/bin + cp ./make ''${out}/bin + chmod 555 ''${out}/bin/make + ''; + }; + }; + }; +} diff --git a/foundation/src/stages/stage1/gnumake/patches/0001-No-impure-bin-sh.patch b/foundation/src/stages/stage1/gnumake/patches/0001-No-impure-bin-sh.patch new file mode 100644 index 0000000..17a08a2 --- /dev/null +++ b/foundation/src/stages/stage1/gnumake/patches/0001-No-impure-bin-sh.patch @@ -0,0 +1,36 @@ +From e00a5257a6ca5fedbf68b09eee7df3502971a057 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= +Date: Sat, 24 Apr 2021 10:11:40 +0200 +Subject: [PATCH 1/2] No impure bin sh + +default_shell is used to populuate default shell used to execute jobs. +Unless SHELL is set to a different value this would be /bin/sh. +Our stdenv provides sh in form of bash anyway. Having this value not +hard-coded has some advantages: + +- It would ensure that on all systems it uses sh from its PATH rather + than /bin/sh, which helps as different systems might have different + shells there (bash vs. dash) +- In the past I had issues with LD_PRELOAD with BEAR, where /bin/sh + used a different glibc than BEAR which came from my development shell. +--- + src/job.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/job.c b/src/job.c +index ae1f18b..6b4ddb3 100644 +--- a/src/job.c ++++ b/src/job.c +@@ -77,7 +77,7 @@ char * vms_strsignal (int status); + + #else + +-const char *default_shell = "/bin/sh"; ++const char *default_shell = "sh"; + int batch_mode_shell = 0; + + #endif +-- +2.31.1 + + diff --git a/foundation/src/stages/stage1/gnumake/patches/0002-remove-impure-dirs.patch b/foundation/src/stages/stage1/gnumake/patches/0002-remove-impure-dirs.patch new file mode 100644 index 0000000..08660a6 --- /dev/null +++ b/foundation/src/stages/stage1/gnumake/patches/0002-remove-impure-dirs.patch @@ -0,0 +1,41 @@ +From 795d63d3c8b5c0dbb7e544954f75507b371b7228 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= +Date: Sat, 24 Apr 2021 10:20:16 +0200 +Subject: [PATCH 2/2] remove impure dirs + +--- + src/read.c | 3 --- + src/remake.c | 2 -- + 2 files changed, 5 deletions(-) + +diff --git a/src/read.c b/src/read.c +index fa197fb..defacfb 100644 +--- a/src/read.c ++++ b/src/read.c +@@ -109,9 +109,6 @@ static const char *default_include_directories[] = + #endif + INCLUDEDIR, + #ifndef _AMIGA +- "/usr/gnu/include", +- "/usr/local/include", +- "/usr/include", + #endif + 0 + }; +diff --git a/src/remake.c b/src/remake.c +index fb237c5..94bff7d 100644 +--- a/src/remake.c ++++ b/src/remake.c +@@ -1601,8 +1601,6 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) + static const char *dirs[] = + { + #ifndef _AMIGA +- "/lib", +- "/usr/lib", + #endif + #if defined(WINDOWS32) && !defined(LIBDIR) + /* +-- +2.31.1 + + diff --git a/foundation/src/stages/stage1/gnumake/patches/0003-tinycc-support.patch b/foundation/src/stages/stage1/gnumake/patches/0003-tinycc-support.patch new file mode 100644 index 0000000..805f156 --- /dev/null +++ b/foundation/src/stages/stage1/gnumake/patches/0003-tinycc-support.patch @@ -0,0 +1,59 @@ +diff --git a/src/dir.c b/src/dir.c +index 3e94b98..cfaa6a2 100644 +--- a/src/dir.c ++++ b/src/dir.c +@@ -1331,10 +1331,9 @@ local_stat (const char *path, struct stat *buf) + + /* Similarly for lstat. */ + #if !defined(lstat) && !defined(WINDOWS32) || defined(VMS) +-# ifndef VMS +-# ifndef HAVE_SYS_STAT_H ++// mes-libc implements but does not declare lstat ++# if (!defined(VMS) && !defined(HAVE_SYS_STAT_H)) || defined(__TINYC__) + int lstat (const char *path, struct stat *sbuf); +-# endif + # else + /* We are done with the fake lstat. Go back to the real lstat */ + # ifdef lstat +diff --git a/src/job.c b/src/job.c +index ea88561..8388a82 100644 +--- a/src/job.c ++++ b/src/job.c +@@ -2052,7 +2052,8 @@ job_next_command (struct child *child) + static int + load_too_high (void) + { +-#if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA) || defined(__riscos__) ++// mes-libc does not support getloadavg ++#if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA) || defined(__riscos__) || defined (__TINYC__) + return 1; + #else + static double last_sec; +diff --git a/src/main.c b/src/main.c +index a9d3a64..664d40f 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -2770,7 +2770,7 @@ main (int argc, char **argv, char **envp) + char *b = alloca (40); + sprintf (b, "MAKE_RESTARTS=%s%u", + OUTPUT_IS_TRACED () ? "-" : "", restarts); +- putenv (b); ++ // mes-libc does not support putenv + } + + fflush (stdout); +diff --git a/src/misc.c b/src/misc.c +index eb14f40..bffca82 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -653,7 +653,8 @@ get_tmppath () + + # ifdef HAVE_MKTEMP + path = get_tmptemplate (); +- if (*mktemp (path) == '\0') ++ // tinycc: "src/misc.c:656: error: pointer expected" ++ if (!strcmp(mktemp (path), "")) + { + OSS (error, NILF, + _("cannot generate temp path from %s: %s"), path, strerror (errno)); + diff --git a/foundation/src/stages/stage1/gnupatch/default.nix b/foundation/src/stages/stage1/gnupatch/default.nix new file mode 100644 index 0000000..ba25b97 --- /dev/null +++ b/foundation/src/stages/stage1/gnupatch/default.nix @@ -0,0 +1,169 @@ +{ + lib, + config, +}: let + cfg = config.aux.foundation.stages.stage1.gnupatch; + + builders = config.aux.foundation.builders; + + stage1 = config.aux.foundation.stages.stage1; +in { + options.aux.foundation.stages.stage1.gnupatch = { + package = lib.options.create { + type = lib.types.package; + description = "The package to use for gnupatch."; + }; + + meta = { + description = lib.options.create { + type = lib.types.string; + description = "Description for the package."; + default.value = "GNU Patch, a program to apply differences to files."; + }; + + homepage = lib.options.create { + type = lib.types.string; + description = "Homepage for the package."; + default.value = "https://www.gnu.org/software/patch"; + }; + + 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"]; + }; + }; + + 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.gnupatch = { + version = "2.5.9"; + + src = builtins.fetchurl { + url = "https://ftpmirror.gnu.org/patch/patch-${cfg.version}.tar.gz"; + sha256 = "12nv7jx3gxfp50y11nxzlnmqqrpicjggw6pcsq0wyavkkm3cddgc"; + }; + + package = let + # Thanks to the live-bootstrap project! + # https://github.com/fosslinux/live-bootstrap/blob/1bc4296091c51f53a5598050c8956d16e945b0f5/sysa/patch-2.5.9/mk/main.mk + cflags = [ + "-I." + "-DHAVE_DECL_GETENV" + "-DHAVE_DECL_MALLOC" + "-DHAVE_DIRENT_H" + "-DHAVE_LIMITS_H" + "-DHAVE_GETEUID" + "-DHAVE_MKTEMP" + "-DPACKAGE_BUGREPORT=" + "-Ded_PROGRAM=\\\"/nullop\\\"" + "-Dmbstate_t=int" # When HAVE_MBRTOWC is not enabled uses of mbstate_t are always a no-op + "-DRETSIGTYPE=int" + "-DHAVE_MKDIR" + "-DHAVE_RMDIR" + "-DHAVE_FCNTL_H" + "-DPACKAGE_NAME=\\\"patch\\\"" + "-DPACKAGE_VERSION=\\\"${cfg.version}\\\"" + "-DHAVE_MALLOC" + "-DHAVE_REALLOC" + "-DSTDC_HEADERS" + "-DHAVE_STRING_H" + "-DHAVE_STDLIB_H" + ]; + + # Maintenance note: List of sources from Makefile.in + files = [ + "addext.c" + "argmatch.c" + "backupfile.c" + "basename.c" + "dirname.c" + "getopt.c" + "getopt1.c" + "inp.c" + "maketime.c" + "partime.c" + "patch.c" + "pch.c" + "quote.c" + "quotearg.c" + "quotesys.c" + "util.c" + "version.c" + "xmalloc.c" + ]; + + sources = + files + ++ [ + # mes-libc doesn't implement `error()` + "error.c" + ]; + + objects = + builtins.map + ( + value: + builtins.replaceStrings + [".c"] + [".o"] + (builtins.baseNameOf value) + ) + sources; + in + builders.kaem.build { + name = "gnupatch-${cfg.version}"; + + meta = cfg.meta; + src = cfg.src; + + deps.build.host = [ + stage1.tinycc.mes.compiler.package + ]; + + script = '' + # Unpack + ungz --file ${cfg.src} --output patch.tar + untar --file patch.tar + rm patch.tar + cd patch-${cfg.version} + + # Configure + catm config.h + + # Build + alias CC="tcc -B ${stage1.tinycc.mes.libs.package}/lib ${builtins.concatStringsSep " " cflags}" + ${lib.strings.concatMapSep "\n" (source: "CC -c ${source}") sources} + + # Link + CC -o patch ${builtins.concatStringsSep " " objects} + + # Check + ./patch --version + + # Install + mkdir -p ''${out}/bin + cp ./patch ''${out}/bin + chmod 555 ''${out}/bin/patch + ''; + }; + }; + }; +}