Compare commits

...

6 commits

15 changed files with 2305 additions and 2157 deletions

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

@ -4,184 +4,166 @@ lib: {
## Merge a list of option definitions into a single value.
##
## @type Location -> List Definition -> Any
default =
location: definitions:
let
values = lib.options.getDefinitionValues definitions;
first = builtins.elemAt values 0;
mergedFunctions = x: lib.options.mergeDefault location (builtins.map (f: f x) values);
mergedLists = builtins.concatLists values;
mergedAttrs = builtins.foldl' lib.attrs.merge { } values;
mergedBools = builtins.any lib.bools.or false values;
mergedStrings = lib.strings.concat values;
in
if builtins.length values == 1 then
builtins.elemAt values 0
else if builtins.all builtins.isFunction values then
mergedFunctions
else if builtins.all builtins.isList values then
mergedLists
else if builtins.all builtins.isAttrs values then
mergedAttrs
else if builtins.all builtins.isBool values then
mergedBools
else if builtins.all lib.strings.isString values then
mergedStrings
else if builtins.all builtins.isInt values && builtins.all (x: x == first) values then
first
default = location: definitions: let
values = lib.options.getDefinitionValues definitions;
first = builtins.elemAt values 0;
mergedFunctions = x: lib.options.mergeDefault location (builtins.map (f: f x) values);
mergedLists = builtins.concatLists values;
mergedAttrs = builtins.foldl' lib.attrs.merge {} values;
mergedBools = builtins.any lib.bools.or false values;
mergedStrings = lib.strings.concat values;
in
if builtins.length values == 1
then builtins.elemAt values 0
else if builtins.all builtins.isFunction values
then mergedFunctions
else if builtins.all builtins.isList values
then mergedLists
else if builtins.all builtins.isAttrs values
then mergedAttrs
else if builtins.all builtins.isBool values
then mergedBools
else if builtins.all lib.strings.isString values
then mergedStrings
else if builtins.all builtins.isInt values && builtins.all (x: x == first) values
then first
# TODO: Improve this error message to show the location and definitions for the option.
else
builtins.throw "Cannot merge definitions.";
else builtins.throw "Cannot merge definitions.";
## Merge multiple option definitions together.
##
## @type Location -> Type -> List Definition
definitions =
location: type: definitions:
let
identifier = lib.options.getIdentifier location;
resolve =
definition:
let
properties = builtins.addErrorContext "while evaluating definitions from `${definition.__file__}`:" (
lib.modules.apply.properties definition.value
);
normalize = value: {
__file__ = definition.__file__;
inherit value;
};
in
builtins.map normalize properties;
resolved = builtins.concatMap resolve definitions;
overridden = lib.modules.apply.overrides resolved;
values =
if builtins.any (definition: lib.types.is "order" definition.value) overridden.values then
lib.modules.apply.order overridden.values
else
overridden.values;
isDefined = values != [ ];
invalid = builtins.filter (definition: !(type.check definition.value)) values;
merged =
if isDefined then
if builtins.all (definition: type.check definition.value) values then
type.merge location values
else
builtins.throw "A definition for `${identifier}` is not of type `${type.description}`. Definition values:${lib.options.getDefinitions invalid}"
else
builtins.throw "The option `${identifier}` is used but not defined.";
optional = if isDefined then { value = merged; } else { };
in
{
inherit
isDefined
values
merged
optional
;
raw = {
inherit values;
inherit (overridden) highestPriority;
definitions = location: type: definitions: let
identifier = lib.options.getIdentifier location;
resolve = definition: let
properties = builtins.addErrorContext "while evaluating definitions from `${definition.__file__ or "<unknown>"}`:" (
lib.modules.apply.properties definition.value
);
normalize = value: {
__file__ = definition.__file__;
inherit value;
};
in
builtins.map normalize properties;
resolved = builtins.concatMap resolve definitions;
overridden = lib.modules.apply.overrides resolved;
values =
if builtins.any (definition: lib.types.is "order" definition.value) overridden.values
then lib.modules.apply.order overridden.values
else overridden.values;
isDefined = values != [];
invalid = builtins.filter (definition: !(type.check definition.value)) values;
merged =
if isDefined
then
if builtins.all (definition: type.check definition.value) values
then type.merge location values
else builtins.throw "A definition for `${identifier}` is not of type `${type.description}`. Definition values:${lib.options.getDefinitions invalid}"
else builtins.throw "The option `${identifier}` is used but not defined.";
optional =
if isDefined
then {value = merged;}
else {};
in {
inherit
isDefined
values
merged
optional
;
raw = {
inherit values;
inherit (overridden) highestPriority;
};
};
## Merge multiple option declarations together.
##
## @type Location -> List Option
declarations =
location: options:
let
merge =
result: option:
let
mergedType = result.type.mergeType option.options.type.functor;
isTypeMergeable = mergedType != null;
shared = name: option.options ? ${name} && result ? ${name};
typeSet = lib.attrs.when ((shared "type") && isTypeMergeable) { type = mergedType; };
files = result.declarations;
serializedFiles = builtins.concatStringsSep " and " files;
getSubModules = option.options.type.getSubModules or null;
submodules =
if getSubModules != null then
builtins.map (module: {
__file__ = option.__file__;
includes = [ module ];
}) getSubModules
++ result.options
else
result.options;
in
if
shared "default"
|| shared "example"
|| shared "description"
|| shared "apply"
|| (shared "type" && !isTypeMergeable)
declarations = location: options: let
merge = result: option: let
mergedType = result.type.mergeType option.options.type.functor;
isTypeMergeable = mergedType != null;
shared = name: option.options ? ${name} && result ? ${name};
typeSet = lib.attrs.when ((shared "type") && isTypeMergeable) {type = mergedType;};
files = result.declarations;
serializedFiles = builtins.concatStringsSep " and " files;
getSubModules = option.options.type.getSubModules or null;
submodules =
if getSubModules != null
then
builtins.throw "The option `${lib.options.getIdentifier location}` in `${option.__file__}` is already declared in ${serializedFiles}"
else
option.options
// result
// {
declarations = result.declarations ++ [ option.__file__ ];
options = submodules;
}
// typeSet;
builtins.map (module: {
__file__ = option.__file__;
includes = [module];
})
getSubModules
++ result.options
else result.options;
in
if
shared "default"
|| shared "example"
|| shared "description"
|| shared "apply"
|| (shared "type" && !isTypeMergeable)
then builtins.throw "The option `${lib.options.getIdentifier location}` in `${option.__file__}` is already declared in ${serializedFiles}"
else
option.options
// result
// {
declarations = result.declarations ++ [option.__file__];
options = submodules;
}
// typeSet;
in
builtins.foldl' merge {
inherit location;
declarations = [ ];
options = [ ];
} options;
declarations = [];
options = [];
}
options;
## Merge an option, only supporting a single unique definition.
##
## @type String -> Location -> List Definition -> Any
unique =
message: location: definitions:
let
identifier = lib.options.getIdentifier location;
total = builtins.length definitions;
first = builtins.elemAt definitions 0;
in
if total == 1 then
first.value
else if total == 0 then
builtins.throw "Cannot merge unused option `${identifier}`.\n${message}"
else
builtins.throw "The option `${identifier}` is defined multiple times, but must be unique.\n${message}\nDefinitions:${lib.options.getDefinitions definitions}";
unique = message: location: definitions: let
identifier = lib.options.getIdentifier location;
total = builtins.length definitions;
first = builtins.elemAt definitions 0;
in
if total == 1
then first.value
else if total == 0
then builtins.throw "Cannot merge unused option `${identifier}`.\n${message}"
else builtins.throw "The option `${identifier}` is defined multiple times, but must be unique.\n${message}\nDefinitions:${lib.options.getDefinitions definitions}";
## Merge a single instance of an option.
##
## @type Location -> List Definition -> Any
one = lib.options.merge.unique "";
equal =
location: definitions:
let
identifier = lib.options.getIdentifier location;
first = builtins.elemAt definitions 0;
rest = builtins.tail definitions;
merge =
x: y:
if x != y then
builtins.throw "The option `${identifier}` has conflicting definitions:${lib.options.getDefinitions definitions}"
else
x;
merged = builtins.foldl' merge first rest;
in
if builtins.length definitions == 0 then
builtins.throw "Cannot merge unused option `${identifier}`."
else if builtins.length definitions == 1 then
first.value
else
merged.value;
equal = location: definitions: let
identifier = lib.options.getIdentifier location;
first = builtins.elemAt definitions 0;
rest = builtins.tail definitions;
merge = x: y:
if x != y
then builtins.throw "The option `${identifier}` has conflicting definitions:${lib.options.getDefinitions definitions}"
else x;
merged = builtins.foldl' merge first rest;
in
if builtins.length definitions == 0
then builtins.throw "Cannot merge unused option `${identifier}`."
else if builtins.length definitions == 1
then first.value
else merged.value;
};
## Check whether a value is an option.
@ -192,50 +174,46 @@ lib: {
## Create an option.
##
## @type { type? :: String | Null, apply? :: (a -> b) | Null, default? :: { value :: a, text :: String }, example? :: String | Null, visible? :: Bool | Null, internal? :: Bool | Null, writable? :: Bool | Null, description? :: String | Null } -> Option a
create =
settings@{
type ? lib.types.unspecified,
apply ? null,
default ? { },
example ? null,
visible ? null,
internal ? null,
writable ? null,
description ? null,
}:
{
__type__ = "option";
inherit
type
apply
default
example
visible
internal
writable
description
;
};
create = settings @ {
type ? lib.types.unspecified,
apply ? null,
default ? {},
example ? null,
visible ? null,
internal ? null,
writable ? null,
description ? null,
}: {
__type__ = "option";
inherit
type
apply
default
example
visible
internal
writable
description
;
};
## Create a sink option.
##
## @type @alias lib.options.create
sink =
settings:
let
defaults = {
internal = true;
visible = false;
default = false;
description = "A sink option for unused definitions";
type = lib.types.create {
name = "sink";
check = lib.fp.const true;
merge = lib.fp.const (lib.fp.const false);
};
apply = value: builtins.throw "Cannot read the value of a Sink option.";
sink = settings: let
defaults = {
internal = true;
visible = false;
default = false;
description = "A sink option for unused definitions";
type = lib.types.create {
name = "sink";
check = lib.fp.const true;
merge = lib.fp.const (lib.fp.const false);
};
in
apply = value: builtins.throw "Cannot read the value of a Sink option.";
};
in
lib.options.create (defaults // settings);
## Get the definition values from a list of options definitions.
@ -246,94 +224,93 @@ lib: {
## Convert a list of option identifiers into a single identifier.
##
## @type List String -> String
getIdentifier =
location:
let
special = [
# lib.types.attrs.of (lib.types.submodule {})
"<name>"
# lib.types.list.of (submodule {})
"*"
# lib.types.function
"<function body>"
];
escape = part: if builtins.elem part special then part else lib.strings.escape.nix.identifier part;
in
getIdentifier = location: let
special = [
# lib.types.attrs.of (lib.types.submodule {})
"<name>"
# lib.types.list.of (submodule {})
"*"
# lib.types.function
"<function body>"
];
escape = part:
if builtins.elem part special
then part
else lib.strings.escape.nix.identifier part;
in
lib.strings.concatMapSep "." escape location;
## Get a string message of the definitions for an option.
##
## @type List Definition -> String
getDefinitions =
definitions:
let
serialize =
definition:
let
valueWithRecursionLimit = lib.generators.withRecursion {
limit = 10;
throw = false;
} definition.value;
getDefinitions = definitions: let
serialize = definition: let
valueWithRecursionLimit =
lib.generators.withRecursion {
limit = 10;
throw = false;
}
definition.value;
eval = builtins.tryEval (lib.generators.pretty { } valueWithRecursionLimit);
eval = builtins.tryEval (lib.generators.pretty {} valueWithRecursionLimit);
lines = lib.strings.split "\n" eval.value;
linesLength = builtins.length lines;
firstFiveLines = lib.lists.take 5 lines;
lines = lib.strings.split "\n" eval.value;
linesLength = builtins.length lines;
firstFiveLines = lib.lists.take 5 lines;
ellipsis = lib.lists.when (linesLength > 5) "...";
ellipsis = lib.lists.when (linesLength > 5) "...";
value = builtins.concatStringsSep "\n " (firstFiveLines ++ ellipsis);
value = builtins.concatStringsSep "\n " (firstFiveLines ++ ellipsis);
result =
if !eval.success then
""
else if linesLength > 1 then
":\n " + value
else
": " + value;
in
"\n- In `${definition.__file__}`${result}";
in
result =
if !eval.success
then ""
else if linesLength > 1
then ":\n " + value
else ": " + value;
in "\n- In `${definition.__file__}`${result}";
in
lib.strings.concatMap serialize definitions;
## Run a set of definitions, calculating the resolved value and associated information.
##
## @type Location -> Option -> List Definition -> String & { value :: Any, highestPriority :: Int, isDefined :: Bool, files :: List String, definitions :: List Any, definitionsWithLocations :: List Definition }
run =
location: option: definitions:
let
identifier = lib.options.getIdentifier location;
run = location: option: definitions: let
identifier = lib.options.getIdentifier location;
definitionsWithDefault =
if option ? default && option.default ? value then
[
{
__file__ = builtins.head option.declarations;
value = lib.modules.overrides.option option.default.value;
}
]
++ definitions
else
definitions;
definitionsWithDefault =
if option ? default && option.default ? value
then
[
{
__file__ = builtins.head option.declarations;
value = lib.modules.overrides.option option.default.value;
}
]
++ definitions
else definitions;
merged =
if option.writable or null == false && builtins.length definitionsWithDefault > 1 then
let
separatedDefinitions = builtins.map (
definition:
merged =
if option.writable or null == false && builtins.length definitionsWithDefault > 1
then let
separatedDefinitions =
builtins.map (
definition:
definition
// {
value = (lib.options.merge.definitions location option.type [ definition ]).merged;
value = (lib.options.merge.definitions location option.type [definition]).merged;
}
) definitionsWithDefault;
in
builtins.throw "The option `${identifier}` is not writable, but is set more than once:${lib.options.getDefinitions separatedDefinitions}"
else
lib.options.merge.definitions location option.type definitionsWithDefault;
)
definitionsWithDefault;
in
builtins.throw "The option `${identifier}` is not writable, but is set more than once:${lib.options.getDefinitions separatedDefinitions}"
else lib.options.merge.definitions location option.type definitionsWithDefault;
value = if option.apply or null != null then option.apply merged.merged else merged.merged;
in
value =
if option.apply or null != null
then option.apply merged.merged
else merged.merged;
in
option
// {
value = builtins.addErrorContext "while evaluating the option `${identifier}`:" value;

File diff suppressed because it is too large Load diff

View file

@ -8,10 +8,10 @@
},
"locked": {
"dir": "foundation",
"dirtyRev": "9850da8aa9dc9be22e237c9b424a18e801e53ecb-dirty",
"dirtyShortRev": "9850da8-dirty",
"lastModified": 1718529861,
"narHash": "sha256-X1Wd6mDz8GTaoxt1ylkvZfrJOcZtspJrEjXMtJ2ZyG0=",
"dirtyRev": "2be3111b2c0911f40b47fe0a1fb22b5f5188cf59-dirty",
"dirtyShortRev": "2be3111-dirty",
"lastModified": 1719251485,
"narHash": "sha256-9G1TPBdlQNXCZf6A66bCT9m2vhodkSF+rDtqOVuFteY=",
"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": "2be3111b2c0911f40b47fe0a1fb22b5f5188cf59-dirty",
"dirtyShortRev": "2be3111-dirty",
"lastModified": 1719251485,
"narHash": "sha256-9G1TPBdlQNXCZf6A66bCT9m2vhodkSF+rDtqOVuFteY=",
"type": "git",
"url": "file:../?dir=lib"
},

View file

@ -1,76 +1,95 @@
{ lib, config }:
let
{
lib,
config,
}: let
cfg = config.builders.basic;
lib' = config.lib;
inherit (config) foundation;
in
{
in {
config.builders = {
basic = {
executable = "${foundation.stage2-bash}/bin/bash";
build =
package:
let
phases = package.phases;
sorted = lib.dag.sort.topographic phases;
build = package: let
phases = lib.dag.apply.defaults package.phases {
unpack = lib.dag.entry.before ["patch"] "";
script = lib.strings.concatMapSep "\n" (
entry: if builtins.isFunction entry.value then entry.value package else entry.value
) sorted.result;
patch = lib.dag.entry.between ["configure"] ["unpack"] "";
system = package.platform.build.double;
configure = lib.dag.entry.between ["build"] ["patch"] "";
built = builtins.derivation (
package.env
// {
inherit (package) name;
inherit script system;
build = lib.dag.entry.between ["install"] ["configure"] "";
passAsFile = [ "script" ];
install = lib.dag.entry.after ["build"] "";
};
sorted = lib.dag.sort.topographic phases;
SHELL = cfg.executable;
script =
lib.strings.concatMapSep "\n" (
entry:
if builtins.isFunction entry.value
then entry.value package
else entry.value
)
sorted.result;
PATH =
let
bins = lib.paths.bin (
(lib'.packages.dependencies.getPackages package.deps.build.host)
++ [
foundation.stage2-bash
foundation.stage2-coreutils
]
);
in
builtins.concatStringsSep ":" (
[ bins ] ++ (lib.lists.when (package.env ? PATH) [ package.env.PATH ])
);
system = package.platform.build.double;
builder = cfg.executable;
built = builtins.derivation (
package.env
// {
inherit (package) name;
inherit script system;
args = [
"-e"
(builtins.toFile "bash-builder.sh" ''
export CONFIG_SHELL=$SHELL
passAsFile = ["script"];
# 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
SHELL = cfg.executable;
bash -eux $scriptPath
'')
];
}
);
in
built // { inherit (package) meta; };
PATH = let
bins = lib.paths.bin (
(lib'.packages.dependencies.getPackages package.deps.build.host)
++ [
foundation.stage2-bash
foundation.stage2-coreutils
]
);
in
builtins.concatStringsSep ":" (
[bins] ++ (lib.lists.when (package.env ? PATH) [package.env.PATH])
);
builder = cfg.executable;
args = [
"-e"
(builtins.toFile "bash-builder.sh" ''
export CONFIG_SHELL=$SHELL
# 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
bash -eux $scriptPath
'')
];
}
);
in
built
// {
inherit (package) meta;
extras = {
inherit package;
};
};
};
};
}

View file

@ -1,18 +1,18 @@
# This file handles creating all of the exports for this project and is not
# exported itself.
{ lib, config }:
let
lib' = config.lib;
in
{
freeform = lib.types.any;
{config}: let
inherit (config) lib;
in {
# freeform = lib.types.any;
config = {
exports = {
lib = config.lib;
inherit lib;
modules = import ./modules.nix;
packages = {
aux-a = config.packages.aux.a;
# foundation-gcc-x86_64 =
# (config.packages.foundation.gcc.versions."13.2.0".extend (args: {
# config = {
@ -23,12 +23,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-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";
# };
# 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

@ -1,11 +1,12 @@
{ lib, config }:
let
in
{
lib,
config,
}: let
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,78 +1,90 @@
{
lib,
lib',
config,
}:
{
}: let
lib' = config.lib;
in {
config = {
lib.packages = {
dependencies = {
getPackages =
dependencies:
let
available = builtins.filter (dependency: !(builtins.isNull dependency)) (
builtins.attrValues dependencies
);
in
getPackages = dependencies: let
available = builtins.filter (dependency: !(builtins.isNull dependency)) (
builtins.attrValues dependencies
);
in
builtins.map (dependency: dependency.package) available;
};
getLatest =
alias:
let
versions = builtins.attrNames alias.versions;
sorted = builtins.sort (lib.versions.gte) versions;
in
getLatest = alias: let
versions = builtins.attrNames alias.versions;
sorted = builtins.sort (lib.versions.gte) versions;
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})
else
package;
resolve = alias:
if alias ? versions
then
alias.versions.${config.preferences.packages.version}
or (alias.versions.${lib'.packages.getLatest alias})
else alias;
buildDependencies =
build': host': target':
builtins.mapAttrs (name: dep: lib'.packages.build dep build' host' target');
build = alias: build: host: target: let
package = lib'.packages.resolve alias;
result = resolved.extend (
{ config }:
{
config = {
platform = {
build = build;
host = host;
target = lib.modules.override 150 target;
};
buildDependencies = build': host': target':
builtins.mapAttrs (name: dep: lib'.packages.build dep build' host' target');
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;
result = lib.modules.run {
modules =
package.__modules__
++ [
lib'.types.package.children.submodule
(
{config}: {
config = {
__modules__ = package.__modules__;
platform = {
build = lib.modules.overrides.force build;
host = lib.modules.overrides.force host;
target = lib.modules.overrides.force 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;
# 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.
resolved =
result.config
// {
deps = {
build = {
only = buildDependencies build build build package.deps.build.only;
build = buildDependencies build build target package.deps.build.build;
host = buildDependencies build host target package.deps.build.host;
target = buildDependencies build target target package.deps.build.target;
};
}
);
in
result;
host = {
only = buildDependencies host host host package.deps.host.only;
host = buildDependencies host host target package.deps.host.host;
target = buildDependencies host target target package.deps.host.target;
};
target = {
only = buildDependencies target target target package.deps.target.only;
target = buildDependencies target target target package.deps.target.target;
};
};
};
in
resolved
// {
package = resolved.builder.build resolved;
};
};
};
}

File diff suppressed because it is too large Load diff

View file

@ -1,60 +1,66 @@
{
lib,
lib',
config,
}:
{
}: let
inherit (config) preferences builders;
lib' = config.lib;
in {
config = {
lib.types = {
license =
let
type = lib.types.submodule (
{ config }:
{
options = {
name = {
full = lib.options.create {
description = "The full name of the license.";
type = lib.types.string;
};
short = lib.options.create {
description = "The short name of the license.";
type = lib.types.string;
};
license = let
type = lib.types.submodule (
{config}: {
options = {
name = {
full = lib.options.create {
description = "The full name of the license.";
type = lib.types.string;
};
spdx = lib.options.create {
description = "The SPDX identifier for the license.";
type = lib.types.nullish lib.types.string;
default.value = null;
};
url = lib.options.create {
description = "The URL for the license.";
type = lib.types.nullish lib.types.string;
};
free = lib.options.create {
description = "Whether the license is free.";
type = lib.types.bool;
default.value = true;
};
redistributable = lib.options.create {
description = "Whether the license is allows redistribution.";
type = lib.types.bool;
default = {
text = "config.free";
value = config.free;
};
short = lib.options.create {
description = "The short name of the license.";
type = lib.types.string;
};
};
}
);
in
spdx = lib.options.create {
description = "The SPDX identifier for the license.";
type = lib.types.nullish lib.types.string;
default.value = null;
};
url = lib.options.create {
description = "The URL for the license.";
type = lib.types.nullish lib.types.string;
};
free = lib.options.create {
description = "Whether the license is free.";
type = lib.types.bool;
default.value = true;
};
redistributable = lib.options.create {
description = "Whether the license is allows redistribution.";
type = lib.types.bool;
default = {
text = "config.free";
value = config.free;
};
};
};
}
);
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 +72,93 @@
};
};
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.attrs.any;
transform = value: let
package = lib'.packages.resolve value;
in
(builtins.trace "building dependency ${package.name}: build=${build.triple} host=${host.triple} target=${target.triple}")
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;
};
}
);
dependencies = lib.types.attrs.of (
lib.types.nullish (lib.types.either lib'.types.alias lib'.types.package)
);
latest = lib.options.create {
description = "The latest version of the package.";
type = lib'.types.package;
};
package = lib.types.submodule (
{ config, meta }:
{
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.attrs.any;
submodule = {config}: let
build = config.platform.build;
host = config.platform.host;
target = config.platform.target;
in {
options = {
extend = lib.options.create {
description = "Extend the package's submodules with additional configuration.";
type = lib.types.function lib.types.raw;
default.value =
value:
let
result = meta.extend {
modules = if builtins.isAttrs value then [ { config = value; } ] else lib.lists.from.any value;
};
in
result.config;
};
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 "";
};
};
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;
__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 = [];
};
meta = {
@ -168,77 +207,52 @@
platforms = lib.options.create {
description = "The platforms the package supports.";
type = lib.types.list.of lib.types.string;
default.value = [ ];
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.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";
};
};
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 = { };
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 "";
};
};
env = lib.options.create {
description = "The environment for the package.";
type = lib.types.attrs.of 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 {
@ -246,66 +260,16 @@
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 = { };
};
phases = lib.options.create {
description = "The phases for the package.";
type = lib.types.dag.of lib.types.string;
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 = { };
};
};
env = lib.options.create {
description = "The environment for the package.";
type = lib.types.attrs.of lib.types.string;
default.value = {};
};
package = lib.options.create {
@ -313,9 +277,86 @@
type = lib.types.derivation;
default.value = config.builder.build config;
};
deps = {
build = {
only = lib.options.create {
description = "Dependencies which are only used in the build environment.";
type = lib'.types.dependencies build build build;
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 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 = {};
};
};
host = {
only = lib.options.create {
description = "Dependencies which are only used in the host environment.";
type = lib'.types.dependencies host host host;
default.value = {};
};
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 = {};
};
};
};
};
}
);
};
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,35 @@
{
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" > $out
'';
};
};
};
};
};
}

View file

@ -0,0 +1,36 @@
{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;
phases = {
install = ''
echo "b" > $out
'';
};
};
};
};
};
}

