Compare commits

...

8 commits

Author SHA1 Message Date
Victor Fuentes d7762a5a78 add bootstraped x86_64-linux cross compiled gcc (#8)
Some checks failed
buildbot/nix-eval Build done.
Work in progress cross compiler for x86_64. I've managed to get a full x86_64 gcc using the binaries built from foundation, and am working on implementing their builds into tidepool.

### Bootstrapping steps
0) Start with i686 tools (gcc, binutils, musl, etc)
1) Build binutils targeting x86_64-linux
2) Build a minimal gcc cross compiler using the cross binutils. This minimal cross compiler does not have support for libc, so is pretty much only useful for building musl or glibc.
3) Use the minimal cross compiler to build x86_64-linux glibc or musl
4) Now that we have a cross compiler and x86_64-linux libc, we can build gcc for the target architecture!
5) Profit! We can now build anything x86_64 using our gcc compiler!

Co-authored-by: Jake Hamilton <jake.hamilton@hey.com>
Reviewed-on: #8
Reviewed-by: Jake Hamilton <jake.hamilton@hey.com>
Co-authored-by: Victor Fuentes <vmfuentes64@gmail.com>
Co-committed-by: Victor Fuentes <vmfuentes64@gmail.com>
2024-09-22 02:55:02 +00:00
Austreelis cadfaabc85 "Fix lib.types.derivations.shell's check" (#7)
Some checks failed
buildbot/nix-eval Build done.
"`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: #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: #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
22 changed files with 1482 additions and 522 deletions

View file

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell #!/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) files=$(find . -name "*.nix" -type f)

View file

@ -3,17 +3,18 @@
"lib": { "lib": {
"locked": { "locked": {
"dir": "lib", "dir": "lib",
"dirtyRev": "2be3111b2c0911f40b47fe0a1fb22b5f5188cf59-dirty", "lastModified": 1723737980,
"dirtyShortRev": "2be3111-dirty", "narHash": "sha256-1WnFatW5kSuO2jjt62hvSbH84TSYyO+VmvkJ0d5e/ZY=",
"lastModified": 1719251485, "ref": "master",
"narHash": "sha256-63NvfFVeTDITfNu60rmCUlaZtAeZUnvrIaOLSk9ScC8=", "rev": "cadfaabc853d20f2bc20bad794fcbe520ea48f13",
"revCount": 82,
"type": "git", "type": "git",
"url": "file:../?dir=lib" "url": "file:../"
}, },
"original": { "original": {
"dir": "lib", "dir": "lib",
"type": "git", "type": "git",
"url": "file:../?dir=lib" "url": "file:../"
} }
}, },
"root": { "root": {

View file

@ -95,7 +95,7 @@ lib: {
## Create a new DAG entry. ## Create a new DAG entry.
## ##
## @type List String -> List String -> a -> { before :: List String, after :: List String, value :: a } ## @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. ## Create a new DAG entry with no dependencies.
## ##
@ -105,12 +105,12 @@ lib: {
## Create a new DAG entry that occurs before other entries. ## Create a new DAG entry that occurs before other entries.
## ##
## @type List String -> a -> { before :: List String, after :: List String, value :: a } ## @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. ## Create a new DAG entry that occurs after other entries.
## ##
## @type List String -> a -> { before :: List String, after :: List String, value :: a } ## @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 = { entries = {
@ -121,7 +121,7 @@ lib: {
tag: tag:
let let
process = process =
i: before: after: entries: i: after: before: entries:
let let
name = "${tag}-${builtins.toString i}"; name = "${tag}-${builtins.toString i}";
entry = builtins.head entries; entry = builtins.head entries;
@ -130,7 +130,7 @@ lib: {
if builtins.length entries == 0 then if builtins.length entries == 0 then
{ } { }
else if builtins.length entries == 1 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 else
{ "${name}" = lib.dag.entry.after after entry; } // (process (i + 1) before [ name ] rest); { "${name}" = lib.dag.entry.after after entry; } // (process (i + 1) before [ name ] rest);
in in
@ -144,12 +144,12 @@ lib: {
## Create a DAG from a list of entries, prefixed with a tag, that occurs before other entries. ## 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 ## @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. ## 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 ## @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

@ -224,5 +224,11 @@ lib: {
filter = result: value: if builtins.elem value result then result else result ++ [ value ]; filter = result: value: if builtins.elem value result then result else result ++ [ value ];
in in
builtins.foldl' filter [ ] list; 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

@ -49,18 +49,18 @@ lib: {
## ##
## @type Attrs -> Attrs ## @type Attrs -> Attrs
create = create =
settings@{ settings@{ name
name, , description ? name
description ? name, , fallback ? { }
fallback ? { }, , check ? lib.fp.const true
check ? lib.fp.const true, , merge ? lib.options.merge.default
merge ? lib.options.merge.default, , functor ? lib.types.functor name
functor ? lib.types.functor name, , mergeType ? lib.types.merge functor
mergeType ? lib.types.merge functor, , getSubOptions ? lib.fp.const { }
getSubOptions ? lib.fp.const { }, , getSubModules ? null
getSubModules ? null, , withSubModules ? lib.fp.const null
withSubModules ? lib.fp.const null, , children ? { }
children ? { }, ,
}: }:
{ {
__type__ = "type"; __type__ = "type";
@ -108,7 +108,7 @@ lib: {
identifier = lib.options.getIdentifier location; identifier = lib.options.getIdentifier location;
first = builtins.elemAt definitions 0; first = builtins.elemAt definitions 0;
files = builtins.map lib.modules.getFiles definitions; files = lib.modules.getFiles definitions;
serializedFiles = builtins.concatStringsSep " and " files; serializedFiles = builtins.concatStringsSep " and " files;
getType = getType =
@ -118,13 +118,16 @@ lib: {
else else
builtins.typeOf value; builtins.typeOf value;
commonType = builtins.foldl' ( commonType = builtins.foldl'
type: definition: (
if getType definition.value != type then type: definition:
builtins.throw "The option `${identifier}` has conflicting definitions in ${files}" if getType definition.value != type then
else builtins.throw "The option `${identifier}` has conflicting definitions in ${serializedFiles}"
type else
) (getType first.value) definitions; type
)
(getType first.value)
definitions;
mergeStringifiableAttrs = lib.options.merge.one; mergeStringifiableAttrs = lib.options.merge.one;
@ -132,7 +135,7 @@ lib: {
mergeList = mergeList =
if builtins.length definitions > 1 then 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 else
(lib.types.list.of lib.types.any).merge; (lib.types.list.of lib.types.any).merge;
@ -140,10 +143,12 @@ lib: {
location: definitions: x: location: definitions: x:
let let
resolvedLocation = location ++ [ "<function body>" ]; resolvedLocation = location ++ [ "<function body>" ];
resolvedDefinitions = builtins.map (definition: { resolvedDefinitions = builtins.map
__file__ = definition.__file__; (definition: {
value = definition.value x; __file__ = definition.__file__;
}) definitions; value = definition.value x;
})
definitions;
in in
lib.types.any.merge resolvedLocation resolvedDefinitions; lib.types.any.merge resolvedLocation resolvedDefinitions;
@ -200,14 +205,15 @@ lib: {
## @type Int -> Int -> Attrs ## @type Int -> Int -> Attrs
between = between =
start: end: 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"; start <= end
lib.types.withCheck lib.types.int (value: value >= start && value <= 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)
name = "IntBetween"; // {
description = "integer between ${description start end}"; name = "IntBetween";
}; description = "integer between ${description start end}";
};
## Create a type that allows an integer value between a given range with a specific ## Create a type that allows an integer value between a given range with a specific
## number of bits. ## number of bits.
@ -317,14 +323,15 @@ lib: {
## @type Int -> Int -> Attrs ## @type Int -> Int -> Attrs
between = between =
start: end: 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"; start <= end
lib.types.withCheck lib.types.number (value: value >= start && value <= 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)
name = "NumberBetween"; // {
description = "numbereger between ${description start end}"; name = "NumberBetween";
}; description = "numbereger between ${description start end}";
};
in in
{ {
inherit between; inherit between;
@ -447,8 +454,7 @@ lib: {
}; };
attrs = { attrs = {
## A type that allows an attribute set containing any type of value. The merged ## A type that allows an attribute set containing any type of value.
## definitions must all be.
## ##
## @type Attrs ## @type Attrs
any = lib.types.create { any = lib.types.create {
@ -480,10 +486,12 @@ lib: {
let let
normalize = normalize =
definition: definition:
builtins.mapAttrs (name: value: { builtins.mapAttrs
__file__ = definition.__file__; (name: value: {
value = value; __file__ = definition.__file__;
}) definition.value; value = value;
})
definition.value;
normalized = builtins.map normalize definitions; normalized = builtins.map normalize definitions;
zipper = zipper =
name: definitions: (lib.options.merge.definitions (location ++ [ name ]) type definitions).optional; name: definitions: (lib.options.merge.definitions (location ++ [ name ]) type definitions).optional;
@ -520,17 +528,19 @@ lib: {
let let
normalize = normalize =
definition: definition:
builtins.mapAttrs (name: value: { builtins.mapAttrs
__file__ = definition.__file__; (name: value: {
value = value; __file__ = definition.__file__;
}) definition.value; value = value;
})
definition.value;
normalized = builtins.map normalize definitions; normalized = builtins.map normalize definitions;
zipper = zipper =
name: definitions: name: definitions:
let let
merged = lib.options.merge.definitions (location ++ [ name ]) type definitions; merged = lib.options.merge.definitions (location ++ [ name ]) type definitions;
in in
merged.optional.value or type.fallback.value or merged.merged; merged.optional.value or type.fallback.value or merged.merged;
in in
builtins.zipAttrsWith zipper normalized; builtins.zipAttrsWith zipper normalized;
getSubOptions = prefix: type.getSubOptions (prefix ++ [ "<name>" ]); getSubOptions = prefix: type.getSubOptions (prefix ++ [ "<name>" ]);
@ -569,7 +579,7 @@ lib: {
## ##
## @type Attrs ## @type Attrs
shell = lib.types.derivation // { shell = lib.types.derivation // {
check = value: lib.packages.isDerivation && builtins.hasAttr "shellPath" value; check = value: lib.packages.isDerivation value && builtins.hasAttr "shellPath" value;
}; };
}; };
@ -606,25 +616,30 @@ lib: {
merge = merge =
location: definitions: location: definitions:
let let
result = lib.lists.mapWithIndex1 ( result = lib.lists.mapWithIndex1
i: definition: (
lib.lists.mapWithIndex1 ( i: definition:
j: value: lib.lists.mapWithIndex1
let (
resolved = j: value:
lib.options.merge.definitions (location ++ [ "[definition ${builtins.toString i}-entry ${j}]" ]) let
type resolved =
[ lib.options.merge.definitions (location ++ [ "[definition ${builtins.toString i}-entry ${j}]" ])
{ type
file = definition.file; [
value = value; {
} file = definition.file;
]; value = value;
in }
resolved.optional ];
) definition.value in
) definitions; resolved.optional
merged = builtins.concatLists result; )
definition.value
)
definitions;
merged = lib.lists.flatten result;
filtered = builtins.filter (definition: definition ? value) merged; filtered = builtins.filter (definition: definition ? value) merged;
values = lib.options.getDefinitionValues filtered; values = lib.options.getDefinitionValues filtered;
in in
@ -777,11 +792,11 @@ lib: {
## ##
## @type { modules :: List Module, args? :: Attrs, description? :: String | Null, shorthand? :: Bool } -> Attrs ## @type { modules :: List Module, args? :: Attrs, description? :: String | Null, shorthand? :: Bool } -> Attrs
of = of =
settings@{ settings@{ modules
modules, , args ? { }
args ? { }, , description ? null
description ? null, , shorthand ? true
shorthand ? true, ,
}: }:
let let
getModules = builtins.map ( getModules = builtins.map (
@ -790,9 +805,12 @@ lib: {
let let
# TODO: Figure out if we can apply additional attributes to the generated module. # TODO: Figure out if we can apply additional attributes to the generated module.
# Currently this causes issues to do with redefined options. # Currently this causes issues to do with redefined options.
rest = builtins.removeAttrs (lib.attrs.filter ( rest = builtins.removeAttrs
name: value: builtins.elem name lib.modules.VALID_KEYS (lib.attrs.filter
) definition.value) [ "freeform" ]; (
name: value: builtins.elem name lib.modules.VALID_KEYS
)
definition.value) [ "freeform" ];
in in
if definition.value ? config then if definition.value ? config then
rest rest
@ -922,10 +940,12 @@ lib: {
merge = location: definitions: { merge = location: definitions: {
includes = includes =
modules modules
++ builtins.map (definition: { ++ builtins.map
__file__ = "${definition.__file__}; via ${lib.options.getIdentifier location}"; (definition: {
includes = [ definition.value ]; __file__ = "${definition.__file__}; via ${lib.options.getIdentifier location}";
}) definitions; includes = [ definition.value ];
})
definitions;
}; };
getSubOptions = submodule.getSubOptions; getSubOptions = submodule.getSubOptions;
getSubModules = submodule.getSubModules; getSubModules = submodule.getSubModules;
@ -961,10 +981,12 @@ lib: {
location: definitions: location: definitions:
let let
first = builtins.elemAt definitions 0; first = builtins.elemAt definitions 0;
modules = builtins.map (definition: { modules = builtins.map
__file__ = definition.__file__; (definition: {
options = lib.options.create { type = definition.value; }; __file__ = definition.__file__;
}) definitions; options = lib.options.create { type = definition.value; };
})
definitions;
merged = lib.modules.fixup location (lib.options.merge.declarations location modules); merged = lib.modules.fixup location (lib.options.merge.declarations location modules);
in in
if builtins.length definitions == 1 then first.value else merged.type; if builtins.length definitions == 1 then first.value else merged.type;
@ -1197,10 +1219,12 @@ lib: {
merge = merge =
location: definitions: location: definitions:
submodule.merge location ( submodule.merge location (
builtins.map (definition: { builtins.map
__file__ = definition.__file__; (definition: {
value = normalize definition; __file__ = definition.__file__;
}) definitions value = normalize definition;
})
definitions
); );
}; };
}; };

View file

@ -8,33 +8,35 @@
}, },
"locked": { "locked": {
"dir": "foundation", "dir": "foundation",
"dirtyRev": "2be3111b2c0911f40b47fe0a1fb22b5f5188cf59-dirty", "lastModified": 1724190751,
"dirtyShortRev": "2be3111-dirty", "narHash": "sha256-e8sOmeXS9YWuQqjW6gvtS3PIueazkf4S1iiJ/94eXv4=",
"lastModified": 1719251485, "ref": "master",
"narHash": "sha256-9G1TPBdlQNXCZf6A66bCT9m2vhodkSF+rDtqOVuFteY=", "rev": "4b36a5a0133f5481840bdfaf693c971215a7ef1f",
"revCount": 84,
"type": "git", "type": "git",
"url": "file:../?dir=foundation" "url": "file:../"
}, },
"original": { "original": {
"dir": "foundation", "dir": "foundation",
"type": "git", "type": "git",
"url": "file:../?dir=foundation" "url": "file:../"
} }
}, },
"lib": { "lib": {
"locked": { "locked": {
"dir": "lib", "dir": "lib",
"dirtyRev": "2be3111b2c0911f40b47fe0a1fb22b5f5188cf59-dirty", "lastModified": 1724190751,
"dirtyShortRev": "2be3111-dirty", "narHash": "sha256-e8sOmeXS9YWuQqjW6gvtS3PIueazkf4S1iiJ/94eXv4=",
"lastModified": 1719251485, "ref": "master",
"narHash": "sha256-9G1TPBdlQNXCZf6A66bCT9m2vhodkSF+rDtqOVuFteY=", "rev": "4b36a5a0133f5481840bdfaf693c971215a7ef1f",
"revCount": 84,
"type": "git", "type": "git",
"url": "file:../?dir=lib" "url": "file:../"
}, },
"original": { "original": {
"dir": "lib", "dir": "lib",
"type": "git", "type": "git",
"url": "file:../?dir=lib" "url": "file:../"
} }
}, },
"root": { "root": {

View file

@ -1,10 +1,8 @@
{ lib, config }: { config }:
let let
cfg = config.builders.basic; cfg = config.builders.basic;
lib' = config.lib; inherit (config) lib foundation;
inherit (config) foundation;
in in
{ {
config.builders = { config.builders = {
@ -14,24 +12,45 @@ in
build = build =
package: package:
let let
phases = lib.dag.apply.defaults package.phases { 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" ] ""; unpack = lib.dag.entry.before [ "patch" ] "";
patch = lib.dag.entry.between [ "configure" ] [ "unpack" ] ""; patch = lib.dag.entry.between [ "unpack" ] [ "configure" ] "";
configure = lib.dag.entry.between [ "build" ] [ "patch" ] ""; configure = lib.dag.entry.between [ "patch" ] [ "build" ] "";
build = lib.dag.entry.between [ "install" ] [ "configure" ] ""; build = lib.dag.entry.between [ "configure" ] [ "install" ] "";
install = lib.dag.entry.after [ "build" ] ""; install = lib.dag.entry.after [ "build" ] "";
}; };
sorted = lib.dag.sort.topographic phases;
script = lib.strings.concatMapSep "\n" ( sorted = lib.dag.sort.topological phases;
entry: if builtins.isFunction entry.value then entry.value package else entry.value
) sorted.result;
system = package.platform.build.double; script = lib.strings.concatMapSep "\n" (entry: entry.value) sorted.result;
built = builtins.derivation ( built = builtins.derivation (
package.env package.env
@ -46,7 +65,15 @@ in
PATH = PATH =
let let
bins = lib.paths.bin ( bins = lib.paths.bin (
(lib'.packages.dependencies.getPackages package.deps.build.host) (lib.packages.dependencies.get dependencies.build.only)
++ (lib.packages.dependencies.get dependencies.build.build)
++ (lib.packages.dependencies.get dependencies.build.host)
++ (lib.packages.dependencies.get dependencies.build.target)
++ (lib.packages.dependencies.get dependencies.host.only)
++ (lib.packages.dependencies.get dependencies.host.host)
++ (lib.packages.dependencies.get dependencies.host.target)
++ (lib.packages.dependencies.get dependencies.target.only)
++ (lib.packages.dependencies.get dependencies.target.target)
++ [ ++ [
foundation.stage2-bash foundation.stage2-bash
foundation.stage2-coreutils foundation.stage2-coreutils
@ -80,12 +107,14 @@ in
} }
); );
in in
# (builtins.trace "build: ${package.name} -> build=${package.platform.build.triple} host=${package.platform.host.triple} target=${package.platform.target.triple}")
built built
// { // {
inherit (package) meta; inherit (package) meta;
extras = { extras = {
inherit package; inherit package context;
}; phases = builtins.listToAttrs sorted.result;
} // package.extras;
}; };
}; };
}; };

View file

@ -14,28 +14,26 @@ in
packages = { packages = {
aux-a = config.packages.aux.a; 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 = {
# platform = {
# target = lib.modules.overrides.force "x86_64-linux";
# };
# };
# }))
# .config;
foundation-gcc = config.packages.foundation.gcc; foundation-gcc = config.packages.foundation.gcc;
foundation-glibc = config.packages.foundation.glibc;
foundation-binutils = config.packages.foundation.binutils; foundation-binutils = config.packages.foundation.binutils;
foundation-linux-headers = config.packages.foundation.linux-headers; 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"; cross-foundation-glibc-x86_64-linux = config.packages.cross.x86_64-linux.foundation.glibc;
# }; cross-foundation-binutils-x86_64-linux = config.packages.cross.x86_64-linux.foundation.binutils;
# example-x = config.packages.example.x;
cross-aux-a-x86_64-linux = config.packages.cross.x86_64-linux.aux.a; cross-tool-foundation-gcc-newlib-x86_64-linux = config.packages.cross-tools.x86_64-linux.foundation.gcc-newlib;
cross-foundation-gcc-x86_64-linux = config.packages.cross.x86_64-linux.foundation.gcc; cross-tool-foundation-gcc-x86_64-linux = config.packages.cross-tools.x86_64-linux.foundation.gcc-cross;
cross-foundation-gcc-x86_64-linux = config.packages.cross.x86_64-linux.foundation.gcc-bootstrap;
example-a = config.packages.foundation.gcc.versions.latest.extend {
platform = {
target = lib.modules.override 0 "x86_64-linux";
};
};
}; };
}; };
# exported.packages.i686-linux.cross-foundation-gcc-x86_64-linux = config.packages.cross.x86_64-linux.foundation.gcc.package;
}; };
} }

View file

@ -6,18 +6,267 @@ in
config = { config = {
lib.packages = { lib.packages = {
dependencies = { dependencies = {
getPackages = get =
dependencies: dependencies:
let let
available = builtins.filter (dependency: !(builtins.isNull dependency)) ( exists = value: !(builtins.isNull value);
builtins.attrValues dependencies available = builtins.filter exists dependencies;
);
in in
builtins.map (dependency: dependency.package) available; builtins.map (dependency: dependency.package) available;
build = build =
build': host': target': build': host': target':
builtins.mapAttrs (name: dep: lib'.packages.build dep 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 = getLatest =

View file

@ -214,7 +214,7 @@ in
}; };
submodule = submodule =
{ config }: { config, meta }:
let let
build = config.platform.build; build = config.platform.build;
host = config.platform.host; host = config.platform.host;
@ -230,11 +230,68 @@ in
default.value = [ ]; 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;
# };
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;
}];
modules = config.__modules__ ++ normalized;
result = lib.modules.run {
modules = [
submodule
{ config.__modules__ = modules; }
] ++ modules;
};
in
result.config;
};
meta = { meta = {
description = lib.options.create { description = lib.options.create {
description = "The description for the package."; description = "The description for the package.";
type = lib.types.nullish lib.types.string; type = lib.types.string;
default.value = null; default.value = "";
}; };
homepage = lib.options.create { homepage = lib.options.create {
@ -280,6 +337,12 @@ in
}; };
}; };
extras = lib.options.create {
description = "Extra information for the package.";
type = lib.types.attrs.of lib.types.any;
default.value = { };
};
platform = { platform = {
build = lib.options.create { build = lib.options.create {
description = "The build platform for the package."; description = "The build platform for the package.";
@ -327,12 +390,6 @@ in
type = lib'.types.builder; type = lib'.types.builder;
}; };
phases = lib.options.create {
description = "The phases for the package.";
type = lib.types.dag.of lib.types.string;
default.value = { };
};
env = lib.options.create { env = lib.options.create {
description = "The environment for the package."; description = "The environment for the package.";
type = lib.types.attrs.of lib.types.string; type = lib.types.attrs.of lib.types.string;
@ -345,6 +402,30 @@ in
default.value = config.builder.build config; 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 { deps = lib.options.create {
description = "The dependencies for the package."; description = "The dependencies for the package.";
type = deps build host target; type = deps build host target;

View file

@ -1,4 +1,4 @@
{ lib', config }: { config }:
let let
inherit (config) builders packages; inherit (config) builders packages;
in in

View file

@ -26,6 +26,22 @@ in
builder = builders.basic; 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 = { phases = {
install = '' install = ''
echo "b" > $out 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

@ -4,13 +4,14 @@ let
doubles = lib.systems.doubles.all; doubles = lib.systems.doubles.all;
packages = builtins.removeAttrs config.packages [ "cross" ]; packages = builtins.removeAttrs config.packages [ "cross" "cross-tools" ];
in in
{ {
includes = [ includes = [
./foundation ./foundation
./aux/a.nix ./aux/a.nix
./aux/b.nix ./aux/b.nix
./aux/c.nix
]; ];
options = { options = {
@ -19,14 +20,32 @@ in
type = lib.types.submodule { type = lib.types.submodule {
freeform = lib.types.packages; freeform = lib.types.packages;
options.cross = lib.attrs.generate doubles ( options = {
system: cross-tools = lib.attrs.generate doubles (
lib.options.create { system:
description = "The cross-compiled package set for the ${system} target."; lib.options.create {
type = lib.types.packages; description = "The cross-compilation tools for the ${system} target.";
default = { }; type = lib.types.packages;
} default.value = { };
); }
);
cross = lib.attrs.generate doubles (
system:
lib.options.create {
description = "The cross-compiled package set for the ${system} target.";
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;
};
};
}; };
}; };
@ -42,65 +61,67 @@ in
}; };
}; };
config.packages.cross = lib.attrs.generate doubles ( config = {
system: packages.cross-tools = lib.attrs.generate doubles (
builtins.mapAttrs ( system:
namespace: builtins.mapAttrs
builtins.mapAttrs ( (
name: alias: namespace:
let builtins.mapAttrs (
setHost = name: alias:
package: let
package setTarget =
// { package:
__modules__ = package.__modules__ ++ [ package
{ // {
config.platform = { __modules__ = package.__modules__ ++ [
host = lib.modules.override 5 system; {
target = lib.modules.override 5 system; config.platform = {
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 = { updated = alias // {
# build = { versions = builtins.mapAttrs (version: package: setTarget package) alias.versions;
# only = setHost package.deps.build.only; };
# build = setHost package.deps.build.build; in
# host = setHost package.deps.build.host; updated
# target = setHost package.deps.build.target; )
# }; )
# host = { packages
# only = setHost package.deps.host.only; );
# host = setHost package.deps.host.host; packages.cross = lib.attrs.generate doubles (
# target = setHost package.deps.host.target; system:
# }; builtins.mapAttrs
# target = { (
# only = setHost package.deps.target.only; namespace:
# target = setHost package.deps.target.target; builtins.mapAttrs (
# }; name: alias:
# }; let
# }; setPlatform =
# } package:
# )) package
# .config // {
# else package; __modules__ = package.__modules__ ++ [
{
config.platform = {
host = lib.modules.override 5 system;
target = lib.modules.override 5 system;
};
}
];
};
updated = alias // { updated = alias // {
versions = builtins.mapAttrs (version: package: setHost package) alias.versions; versions = builtins.mapAttrs (version: package: setPlatform package) alias.versions;
}; };
in in
updated updated
) )
) packages )
); packages
);
};
} }

View file

@ -1,8 +1,8 @@
{ { lib
lib, , lib'
lib', , config
config, , options
options, ,
}: }:
let let
inherit (config) inherit (config)
@ -27,101 +27,149 @@ in
}; };
}; };
config = { config =
meta = { let
platforms = [ "i686-linux" ]; isBuildBootstrapped = config.platform.build.double == "i686-linux";
}; isHostBootstrapped = config.platform.host.double == "i686-linux";
pname = "binutils"; isBootstrapped = isBuildBootstrapped && isHostBootstrapped;
version = "2.41";
builder = builders.basic; isCross =
config.platform.build.double != config.platform.host.double
&& config.platform.host.double == config.platform.target.double;
in
{
meta = {
platforms = [
"i686-linux"
"x86_64-linux"
];
};
deps = { pname = "binutils";
build = { version = "2.41";
host = {
inherit (packages.foundation) gcc; builder = builders.basic;
deps = {
build = {
only = {
gcc = lib.modules.when (!isBootstrapped) (
if isCross then
packages.foundation.gcc-cross.versions.latest.extend
{
platform = lib.modules.override 0 {
inherit (config.platform) build target;
host = config.platform.build;
};
}
else
packages.foundation.gcc.versions.latest
);
glibc = lib.modules.when (isCross) (
packages.foundation.glibc.versions.latest.extend {
platform = lib.modules.override 0 {
inherit (config.platform) host target build;
};
}
);
binutils = lib.modules.when (isCross) (
packages.foundation.binutils.versions.latest.extend {
platform = lib.modules.override 0 {
inherit (config.platform) target build;
host = config.platform.build;
};
}
);
};
}; };
}; };
};
env = { env = {
PATH = lib.paths.bin [ PATH = lib.paths.bin (
# foundation.stage2-gcc lib.lists.when (isBootstrapped) [ foundation.stage2-gcc ]
foundation.stage2-binutils ++ [
foundation.stage2-gnumake foundation.stage2-gcc
foundation.stage2-gnupatch foundation.stage2-binutils
foundation.stage2-gnused foundation.stage2-gnumake
foundation.stage2-gnugrep foundation.stage2-gnupatch
foundation.stage2-gawk foundation.stage2-gnused
foundation.stage2-diffutils foundation.stage2-gnugrep
foundation.stage2-findutils foundation.stage2-gawk
foundation.stage2-gnutar foundation.stage2-diffutils
foundation.stage1-xz foundation.stage2-findutils
]; foundation.stage2-gnutar
}; foundation.stage1-xz
]
);
} // (lib.attrs.when (isCross) {
LDFLAGS_FOR_TARGET = "-B${config.deps.build.only.glibc.package}/lib -L${config.deps.build.only.glibc.package}/lib -I${config.deps.build.only.glibc.package}/include";
});
phases = phases =
let let
patches = [ patches = [
# Make binutils output deterministic by default. # Make binutils output deterministic by default.
./patches/deterministic.patch ./patches/deterministic.patch
]; ];
configureFlags = [ configureFlags =
# "CC=musl-gcc" lib.lists.when (!isCross) [
"LDFLAGS=--static" "LDFLAGS=--static"
"--prefix=${builtins.placeholder "out"}" ]
"--build=${config.platform.build.triple}" ++ [
"--host=${config.platform.host.triple}" "--prefix=${builtins.placeholder "out"}"
"--target=${config.platform.target.triple}" "--build=${config.platform.build.triple}"
"--host=${config.platform.host.triple}"
"--target=${config.platform.target.triple}"
"--with-sysroot=/" "--with-sysroot=/"
"--enable-deterministic-archives" "--enable-deterministic-archives"
# depends on bison # depends on bison
"--disable-gprofng" "--disable-gprofng"
# Turn on --enable-new-dtags by default to make the linker set # Turn on --enable-new-dtags by default to make the linker set
# RUNPATH instead of RPATH on binaries. This is important because # RUNPATH instead of RPATH on binaries. This is important because
# RUNPATH can be overridden using LD_LIBRARY_PATH at runtime. # RUNPATH can be overridden using LD_LIBRARY_PATH at runtime.
"--enable-new-dtags" "--enable-new-dtags"
# By default binutils searches $libdir for libraries. This brings in # By default binutils searches $libdir for libraries. This brings in
# libbfd and libopcodes into a default visibility. Drop default lib # libbfd and libopcodes into a default visibility. Drop default lib
# path to force users to declare their use of these libraries. # path to force users to declare their use of these libraries.
"--with-lib-path=:" "--with-lib-path=:"
"--disable-multilib" "--disable-multilib"
];
in
{
unpack = ''
tar xf ${config.src}
cd binutils-${config.version}
'';
patch = '' ];
${lib.strings.concatMapSep "\n" (file: "patch -Np1 -i ${file}") patches} in
''; {
unpack = ''
tar xf ${config.src}
cd binutils-${config.version}
'';
configure = '' patch = ''
bash ./configure ${builtins.concatStringsSep " " configureFlags} ${lib.strings.concatMapSep "\n" (file: "patch -Np1 -i ${file}") patches}
''; '';
build = '' configure = ''
make -j $NIX_BUILD_CORES bash ./configure ${builtins.concatStringsSep " " configureFlags}
''; '';
install = '' build = ''
make -j $NIX_BUILD_CORES install-strip make -j $NIX_BUILD_CORES
''; '';
install = ''
make -j $NIX_BUILD_CORES install-strip
'';
};
src = builtins.fetchurl {
url = "${mirrors.gnu}/binutils/binutils-${config.version}.tar.xz";
sha256 = "rppXieI0WeWWBuZxRyPy0//DHAMXQZHvDQFb3wYAdFA=";
}; };
src = builtins.fetchurl {
url = "${mirrors.gnu}/binutils/binutils-${config.version}.tar.xz";
sha256 = "rppXieI0WeWWBuZxRyPy0//DHAMXQZHvDQFb3wYAdFA=";
}; };
};
}; };
}; };
}; };

View file

@ -0,0 +1,84 @@
{ config, options }:
let
inherit (config)
lib
packages
;
in
{
config.packages.foundation.gcc-bootstrap = {
versions = {
"latest" = config.packages.foundation.gcc.versions.latest.extend
(
{ config }:
{
config = {
meta = {
platforms = lib.modules.override 0 [
"i686-linux"
];
};
deps = {
build = {
build = {
gcc = lib.modules.override 0 (
packages.foundation.gcc-cross.versions.latest.extend {
platform = lib.modules.override 0 {
build = "i686-linux";
target = config.platform.target;
host = "i686-linux";
};
}
);
binutils = lib.modules.override 0 (
packages.foundation.binutils.versions.latest.extend {
platform = lib.modules.override 0 {
build = "i686-linux";
target = config.platform.target;
host = config.platform.host;
};
}
);
glibc = lib.modules.override 0 (
packages.foundation.glibc.versions.latest.extend {
platform = lib.modules.override 0 {
build = "i686-linux";
target = config.platform.target;
host = config.platform.host;
};
}
);
};
};
};
env = {
LIBRARY_PATH = lib.modules.override 0 "${config.deps.build.build.glibc.package}/lib";
LDFLAGS_FOR_TARGET =
lib.modules.override 0
"-L$(pwd)/${config.platform.target.triple}/libgcc -L${config.deps.build.build.glibc.package}/lib";
};
configureFlags = lib.modules.override 0 [
"--prefix=${builtins.placeholder "out"}"
# Pretend we're native even though we're not
"--build=${config.platform.target.triple}"
"--host=${config.platform.host.triple}"
"--target=${config.platform.target.triple}"
"--with-as=${config.deps.build.build.binutils.package}/bin/as"
"--with-ld=${config.deps.build.build.binutils.package}/bin/ld"
"--enable-languages=c,c++"
"--disable-bootstrap"
"--disable-libsanitizer"
"--disable-multilib"
"--with-native-system-header-dir=${config.deps.build.build.glibc.package}/include"
"--with-gxx-include-dir=${placeholder "out"}/include/c++/${config.version}/"
"--with-build-sysroot=/"
];
};
}
);
};
};
}

View file

@ -0,0 +1,104 @@
{ config, options }:
let
inherit (config)
lib
foundation
packages
;
in
{
config.packages.foundation.gcc-cross = {
versions = {
"latest" = config.packages.foundation.gcc.versions.latest.extend
(
{ config }:
{
config =
let
programPrefix = lib.strings.when
(
config.platform.build.triple != config.platform.target.triple
) "${config.platform.target.triple}-";
in
{
meta = {
platforms = lib.modules.override 0 [
"i686-linux"
];
};
deps = {
build = {
build = {
binutils = (
packages.foundation.binutils.versions.latest.extend {
platform = lib.modules.override 0 config.platform;
}
);
glibc = (
packages.foundation.glibc.versions.latest.extend {
platform = lib.modules.override 0 {
inherit (config.platform) build target;
host = config.platform.target;
};
}
);
linux-headers = (
packages.foundation.linux-headers.versions.latest.extend {
platform.target = lib.modules.override 0 config.platform.target;
}
);
};
};
};
env = {
# LIBRARY_PATH = lib.modules.override 0 "${foundation.stage1-musl}/lib";
CC = lib.modules.override 0 "gcc -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so -idirafter ${foundation.stage1-musl}/include";
CXX = lib.modules.override 0 "g++ -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so -idirafter ${foundation.stage1-musl}/include";
CFLAGS_FOR_TARGET =
lib.modules.override 0
"-Wl,-dynamic-linker -Wl,${config.deps.build.build.glibc.package}/lib/ld-linux-x86-64.so.2 -B${config.deps.build.build.glibc.package}/lib";
LDFLAGS_FOR_TARGET =
lib.modules.override 0
"-L$(pwd)/${config.platform.target.triple}/libgcc -L${config.deps.build.build.glibc.package}/lib";
};
configureFlags = lib.modules.override 0 [
"--prefix=${builtins.placeholder "out"}"
"--build=${config.platform.build.triple}"
"--host=${config.platform.host.triple}"
"--target=${config.platform.target.triple}"
"--with-as=${config.deps.build.build.binutils.package}/bin/${programPrefix}as"
"--with-ld=${config.deps.build.build.binutils.package}/bin/${programPrefix}ld"
"--enable-languages=c,c++"
"--disable-libsanitizer"
"--disable-lto"
"--disable-multilib"
"--with-headers=${config.deps.build.build.glibc.package}/include"
"--with-build-sysroot=/"
# "--with-sysroot=${config.deps.build.build.glibc.package}"
"--with-native-system-header-dir=${config.deps.build.build.glibc.package}/include"
];
phases.configure = lib.modules.override 0 ''
# Configure
mkdir build
cd build
echo PATH=$PATH
# TODO(vlinkz) Hack to fix missing crti.o and crtn.o. Figure out how to properly find their paths.
mkdir gcc
ln -sv ${config.deps.build.build.glibc.package}/lib/{crti.o,crtn.o} gcc
mkdir -p x86_64-unknown-linux-gnu/libstdc++-v3/src
ln -sv ${config.deps.build.build.glibc.package}/lib/{crti.o,crtn.o} x86_64-unknown-linux-gnu/libstdc++-v3/src
bash ../configure ${builtins.concatStringsSep " " config.configureFlags}
'';
};
}
);
};
};
}

View file

@ -11,6 +11,12 @@ let
; ;
in in
{ {
includes = [
./newlib.nix
./cross.nix
./bootstrap.nix
];
config.packages.foundation.gcc = { config.packages.foundation.gcc = {
versions = { versions = {
"latest" = "latest" =
@ -75,135 +81,239 @@ in
description = "Version of isl."; description = "Version of isl.";
}; };
}; };
};
config = { configureFlags = lib.options.create {
meta = { type = lib.types.list.of lib.types.string;
platforms = [ "i686-linux" ]; description = "Flags to pass to the configure script.";
}; };
pname = "gcc"; exports = lib.options.create {
version = "13.2.0"; type = lib.types.attrs.of lib.types.string;
description = "List of exports to add to the environment.";
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 = ''
# 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 = ''
# Patch
# force musl even if host triple is gnu
sed -i 's|"os/gnu-linux"|"os/generic"|' libstdc++-v3/configure.host
'';
configure = ''
# 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 = ''
# Build
make -j $NIX_BUILD_CORES
'';
install = ''
# 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=";
};
}; };
}; };
config =
let
isBuildBootstrapped = config.platform.build.double == "i686-linux";
isHostBootstrapped = config.platform.host.double == "i686-linux";
isBootstrapped = isBuildBootstrapped && isHostBootstrapped;
crossTool =
(config.platform.target.triple != config.platform.host.triple)
&& (config.platform.host.triple == config.platform.build.triple);
cross =
(config.platform.target.triple != config.platform.host.triple)
&& (config.platform.host.triple == config.platform.target.triple);
programPrefix = lib.strings.when
(
config.platform.build.triple != config.platform.target.triple
) "${config.platform.target.triple}-";
libc = if isBootstrapped then foundation.stage1-musl else config.deps.build.build.glibc.package;
libcLd =
if isBootstrapped then
"${foundation.stage1-musl}/lib/libc.so"
else
"${config.deps.build.build.glibc.package}/lib/ld-linux-x86-64.so.2";
host = lib.systems.withBuildInfo config.platform.host;
target = lib.systems.withBuildInfo config.platform.target;
in
{
meta = {
platforms = [
"i686-linux"
];
};
pname = "gcc-${config.platform.build.double}--${config.platform.host.double}--${config.platform.target.double}";
version = "13.2.0";
builder = builders.basic;
deps = {
build = {
build = lib.modules.when (!isBootstrapped) {
gcc = packages.foundation.gcc-cross.versions.latest;
glibc = packages.foundation.glibc.versions.latest;
linux-headers = packages.foundation.linux-headers.versions.latest;
binutils = packages.foundation.binutils.versions.latest;
};
};
};
env =
{
PATH = lib.modules.when (isBuildBootstrapped) (
lib.paths.bin ([
foundation.stage2-gnumake
foundation.stage2-gnused
foundation.stage2-gnugrep
foundation.stage2-gnupatch
foundation.stage2-gawk
foundation.stage2-diffutils
foundation.stage2-findutils
foundation.stage2-gnutar
foundation.stage2-gzip
foundation.stage2-bzip2
foundation.stage1-xz
] ++ (lib.lists.when (isBootstrapped) [
foundation.stage2-gcc
foundation.stage2-binutils
]))
);
CFLAGS_FOR_TARGET = "-Wl,-dynamic-linker -Wl,${libcLd}";
}
// lib.attrs.when (isBootstrapped) {
CC = "gcc -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so";
CXX = "g++ -Wl,-dynamic-linker -Wl,${foundation.stage1-musl}/lib/libc.so";
}
// lib.attrs.when (!cross && !crossTool) {
LIBRARY_PATH = "${libc}/lib";
};
hooks =
let
flags =
if (isBootstrapped && !(cross || crossTool)) then
[
"-Wl,-dynamic-linker"
"-Wl,${foundation.stage1-musl}/lib/libc.so"
]
else
[
"-Wl,-dynamic-linker"
"-Wl,${config.deps.build.build.glibc.package}/lib/ld-linux${lib.strings.when (target.isx86 && target.is64bit) "-x86-64"}.so.2"
"-B${config.deps.build.build.glibc.package}/lib"
# "-idirafter ${config.deps.build.build.glibc.package}/include"
];
in
ctx: {
"aux:gcc:env" = lib.dag.entry.between [ "unpack" ] [ "configure" ] ''
export CC='${config.package}/bin/${programPrefix}gcc ${builtins.concatStringsSep " " flags}'
export CXX='${config.package}/bin/${programPrefix}g++ ${builtins.concatStringsSep " " flags}'
export CC_FOR_TARGET=$CC
export CXX_FOR_TARGET=$CXX
export CC_FOR_BUILD=$CC
export CXX_FOR_BUILD=$CXX
alias gcc='$CC'
alias g++='$CXX'
'';
};
configureFlags =
[
"--prefix=${builtins.placeholder "out"}"
"--build=${config.platform.build.triple}"
"--host=${config.platform.host.triple}"
"--target=${config.platform.target.triple}"
"--enable-languages=c,c++"
"--disable-bootstrap"
"--disable-libsanitizer"
"--disable-multilib"
"--with-build-sysroot=/"
"--with-native-system-header-dir=${libc}/include"
]
++ lib.lists.when (isBootstrapped) [
"--disable-lto"
];
phases =
let
patches = [
# Make binutils output deterministic by default.
./patches/libstdc++-target.patch
];
in
{
unpack = ''
# 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.strings.concatMapSep "\n" (file: "patch -Np1 -i ${file}") patches}
${lib.strings.when (isBootstrapped && !(crossTool || cross))''
# force musl even if host triple is gnu
sed -i 's|"os/gnu-linux"|"os/generic"|' libstdc++-v3/configure.host
''}
'';
configure = ''
# Configure
mkdir build
cd build
bash ../configure ${builtins.concatStringsSep " " config.configureFlags}
'';
build = ''
# Build
make -j $NIX_BUILD_CORES
'';
install = ''
# Install
${
lib.strings.when (host.is64bit) ''
mkdir -p $out/lib
ln -s lib $out/lib64
''
}
make -j $NIX_BUILD_CORES install
'';
};
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=";
};
};
};
}; };
}; };
}; };

