WIP: basic capabilities #56

Draft
vlinkz wants to merge 3 commits from vlinkz/labs:capabilitiespoc into main
6 changed files with 184 additions and 44 deletions

View file

@ -49,6 +49,7 @@ let
};
in
new [
./src/capabilities
./src/packages
./src/builders/foundation/basic.nix
]

View file

@ -0,0 +1,53 @@
{
config.capabilities.configure =
{ config, global, ... }:
let
inherit (global)
lib
;
platform = {
build = lib.systems.withBuildInfo config.platform.build;
host = lib.systems.withBuildInfo config.platform.host;
};
in
{
options.configure = {
flags = lib.options.create {
description = "List of flags to pass to configure.";
type = lib.types.list.of lib.types.string;
default.value = [ ];
};
prefix = lib.options.create {
description = "Include prefix configure flag.";
type = lib.types.bool;
default.value = true;
};
platforms = lib.options.create {
description = "Include platform configure flags.";
type = lib.types.bool;
default.value = true;
};
};
config = {
phases =
let
configureFlags = builtins.concatStringsSep " " (
lib.lists.when config.configure.prefix [ "--prefix=$out" ]
++ lib.lists.when config.configure.platforms [
"--build=${platform.build.triple}"
"--host=${platform.host.triple}"
]
++ config.configure.flags
);
in
{
configureConfigure = lib.dag.entry.between [ "unpack" ] [ "configure" ] ''

It is a bit unfortunate that they cannot directly set the configure phase

It is a bit unfortunate that they cannot directly set the `configure` phase
bash ./configure \

We shouldn't call bash ./configure directly because there is more software than you may realize that use Python, Perl, Scheme, or something else for their configure scripts. I would prefer to just use the shebangs, but Aux does not have a way to patch shebangs (yet), so I would instead just put a TODO.

We shouldn't call `bash ./configure` directly because there is more software than you may realize that use Python, Perl, Scheme, or something else for their configure scripts. I would prefer to just use the shebangs, but Aux does not have a way to patch shebangs (yet), so I would instead just put a TODO.
${configureFlags}

One thing I'd like to devise is a way to pass arguments down the to derivation call so that we can use structuredAttrs for configure flags and such, as they means Aux doesn't need to worry about escaping and spaces, as it will Just Work since Nix does the proper escaping for us.

If you don't want to, can just put a TODO there.

One thing I'd like to devise is a way to pass arguments down the to derivation call so that we can use `structuredAttrs` for configure flags and such, as they means Aux doesn't need to worry about escaping and spaces, as it will Just Work since Nix does the proper escaping for us. If you don't want to, can just put a TODO there.
'';
};
};
};
}

View file

@ -0,0 +1,20 @@
{ config }:
let
inherit (config) lib;
in
{
includes = [
./unpack.nix
./make.nix
./configure.nix
];
options = {
capabilities = lib.options.create {
description = "A set of capabilities that can be added to packages to provide build functionality.";
# TODO: define proper type
type = lib.types.attrs.of (lib.types.function lib.types.any);
default.value = { };
};
};
}

View file

@ -0,0 +1,47 @@
{
config.capabilities.make =
{ config, global, ... }:
let
inherit (global)
lib
packages
;
in
{
options.make = {
flags = lib.options.create {
description = "List of flags to pass to make.";
type = lib.types.list.of lib.types.string;
default.value = [ ];
};
bootstrap = lib.options.create {
description = "Whether to use the bootstrap tools for i686-linux builds.";
type = lib.types.bool;
default.value = false;
};
};
config = {
deps.build = {
gnumake =
if (config.make.bootstrap && config.platform.build == "i686-linux") then
packages.foundation.gnumake.versions."4.4.1-bootstrap"
else
packages.foundation.gnumake.versions."4.4.1-stage1-passthrough";
};
phases =
let
makeFlags = builtins.concatStringsSep " " config.make.flags;

Same thing, TODO for structuredAttrs if you want, so we don't need to concat things with spaces naively.

As a minor improvement quoting each argument is probably fine.

Same thing, TODO for `structuredAttrs` if you want, so we don't need to concat things with spaces naively. As a minor improvement quoting each argument is probably fine.
in
{
makeBuild = lib.dag.entry.between [ "configure" ] [ "build" ] ''
make -j $NIX_BUILD_CORES ${makeFlags}
'';
makeInstall = lib.dag.entry.between [ "build" ] [ "install" ] ''
make -j $NIX_BUILD_CORES install ${makeFlags}
'';
};
};
};
}

View file

