Compare commits

...

10 commits

11 changed files with 354 additions and 141 deletions

View file

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

View file

@ -71,111 +71,84 @@ in
(lib.packages.build packages.foundation.bash.versions."5.2.15-stage1" "x86_64-linux" system).package
}/bin/bash";
# Validates that the exported environment variables are stringy
validateEnvVarType =
name: var:
if builtins.isString var || builtins.isPath var || lib.packages.isDerivation var then
var
else
throw "${builtins.unsafeGetAttrPos name package.env}: 'env.${name}' at is not a string, path, or derivation";
built = builtins.derivation (
package.vars
// {
inherit (package) name env;
inherit script system;
# Essentially black-listed environment variable names
# this is a list of attributes on the builtin.derivation below, keep it in sync if possible.
reservedVars = [
"name"
"script"
"system"
"script"
"env"
"__structuredAttrs"
"SHELL"
"builder"
"args"
];
validateEnvVarName =
name: var:
if !(builtins.elem name reservedVars) then
var
else
throw "${builtins.unsafeGetAttrPos name package.env}: 'env.${name}' is a reserved name";
__structuredAttrs = true;
built = builtins.derivation ({
inherit (package) name;
inherit script system;
outputs = builtins.attrNames (lib.packages.getOutputs package);
env = builtins.mapAttrs (lib.fp.compose validateEnvVarType validateEnvVarName) package.env;
SHELL = executable;
__structuredAttrs = true;
outputs = builtins.attrNames (lib.packages.getOutputs package);
SHELL = executable;
PATH =
let
bins = lib.paths.bin (
(lib.packages.dependencies.get dependencies.build)
++ (lib.packages.dependencies.get dependencies.host)
++ lib.lists.when (system == "i686-linux") [
foundation.stage2-bash
foundation.stage2-coreutils
]
++ lib.lists.when (system == "x86_64-linux") [
(lib.packages.build packages.foundation.bash.versions."5.2.15-stage1" "i686-linux" system).package
(lib.packages.build packages.foundation.coreutils.versions."9.4-stage1" "i686-linux" system).package
]
++ lib.lists.when (system != "i686-linux" && system != "x86_64-linux") [
(lib.packages.build packages.foundation.bash.versions."5.2.15-stage1" "x86_64-linux" system).package
(lib.packages.build packages.foundation.coreutils.versions."9.4-stage1" "x86_64-linux" system)
.package
]
PATH =
let
bins = lib.paths.bin (
(lib.packages.dependencies.get dependencies.build)
++ (lib.packages.dependencies.get dependencies.host)
++ lib.lists.when (system == "i686-linux") [
foundation.stage2-bash
foundation.stage2-coreutils
]
++ lib.lists.when (system == "x86_64-linux") [
(lib.packages.build packages.foundation.bash.versions."5.2.15-stage1" "i686-linux" system).package
(lib.packages.build packages.foundation.coreutils.versions."9.4-stage1" "i686-linux" system).package
]
++ lib.lists.when (system != "i686-linux" && system != "x86_64-linux") [
(lib.packages.build packages.foundation.bash.versions."5.2.15-stage1" "x86_64-linux" system).package
(lib.packages.build packages.foundation.coreutils.versions."9.4-stage1" "x86_64-linux" system)
.package
]
);
in
builtins.concatStringsSep ":" (
[ bins ] ++ (lib.lists.when (package.env ? PATH) [ package.env.PATH ])
);
in
builtins.concatStringsSep ":" (
[ bins ] ++ (lib.lists.when (package.env ? PATH) [ package.env.PATH ])
);
builder = executable;
builder = executable;
args = [
"-e"
(builtins.toFile "bash-builder.sh" ''
set -eEuo pipefail
args = [
"-e"
(builtins.toFile "bash-builder.sh" ''
set -eEuo pipefail
if [[ -e $NIX_ATTRS_SH_FILE ]]; then
source "$NIX_ATTRS_SH_FILE";
else
echo "Failed to find structuredAttrs"
exit 1
fi
if [[ -e $NIX_ATTRS_SH_FILE ]]; then
source "$NIX_ATTRS_SH_FILE";
else
echo "Failed to find structuredAttrs"
exit 1
fi
export CONFIG_SHELL=$SHELL
export CONFIG_SHELL=$SHELL
# With structuredAttrs each output var must be exported manually
for outputName in "''${!outputs[@]}"; do
# Need to set $out=/nix/store...
export "$outputName=''${outputs[$outputName]}"
done
# With structuredAttrs each output var must be exported manually
for outputName in "''${!outputs[@]}"; do
# Need to set $out=/nix/store...
export "$outputName=''${outputs[$outputName]}"
done
# Also need to export vars
for envVar in "''${!env[@]}"; do
export "$envVar=''${env[$envVar]}"
done
# Also need to export vars
for envVar in "''${!env[@]}"; do
export "$envVar=''${env[$envVar]}"
done
# 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.
NIX_BUILD_CORES="''${NIX_BUILD_CORES:-1}"
if ((NIX_BUILD_CORES <= 0)); then
guess=$(nproc 2>/dev/null || true)
((NIX_BUILD_CORES = guess <= 0 ? 1 : guess))
fi
export NIX_BUILD_CORES
# 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.
NIX_BUILD_CORES="''${NIX_BUILD_CORES:-1}"
if ((NIX_BUILD_CORES <= 0)); then
guess=$(nproc 2>/dev/null || true)
((NIX_BUILD_CORES = guess <= 0 ? 1 : guess))
fi
export NIX_BUILD_CORES
eval "$script"
'')
];
});
eval "$script"
'')
];
}
);
result = built // {
inherit package;