View file

@ -1,29 +1,29 @@
{
lib,
lib',
config,
}:
let
doubles = lib'.systems.doubles.all;
{config}: let
inherit (config) lib;
packages = builtins.removeAttrs config.packages [ "cross" ];
in
{
includes = [ ./foundation ];
doubles = lib.systems.doubles.all;
packages = builtins.removeAttrs config.packages ["cross"];
in {
includes = [
./foundation
./aux/a.nix
./aux/b.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 (
system:
lib.options.create {
description = "The cross-compiled package set for the ${system} target.";
type = lib'.types.packages;
default = { };
}
lib.options.create {
description = "The cross-compiled package set for the ${system} target.";
type = lib.types.packages;
default = {};
}
);
};
};
@ -42,52 +42,63 @@ in
config.packages.cross = lib.attrs.generate doubles (
system:
builtins.mapAttrs (
namespace:
builtins.mapAttrs (
name: alias:
let
setHost =
package:
if package != { } then
(package.extend (
{ config }:
{
config = {
platform = {
host = lib.modules.overrides.force system;
target = lib.modules.overrides.default system;
namespace:
builtins.mapAttrs (
name: alias: let
setHost = package:
package // {
__modules__ = package.__modules__ ++ [
{
config.platform = {
host = lib.modules.override 5 system;
target = lib.modules.override 5 system;
};
}
];
};
# if package != {}
# then
# (package.extend (
# {config}: {
# 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
else
package;
# 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
# else package;
updated = alias // {
versions = builtins.mapAttrs (version: package: setHost package) alias.versions;
};
in
updated
updated =
alias
// {
versions = builtins.mapAttrs (version: package: setHost package) alias.versions;
};
in
updated
)
)
) packages
packages
);
}

View file

@ -3,117 +3,121 @@
lib',
config,
options,
}:
let
inherit (config)
}: let
inherit
(config)
mirrors
builders
# These are the upstream foundational packages exported from the Aux Foundation project.
foundation
packages
;
in
{
in {
config.packages.foundation.binutils = {
versions = {
"latest" =
{ config, meta }:
{
options = {
src = lib.options.create {
type = lib.types.derivation;
description = "Source for the package.";
};
};
config = {
meta = {
platforms = [ "i686-linux" ];
};
pname = "binutils";
version = "2.41";
builder = builders.basic;
env = {
PATH = lib.paths.bin [
foundation.stage2-gcc
foundation.stage2-binutils
foundation.stage2-gnumake
foundation.stage2-gnupatch
foundation.stage2-gnused
foundation.stage2-gnugrep
foundation.stage2-gawk
foundation.stage2-diffutils
foundation.stage2-findutils
foundation.stage2-gnutar
foundation.stage1-xz
];
};
phases =
let
patches = [
# Make binutils output deterministic by default.
./patches/deterministic.patch
];
configureFlags = [
# "CC=musl-gcc"
"LDFLAGS=--static"
"--prefix=${builtins.placeholder "out"}"
"--build=${config.platform.build.triple}"
"--host=${config.platform.host.triple}"
"--target=${config.platform.target.triple}"
"--with-sysroot=/"
"--enable-deterministic-archives"
# depends on bison
"--disable-gprofng"
# Turn on --enable-new-dtags by default to make the linker set
# RUNPATH instead of RPATH on binaries. This is important because
# RUNPATH can be overridden using LD_LIBRARY_PATH at runtime.
"--enable-new-dtags"
# By default binutils searches $libdir for libraries. This brings in
# libbfd and libopcodes into a default visibility. Drop default lib
# path to force users to declare their use of these libraries.
"--with-lib-path=:"
"--disable-multilib"
];
in
{
unpack = lib.dag.entry.before [ "patch" ] ''
tar xf ${config.src}
cd binutils-${config.version}
'';
patch = lib.dag.entry.between [ "configure" ] [ "unpack" ] ''
${lib.strings.concatMapSep "\n" (file: "patch -Np1 -i ${file}") patches}
'';
configure = lib.dag.entry.between [ "build" ] [ "patch" ] ''
bash ./configure ${builtins.concatStringsSep " " configureFlags}
'';
build = lib.dag.entry.between [ "install" ] [ "configure" ] ''
make -j $NIX_BUILD_CORES
'';
install = lib.dag.entry.after [ "build" ] ''
make -j $NIX_BUILD_CORES install-strip
'';
};
src = builtins.fetchurl {
url = "${mirrors.gnu}/binutils/binutils-${config.version}.tar.xz";
sha256 = "rppXieI0WeWWBuZxRyPy0//DHAMXQZHvDQFb3wYAdFA=";
};
"latest" = {config}: {
options = {
src = lib.options.create {
type = lib.types.derivation;
description = "Source for the package.";
};
};
config = {
meta = {
platforms = ["i686-linux"];
};
pname = "binutils";
version = "2.41";
builder = builders.basic;
# deps = {
# build = {
# host = {
# inherit (packages.foundation) gcc;
# };
# };
# };
env = {
PATH = lib.paths.bin [
# foundation.stage2-gcc
foundation.stage2-binutils
foundation.stage2-gnumake
foundation.stage2-gnupatch
foundation.stage2-gnused
foundation.stage2-gnugrep
foundation.stage2-gawk
foundation.stage2-diffutils
foundation.stage2-findutils
foundation.stage2-gnutar
foundation.stage1-xz
];
};
phases = let
patches = [
# Make binutils output deterministic by default.
./patches/deterministic.patch
];
configureFlags = [
# "CC=musl-gcc"
"LDFLAGS=--static"
"--prefix=${builtins.placeholder "out"}"
"--build=${config.platform.build.triple}"
"--host=${config.platform.host.triple}"
"--target=${config.platform.target.triple}"
"--with-sysroot=/"
"--enable-deterministic-archives"
# depends on bison
"--disable-gprofng"
# Turn on --enable-new-dtags by default to make the linker set
# RUNPATH instead of RPATH on binaries. This is important because
# RUNPATH can be overridden using LD_LIBRARY_PATH at runtime.
"--enable-new-dtags"
# By default binutils searches $libdir for libraries. This brings in
# libbfd and libopcodes into a default visibility. Drop default lib
# path to force users to declare their use of these libraries.
"--with-lib-path=:"
"--disable-multilib"
];
in {
unpack = lib.dag.entry.before ["patch"] ''
tar xf ${config.src}
cd binutils-${config.version}
'';
patch = lib.dag.entry.between ["configure"] ["unpack"] ''
${lib.strings.concatMapSep "\n" (file: "patch -Np1 -i ${file}") patches}
'';
configure = lib.dag.entry.between ["build"] ["patch"] ''
bash ./configure ${builtins.concatStringsSep " " configureFlags}
'';
build = lib.dag.entry.between ["install"] ["configure"] ''
make -j $NIX_BUILD_CORES
'';
install = lib.dag.entry.after ["build"] ''
make -j $NIX_BUILD_CORES install-strip
'';
};
src = builtins.fetchurl {
url = "${mirrors.gnu}/binutils/binutils-${config.version}.tar.xz";
sha256 = "rppXieI0WeWWBuZxRyPy0//DHAMXQZHvDQFb3wYAdFA=";
};
};
};
};
};
}

View file

@ -1,236 +1,217 @@
{
lib,
lib',
config,
options,
}:
let
inherit (config)
}: let
inherit
(config)
lib
mirrors
builders
# These are the upstream foundational packages exported from the Aux Foundation project.
foundation
packages
;
in
{
in {
config.packages.foundation.gcc = {
versions = {
"latest" =
{ config, meta }:
{
options = {
"latest" = {
config,
meta,
}: {
options = {
src = lib.options.create {
type = lib.types.derivation;
description = "Source for the package.";
};
cc = {
src = lib.options.create {
type = lib.types.derivation;
description = "Source for the package.";
};
cc = {
src = lib.options.create {
type = lib.types.derivation;
description = "The cc source for the package.";
};
};
gmp = {
src = lib.options.create {
type = lib.types.derivation;
description = "The gmp source for the package.";
};
version = lib.options.create {
type = lib.types.string;
description = "Version of gmp.";
};
};
mpfr = {
src = lib.options.create {
type = lib.types.derivation;
description = "The mpfr source for the package.";
};
version = lib.options.create {
type = lib.types.string;
description = "Version of mpfr.";
};
};
mpc = {
src = lib.options.create {
type = lib.types.derivation;
description = "The mpc source for the package.";
};
version = lib.options.create {
type = lib.types.string;
description = "Version of mpc.";
};
};
isl = {
src = lib.options.create {
type = lib.types.derivation;
description = "The isl source for the package.";
};
version = lib.options.create {
type = lib.types.string;
description = "Version of isl.";
};
description = "The cc source for the package.";
};
};
config = {
meta = {
platforms = [ "i686-linux" ];
gmp = {
src = lib.options.create {
type = lib.types.derivation;
description = "The gmp source for the package.";
};
pname = "gcc";
version = "13.2.0";
version = lib.options.create {
type = lib.types.string;
description = "Version of gmp.";
};
};
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 [
foundation.stage2-gcc
foundation.stage2-binutils
foundation.stage2-gnumake
foundation.stage2-gnused
foundation.stage2-gnugrep
foundation.stage2-gawk
foundation.stage2-diffutils
foundation.stage2-findutils
foundation.stage2-gnutar
foundation.stage2-gzip
foundation.stage2-bzip2
foundation.stage1-xz
];
mpfr = {
src = lib.options.create {
type = lib.types.derivation;
description = "The mpfr source for the package.";
};
phases =
let
host = lib'.systems.withBuildInfo config.platform.host;
version = lib.options.create {
type = lib.types.string;
description = "Version of mpfr.";
};
};
mbits = if host.system.cpu.family == "x86" then if host.is64bit then "-m64" else "-m32" else "";
in
{
unpack = lib.dag.entry.before [ "patch" ] ''
# Unpack
tar xf ${config.src}
tar xf ${config.gmp.src}
tar xf ${config.mpfr.src}
tar xf ${config.mpc.src}
tar xf ${config.isl.src}
cd gcc-${config.version}
ln -s ../gmp-${config.gmp.version} gmp
ln -s ../mpfr-${config.mpfr.version} mpfr
ln -s ../mpc-${config.mpc.version} mpc
ln -s ../isl-${config.isl.version} isl
'';
patch = lib.dag.entry.between [ "configure" ] [ "unpack" ] ''
# 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
export CC="gcc -Wl,-dynamic-linker -march=${
host.gcc.arch or host.system.cpu.family
} ${mbits} -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"
bash ./configure \
--prefix=$out \
--build=${config.platform.build.triple} \
--host=${config.platform.host.triple} \
--target=${config.platform.target.triple} \
--with-native-system-header-dir=/include \
--with-sysroot=${foundation.stage1-musl} \
--enable-languages=c,c++ \
--disable-bootstrap \
--disable-libsanitizer \
--disable-lto \
--disable-multilib \
--disable-plugin \
CFLAGS=-static \
CXXFLAGS=-static
'';
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
'';
};
src = builtins.fetchurl {
url = "${mirrors.gnu}/gcc/gcc-${config.version}/gcc-${config.version}.tar.xz";
sha256 = "4nXnZEKmBnNBon8Exca4PYYTFEAEwEE1KIY9xrXHQ9o=";
mpc = {
src = lib.options.create {
type = lib.types.derivation;
description = "The mpc source for the package.";
};
gmp = {
version = "6.3.0";
src = builtins.fetchurl {
url = "${mirrors.gnu}/gmp/gmp-${config.gmp.version}.tar.xz";
sha256 = "o8K4AgG4nmhhb0rTC8Zq7kknw85Q4zkpyoGdXENTiJg=";
};
version = lib.options.create {
type = lib.types.string;
description = "Version of mpc.";
};
};
mpfr = {
version = "4.2.1";
src = builtins.fetchurl {
url = "${mirrors.gnu}/mpfr/mpfr-${config.mpfr.version}.tar.xz";
sha256 = "J3gHNTpnJpeJlpRa8T5Sgp46vXqaW3+yeTiU4Y8fy7I=";
};
isl = {
src = lib.options.create {
type = lib.types.derivation;
description = "The isl source for the package.";
};
mpc = {
version = "1.3.1";
src = builtins.fetchurl {
url = "${mirrors.gnu}/mpc/mpc-${config.mpc.version}.tar.gz";
sha256 = "q2QkkvXPiCt0qgy3MM1BCoHtzb7IlRg86TDnBsHHWbg=";
};
};
isl = {
version = "0.24";
src = builtins.fetchurl {
url = "https://gcc.gnu.org/pub/gcc/infrastructure/isl-${config.isl.version}.tar.bz2";
sha256 = "/PeN2WVsEOuM+fvV9ZoLawE4YgX+GTSzsoegoYmBRcA=";
};
version = lib.options.create {
type = lib.types.string;
description = "Version of isl.";
};
};
};
config = {
meta = {
platforms = ["i686-linux"];
};
pname = "gcc";
version = "13.2.0";
builder = builders.basic;
env = {
PATH = lib.paths.bin [
foundation.stage2-gcc
foundation.stage2-binutils
foundation.stage2-gnumake
foundation.stage2-gnused
foundation.stage2-gnugrep
foundation.stage2-gawk
foundation.stage2-diffutils
foundation.stage2-findutils
foundation.stage2-gnutar
foundation.stage2-gzip
foundation.stage2-bzip2
foundation.stage1-xz
];
};
phases = let
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
tar xf ${config.src}
tar xf ${config.gmp.src}
tar xf ${config.mpfr.src}
tar xf ${config.mpc.src}
tar xf ${config.isl.src}
cd gcc-${config.version}
ln -s ../gmp-${config.gmp.version} gmp
ln -s ../mpfr-${config.mpfr.version} mpfr
ln -s ../mpc-${config.mpc.version} mpc
ln -s ../isl-${config.isl.version} isl
'';
patch = lib.dag.entry.between ["configure"] ["unpack"] ''
# 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
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"
bash ./configure \
--prefix=$out \
--build=${config.platform.build.triple} \
--host=${config.platform.host.triple} \
--target=${config.platform.target.triple} \
--with-native-system-header-dir=/include \
--with-sysroot=${foundation.stage1-musl} \
--enable-languages=c,c++ \
--disable-bootstrap \
--disable-libsanitizer \
--disable-lto \
--disable-multilib \
--disable-plugin \
CFLAGS=-static \
CXXFLAGS=-static
'';
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
'';
};
src = builtins.fetchurl {
url = "${mirrors.gnu}/gcc/gcc-${config.version}/gcc-${config.version}.tar.xz";
sha256 = "4nXnZEKmBnNBon8Exca4PYYTFEAEwEE1KIY9xrXHQ9o=";
};
gmp = {
version = "6.3.0";
src = builtins.fetchurl {
url = "${mirrors.gnu}/gmp/gmp-${config.gmp.version}.tar.xz";
sha256 = "o8K4AgG4nmhhb0rTC8Zq7kknw85Q4zkpyoGdXENTiJg=";
};
};
mpfr = {
version = "4.2.1";
src = builtins.fetchurl {
url = "${mirrors.gnu}/mpfr/mpfr-${config.mpfr.version}.tar.xz";
sha256 = "J3gHNTpnJpeJlpRa8T5Sgp46vXqaW3+yeTiU4Y8fy7I=";
};
};
mpc = {
version = "1.3.1";
src = builtins.fetchurl {
url = "${mirrors.gnu}/mpc/mpc-${config.mpc.version}.tar.gz";
sha256 = "q2QkkvXPiCt0qgy3MM1BCoHtzb7IlRg86TDnBsHHWbg=";
};
};
isl = {
version = "0.24";
src = builtins.fetchurl {
url = "https://gcc.gnu.org/pub/gcc/infrastructure/isl-${config.isl.version}.tar.bz2";
sha256 = "/PeN2WVsEOuM+fvV9ZoLawE4YgX+GTSzsoegoYmBRcA=";
};
};
};
};
};
};
}