@ -0,0 +1,46 @@
{
config.capabilities.unpack =
{ config, global, ... }:
let
inherit (global)
lib
packages
;
in
{
options.unpack = {

Should add an option for the command to run for unpacking, defaulting to tar xfz so that other formats can be unpacked (zip, deb, ...)

Should add an option for the command to run for unpacking, defaulting to `tar xfz` so that other formats can be unpacked (zip, deb, ...)
bootstrap = lib.options.create {
description = "Whether to use the bootstrap tools for i686-linux builds.";
type = lib.types.bool;
default.value = false;
};
};
config = {
deps.build =
if (config.make.bootstrap && config.platform.build == "i686-linux") then
{
bzip2 = packages.foundation.bzip2.versions."1.0.8-bootstrap";
gnutar = packages.foundation.gnutar.versions."1.35-bootstrap";
gzip = packages.foundation.gzip.versions."1.13-bootstrap";
xz = packages.foundation.xz.versions."5.4.3-bootstrap";
}
else
{
bzip2 = packages.foundation.bzip2.versions."1.0.8-stage1-passthrough";
gnutar = packages.foundation.gnutar.versions."1.35-stage1-passthrough";
gzip = packages.foundation.gzip.versions."1.13-stage1-passthrough";
xz = packages.foundation.xz.versions."5.4.3-stage1-passthrough";
};
phases = {

Same thing about structuredAttrs here as well.

Same thing about `structuredAttrs` here as well.
unpackUnpack = lib.dag.entry.before [ "unpack" ] ''
before=$(ls -d */ 2>/dev/null | sort)

I would recommend using find instead as ls is really only for human output, and ls will often adjust names for better human consumption (if they are not alphanumeric).

Also the glob will fail if there are names with dashes in it, so it should be something like ls -d -- */, or else they will becomes arguments to ls

I would recommend using `find` instead as `ls` is really only for human output, and `ls` will often adjust names for better human consumption (if they are not alphanumeric). Also the glob will fail if there are names with dashes in it, so it should be something like `ls -d -- */`, or else they will becomes arguments to `ls`
tar xzf ${config.src}
after=$(ls -d */ 2>/dev/null | sort)
cd $(comm -13 <(echo "$before") <(echo "$after") | head -1)
'';
};
};
};
}

View file

@ -3,19 +3,21 @@
let
inherit (global)
lib
capabilities
packages
builders
mirrors
;
version = lib.strings.removeSuffix "-stage1" config.version;
platform = {
build = lib.systems.withBuildInfo config.platform.build;
host = lib.systems.withBuildInfo config.platform.host;
};
in
{
includes = with capabilities; [
unpack
make
configure
];
config = {
meta = {
description = "GNU Bourne-Again Shell, the de facto standard shell on Linux";
@ -50,13 +52,10 @@ in
(
if (config.platform.build == "i686-linux") then
{
gnumake = packages.foundation.gnumake.versions."4.4.1-bootstrap";
gnupatch = packages.foundation.gnupatch.versions."2.7-bootstrap";
gnused = packages.foundation.gnused.versions."4.9-bootstrap";
gnutar = packages.foundation.gnutar.versions."1.35-bootstrap";
gnugrep = packages.foundation.gnugrep.versions."3.11-bootstrap";
gawk = packages.foundation.gawk.versions."5.2.2-bootstrap";
gzip = packages.foundation.gzip.versions."1.13-bootstrap";
diffutils = packages.foundation.diffutils.versions."3.10-bootstrap";
findutils = packages.foundation.findutils.versions."4.9.0-bootstrap";
gcc = packages.foundation.gcc.versions."13.2.0-bootstrap";
@ -64,13 +63,10 @@ in
}
else
{
gnumake = packages.foundation.gnumake.versions."4.4.1-stage1-passthrough";
gnupatch = packages.foundation.gnupatch.versions."2.7-stage1-passthrough";
gnused = packages.foundation.gnused.versions."4.9-stage1-passthrough";
gnutar = packages.foundation.gnutar.versions."1.35-stage1-passthrough";
gnugrep = packages.foundation.gnugrep.versions."3.11-stage1-passthrough";
gawk = packages.foundation.gawk.versions."5.2.2-stage1-passthrough";
gzip = packages.foundation.gzip.versions."1.13-stage1-passthrough";
diffutils = packages.foundation.diffutils.versions."3.10-stage1-passthrough";
findutils = packages.foundation.findutils.versions."4.9.0-stage1-passthrough";
gcc = packages.foundation.gcc.versions."13.2.0-stage4";
@ -83,42 +79,19 @@ in
};
};
unpack.bootstrap = true;

This looks great!

This looks great!
make.bootstrap = true;
configure.flags = [
"--enable-static-link"
"bash_cv_func_strtoimax=y"
]
++ lib.lists.when (config.platform.host == "i686-linux") [
"--without-bash-malloc"
];
phases = {
unpack = ''
# Unpack
tar xf ${config.src}
cd bash-${version}
'';
configure =
let
flags = builtins.concatStringsSep " " (
[
"--prefix=$out"
"--build=${platform.build.triple}"
"--host=${platform.host.triple}"
"--enable-static-link"
]
++ lib.lists.when (config.platform.host == "i686-linux") [
"--without-bash-malloc"
]
);
in
''
# Configure
bash ./configure \
${flags} \
bash_cv_func_strtoimax=y
'';
build = ''
# Build
make -j $NIX_BUILD_CORES
'';
install = ''
# Install
make -j $NIX_BUILD_CORES install
rm $out/bin/bashbug
ln -s $out/bin/bash $out/bin/sh