View file

@ -0,0 +1,55 @@
{
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" ] ''
pwd
# Configure
bash ./configure \
${configureFlags}
'';
};
};
};
}

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;
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 = {
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 = {
unpackUnpack = lib.dag.entry.before [ "unpack" ] ''
before=$(ls -d */ 2>/dev/null | sort)
tar xzf ${config.src}
after=$(ls -d */ 2>/dev/null | sort)
cd $(comm -13 <(echo "$before") <(echo "$after") | head -1)
'';
};
};
};
}

View file

@ -2,11 +2,83 @@
let
inherit (config) lib;
# Essentially black-listed environment variable names
#
# This is just a list of attributes based into builtins.derivation in
# tidepool/src/builders/foundation/basic.nix
#
# Please keep it in sync
reservedVars = [
"name"
"script"
"system"
"script"
"env"
"__structuredAttrs"
"SHELL"
"builder"
"args"
];
# str -> bool
notReservedVar = name: !(builtins.elem name reservedVars);
pretty = lib.generators.pretty { };
in
{
config = {
lib.types = {
# When passed-down to Bash, paths and derivations are just strings.
bashString =
(lib.types.one [
lib.types.string
lib.types.path
lib.types.derivation
])
// {
name = "BashString";
description = "A Bash-compatible string";
};
# Lists in Bash cannot be nested, just hold numbers and strings.
bashList =
(lib.types.list.of (
lib.types.one [
lib.types.number
lib.types.bashString
]
))
// {
name = "BashList";
description = "A bash-compatible list";
};
# Hashmaps/attrset/associated lists in Bash cannot be nested or hold lists. They just map
# strings to numbers or strings to strings.
bashMap =
(lib.types.attrs.of (
lib.types.one [
lib.types.number
lib.types.bashString
]
))
// {
name = "BashMap";
description = "A bash-compatible attrset/associated list";
};
# Any arbitrary Bash variable
bashVar =
(lib.types.one [
lib.types.number
lib.types.bashString
lib.types.bashList
lib.types.bashMap
])
// {
name = "BashVar";
description = "A bash-compatible variable";
};
license =
let
type = lib.types.submodule (
@ -754,8 +826,34 @@ in
};
env = lib.options.create {
description = "The environment for the package.";
type = lib.types.attrs.of lib.types.string;
description = "Environment variables in the derivation";
type = lib.types.withCheck (lib.types.attrs.of lib.types.bashString) (
# TODO: Better errors, these suck right now.
lib.fp.pipe [
builtins.attrNames
(builtins.all notReservedVar)
]
);
default.value = { };
};
# TOTHINK: Currently this only validates for Bash variables.
# In the future we could/should allow users to have JSON exports
# as well, which have relaxes requirements compared to Bash.
#
# Either relaxing this var, or adding another var.
vars = lib.options.create {
description = "Bash variables set in the derivation";
type = lib.types.withCheck (lib.types.attrs.of lib.types.bashVar) (
lib.fp.pipe [
# TODO: Better errors, these suck right now.
builtins.attrNames
# Cannot be a reservd name, and cannot be an environment variable
(builtins.all (
name: (notReservedVar name) && !(builtins.elem name (builtins.attrNames config.env))
))
]
);
default.value = { };
};

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;
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

View file

@ -10,7 +10,7 @@ in
description = "A general-purpose data compression software, successor of LZMA.";
homepage = "https://tukaani.org/xz";
license = [
lib.licences.gpl2Plus
lib.licenses.gpl2Plus
lib.licenses.lgpl21Plus
];
};

View file

@ -28,7 +28,7 @@ in
description = "A general-purpose data compression software, successor of LZMA.";
homepage = "https://tukaani.org/xz";
license = [
lib.licences.gpl2Plus
lib.licenses.gpl2Plus
lib.licenses.lgpl21Plus
];
};

View file

@ -20,7 +20,7 @@ in
description = "A general-purpose data compression software, successor of LZMA.";
homepage = "https://tukaani.org/xz";
license = [
lib.licences.gpl2Plus
lib.licenses.gpl2Plus
lib.licenses.lgpl21Plus
];
};