View file

@ -0,0 +1,71 @@
{ config, options }:
let
inherit (config)
lib
packages
;
in
{
config.packages.foundation.gcc-newlib = {
versions = {
"latest" = config.packages.foundation.gcc.versions.latest.extend (
{ config }:
{
config =
let
programPrefix = lib.strings.when
(
config.platform.build.triple != config.platform.target.triple
) "${config.platform.target.triple}-";
in
{
meta = {
platforms = lib.modules.override 0 [
"i686-linux"
];
};
deps = {
build = {
build = {
binutils = (
packages.foundation.binutils.versions.latest.extend {
platform = lib.modules.override 0 config.platform;
}
);
};
};
};
configureFlags = lib.modules.override 0 [
"--prefix=${builtins.placeholder "out"}"
"--build=${config.platform.build.triple}"
"--host=${config.platform.host.triple}"
"--target=${config.platform.target.triple}"
"--with-as=${config.deps.build.build.binutils.package}/bin/${programPrefix}as"
"--with-ld=${config.deps.build.build.binutils.package}/bin/${programPrefix}ld"
"--enable-languages=c,c++"
"--disable-bootstrap"
"--disable-libsanitizer"
"--disable-lto"
"--disable-multilib"
"--disable-plugin"
"--disable-libssp"
"--disable-libvtv"
"--disable-libstdcxx"
"--disable-libquadmath"
"--disable-threads"
"--disable-decimal-float"
"--disable-shared"
"--disable-libmudflap"
"--disable-libgomp"
"--disable-libatomic"
"--without-headers"
"--with-newlib"
];
};
}
);
};
};
}

