Compare commits

...

19 commits

Author SHA1 Message Date
Austreelis cadfaabc85 "Fix lib.types.derivations.shell's check" (#7)
"`lib.types.derivations.shell` uses `lib.packages.isDerivation` but didn't passed an argument, making code using it fail with `error: value is a function while a Boolean was expected`"

Co-authored-by: Austreelis <dev@austreelis.net>
Reviewed-on: auxolotl/labs#7
Reviewed-by: isabel roses <isabel@isabelroses.com>
Reviewed-by: Jake Hamilton <jake.hamilton@hey.com>
Co-authored-by: Austreelis <austreelis@noreply.git.auxolotl.org>
Co-committed-by: Austreelis <austreelis@noreply.git.auxolotl.org>
2024-08-15 16:06:20 +00:00
Jake Hamilton 7d94b7f665
feat: package extend, dynamic propagation 2024-07-09 02:54:33 -07:00
Jake Hamilton 3f9d287065
refactor: format 2024-07-09 01:49:44 -07:00
Jake Hamilton ea200d834e
feat: pass through package dependencies via context 2024-07-08 23:18:11 -07:00
Jake Hamilton 62bc2f4eee
feat: propagating hooks and context 2024-07-08 23:07:59 -07:00
Steve D 42e69f7d43 "topographic" -> "topological" in latest tidepool commit (#6)
Reviewed-on: auxolotl/labs#6
Co-authored-by: Steve Dodd <steved424@gmail.com>
Co-committed-by: Steve Dodd <steved424@gmail.com>
2024-07-08 19:19:49 +00:00
Jake Hamilton 0ad14e8795
refactor: make dag helpers easier to reason about 2024-07-07 15:10:37 -07:00
Jake Hamilton 0a63667459
refactor(format): apply formatting 2024-07-07 15:03:48 -07:00
Jake Hamilton d2b053d63a
feat: export linux-headers 2024-07-07 15:03:47 -07:00
Jake Hamilton 7774f65079
refactor: minor cleanup 2024-07-07 15:03:46 -07:00
Jake Hamilton fd9b85f29e
feat: apply platform to deps inside submodules 2024-07-07 15:03:45 -07:00
Jake Hamilton b315ae81f6
refactor: only support i686-linux for foundation gcc 2024-07-07 15:03:45 -07:00
Jake Hamilton 193a52cbc8
fix: cross-platform deps 2024-07-07 15:03:44 -07:00
Jake Hamilton 27a0e3d59f
fix: remove failing build args 2024-07-07 15:03:43 -07:00
Jake Hamilton 2b5f90d4e5
refactor: make dependencies dynamically built per-package 2024-07-07 15:03:42 -07:00
Jake Hamilton 008632bc8b
feat: working transient deps 2024-07-07 15:03:41 -07:00
Jake Hamilton 0f602b1cb7
wip: working single dependency reference via coercion 2024-07-07 15:03:38 -07:00
Alex Kladov 8233d4aedf use correct name for topological sort (#5)
I am 0.8 sure this is a typo, I've never seen this being referred to as topographic sorting!

Reviewed-on: auxolotl/labs#5
Reviewed-by: Jake Hamilton <jake.hamilton@hey.com>
Co-authored-by: Alex Kladov <aleksey.kladov@gmail.com>
Co-committed-by: Alex Kladov <aleksey.kladov@gmail.com>
2024-06-23 18:39:30 +00:00
Steve D a2f0a06426 Fix non-deterministic "missing: Permission denied" errors (#4)
Make 'missing' executable where source tarballs use autotools and are unpacked with untar.  untar doesn't preserve or set mtime, which may result in autotools generated files, e.g. configure, having newer timestamps than their source files (e.g. configure.in.) In these circumstances autotools generated Makefiles will call 'missing' to either regenerate them or fix-up the timestamps.

Reviewed-on: auxolotl/labs#4
Reviewed-by: isabel roses <isabel@isabelroses.com>
Reviewed-by: Jake Hamilton <jake.hamilton@hey.com>
Co-authored-by: Steve Dodd <steved424@gmail.com>
Co-committed-by: Steve Dodd <steved424@gmail.com>
2024-06-23 17:32:11 +00:00
26 changed files with 1203 additions and 558 deletions

View file

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -I "nixpkgs=https://github.com/nixos/nixpkgs/archive/nixos-24.05.tar.gz" -p nixfmt-rfc-style
#!nix-shell -i bash -I "nixpkgs=https://github.com/nixos/nixpkgs/archive/nixos-unstable.tar.gz" -p nixfmt-rfc-style
files=$(find . -name "*.nix" -type f)

View file

@ -3,10 +3,10 @@
"lib": {
"locked": {
"dir": "lib",
"dirtyRev": "9850da8aa9dc9be22e237c9b424a18e801e53ecb-dirty",
"dirtyShortRev": "9850da8-dirty",
"lastModified": 1718529861,
"narHash": "sha256-tv/0C7ixH+9Ij+r+5nua48OlXXXnbdEsnenxX4eG/Sk=",
"dirtyRev": "2be3111b2c0911f40b47fe0a1fb22b5f5188cf59-dirty",
"dirtyShortRev": "2be3111-dirty",
"lastModified": 1719251485,
"narHash": "sha256-63NvfFVeTDITfNu60rmCUlaZtAeZUnvrIaOLSk9ScC8=",
"type": "git",
"url": "file:../?dir=lib"
},

View file

@ -68,6 +68,7 @@ in
export CC="tcc -B ${stage1.tinycc.mes.libs.package}/lib"
export ac_cv_func_getpgrp_void=yes
export ac_cv_func_tzset=yes
chmod 0755 missing
bash ./configure \
--build=${platform.build} \
--host=${platform.host} \

View file

@ -58,6 +58,7 @@ in
# Configure
export CC="tcc -B ${stage1.tinycc.mes.libs.package}/lib"
chmod 0755 missing
bash ./configure \
--build=${platform.build} \
--host=${platform.host} \

View file

@ -59,6 +59,7 @@ in
export ac_cv_sizeof_unsigned_long=4
export ac_cv_sizeof_long_long=8
export ac_cv_header_netdb_h=no
chmod 0755 missing
bash ./configure \
--prefix=$out \
--build=${platform.build} \

View file

@ -21,7 +21,7 @@ lib: {
## Apply a topological sort to a DAG.
##
## @type Dag a -> { result :: List a } | { cycle :: List a, loops :: List a }
topographic =
topological =
graph:
let
getEntriesBefore =
@ -43,7 +43,7 @@ lib: {
isBefore = a: b: builtins.elem a.name b.after;
sorted = lib.lists.sort.topographic isBefore entries;
sorted = lib.lists.sort.topological isBefore entries;
in
if sorted ? result then
{
@ -95,7 +95,7 @@ lib: {
## Create a new DAG entry.
##
## @type List String -> List String -> a -> { before :: List String, after :: List String, value :: a }
between = before: after: value: { inherit before after value; };
between = after: before: value: { inherit before after value; };
## Create a new DAG entry with no dependencies.
##
@ -105,12 +105,12 @@ lib: {
## Create a new DAG entry that occurs before other entries.
##
## @type List String -> a -> { before :: List String, after :: List String, value :: a }
before = before: lib.dag.entry.between before [ ];
before = before: lib.dag.entry.between [ ] before;
## Create a new DAG entry that occurs after other entries.
##
## @type List String -> a -> { before :: List String, after :: List String, value :: a }
after = lib.dag.entry.between [ ];
after = after: lib.dag.entry.between after [ ];
};
entries = {
@ -121,7 +121,7 @@ lib: {
tag:
let
process =
i: before: after: entries:
i: after: before: entries:
let
name = "${tag}-${builtins.toString i}";
entry = builtins.head entries;
@ -130,7 +130,7 @@ lib: {
if builtins.length entries == 0 then
{ }
else if builtins.length entries == 1 then
{ "${name}" = lib.dag.entry.between before after entry; }
{ "${name}" = lib.dag.entry.between after before entry; }
else
{ "${name}" = lib.dag.entry.after after entry; } // (process (i + 1) before [ name ] rest);
in
@ -144,12 +144,12 @@ lib: {
## Create a DAG from a list of entries, prefixed with a tag, that occurs before other entries.
##
## @type String -> List String -> List a -> Dag a
before = tag: before: lib.dag.entries.between tag before [ ];
before = tag: before: lib.dag.entries.between tag [ ] before;
## Create a DAG from a list of entries, prefixed with a tag, that occurs after other entries.
##
## @type String -> List String -> List a -> Dag a
after = tag: lib.dag.entries.between tag [ ];
after = tag: after: lib.dag.entries.between tag after [ ];
};
};
}

View file

@ -119,11 +119,11 @@ in
};
"sort" = {
"topographic" = {
"topological" = {
"handles an empty graph" =
let
expected = [ ];
actual = lib.dag.sort.topographic { };
actual = lib.dag.sort.topological { };
in
actual.result == expected;
@ -147,7 +147,7 @@ in
value = "d";
}
];
actual = lib.dag.sort.topographic {
actual = lib.dag.sort.topological {
a = lib.dag.entry.anywhere "a";
b = lib.dag.entry.between [ "c" ] [ "a" ] "b";
c = lib.dag.entry.before [ "c" ] "c";

View file

@ -31,15 +31,15 @@ lib: {
in
builtins.map (x: builtins.elemAt x 1) (builtins.sort isLess prepared);
## Perform a topographic sort on a list of items. The predicate function determines whether
## Perform a topological sort on a list of items. The predicate function determines whether
## its first argument comes before the second argument.
##
## @type (a -> a -> Bool) -> List a -> List a
topographic =
topological =
predicate: list:
let
searched = lib.lists.search.depthFirst true predicate list;
results = lib.lists.sort.topographic predicate (searched.visited ++ searched.rest);
results = lib.lists.sort.topological predicate (searched.visited ++ searched.rest);
in
if builtins.length list < 2 then
{ result = list; }
@ -224,5 +224,11 @@ lib: {
filter = result: value: if builtins.elem value result then result else result ++ [ value ];
in
builtins.foldl' filter [ ] list;
## Flatten a list of lists into a single list.
##
## @type List (List a) -> List a
flatten =
value: if builtins.isList value then builtins.concatMap lib.lists.flatten value else [ value ];
};
}

View file

@ -43,7 +43,7 @@ lib: {
resolve =
definition:
let
properties = builtins.addErrorContext "while evaluating definitions from `${definition.__file__}`:" (
properties = builtins.addErrorContext "while evaluating definitions from `${definition.__file__ or "<unknown>"}`:" (
lib.modules.apply.properties definition.value
);
normalize = value: {

View file

@ -49,18 +49,18 @@ lib: {
##
## @type Attrs -> Attrs
create =
settings@{
name,
description ? name,
fallback ? { },
check ? lib.fp.const true,
merge ? lib.options.merge.default,
functor ? lib.types.functor name,
mergeType ? lib.types.merge functor,
getSubOptions ? lib.fp.const { },
getSubModules ? null,
withSubModules ? lib.fp.const null,
children ? { },
settings@{ name
, description ? name
, fallback ? { }
, check ? lib.fp.const true
, merge ? lib.options.merge.default
, functor ? lib.types.functor name
, mergeType ? lib.types.merge functor
, getSubOptions ? lib.fp.const { }
, getSubModules ? null
, withSubModules ? lib.fp.const null
, children ? { }
,
}:
{
__type__ = "type";
@ -108,7 +108,7 @@ lib: {
identifier = lib.options.getIdentifier location;
first = builtins.elemAt definitions 0;
files = builtins.map lib.modules.getFiles definitions;
files = lib.modules.getFiles definitions;
serializedFiles = builtins.concatStringsSep " and " files;
getType =
@ -118,13 +118,16 @@ lib: {
else
builtins.typeOf value;
commonType = builtins.foldl' (
commonType = builtins.foldl'
(
type: definition:
if getType definition.value != type then
builtins.throw "The option `${identifier}` has conflicting definitions in ${files}"
builtins.throw "The option `${identifier}` has conflicting definitions in ${serializedFiles}"
else
type
) (getType first.value) definitions;
)
(getType first.value)
definitions;
mergeStringifiableAttrs = lib.options.merge.one;
@ -132,7 +135,7 @@ lib: {
mergeList =
if builtins.length definitions > 1 then
builtins.throw "The option `${identifier}` has conflicting definitions in ${files}"
builtins.throw "The option `${identifier}` has conflicting definitions in ${serializedFiles}"
else
(lib.types.list.of lib.types.any).merge;
@ -140,10 +143,12 @@ lib: {
location: definitions: x:
let
resolvedLocation = location ++ [ "<function body>" ];
resolvedDefinitions = builtins.map (definition: {
resolvedDefinitions = builtins.map
(definition: {
__file__ = definition.__file__;
value = definition.value x;
}) definitions;
})
definitions;
in
lib.types.any.merge resolvedLocation resolvedDefinitions;
@ -200,7 +205,8 @@ lib: {
## @type Int -> Int -> Attrs
between =
start: end:
assert lib.errors.trace (
assert lib.errors.trace
(
start <= end
) "lib.types.ints.between start must be less than or equal to end";
lib.types.withCheck lib.types.int (value: value >= start && value <= end)
@ -317,7 +323,8 @@ lib: {
## @type Int -> Int -> Attrs
between =
start: end:
assert lib.errors.trace (
assert lib.errors.trace
(
start <= end
) "lib.types.numbers.between start must be less than or equal to end";
lib.types.withCheck lib.types.number (value: value >= start && value <= end)
@ -447,8 +454,7 @@ lib: {
};
attrs = {
## A type that allows an attribute set containing any type of value. The merged
## definitions must all be.
## A type that allows an attribute set containing any type of value.
##
## @type Attrs
any = lib.types.create {
@ -480,10 +486,12 @@ lib: {
let
normalize =
definition:
builtins.mapAttrs (name: value: {
builtins.mapAttrs
(name: value: {
__file__ = definition.__file__;
value = value;
}) definition.value;
})
definition.value;
normalized = builtins.map normalize definitions;
zipper =
name: definitions: (lib.options.merge.definitions (location ++ [ name ]) type definitions).optional;
@ -520,10 +528,12 @@ lib: {
let
normalize =
definition:
builtins.mapAttrs (name: value: {
builtins.mapAttrs
(name: value: {
__file__ = definition.__file__;
value = value;
}) definition.value;
})
definition.value;
normalized = builtins.map normalize definitions;
zipper =
name: definitions:
@ -569,7 +579,7 @@ lib: {
##
## @type Attrs
shell = lib.types.derivation // {
check = value: lib.packages.isDerivation && builtins.hasAttr "shellPath" value;
check = value: lib.packages.isDerivation value && builtins.hasAttr "shellPath" value;
};
};
@ -606,9 +616,11 @@ lib: {
merge =
location: definitions:
let
result = lib.lists.mapWithIndex1 (
result = lib.lists.mapWithIndex1
(
i: definition:
lib.lists.mapWithIndex1 (
lib.lists.mapWithIndex1
(
j: value:
let
resolved =
@ -622,9 +634,12 @@ lib: {
];
in
resolved.optional
) definition.value
) definitions;
merged = builtins.concatLists result;
)
definition.value
)
definitions;
merged = lib.lists.flatten result;
filtered = builtins.filter (definition: definition ? value) merged;
values = lib.options.getDefinitionValues filtered;
in
@ -777,11 +792,11 @@ lib: {
##
## @type { modules :: List Module, args? :: Attrs, description? :: String | Null, shorthand? :: Bool } -> Attrs
of =
settings@{
modules,
args ? { },
description ? null,
shorthand ? true,
settings@{ modules
, args ? { }
, description ? null
, shorthand ? true
,
}:
let
getModules = builtins.map (
@ -790,9 +805,12 @@ lib: {
let
# TODO: Figure out if we can apply additional attributes to the generated module.
# Currently this causes issues to do with redefined options.
rest = builtins.removeAttrs (lib.attrs.filter (
rest = builtins.removeAttrs
(lib.attrs.filter
(
name: value: builtins.elem name lib.modules.VALID_KEYS
) definition.value) [ "freeform" ];
)
definition.value) [ "freeform" ];
in
if definition.value ? config then
rest
@ -922,10 +940,12 @@ lib: {
merge = location: definitions: {
includes =
modules
++ builtins.map (definition: {
++ builtins.map
(definition: {
__file__ = "${definition.__file__}; via ${lib.options.getIdentifier location}";
includes = [ definition.value ];
}) definitions;
})
definitions;
};
getSubOptions = submodule.getSubOptions;
getSubModules = submodule.getSubModules;
@ -961,10 +981,12 @@ lib: {
location: definitions:
let
first = builtins.elemAt definitions 0;
modules = builtins.map (definition: {
modules = builtins.map
(definition: {
__file__ = definition.__file__;
options = lib.options.create { type = definition.value; };
}) definitions;
})
definitions;
merged = lib.modules.fixup location (lib.options.merge.declarations location modules);
in
if builtins.length definitions == 1 then first.value else merged.type;
@ -1100,6 +1122,43 @@ lib: {
};
};
## Create a type that allows a value which is either the final type or is transformable
## to the final type.
##
## @type Attrs -> (Any -> Any) -> Attrs -> Attrs
coerceWithLocation =
initial: transform: final:
let
in
if initial.getSubModules != null then
builtins.throw "lib.types.coerceWithLocation's first argument may not have submodules, but got ${initial.description}"
else
lib.types.create {
name = "Coerce";
description = "${initial.description} that is transformed to ${final.description}";
fallback = final.fallback;
check = value: final.check value || (initial.check value && final.check (transform [ ] value));
merge =
location: definitions:
let
process = value: if initial.check value then transform location value else value;
normalize = definition: definition // { value = process definition.value; };
normalized = builtins.map normalize definitions;
in
final.merge location normalized;
getSubOptions = final.getSubOptions;
getSubModules = final.getSubModules;
withSubModules =
modules: lib.types.coerceWithLocation initial transform (final.withSubModules modules);
mergeType = x: y: null;
functor = lib.types.functor "coerceWithLocation" // {
wrapped = final;
};
children = {
inherit initial final;
};
};
dag = {
## Create a type that allows a DAG (Directed Acyclic Graph) of a given type.
##
@ -1160,10 +1219,12 @@ lib: {
merge =
location: definitions:
submodule.merge location (
builtins.map (definition: {
builtins.map
(definition: {
__file__ = definition.__file__;
value = normalize definition;
}) definitions
})
definitions
);
};
};

View file

@ -8,10 +8,10 @@
},
"locked": {
"dir": "foundation",
"dirtyRev": "9850da8aa9dc9be22e237c9b424a18e801e53ecb-dirty",
"dirtyShortRev": "9850da8-dirty",
"lastModified": 1718529861,
"narHash": "sha256-X1Wd6mDz8GTaoxt1ylkvZfrJOcZtspJrEjXMtJ2ZyG0=",
"dirtyRev": "3f9d287065ac685ce500c2cddb35428b2927f5a2-dirty",
"dirtyShortRev": "3f9d287-dirty",
"lastModified": 1720514984,
"narHash": "sha256-AuixwSlYk34Z6+GEc7y4QotF3Hk963zC9I9hAwX5KCE=",
"type": "git",
"url": "file:../?dir=foundation"
},
@ -24,10 +24,10 @@
"lib": {
"locked": {
"dir": "lib",
"dirtyRev": "9850da8aa9dc9be22e237c9b424a18e801e53ecb-dirty",
"dirtyShortRev": "9850da8-dirty",
"lastModified": 1718529861,
"narHash": "sha256-X1Wd6mDz8GTaoxt1ylkvZfrJOcZtspJrEjXMtJ2ZyG0=",
"dirtyRev": "3f9d287065ac685ce500c2cddb35428b2927f5a2-dirty",
"dirtyShortRev": "3f9d287-dirty",
"lastModified": 1720514984,
"narHash": "sha256-AuixwSlYk34Z6+GEc7y4QotF3Hk963zC9I9hAwX5KCE=",
"type": "git",
"url": "file:../?dir=lib"
},

View file

@ -1,10 +1,8 @@
{ lib, config }:
{ config }:
let
cfg = config.builders.basic;
lib' = config.lib;
inherit (config) foundation;
inherit (config) lib foundation;
in
{
config.builders = {
@ -14,15 +12,46 @@ in
build =
package:
let
phases = package.phases;
sorted = lib.dag.sort.topographic phases;
script = lib.strings.concatMapSep "\n" (
entry: if builtins.isFunction entry.value then entry.value package else entry.value
) sorted.result;
system = package.platform.build.double;
dependencies = lib.packages.dependencies.collect package;
context = lib.packages.context.create dependencies { };
hooks = lib.packages.hooks.create dependencies context;
phasesWithHooks =
let
all = lib.lists.flatten [
hooks.build.only
hooks.build.build
hooks.build.host
hooks.build.target
hooks.host.only
hooks.host.host
hooks.host.target
hooks.target.only
hooks.target.target
];
in
builtins.foldl' (final: defaults: lib.dag.apply.defaults final defaults) package.phases all;
phases = lib.dag.apply.defaults phasesWithHooks {
unpack = lib.dag.entry.before [ "patch" ] "";
patch = lib.dag.entry.between [ "unpack" ] [ "configure" ] "";
configure = lib.dag.entry.between [ "patch" ] [ "build" ] "";
build = lib.dag.entry.between [ "configure" ] [ "install" ] "";
install = lib.dag.entry.after [ "build" ] "";
};
sorted = lib.dag.sort.topological phases;
script = lib.strings.concatMapSep "\n" (entry: entry.value) sorted.result;
built = builtins.derivation (
package.env
// {
@ -36,7 +65,7 @@ in
PATH =
let
bins = lib.paths.bin (
(lib'.packages.dependencies.getPackages package.deps.build.host)
(lib.packages.dependencies.get dependencies.build.host)
++ [
foundation.stage2-bash
foundation.stage2-coreutils
@ -70,7 +99,14 @@ in
}
);
in
built // { inherit (package) meta; };
built
// {
inherit (package) meta;
extras = {
inherit package context;
phases = builtins.listToAttrs sorted.result;
} // package.extras;
};
};
};
}

View file

@ -1,18 +1,21 @@
# This file handles creating all of the exports for this project and is not
# exported itself.
{ lib, config }:
{ config }:
let
lib' = config.lib;
inherit (config) lib;
in
{
freeform = lib.types.any;
# freeform = lib.types.any;
config = {
exports = {
lib = config.lib;
inherit lib;
modules = import ./modules.nix;
packages = {
aux-a = config.packages.aux.a;
aux-b = config.packages.aux.b;
# foundation-gcc-x86_64 =
# (config.packages.foundation.gcc.versions."13.2.0".extend (args: {
# config = {
@ -24,11 +27,13 @@ in
# .config;
foundation-gcc = config.packages.foundation.gcc;
foundation-binutils = config.packages.foundation.binutils;
foundation-linux-headers = config.packages.foundation.linux-headers.versions.latest.extend {
platform.host = lib.modules.overrides.force "x86_64-linux";
};
foundation-linux-headers = config.packages.foundation.linux-headers;
# foundation-linux-headers = config.packages.foundation.linux-headers.versions.latest.extend {
# platform.host = lib.modules.overrides.force "x86_64-linux";
# };
# example-x = config.packages.example.x;
# cross-example-x-x86_64-linux = config.packages.cross.x86_64-linux.example.x;
cross-aux-a-x86_64-linux = config.packages.cross.x86_64-linux.aux.a;
cross-foundation-gcc-x86_64-linux = config.packages.cross.x86_64-linux.foundation.gcc;
};
};

View file

@ -5,7 +5,7 @@ in
config = {
lib.options = {
package = lib.options.create {
type = config.lib.types.package;
type = config.lib.types.package.base;
description = "A package definition.";
};
};

View file

@ -1,20 +1,272 @@
{
lib,
lib',
config,
}:
{ lib, config }:
let
lib' = config.lib;
in
{
config = {
lib.packages = {
dependencies = {
getPackages =
get =
dependencies:
let
available = builtins.filter (dependency: !(builtins.isNull dependency)) (
builtins.attrValues dependencies
);
exists = value: !(builtins.isNull value);
available = builtins.filter exists dependencies;
in
builtins.map (dependency: dependency.package) available;
build =
build': host': target':
builtins.mapAttrs (name: dep: lib'.packages.build dep build' host' target');
collect =
package:
let
isPropagated = name: package: package.propagate or false;
getPropagatedDependencies = target: builtins.attrValues (lib.attrs.filter isPropagated target);
process =
dependencies:
let
getDeps =
name: dependency:
let
deps = {
build = {
only = getPropagatedDependencies dependency.deps.build.only ++ process dependency.deps.build.only;
build =
getPropagatedDependencies dependency.deps.build.build
++ process dependency.deps.build.build;
host = getPropagatedDependencies dependency.deps.build.host ++ process dependency.deps.build.host;
target =
getPropagatedDependencies dependency.deps.build.target
++ process dependency.deps.build.target;
};
host = {
only = getPropagatedDependencies dependency.deps.host.only ++ process dependency.deps.host.only;
host = getPropagatedDependencies dependency.deps.host.host ++ process dependency.deps.host.host;
target =
getPropagatedDependencies dependency.deps.host.target
++ process dependency.deps.host.target;
};
target = {
only = getPropagatedDependencies dependency.deps.target.only ++ process dependency.deps.target.only;
target =
getPropagatedDependencies dependency.deps.target.target
++ process dependency.deps.target.target;
};
};
in
lib.lists.flatten [
deps.build.only
deps.build.build
deps.build.host
deps.build.target
deps.host.only
deps.host.host
deps.host.target
deps.target.only
deps.target.target
];
propagated = lib.attrs.mapToList getDeps dependencies;
in
lib.lists.flatten propagated;
in
{
build = {
only = builtins.attrValues package.deps.build.only ++ process package.deps.build.only;
build = builtins.attrValues package.deps.build.build ++ process package.deps.build.build;
host = builtins.attrValues package.deps.build.host ++ process package.deps.build.host;
target = builtins.attrValues package.deps.build.target ++ process package.deps.build.target;
};
host = {
only = builtins.attrValues package.deps.host.only ++ process package.deps.host.only;
host = builtins.attrValues package.deps.host.host ++ process package.deps.host.host;
target = builtins.attrValues package.deps.host.target ++ process package.deps.host.target;
};
target = {
only = builtins.attrValues package.deps.target.only ++ process package.deps.target.only;
target = builtins.attrValues package.deps.target.target ++ process package.deps.target.target;
};
};
};
context = {
create =
collected: ctx:
let
process =
path:
let
dependencies = lib.attrs.selectOrThrow path collected;
contexts = builtins.map (dependency: dependency.context or { }) dependencies;
result = lib.modules.run {
prefix = [ "<package>" ];
modules = builtins.map (context: { config = context; }) contexts ++ [
{
freeform = lib.types.any;
options = config.packages.context.options // {
target = lib.options.create {
description = "The dependency target that is being generated.";
type = lib.types.enum [
"build.only"
"build.build"
"build.host"
"build.target"
"host.only"
"host.host"
"host.target"
"target.only"
"target.target"
];
writable = false;
default.value = builtins.concatStringsSep "." path;
};
deps = lib.options.create {
description = "The collected dependencies.";
writable = false;
default.value = collected;
type = lib.types.submodule {
options = {
build = {
only = lib.options.create { type = lib.types.list.of lib'.types.package; };
build = lib.options.create { type = lib.types.list.of lib'.types.package; };
host = lib.options.create { type = lib.types.list.of lib'.types.package; };
target = lib.options.create { type = lib.types.list.of lib'.types.package; };
};
host = {
only = lib.options.create { type = lib.types.list.of lib'.types.package; };
host = lib.options.create { type = lib.types.list.of lib'.types.package; };
target = lib.options.create { type = lib.types.list.of lib'.types.package; };
};
target = {
only = lib.options.create { type = lib.types.list.of lib'.types.package; };
target = lib.options.create { type = lib.types.list.of lib'.types.package; };
};
};
};
};
};
config = ctx;
}
];
};
in
result.config;
in
{
build = {
only = process [
"build"
"only"
];
build = process [
"build"
"build"
];
host = process [
"build"
"host"
];
target = process [
"build"
"target"
];
};
host = {
only = process [
"host"
"only"
];
host = process [
"host"
"host"
];
target = process [
"host"
"target"
];
};
target = {
only = process [
"target"
"only"
];
target = process [
"target"
"target"
];
};
};
};
hooks = {
create =
collected: ctx:
let
process =
path:
let
dependencies = lib.attrs.selectOrThrow path collected;
hooks = builtins.map
(
dependency:
let
getHooks = dependency.hooks or (lib.fp.const { });
in
getHooks ctx
)
dependencies;
in
hooks;
in
{
build = {
only = process [
"build"
"only"
];
build = process [
"build"
"build"
];
host = process [
"build"
"host"
];
target = process [
"build"
"target"
];
};
host = {
only = process [
"host"
"only"
];
host = process [
"host"
"host"
];
target = process [
"host"
"target"
];
};
target = {
only = process [
"target"
"only"
];
target = process [
"target"
"target"
];
};
};
};
getLatest =
@ -25,54 +277,89 @@
in
builtins.head sorted;
build =
package: build: host: target:
let
resolved =
if package ? versions then
package.versions.${config.preferences.packages.version}
or (package.versions.${lib'.packages.getLatest package})
resolve =
alias:
if alias ? versions then
alias.versions.${config.preferences.packages.version}
or (alias.versions.${lib'.packages.getLatest alias})
else
package;
alias;
build =
alias: build: host: target:
let
package = lib'.packages.resolve alias;
buildDependencies =
build': host': target':
builtins.mapAttrs (name: dep: lib'.packages.build dep build' host' target');
result = resolved.extend (
platform = {
build = lib.modules.overrides.force build;
host = lib.modules.overrides.force host;
target = lib.modules.overrides.force target;
};
withPlatform = lib.modules.run {
modules = package.__modules__ ++ [
lib'.types.package.children.submodule
(
{ config }:
{
config = {
platform = {
build = build;
host = host;
target = lib.modules.override 150 target;
};
__modules__ = package.__modules__;
deps = {
build = {
only = buildDependencies build build build resolved.deps.build.only;
build = buildDependencies build build target resolved.deps.build.build;
host = buildDependencies build host target resolved.deps.build.host;
target = buildDependencies build target target resolved.deps.build.target;
};
host = {
only = buildDependencies host host host resolved.deps.host.only;
host = buildDependencies host host target resolved.deps.host.host;
target = buildDependencies host target target resolved.deps.host.target;
};
target = {
only = buildDependencies target target target resolved.deps.target.only;
target = buildDependencies target target target resolved.deps.target.target;
};
};
package = config.builder.build config;
inherit platform;
};
}
);
)
];
};
# Not all platform information can be effectively handled via submodules. To handle
# the case where a user copies the resolved config over we need to ensure that
# dependencies are appropriately updated.
withDeps = withPlatform.config // {
deps = {
build = {
only = buildDependencies build build build withPlatform.config.deps.build.only;
build = buildDependencies build build target withPlatform.config.deps.build.build;
host = buildDependencies build host target withPlatform.config.deps.build.host;
target = buildDependencies build target target withPlatform.config.deps.build.target;
};
host = {
only = buildDependencies host host host withPlatform.config.deps.host.only;
host = buildDependencies host host target withPlatform.config.deps.host.host;
target = buildDependencies host target target withPlatform.config.deps.host.target;
};
target = {
only = buildDependencies target target target withPlatform.config.deps.target.only;
target = buildDependencies target target target withPlatform.config.deps.target.target;
};
};
};
withPackage = lib.modules.run {
modules = package.__modules__ ++ [
lib'.types.package.children.submodule
(
{ config }:
{
config = {
__modules__ = package.__modules__;
inherit platform;
deps = lib.modules.overrides.force withDeps.deps;
package = lib.modules.overrides.force (withDeps.builder.build withDeps);
};
}
)
];
};
in
result;
withPackage.config;
};
};
}

View file

@ -1220,6 +1220,7 @@ in
vendor,
kernel,
abi,
...
}:
types.cpu.check cpu
&& types.vendor.check vendor
@ -1227,6 +1228,17 @@ in
&& types.abi.check abi;
};
platformWithBuildInfo = lib.types.create {
name = "systemWithBuildInfo";
description = "fully parsed representation of llvm- or nix-style platform tuple with build information";
merge = lib.options.merge.one;
check =
value:
lib.types.is "systemWithBuildInfo" value
&& value ? system
&& lib'.systems.types.platform.check value.system;
};
endian = lib.types.enum (builtins.attrValues types.endians);
endians = setTypes types.generic.endian {
@ -2792,7 +2804,7 @@ in
assert resolved.useAndroidPrebuilt -> resolved.isAndroid;
assert assertions;
# And finally, return the generated system info.
resolved;
lib.types.set "systemWithBuildInfo" resolved;
};
};
}

View file

@ -1,8 +1,9 @@
{
lib,
lib',
config,
}:
{ lib, config }:
let
inherit (config) preferences builders;
lib' = config.lib;
in
{
config = {
lib.types = {
@ -55,6 +56,10 @@
in
lib.types.either type (lib.types.list.of type);
platform =
lib.types.coerce lib.types.string lib'.systems.withBuildInfo
lib'.systems.types.platformWithBuildInfo;
builder = lib.types.submodule {
freeform = lib.types.any;
@ -66,60 +71,191 @@
};
};
packages = lib.types.attrs.of (lib'.types.alias);
packages = lib.types.attrs.of (lib.types.attrs.of lib'.types.alias);
alias = lib.types.attrs.of (
lib.types.submodule {
options = {
versions = lib.options.create {
description = "All available package versions.";
type = lib.types.attrs.of lib'.types.package;
};
};
}
);
dependencies =
build: host: target:
let
initial = lib.types.raw;
dependencies = lib.types.attrs.of (
lib.types.nullish (lib.types.either lib'.types.alias lib'.types.package)
);
package = lib.types.submodule (
{ config, meta }:
{
options = {
extend = lib.options.create {
description = "Extend the package's submodules with additional configuration.";
type = lib.types.function lib.types.raw;
default.value =
transform =
value:
let
result = meta.extend {
modules = if builtins.isAttrs value then [ { config = value; } ] else lib.lists.from.any value;
package = lib'.packages.resolve value;
in
lib'.packages.build package build host target;
in
lib.types.attrs.of (lib.types.coerce initial transform lib'.types.package);
alias = lib.types.submodule {
options = {
stable = lib.options.create {
description = "The stable version of the package.";
type = lib.types.nullish lib'.types.package;
};
latest = lib.options.create {
description = "The latest version of the package.";
type = lib'.types.package;
};
versions = lib.options.create {
description = "Available versions of the package.";
type = lib.types.attrs.of lib'.types.package;
default.value = { };
};
};
};
package =
let
normalize =
value:
if builtins.isFunction value || builtins.isList value then
value
else if value ? __modules__ then
value.__modules__
else
{ config = value; };
initial = lib.types.create {
name = "PackageConfig";
description = "configuration for a package";
check = value: builtins.isFunction value || builtins.isAttrs value || builtins.isList value;
merge =
location: definitions:
let
normalized = builtins.map (definition: lib.lists.from.any (normalize definition.value)) definitions;
in
builtins.concatLists normalized;
};
transform =
location: value:
let
modules = lib.lists.from.any (normalize value);
result = lib.modules.run {
prefix = location;
modules = modules ++ [
submodule
{ config.__modules__ = modules; }
];
};
in
result.config;
final = lib.types.raw;
deps =
build: host: target:
lib.types.submodule {
options = {
build = {
only = lib.options.create {
description = "Dependencies which are only used in the build environment.";
type = lib'.types.dependencies build build build;
default.value = { };
};
name = lib.options.create {
description = "The name of the package.";
type = lib.types.string;
default = {
text = "\${config.pname}-\${config.version}";
value =
if config.pname != null && config.version != null then "${config.pname}-${config.version}" else "";
build = lib.options.create {
description = "Dependencies which are created in the build environment and are executed in the build environment.";
type = lib'.types.dependencies build build target;
default.value = { };
};
host = lib.options.create {
description = "Dependencies which are created in the build environment and are executed in the host environment.";
type = lib'.types.dependencies build host target;
default.value = { };
};
target = lib.options.create {
description = "Dependencies which are created in the build environment and are executed in the target environment.";
type = lib'.types.dependencies build target target;
default.value = { };
};
};
pname = lib.options.create {
description = "The program name for the package";
type = lib.types.nullish lib.types.string;
default.value = null;
host = {
only = lib.options.create {
description = "Dependencies which are only used in the host environment.";
type = lib'.types.dependencies host host host;
default.value = { };
};
version = lib.options.create {
description = "The version for the package.";
type = lib.types.nullish lib.types.version;
default.value = null;
host = lib.options.create {
description = "Dependencies which are executed in the host environment.";
type = lib'.types.dependencies host host target;
default.value = { };
};
target = lib.options.create {
description = "Dependencies which are executed in the host environment which produces code for the target environment.";
type = lib'.types.dependencies host target target;
default.value = { };
};
};
target = {
only = lib.options.create {
description = "Dependencies which are only used in the target environment.";
type = lib'.types.dependencies target target target;
default.value = { };
};
target = lib.options.create {
description = "Dependencies which are executed in the target environment.";
type = lib'.types.dependencies target target target;
default.value = { };
};
};
};
};
submodule =
{ config, meta }:
let
build = config.platform.build;
host = config.platform.host;
target = config.platform.target;
in
{
options = {
__modules__ = lib.options.create {
description = "User specified modules for the package definition.";
type = lib.types.list.of (initial // { merge = lib.options.merge.one; });
# writable = false;
internal = true;
default.value = [ ];
};
extend = lib.options.create {
description = "Extend the package definition.";
type = lib.types.function lib.types.raw;
internal = true;
writable = false;
default.value = module:
let
normalized =
if builtins.isList module then
module
else if builtins.isFunction module || module ? config then
[ module ]
else
[{
config = module;
}];
result = meta.extend {
modules =
normalized ++ [
{
config.__modules__ = lib.modules.overrides.force (config.__modules__ ++ normalized);
}
];
};
in
result.config;
};
meta = {
@ -172,67 +308,57 @@
};
};
extras = lib.options.create {
description = "Extra information for the package.";
type = lib.types.attrs.of lib.types.any;
default.value = { };
};
platform = {
build = lib.options.create {
description = "The build platform for the package.";
type = lib.types.string;
default.value = "x86_64-linux";
apply =
raw:
let
system = lib'.systems.from.string raw;
x = lib'.systems.withBuildInfo raw;
in
x;
type = lib'.types.platform;
default.value = lib'.systems.withBuildInfo "x86_64-linux";
};
host = lib.options.create {
description = "The host platform for the package.";
type = lib.types.string;
default.value = "x86_64-linux";
# apply = raw: let
# system = lib'.systems.from.string raw;
# in {
# inherit raw system;
# double = lib'.systems.into.double system;
# triple = lib'.systems.into.triple system;
# };
apply =
raw:
let
system = lib'.systems.from.string raw;
x = lib'.systems.withBuildInfo raw;
in
x;
type = lib'.types.platform;
default.value = lib'.systems.withBuildInfo "x86_64-linux";
};
target = lib.options.create {
description = "The target platform for the package.";
type = lib'.types.platform;
default.value = lib'.systems.withBuildInfo "x86_64-linux";
};
};
name = lib.options.create {
description = "The name of the package.";
type = lib.types.string;
default.value = "x86_64-linux";
# apply = raw: let
# system = lib'.systems.from.string raw;
# in {
# inherit raw system;
# double = lib'.systems.into.double system;
# triple = lib'.systems.into.triple system;
# };
apply =
raw:
let
system = lib'.systems.from.string raw;
x = lib'.systems.withBuildInfo raw;
in
x;
default = {
text = "\${config.pname}-\${config.version}";
value =
if config.pname != null && config.version != null then "${config.pname}-${config.version}" else "";
};
};
phases = lib.options.create {
description = "The phases for the package.";
type = lib.types.dag.of (lib.types.either lib.types.string (lib.types.function lib.types.string));
default.value = { };
pname = lib.options.create {
description = "The program name for the package";
type = lib.types.nullish lib.types.string;
default.value = null;
};
version = lib.options.create {
description = "The version for the package.";
type = lib.types.nullish lib.types.version;
default.value = null;
};
builder = lib.options.create {
description = "The builder for the package.";
type = lib'.types.builder;
};
env = lib.options.create {
@ -241,81 +367,72 @@
default.value = { };
};
builder = lib.options.create {
description = "The builder for the package.";
type = lib'.types.builder;
};
deps = {
build = {
only = lib.options.create {
description = "Dependencies which are only used in the build environment.";
type = lib'.types.dependencies;
default.value = { };
};
build = lib.options.create {
description = "Dependencies which are created in the build environment and are executed in the build environment.";
type = lib'.types.dependencies;
default.value = { };
};
host = lib.options.create {
description = "Dependencies which are created in the build environment and are executed in the host environment.";
type = lib'.types.dependencies;
default.value = { };
};
target = lib.options.create {
description = "Dependencies which are created in the build environment and are executed in the target environment.";
type = lib'.types.dependencies;
default.value = { };
};
};
host = {
only = lib.options.create {
description = "Dependencies which are only used in the host environment.";
type = lib'.types.dependencies;
default.value = { };
};
host = lib.options.create {
description = "Dependencies which are executed in the host environment.";
type = lib'.types.dependencies;
default.value = { };
};
target = lib.options.create {
description = "Dependencies which are executed in the host environment which produces code for the target environment.";
type = lib'.types.dependencies;
default.value = { };
};
};
target = {
only = lib.options.create {
description = "Dependencies which are only used in the target environment.";
type = lib'.types.dependencies;
default.value = { };
};
target = lib.options.create {
description = "Dependencies which are executed in the target environment.";
type = lib'.types.dependencies;
default.value = { };
};
};
};
package = lib.options.create {
description = "The built derivation.";
type = lib.types.derivation;
default.value = config.builder.build config;
};
phases = lib.options.create {
description = "The phases for the package.";
type = lib.types.dag.of lib.types.string;
default.value = { };
};
context = lib.options.create {
description = "The context information that the package provides.";
type = lib.types.attrs.of lib.types.raw;
default.value = { };
};
hooks = lib.options.create {
description = "The hooks that the package provides.";
type = lib.types.function (lib.types.dag.of lib.types.string);
default.value = ctx: { };
};
propagate = lib.options.create {
description = "Whether the package should propagate its hooks and context.";
type = lib.types.bool;
default.value = false;
};
deps = lib.options.create {
description = "The dependencies for the package.";
type = deps build host target;
default.value = { };
apply = value: {
build = {
only = lib'.packages.dependencies.build build build build value.build.only;
build = lib'.packages.dependencies.build build build target value.build.build;
host = lib'.packages.dependencies.build build host target value.build.host;
target = lib'.packages.dependencies.build build target target value.build.target;
};
host = {
only = lib'.packages.dependencies.build host host host value.host.only;
host = lib'.packages.dependencies.build host host target value.host.host;
target = lib'.packages.dependencies.build host target target value.host.target;
};
target = {
only = lib'.packages.dependencies.build target target target value.target.only;
target = lib'.packages.dependencies.build target target target value.target.target;
};
};
};
};
};
type = (lib.types.coerceWithLocation initial transform final) // {
name = "Package";
description = "a package definition";
};
in
type
// {
children = type.children // {
inherit submodule;
};
};
}
);
};
};
}

View file

@ -0,0 +1,36 @@
{ lib', config }:
let
inherit (config) builders packages;
in
{
config.packages.aux.a = {
versions = {
"latest" =
{ config }:
{
config = {
meta = {
platforms = [ "i686-linux" ];
};
name = "${config.pname}-${config.version}";
pname = "a";
version = "1.0.0";
builder = builders.basic;
deps.build.host = {
inherit (packages.aux) b;
};
phases = {
install = ''
echo "a with b: ${config.deps.build.host.b.package.system}" > $out
'';
};
};
};
};
};
}

View file

@ -0,0 +1,54 @@
{ config }:
let
inherit (config) lib builders packages;
in
{
config.packages.aux.b = {
versions = {
"latest" =
{ config }:
{
options = {
custom = lib.options.create { type = lib.types.bool; };
};
config = {
meta = {
platforms = [ "i686-linux" ];
};
name = "${config.pname}-${config.version}";
custom = true;
pname = "b";
version = "1.0.0";
builder = builders.basic;
deps = {
build = {
host = {
c = packages.aux.c.versions.latest.extend {
propagate = true;
};
};
};
};
context = {
"foundation:cflags" = [ "-I $AUX_B/include" ];
};
hooks = ctx: { "aux:b:env" = lib.dag.entry.after [ "unpack" ] ''export AUX_B=${config.package}''; };
phases = {
install = ''
echo "b" > $out
'';
};
};
};
};
};
}

View file

@ -0,0 +1,44 @@
{ config }:
let
inherit (config) lib builders packages;
in
{
config.packages.aux.c = {
versions = {
"latest" =
{ config }:
{
options = {
custom = lib.options.create { type = lib.types.bool; };
};
config = {
meta = {
platforms = [ "i686-linux" ];
};
name = "${config.pname}-${config.version}";
custom = true;
pname = "c";
version = "1.0.0";
builder = builders.basic;
context = {
"foundation:cflags" = [ "-I $AUX_C/include" ];
};
hooks = ctx: { "aux:c:env" = lib.dag.entry.after [ "unpack" ] ''export AUX_C=${config.package}''; };
phases = {
install = ''
echo "c" > $out
'';
};
};
};
};
};
}

View file

@ -1,30 +1,43 @@
{
lib,
lib',
config,
}:
{ config }:
let
doubles = lib'.systems.doubles.all;
inherit (config) lib;
doubles = lib.systems.doubles.all;
packages = builtins.removeAttrs config.packages [ "cross" ];
in
{
includes = [ ./foundation ];
includes = [
./foundation
./aux/a.nix
./aux/b.nix
./aux/c.nix
];
options = {
packages = lib.options.create {
description = "The package set.";
type = lib.types.submodule {
freeform = lib.types.attrs.of (lib.types.submodule { freeform = lib'.types.alias; });
freeform = lib.types.packages;
options.cross = lib.attrs.generate doubles (
options = {
cross = lib.attrs.generate doubles (
system:
lib.options.create {
description = "The cross-compiled package set for the ${system} target.";
type = lib'.types.packages;
default = { };
type = lib.types.packages;
default.value = { };
}
);
# NOTE: We may offer a way to set default context values. For this reason we have
# nested `options` under `context` rather than using a plain option directly under `packages`.
context.options = lib.options.create {
description = "The available options for package contexts.";
default.value = { };
type = lib.types.attrs.of lib.types.option;
};
};
};
};
@ -40,47 +53,28 @@ in
};
};
config.packages.cross = lib.attrs.generate doubles (
config = {
packages.cross = lib.attrs.generate doubles (
system:
builtins.mapAttrs (
builtins.mapAttrs
(
namespace:
builtins.mapAttrs (
name: alias:
let
setHost =
package:
if package != { } then
(package.extend (
{ config }:
package
// {
__modules__ = package.__modules__ ++ [
{
config = {
platform = {
host = lib.modules.overrides.force system;
target = lib.modules.overrides.default system;
};
deps = {
build = {
only = setHost package.deps.build.only;
build = setHost package.deps.build.build;
host = setHost package.deps.build.host;
target = setHost package.deps.build.target;
};
host = {
only = setHost package.deps.host.only;
host = setHost package.deps.host.host;
target = setHost package.deps.host.target;
};
target = {
only = setHost package.deps.target.only;
target = setHost package.deps.target.target;
};
};
config.platform = {
host = lib.modules.override 5 system;
target = lib.modules.override 5 system;
};
}
)).config
else
package;
];
};
updated = alias // {
versions = builtins.mapAttrs (version: package: setHost package) alias.versions;
@ -88,6 +82,8 @@ in
in
updated
)
) packages
)
packages
);
};
}

View file

@ -11,13 +11,14 @@ let
# These are the upstream foundational packages exported from the Aux Foundation project.
foundation
packages
;
in
{
config.packages.foundation.binutils = {
versions = {
"latest" =
{ config, meta }:
{ config }:
{
options = {
src = lib.options.create {
@ -36,9 +37,17 @@ in
builder = builders.basic;
deps = {
build = {
host = {
inherit (packages.foundation) gcc;
};
};
};
env = {
PATH = lib.paths.bin [
foundation.stage2-gcc
# foundation.stage2-gcc
foundation.stage2-binutils
foundation.stage2-gnumake
foundation.stage2-gnupatch
@ -86,24 +95,24 @@ in
];
in
{
unpack = lib.dag.entry.before [ "patch" ] ''
unpack = ''
tar xf ${config.src}
cd binutils-${config.version}
'';
patch = lib.dag.entry.between [ "configure" ] [ "unpack" ] ''
patch = ''
${lib.strings.concatMapSep "\n" (file: "patch -Np1 -i ${file}") patches}
'';
configure = lib.dag.entry.between [ "build" ] [ "patch" ] ''
configure = ''
bash ./configure ${builtins.concatStringsSep " " configureFlags}
'';
build = lib.dag.entry.between [ "install" ] [ "configure" ] ''
build = ''
make -j $NIX_BUILD_CORES
'';
install = lib.dag.entry.after [ "build" ] ''
install = ''
make -j $NIX_BUILD_CORES install-strip
'';
};

View file

@ -9,6 +9,8 @@
./gcc
./binutils
./linux-headers
./glibc
# ./xz
];
config = {

View file

@ -1,19 +1,23 @@
{
lib,
lib',
config,
options,
}:
{ config, options }:
let
inherit (config)
lib
mirrors
builders
# These are the upstream foundational packages exported from the Aux Foundation project.
foundation
packages
;
in
{
config.packages.context.options = {
"foundation:cflags" = lib.options.create {
type = lib.types.list.of lib.types.string;
default.value = [ ];
};
};
config.packages.foundation.gcc = {
versions = {
"latest" =
@ -91,28 +95,7 @@ in
builder = builders.basic;
env = {
PATH =
let
gcc =
if
config.platform.build.triple == config.platform.host.triple
# If we're on the same system then we can use the existing GCC instance.
then
foundation.stage2-gcc
# Otherwise we are going to need a cross-compiler.
else
# TODO: Create a gcc-cross package.
(meta.extend (args: {
config = {
platform = {
build = config.platform.build.triple;
host = config.platform.build.triple;
target = lib.modules.override.force config.platform.host.triple;
};
};
})).config.package;
in
lib.paths.bin [
PATH = lib.paths.bin [
foundation.stage2-gcc
foundation.stage2-binutils
foundation.stage2-gnumake
@ -130,12 +113,12 @@ in
phases =
let
host = lib'.systems.withBuildInfo config.platform.host;
host = lib.systems.withBuildInfo config.platform.host;
mbits = if host.system.cpu.family == "x86" then if host.is64bit then "-m64" else "-m32" else "";
in
{
unpack = lib.dag.entry.before [ "patch" ] ''
unpack = ''
# Unpack
tar xf ${config.src}
tar xf ${config.gmp.src}
@ -150,17 +133,15 @@ in
ln -s ../isl-${config.isl.version} isl
'';
patch = lib.dag.entry.between [ "configure" ] [ "unpack" ] ''
patch = ''
# Patch
# force musl even if host triple is gnu
sed -i 's|"os/gnu-linux"|"os/generic"|' libstdc++-v3/configure.host
'';
configure = lib.dag.entry.between [ "build" ] [ "patch" ] ''
configure = ''
# Configure
export CC="gcc -Wl,-dynamic-linker -march=${
host.gcc.arch or host.system.cpu.family
} ${mbits} -Wl,${foundation.stage1-musl}/lib/libc.so"
export CC="gcc -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so"
export CXX="g++ -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so"
export CFLAGS_FOR_TARGET="-Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so"
export LIBRARY_PATH="${foundation.stage1-musl}/lib"
@ -182,12 +163,12 @@ in
CXXFLAGS=-static
'';
build = lib.dag.entry.between [ "install" ] [ "configure" ] ''
build = ''
# Build
make -j $NIX_BUILD_CORES
'';
install = lib.dag.entry.after [ "build" ] ''
install = ''
# Install
make -j $NIX_BUILD_CORES install-strip
'';

View file

@ -79,12 +79,12 @@ in
};
phases = {
unpack = lib.dag.entry.before [ "patch" ] ''
unpack = ''
tar xf ${config.src}
cd glibc-${config.version}
'';
configure = lib.dag.entry.between [ "build" ] [ "patch" ] ''
configure = ''
mkdir build
cd build
# libstdc++.so is built against musl and fails to link
@ -96,12 +96,12 @@ in
--with-headers=${foundation.stage1-linux-headers}/include
'';
build = lib.dag.entry.between [ "install" ] [ "configure" ] ''
build = ''
# Build
make -j $NIX_BUILD_CORES
'';
install = lib.dag.entry.after [ "build" ] ''
install = ''
# Install
make -j $NIX_BUILD_CORES install-strip
'';

View file

@ -54,20 +54,16 @@ in
};
phases = {
unpack = lib.dag.entry.before [ "patch" ] ''
unpack = ''
tar xf ${config.src}
cd linux-${config.version}
'';
patch = lib.dag.entry.between [ "configure" ] [ "unpack" ] '''';
configure = lib.dag.entry.between [ "build" ] [ "patch" ] '''';
build = lib.dag.entry.between [ "install" ] [ "configure" ] ''
build = ''
make -j $NIX_BUILD_CORES CC=musl-gcc HOSTCC=musl-gcc ARCH=${config.platform.host.linux.arch} headers
'';
install = lib.dag.entry.after [ "build" ] ''
install = ''
find usr/include -name '.*' -exec rm {} +
mkdir -p $out
cp -rv usr/include $out/