View file

@ -0,0 +1,33 @@
# From https://github.com/NixOS/nixpkgs/blob/nixos-24.05/pkgs/development/compilers/gcc/patches/libstdc%2B%2B-target.patch
Patch to make the target libraries 'configure' scripts find the proper CPP.
I noticed that building the mingw32 cross compiler.
Looking at the build script for mingw in archlinux, I think that only nixos
needs this patch. I don't know why.
diff --git a/Makefile.in b/Makefile.in
index 93f66b6..d691917 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -266,6 +266,7 @@ BASE_TARGET_EXPORTS = \
AR="$(AR_FOR_TARGET)"; export AR; \
AS="$(COMPILER_AS_FOR_TARGET)"; export AS; \
CC="$(CC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CC; \
+ CPP="$(CC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS -E"; export CC; \
CFLAGS="$(CFLAGS_FOR_TARGET)"; export CFLAGS; \
CONFIG_SHELL="$(SHELL)"; export CONFIG_SHELL; \
CPPFLAGS="$(CPPFLAGS_FOR_TARGET)"; export CPPFLAGS; \
@@ -291,11 +292,13 @@ BASE_TARGET_EXPORTS = \
RAW_CXX_TARGET_EXPORTS = \
$(BASE_TARGET_EXPORTS) \
CXX_FOR_TARGET="$(RAW_CXX_FOR_TARGET)"; export CXX_FOR_TARGET; \
- CXX="$(RAW_CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX;
+ CXX="$(RAW_CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX; \
+ CXXCPP="$(RAW_CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS -E"; export CXX;
NORMAL_TARGET_EXPORTS = \
$(BASE_TARGET_EXPORTS) \
- CXX="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX;
+ CXX="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX; \
+ CXXCPP="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS -E"; export CXX;
# Where to find GMP
HOST_GMPLIBS = @gmplibs@

View file

@ -3,6 +3,7 @@
lib', lib',
config, config,
options, options,
packages,
}: }:
let let
inherit (config) inherit (config)
@ -10,6 +11,7 @@ let
builders builders
# These are the upstream foundational packages exported from the Aux Foundation project. # These are the upstream foundational packages exported from the Aux Foundation project.
packages
foundation foundation
; ;
in in
@ -26,87 +28,124 @@ in
}; };
}; };
config = { config =
meta = { let
platforms = [ "i686-linux" ]; isCross =
}; (config.platform.build.triple != config.platform.host.triple)
&& (config.platform.host.triple == config.platform.target.triple);
pname = "gcc"; binutils =
version = "2.38"; if isCross then
"${
(packages.foundation.binutils.versions.latest.extend {
platform = lib.modules.override 0 {
inherit (config.platform) build target;
host = config.platform.build;
};
}).package
}/${config.platform.target.triple}"
else
foundation.stage2-binutils;
in
{
src = builtins.fetchurl { meta = {
url = "${mirrors.gnu}/libc/glibc-${config.version}.tar.xz"; platforms = [
sha256 = "+4KZiZiyspllRnvBtp0VLpwwfSzzAcnq+0VVt3DvP9I="; "i686-linux"
}; "x86_64-linux"
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
(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
]; ];
};
pname = "glibc";
version = "2.38";
src = builtins.fetchurl {
url = "${mirrors.gnu}/libc/glibc-${config.version}.tar.xz";
sha256 = "+4KZiZiyspllRnvBtp0VLpwwfSzzAcnq+0VVt3DvP9I=";
};
builder = builders.basic;
deps = {
build = {
host = {
linux-headers = (
packages.foundation.linux-headers.versions.latest.extend {
platform.target = lib.modules.override 0 config.platform.target;
}
);
};
};
};
env = {
PATH =
let
gcc =
if
isCross
# Otherwise we are going to need a cross-compiler.
then
(packages.foundation.gcc-newlib.versions.latest.extend {
platform = lib.modules.override 0 {
inherit (config.platform) build target;
host = config.platform.build;
};
}).package
# If we're on the same system then we can use the existing GCC instance.
else
foundation.stage2-gcc;
in
lib.paths.bin [
gcc
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-python
foundation.stage1-bison
foundation.stage1-xz
];
};
phases =
{
unpack = ''
tar xf ${config.src}
cd glibc-${config.version}
'';
configure = ''
mkdir build
cd build
bash ../configure \
--prefix=$out \
--build=${config.platform.build.triple} \
--host=${config.platform.host.triple} \
--with-headers=${config.deps.build.host.linux-headers.package}/include \
--with-binutils=${binutils}/bin
'';
build = ''
# Build
make -j $NIX_BUILD_CORES
'';
install = ''
# Install
make -j $NIX_BUILD_CORES install
ln -sv $(ls -d ${config.deps.build.host.linux-headers.package}/include/* | grep -v scsi\$) $out/include/
'';
};
}; };
phases = {
unpack = lib.dag.entry.before [ "patch" ] ''
tar xf ${config.src}
cd glibc-${config.version}
'';
configure = lib.dag.entry.between [ "build" ] [ "patch" ] ''
mkdir build
cd build
# libstdc++.so is built against musl and fails to link
export CXX=false
bash ../configure \
--prefix=$out \
--build=${config.platform.build.triple} \
--host=${config.platform.host.triple} \
--with-headers=${foundation.stage1-linux-headers}/include
'';
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

@ -1,8 +1,8 @@
{ { lib
lib, , lib'
lib', , config
config, , options
options, ,
}: }:
let let
inherit (config) inherit (config)
@ -28,7 +28,7 @@ in
config = { config = {
meta = { meta = {
platforms = [ "i686-linux" ]; platforms = [ "x86_64-linux" "i686-linux" ];
}; };
pname = "linux-headers"; pname = "linux-headers";
@ -60,7 +60,7 @@ in
''; '';
build = '' build = ''
make -j $NIX_BUILD_CORES CC=musl-gcc HOSTCC=musl-gcc ARCH=${config.platform.host.linux.arch} headers make -j $NIX_BUILD_CORES CC=musl-gcc HOSTCC=musl-gcc ARCH=${config.platform.target.linux.arch} headers
''; '';
install = '' install = ''