feat: system info

This commit is contained in:
Jake Hamilton 2024-06-12 22:00:03 -07:00
parent cd12786be1
commit f9ce7ff68b
Signed by: jakehamilton
GPG key ID: 9762169A1B35EA68
14 changed files with 1290 additions and 271 deletions

View file

@ -66,6 +66,38 @@ lib: {
then lib.attrs.select path null target then lib.attrs.select path null target
else error; else error;
## Zip specific attributes from a list of attribute sets.
##
## @type List String -> (List Any -> Any) -> List Attrs -> Attrs
zipWithNames = names: f: list: let
transform = name: {
inherit name;
value = f name (builtins.catAttrs name list);
};
results = builtins.map transform names;
in
builtins.listToAttrs results;
## Match an attribute set against a pattern.
##
## @type Attrs -> Attrs -> Bool
match = pattern: value: let
process = name: values: let
first = builtins.elemAt values 0;
second = builtins.elemAt values 1;
in
if builtins.length values == 1
then false
else if builtins.isAttrs first
then builtins.isAttrs second && lib.attrs.match first second
else first == second;
result = lib.attrs.zipWithNames (builtins.attrNames pattern) process [pattern value];
in
assert lib.errors.trace (builtins.isAttrs pattern) "Pattern must be an attribute set";
assert lib.errors.trace (builtins.isAttrs value) "Value must be an attribute set";
builtins.all lib.fp.id (builtins.attrValues result);
## Create a nested attribute set with a value as the leaf node. ## Create a nested attribute set with a value as the leaf node.
## ##
## @type (List String) -> a -> Attrs ## @type (List String) -> a -> Attrs

View file

@ -68,7 +68,7 @@ lib: {
escapedLines = builtins.map escapeMultiline lines; escapedLines = builtins.map escapeMultiline lines;
# The last line gets a special treatment: if it's empty, '' is on its own line at the "outer" # The last line gets a special treatment: if it's empty, '' is on its own line at the "outer"
# indentation level. Otherwise, '' is appended to the last line. # indentation level. Otherwise, '' is appended to the last line.
lastLine = lib.last escapedLines; lastLine = lib.lists.last escapedLines;
contents = builtins.concatStringsSep prefix (lib.lists.init escapedLines); contents = builtins.concatStringsSep prefix (lib.lists.init escapedLines);
contentsSuffix = contentsSuffix =
if lastLine == "" if lastLine == ""

View file

@ -154,6 +154,13 @@ lib: {
in in
lib.lists.slice count listLength list; lib.lists.slice count listLength list;
## Take all but the last element of a list.
##
## @type List -> List
init = list:
assert lib.errors.trace (builtins.length list != 0) "lib.lists.init: list must not be empty.";
lib.lists.take (builtins.length list - 1) list;
## Reverse a list. ## Reverse a list.
## ##
## @type List -> List ## @type List -> List

View file

@ -5,11 +5,21 @@ lib: {
## @type String -> String -> Bool ## @type String -> String -> Bool
gt = first: second: builtins.compareVersions first second == -1; gt = first: second: builtins.compareVersions first second == -1;
## Check if a version is greater than or equal to another.
##
## @type String -> String -> Bool
gte = first: second: builtins.compareVersions first second != 1;
## Check if a version is less than another. ## Check if a version is less than another.
## ##
## @type String -> String -> Bool ## @type String -> String -> Bool
lt = first: second: builtins.compareVersions first second == 1; lt = first: second: builtins.compareVersions first second == 1;
## Check if a version is less than or equal to another.
##
## @type String -> String -> Bool
lte = first: second: builtins.compareVersions first second != -1;
## Check if a version is equal to another. ## Check if a version is equal to another.
## ##
## @type String -> String -> Bool ## @type String -> String -> Bool

23
potluck/LICENSE Normal file
View file

@ -0,0 +1,23 @@
MIT License
Copyright (c) 2003-2023 Eelco Dolstra and the Nixpkgs/NixOS contributors
Copyright (c) 2024 Aux Contributors
Permission is hereby granted, free
of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice
(including the next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -8,10 +8,10 @@
}, },
"locked": { "locked": {
"dir": "foundation", "dir": "foundation",
"dirtyRev": "f24f0876a9103c7adb8120ce9709fb90c73f2a7c-dirty", "dirtyRev": "cd12786be17a611976b44fbba3e245eca512535f-dirty",
"dirtyShortRev": "f24f087-dirty", "dirtyShortRev": "cd12786-dirty",
"lastModified": 1718105966, "lastModified": 1718199069,
"narHash": "sha256-cvGKyJzoPAXjuM+YDpQM30qwshgoYZmAYtJywFPyfGI=", "narHash": "sha256-H2Mkyp9BPDPte+E++uIG2N/vGtcS3H9Q7tM3fOOEXT0=",
"type": "git", "type": "git",
"url": "file:../?dir=foundation" "url": "file:../?dir=foundation"
}, },
@ -24,10 +24,10 @@
"lib": { "lib": {
"locked": { "locked": {
"dir": "lib", "dir": "lib",
"dirtyRev": "f24f0876a9103c7adb8120ce9709fb90c73f2a7c-dirty", "dirtyRev": "cd12786be17a611976b44fbba3e245eca512535f-dirty",
"dirtyShortRev": "f24f087-dirty", "dirtyShortRev": "cd12786-dirty",
"lastModified": 1718105966, "lastModified": 1718199069,
"narHash": "sha256-cvGKyJzoPAXjuM+YDpQM30qwshgoYZmAYtJywFPyfGI=", "narHash": "sha256-H2Mkyp9BPDPte+E++uIG2N/vGtcS3H9Q7tM3fOOEXT0=",
"type": "git", "type": "git",
"url": "file:../?dir=lib" "url": "file:../?dir=lib"
}, },

View file

@ -7,6 +7,7 @@
in { in {
config = { config = {
exports = { exports = {
lib = config.lib;
modules = import ./modules.nix; modules = import ./modules.nix;
}; };
}; };

View file

@ -1,5 +1,6 @@
{ {
includes = [ includes = [
./lib.nix
./packages.nix ./packages.nix
./modules.nix ./modules.nix
]; ];

View file

@ -0,0 +1,19 @@
{
config,
lib,
}: let
in {
options = {
exports.lib = lib.options.create {
default.value = {};
};
exported.lib = lib.options.create {
default.value = {};
};
};
config = {
exported.lib = config.exports.lib;
};
}

View file

@ -6,11 +6,10 @@
in { in {
includes = [ includes = [
./options.nix ./options.nix
./systems.nix
./types.nix ./types.nix
]; ];
freeform = lib.types.any;
options = { options = {
lib = lib.options.create { lib = lib.options.create {
type = lib.types.attrs.any; type = lib.types.attrs.any;

View file

@ -3,10 +3,12 @@
config, config,
}: let }: let
in { in {
lib.options = { config = {
package = lib.options.create { lib.options = {
type = config.lib.types.package; package = lib.options.create {
description = "A package definition."; type = config.lib.types.package;
description = "A package definition.";
};
}; };
}; };
} }

925
potluck/src/lib/systems.nix Normal file
View file

@ -0,0 +1,925 @@
{
lib,
config,
}: let
lib' = config.lib;
types = config.lib.systems.types;
setTypes = type: let
assign = name: value:
assert lib.errors.trace (type.check value) "${name} is not of type ${type.name}: ${lib.generators.pretty {} value}";
lib.types.set name ({inherit name;} // value);
in
builtins.mapAttrs assign;
matchAnyAttrs = patterns:
if builtins.isList patterns
then value: builtins.any (pattern: lib.attrs.match pattern value) patterns
else lib.attrs.match patterns;
in {
config = {
lib.systems = {
match = builtins.mapAttrs (lib.fp.const matchAnyAttrs) lib'.systems.patterns;
types = {
generic = {
endian = lib.types.create {
name = "Endian";
description = "Endianness";
merge = lib.options.merge.one;
};
cpu = lib.types.create {
name = "Cpu";
description = "Instruction set architecture name and information";
merge = lib.options.merge.one;
check = x:
types.bits.check x.bits
&& (
if 8 < x.bits
then types.endian.check x.endian
else !(x ? endian)
);
};
family = lib.types.create {
name = "Family";
description = "The kernel family.";
merge = lib.options.merge.one;
};
exec = lib.types.create {
name = "Exec";
description = "Executable container used by the kernel";
merge = lib.options.merge.one;
};
kernel = lib.types.create {
name = "Kernel";
description = "Kernel name and information";
merge = lib.options.merge.one;
check = value:
types.exec.check value.exec
&& builtins.all types.family.check (builtins.attrValues value.families);
};
abi = lib.types.create {
name = "Abi";
description = "Binary interface for compiled code and syscalls";
merge = lib.options.merge.one;
};
vendor = lib.types.create {
name = "Vendor";
description = "Vendor for the platform";
merge = lib.options.merge.one;
};
};
platform = lib.types.create {
name = "system";
description = "fully parsed representation of llvm- or nix-style platform tuple";
merge = lib.options.merge.one;
check = {
cpu,
vendor,
kernel,
abi,
}:
types.cpu.check cpu
&& types.vendor.check vendor
&& types.kernel.check kernel
&& types.abi.check abi;
};
endian = lib.types.enum (builtins.attrValues types.endians);
endians = setTypes types.generic.endian {
big = {};
little = {};
};
bits = lib.types.enum [8 16 32 64 128];
exec = lib.types.enum (builtins.attrValues types.execs);
execs = setTypes types.generic.exec {
aout = {}; # a.out
elf = {};
macho = {};
pe = {};
wasm = {};
unknown = {};
};
vendor = lib.types.enum (builtins.attrValues types.vendors);
vendors = setTypes types.generic.vendor {
apple = {};
pc = {};
knuth = {};
# Actually matters, unlocking some MinGW-w64-specific options in GCC. See
# bottom of https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/
w64 = {};
none = {};
unknown = {};
};
family = lib.types.enum (builtins.attrValues types.families);
families = setTypes types.generic.family {
bsd = {};
darwin = {};
};
kernel = lib.types.enum (builtins.attrValues types.kernels);
kernels = setTypes types.generic.kernel {
# TODO(@Ericson2314): Don't want to mass-rebuild yet to keeping 'darwin' as
# the normalized name for macOS.
macos = {
exec = types.execs.macho;
families = {
darwin = types.families.darwin;
};
name = "darwin";
};
ios = {
exec = types.execs.macho;
families = {darwin = types.families.darwin;};
};
# A tricky thing about FreeBSD is that there is no stable ABI across
# versions. That means that putting in the version as part of the
# config string is paramount.
freebsd12 = {
exec = types.execs.elf;
families = {bsd = types.families.bsd;};
name = "freebsd";
version = 12;
};
freebsd13 = {
exec = types.execs.elf;
families = {bsd = types.families.bsd;};
name = "freebsd";
version = 13;
};
linux = {
exec = types.execs.elf;
families = {};
};
netbsd = {
exec = types.execs.elf;
families = {bsd = types.families.bsd;};
};
none = {
exec = types.execs.unknown;
families = {};
};
openbsd = {
exec = types.execs.elf;
families = {bsd = types.families.bsd;};
};
solaris = {
exec = types.execs.elf;
families = {};
};
wasi = {
exec = types.execs.wasm;
families = {};
};
redox = {
exec = types.execs.elf;
families = {};
};
windows = {
exec = types.execs.pe;
families = {};
};
ghcjs = {
exec = types.execs.unknown;
families = {};
};
genode = {
exec = types.execs.elf;
families = {};
};
mmixware = {
exec = types.execs.unknown;
families = {};
};
# aliases
# 'darwin' is the kernel for all of them. We choose macOS by default.
darwin = types.kernels.macos;
watchos = types.kernels.ios;
tvos = types.kernels.ios;
win32 = types.kernels.windows;
};
cpu = lib.types.enum (builtins.attrValues types.cpus);
cpus = setTypes types.generic.cpu {
arm = {
bits = 32;
endian = types.endians.little;
family = "arm";
};
armv5tel = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "5";
arch = "armv5t";
};
armv6m = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "6";
arch = "armv6-m";
};
armv6l = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "6";
arch = "armv6";
};
armv7a = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "7";
arch = "armv7-a";
};
armv7r = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "7";
arch = "armv7-r";
};
armv7m = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "7";
arch = "armv7-m";
};
armv7l = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "7";
arch = "armv7";
};
armv8a = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "8";
arch = "armv8-a";
};
armv8r = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "8";
arch = "armv8-a";
};
armv8m = {
bits = 32;
endian = types.endians.little;
family = "arm";
version = "8";
arch = "armv8-m";
};
aarch64 = {
bits = 64;
endian = types.endians.little;
family = "arm";
version = "8";
arch = "armv8-a";
};
aarch64_be = {
bits = 64;
endian = types.endians.big;
family = "arm";
version = "8";
arch = "armv8-a";
};
i386 = {
bits = 32;
endian = types.endians.little;
family = "x86";
arch = "i386";
};
i486 = {
bits = 32;
endian = types.endians.little;
family = "x86";
arch = "i486";
};
i586 = {
bits = 32;
endian = types.endians.little;
family = "x86";
arch = "i586";
};
i686 = {
bits = 32;
endian = types.endians.little;
family = "x86";
arch = "i686";
};
x86_64 = {
bits = 64;
endian = types.endians.little;
family = "x86";
arch = "x86-64";
};
microblaze = {
bits = 32;
endian = types.endians.big;
family = "microblaze";
};
microblazeel = {
bits = 32;
endian = types.endians.little;
family = "microblaze";
};
mips = {
bits = 32;
endian = types.endians.big;
family = "mips";
};
mipsel = {
bits = 32;
endian = types.endians.little;
family = "mips";
};
mips64 = {
bits = 64;
endian = types.endians.big;
family = "mips";
};
mips64el = {
bits = 64;
endian = types.endians.little;
family = "mips";
};
mmix = {
bits = 64;
endian = types.endians.big;
family = "mmix";
};
m68k = {
bits = 32;
endian = types.endians.big;
family = "m68k";
};
powerpc = {
bits = 32;
endian = types.endians.big;
family = "power";
};
powerpc64 = {
bits = 64;
endian = types.endians.big;
family = "power";
};
powerpc64le = {
bits = 64;
endian = types.endians.little;
family = "power";
};
powerpcle = {
bits = 32;
endian = types.endians.little;
family = "power";
};
riscv32 = {
bits = 32;
endian = types.endians.little;
family = "riscv";
};
riscv64 = {
bits = 64;
endian = types.endians.little;
family = "riscv";
};
s390 = {
bits = 32;
endian = types.endians.big;
family = "s390";
};
s390x = {
bits = 64;
endian = types.endians.big;
family = "s390";
};
sparc = {
bits = 32;
endian = types.endians.big;
family = "sparc";
};
sparc64 = {
bits = 64;
endian = types.endians.big;
family = "sparc";
};
wasm32 = {
bits = 32;
endian = types.endians.little;
family = "wasm";
};
wasm64 = {
bits = 64;
endian = types.endians.little;
family = "wasm";
};
alpha = {
bits = 64;
endian = types.endians.little;
family = "alpha";
};
rx = {
bits = 32;
endian = types.endians.little;
family = "rx";
};
msp430 = {
bits = 16;
endian = types.endians.little;
family = "msp430";
};
avr = {
bits = 8;
family = "avr";
};
vc4 = {
bits = 32;
endian = types.endians.little;
family = "vc4";
};
or1k = {
bits = 32;
endian = types.endians.big;
family = "or1k";
};
loongarch64 = {
bits = 64;
endian = types.endians.little;
family = "loongarch";
};
javascript = {
bits = 32;
endian = types.endians.little;
family = "javascript";
};
};
abi = lib.types.enum (builtins.attrValues types.abis);
abis = setTypes types.generic.abi {
cygnus = {};
msvc = {};
# Note: eabi is specific to ARM and PowerPC.
# On PowerPC, this corresponds to PPCEABI.
# On ARM, this corresponds to ARMEABI.
eabi = {float = "soft";};
eabihf = {float = "hard";};
# Other architectures should use ELF in embedded situations.
elf = {};
androideabi = {};
android = {
assertions = [
{
assertion = platform: !platform.isAarch32;
message = ''
The "android" ABI is not for 32-bit ARM. Use "androideabi" instead.
'';
}
];
};
gnueabi = {float = "soft";};
gnueabihf = {float = "hard";};
gnu = {
assertions = [
{
assertion = platform: !platform.isAarch32;
message = ''
The "gnu" ABI is ambiguous on 32-bit ARM. Use "gnueabi" or "gnueabihf" instead.
'';
}
{
assertion = platform: with platform; !(isPower64 && isBigEndian);
message = ''
The "gnu" ABI is ambiguous on big-endian 64-bit PowerPC. Use "gnuabielfv2" or "gnuabielfv1" instead.
'';
}
];
};
gnuabi64 = {abi = "64";};
muslabi64 = {abi = "64";};
# NOTE: abi=n32 requires a 64-bit MIPS chip! That is not a typo.
# It is basically the 64-bit abi with 32-bit pointers. Details:
# https://www.linux-mips.org/pub/linux/mips/doc/ABI/MIPS-N32-ABI-Handbook.pdf
gnuabin32 = {abi = "n32";};
muslabin32 = {abi = "n32";};
gnuabielfv2 = {abi = "elfv2";};
gnuabielfv1 = {abi = "elfv1";};
musleabi = {float = "soft";};
musleabihf = {float = "hard";};
musl = {};
uclibceabi = {float = "soft";};
uclibceabihf = {float = "hard";};
uclibc = {};
unknown = {};
};
};
from = {
string = value: let
parts = lib.strings.split "-" value;
skeleton = lib'.systems.skeleton parts;
system = lib'.systems.create (lib'.systems.from.skeleton skeleton);
in
system;
skeleton = spec @ {
cpu,
vendor ? assert false; null,
kernel,
abi ? assert false; null,
}: let
getCpu = name: types.cpus.${name} or (throw "Unknown CPU type: ${name}");
getVendor = name: types.vendors.${name} or (throw "Unknown vendor: ${name}");
getKernel = name: types.kernels.${name} or (throw "Unknown kernel: ${name}");
getAbi = name: types.abis.${name} or (throw "Unknown ABI: ${name}");
resolved = {
cpu = getCpu spec.cpu;
vendor =
if spec ? vendor
then getVendor spec.vendor
else if lib'.systems.match.isDarwin resolved
then types.vendors.apple
else if lib'.systems.match.isWindows resolved
then types.vendors.pc
else types.vendors.unknown;
kernel =
if lib.strings.hasPrefix "darwin" spec.kernel
then getKernel "darwin"
else if lib.strings.hasPrefix "netbsd" spec.kernel
then getKernel "netbsd"
else getKernel spec.kernel;
abi =
if spec ? abi
then getAbi spec.abi
else if lib'.systems.match.isLinux resolved || lib'.systems.match.isWindows resolved
then
if lib'.systems.match.isAarch32 resolved
then
if lib.versions.gte "6" (resolved.cpu.version)
then types.abis.gnueabihf
else types.abis.gnueabi
else if lib'.systems.match.isPower64 resolved && lib'.systems.match.isBigEndian resolved
then types.abis.gnuabielfv2
else types.abis.gnu
else types.abis.unknown;
};
in
resolved;
};
into = {
double = {
cpu,
kernel,
abi,
...
}: let
kernelName = kernel.name + builtins.toString (kernel.version or "");
in
if abi == types.abis.cygnus
then "${cpu.name}-cygwin"
else if kernel.families ? darwin
then "${cpu.name}-darwin"
else "${cpu.name}-${kernelName}";
triple = {
cpu,
vendor,
kernel,
abi,
...
}: let
kernelName = kernel.name + builtins.toString (kernel.version or "");
netbsdExec =
if
(cpu.family == "arm" && cpu.bits == 32)
|| (cpu.family == "sparc" && cpu.bits == 32)
|| (cpu.family == "m68k" && cpu.bits == 32)
|| (cpu.family == "x86" && cpu.bits == 32)
then types.execs.aout
else types.execs.elf;
exec =
lib.strings.when
(kernel.name == "netbsd" && netbsdExec != kernel.exec)
kernel.exec.name;
abi = lib.strings.when (abi != types.abis.unknown) "-${abi.name}";
in "${cpu.name}-${vendor.name}-${kernelName}${exec}${abi}";
};
create = components:
assert types.platform.check components;
lib.types.set "system" components;
skeleton = parts: let
length = builtins.length parts;
first = builtins.elemAt parts 0;
second = builtins.elemAt parts 1;
third = builtins.elemAt parts 2;
fourth = builtins.elemAt parts 3;
in
if length == 1
then
if first == "avr"
then {
cpu = first;
kernel = "none";
abi = "unknown";
}
else builtins.throw "Target specification with 1 component is ambiguous."
else if length == 2
then
if second == "cygwin"
then {
cpu = first;
kernel = "windows";
abi = "cygnus";
}
else if second == "windows"
then {
cpu = first;
kernel = "windows";
abi = "msvc";
}
else if second == "elf"
then {
cpu = first;
vendor = "unkonwn";
kernel = "none";
abi = second;
}
else {
cpu = first;
kernel = second;
}
else if length == 3
then
if second == "linux" || (builtins.elem third ["eabi" "eabihf" "elf" "gnu"])
then {
cpu = first;
vendor = "unknown";
kernel = second;
abi = third;
}
else if
(second == "apple")
|| lib.strings.hasPrefix "freebsd" third
|| lib.strings.hasPrefix "netbsd" third
|| lib.strings.hasPrefix "genode" third
|| (builtins.elem third ["wasi" "redox" "mmixware" "ghcjs" "mingw32"])
then {
cpu = first;
vendor = second;
kernel =
if third == "mingw32"
then "windows"
else third;
}
else builtins.throw "Target specification with 3 components is ambiguous."
else if length == 4
then {
cpu = first;
vendor = second;
kernel = third;
abi = fourth;
}
else builtins.throw "Invalid component count for creating system skeleton. Expected 1-4, but got ${builtins.toString length}.";
patterns = {
isi686 = {cpu = types.cpus.i686;};
isx86_32 = {
cpu = {
family = "x86";
bits = 32;
};
};
isx86_64 = {
cpu = {
family = "x86";
bits = 64;
};
};
isPower = {cpu = {family = "power";};};
isPower64 = {
cpu = {
family = "power";
bits = 64;
};
};
# This ABI is the default in NixOS PowerPC64 BE, but not on mainline GCC,
# so it sometimes causes issues in certain packages that makes the wrong
# assumption on the used ABI.
isAbiElfv2 = [
{abi = {abi = "elfv2";};}
{
abi = {name = "musl";};
cpu = {
family = "power";
bits = 64;
};
}
];
isx86 = {cpu = {family = "x86";};};
isAarch32 = {
cpu = {
family = "arm";
bits = 32;
};
};
isArmv7 =
map ({arch, ...}: {cpu = {inherit arch;};})
(lib.filter (cpu: lib.hasPrefix "armv7" cpu.arch or "")
(lib.attrValues types.cpus));
isAarch64 = {
cpu = {
family = "arm";
bits = 64;
};
};
isAarch = {cpu = {family = "arm";};};
isMicroBlaze = {cpu = {family = "microblaze";};};
isMips = {cpu = {family = "mips";};};
isMips32 = {
cpu = {
family = "mips";
bits = 32;
};
};
isMips64 = {
cpu = {
family = "mips";
bits = 64;
};
};
isMips64n32 = {
cpu = {
family = "mips";
bits = 64;
};
abi = {abi = "n32";};
};
isMips64n64 = {
cpu = {
family = "mips";
bits = 64;
};
abi = {abi = "64";};
};
isMmix = {cpu = {family = "mmix";};};
isRiscV = {cpu = {family = "riscv";};};
isRiscV32 = {
cpu = {
family = "riscv";
bits = 32;
};
};
isRiscV64 = {
cpu = {
family = "riscv";
bits = 64;
};
};
isRx = {cpu = {family = "rx";};};
isSparc = {cpu = {family = "sparc";};};
isWasm = {cpu = {family = "wasm";};};
isMsp430 = {cpu = {family = "msp430";};};
isVc4 = {cpu = {family = "vc4";};};
isAvr = {cpu = {family = "avr";};};
isAlpha = {cpu = {family = "alpha";};};
isOr1k = {cpu = {family = "or1k";};};
isM68k = {cpu = {family = "m68k";};};
isS390 = {cpu = {family = "s390";};};
isS390x = {
cpu = {
family = "s390";
bits = 64;
};
};
isLoongArch64 = {
cpu = {
family = "loongarch";
bits = 64;
};
};
isJavaScript = {cpu = types.cpus.javascript;};
is32bit = {cpu = {bits = 32;};};
is64bit = {cpu = {bits = 64;};};
isILP32 = builtins.map (a: {abi = {abi = a;};}) ["n32" "ilp32" "x32"];
isBigEndian = {cpu = {endian = types.endians.big;};};
isLittleEndian = {cpu = {endian = types.endians.little;};};
isBSD = {kernel = {families = {bsd = types.families.bsd;};};};
isDarwin = {kernel = {families = {darwin = types.families.darwin;};};};
isUnix = [lib'.systems.match.isBSD lib'.systems.match.isDarwin lib'.systems.match.isLinux lib'.systems.match.isSunOS lib'.systems.match.isCygwin lib'.systems.match.isRedox];
isMacOS = {kernel = types.kernels.macos;};
isiOS = {kernel = types.kernels.ios;};
isLinux = {kernel = types.kernels.linux;};
isSunOS = {kernel = types.kernels.solaris;};
isFreeBSD = {kernel = {name = "freebsd";};};
isNetBSD = {kernel = types.kernels.netbsd;};
isOpenBSD = {kernel = types.kernels.openbsd;};
isWindows = {kernel = types.kernels.windows;};
isCygwin = {
kernel = types.kernels.windows;
abi = types.abis.cygnus;
};
isMinGW = {
kernel = types.kernels.windows;
abi = types.abis.gnu;
};
isWasi = {kernel = types.kernels.wasi;};
isRedox = {kernel = types.kernels.redox;};
isGhcjs = {kernel = types.kernels.ghcjs;};
isGenode = {kernel = types.kernels.genode;};
isNone = {kernel = types.kernels.none;};
isAndroid = [{abi = types.abis.android;} {abi = types.abis.androideabi;}];
isGnu = builtins.map (value: {abi = value;}) [types.abis.gnuabi64 types.abis.gnuabin32 types.abis.gnu types.abis.gnueabi types.abis.gnueabihf types.abis.gnuabielfv1 types.abis.gnuabielfv2];
isMusl = builtins.map (value: {abi = value;}) [types.abis.musl types.abis.musleabi types.abis.musleabihf types.abis.muslabin32 types.abis.muslabi64];
isUClibc = builtins.map (value: {abi = value;}) [types.abis.uclibc types.abis.uclibceabi types.abis.uclibceabihf];
isEfi = [
{
cpu = {
family = "arm";
version = "6";
};
}
{
cpu = {
family = "arm";
version = "7";
};
}
{
cpu = {
family = "arm";
version = "8";
};
}
{cpu = {family = "riscv";};}
{cpu = {family = "x86";};}
];
};
};
};
}

View file

@ -4,274 +4,276 @@
}: let }: let
lib' = config.lib; lib' = config.lib;
in { in {
lib.types = { config = {
license = let lib.types = {
type = lib.types.submodule ({config}: { license = let
options = { type = lib.types.submodule ({config}: {
name = { options = {
full = lib.options.create { name = {
type = lib.types.string; full = lib.options.create {
description = "The full name of the license."; type = lib.types.string;
description = "The full name of the license.";
};
short = lib.options.create {
type = lib.types.string;
description = "The short name of the license.";
};
}; };
short = lib.options.create { spdx = lib.options.create {
type = lib.types.string; type = lib.types.nullish lib.types.string;
description = "The short name of the license."; default.value = null;
description = "The SPDX identifier for the license.";
};
url = lib.options.create {
type = lib.types.nullish lib.types.string;
description = "The URL for the license.";
};
free = lib.options.create {
type = lib.types.bool;
default.value = true;
description = "Whether the license is free.";
};
redistributable = lib.options.create {
type = lib.types.bool;
default = {
text = "config.free";
value = config.free;
};
description = "Whether the license is allows redistribution.";
}; };
}; };
});
in
lib.types.either type (lib.types.list.of type);
spdx = lib.options.create { meta = lib.types.submodule {
options = {
name = lib.options.create {
type = lib.types.string;
description = "The name of the package.";
};
description = lib.options.create {
type = lib.types.nullish lib.types.string; type = lib.types.nullish lib.types.string;
default.value = null; default.value = null;
description = "The SPDX identifier for the license."; description = "The description for the package.";
}; };
url = lib.options.create { homepage = lib.options.create {
type = lib.types.nullish lib.types.string; type = lib.types.nullish lib.types.string;
description = "The URL for the license."; default.value = null;
description = "The homepage for the package.";
};
license = lib.options.create {
type = config.lib.types.license;
description = "The license for the package.";
}; };
free = lib.options.create { free = lib.options.create {
type = lib.types.bool; type = lib.types.bool;
default.value = true; default.value = true;
description = "Whether the license is free."; description = "Whether the package is free.";
}; };
redistributable = lib.options.create { insecure = lib.options.create {
type = lib.types.bool; type = lib.types.bool;
default.value = false;
description = "Whether the package is insecure.";
};
broken = lib.options.create {
type = lib.types.bool;
default.value = false;
description = "Whether the package is broken.";
};
main = lib.options.create {
type = lib.types.nullish lib.types.string;
default.value = null;
description = "The main entry point for the package.";
};
platforms = lib.options.create {
type = lib.types.list.of lib.types.string;
default.value = [];
description = "The platforms the package supports.";
};
};
};
package = lib.types.submodule ({config}: {
freeform = lib.types.any;
options = {
name = lib.options.create {
type = lib.types.string;
default = { default = {
text = "config.free"; value = "${config.pname}-${config.version or "unknown"}";
value = config.free; text = "\${config.pname}-\${config.version}";
}; };
description = "Whether the license is allows redistribution."; description = "The name of the package.";
};
pname = lib.options.create {
type = lib.types.nullish lib.types.string;
default.value = null;
description = "The name of the package.";
};
version = lib.options.create {
type = lib.types.nullish lib.types.string;
default.value = null;
description = "The version of the package.";
};
meta = lib.options.create {
type = lib'.types.meta;
default = {
text = "{ name = <package>.pname; }";
value = {
name = config.pname;
};
};
description = "The metadata for the package.";
};
env = lib.options.create {
type = lib.types.attrs.of lib.types.string;
default.value = {};
description = "Environment variables for the package's builder to use.";
};
phases = lib.options.create {
type = lib.types.dag.of (
lib.types.either
lib.types.string
(lib.types.function lib.types.string)
);
default.value = {};
description = "Phases for the package's builder to use.";
};
platform = {
build = lib.options.create {
type = lib.types.string;
description = "The platform the package is built on.";
};
host = lib.options.create {
type = lib.types.string;
description = "The platform the package is run on.";
};
target = lib.options.create {
type = lib.types.string;
description = "The platform the package generates code for.";
};
};
builder = lib.options.create {
type = lib'.types.builder;
description = "The builder for the package.";
};
package = lib.options.create {
type = lib.types.derivation;
default = {
value = config.builder.build config.builder config;
text = "<derivation>";
};
description = "The package derivation.";
};
deps = {
build = {
only = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are only used in the build environment.";
};
build = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are created in the build environment and are run in the build environment.";
};
host = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are created in the build environment and are run in the host environment.";
};
target = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are created in the build environment and are run in the target environment.";
};
};
host = {
only = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are only used in the host environment.";
};
host = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are run in the host environment.";
};
target = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are run in the host environment which produces code for the target environment.";
};
};
target = {
only = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are only used in the target environment.";
};
target = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are run in the target environment.";
};
};
};
versions = lib.options.create {
type = lib.types.attrs.of lib'.types.package;
default.value = {};
description = "Available versions of the package.";
}; };
}; };
}); });
in
lib.types.either type (lib.types.list.of type);
meta = lib.types.submodule { dependencies = lib.types.attrs.of (lib.types.nullish lib'.types.package);
options = {
name = lib.options.create {
type = lib.types.string;
description = "The name of the package.";
};
description = lib.options.create { packages = lib.types.attrs.of (lib.types.submodule {
type = lib.types.nullish lib.types.string; freeform = lib.types.nullish lib'.types.package;
default.value = null; });
description = "The description for the package.";
};
homepage = lib.options.create { builder = lib.types.submodule {
type = lib.types.nullish lib.types.string; freeform = lib.types.any;
default.value = null;
description = "The homepage for the package.";
};
license = lib.options.create { options = {
type = config.lib.types.license;
description = "The license for the package.";
};
free = lib.options.create {
type = lib.types.bool;
default.value = true;
description = "Whether the package is free.";
};
insecure = lib.options.create {
type = lib.types.bool;
default.value = false;
description = "Whether the package is insecure.";
};
broken = lib.options.create {
type = lib.types.bool;
default.value = false;
description = "Whether the package is broken.";
};
main = lib.options.create {
type = lib.types.nullish lib.types.string;
default.value = null;
description = "The main entry point for the package.";
};
platforms = lib.options.create {
type = lib.types.list.of lib.types.string;
default.value = [];
description = "The platforms the package supports.";
};
};
};
package = lib.types.submodule ({config}: {
freeform = lib.types.any;
options = {
name = lib.options.create {
type = lib.types.string;
default = {
value = "${config.pname}-${config.version or "unknown"}";
text = "\${config.pname}-\${config.version}";
};
description = "The name of the package.";
};
pname = lib.options.create {
type = lib.types.nullish lib.types.string;
default.value = null;
description = "The name of the package.";
};
version = lib.options.create {
type = lib.types.nullish lib.types.string;
default.value = null;
description = "The version of the package.";
};
meta = lib.options.create {
type = lib'.types.meta;
default = {
text = "{ name = <package>.pname; }";
value = {
name = config.pname;
};
};
description = "The metadata for the package.";
};
env = lib.options.create {
type = lib.types.attrs.of lib.types.string;
default.value = {};
description = "Environment variables for the package's builder to use.";
};
phases = lib.options.create {
type = lib.types.dag.of (
lib.types.either
lib.types.string
(lib.types.function lib.types.string)
);
default.value = {};
description = "Phases for the package's builder to use.";
};
platform = {
build = lib.options.create { build = lib.options.create {
type = lib.types.string; type = lib.types.function lib.types.derivation;
description = "The platform the package is built on."; description = "The function that creates the package derivation.";
}; };
host = lib.options.create {
type = lib.types.string;
description = "The platform the package is run on.";
};
target = lib.options.create {
type = lib.types.string;
description = "The platform the package generates code for.";
};
};
builder = lib.options.create {
type = lib'.types.builder;
description = "The builder for the package.";
};
package = lib.options.create {
type = lib.types.derivation;
default = {
value = config.builder.build config.builder config;
text = "<derivation>";
};
description = "The package derivation.";
};
deps = {
build = {
only = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are only used in the build environment.";
};
build = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are created in the build environment and are run in the build environment.";
};
host = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are created in the build environment and are run in the host environment.";
};
target = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are created in the build environment and are run in the target environment.";
};
};
host = {
only = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are only used in the host environment.";
};
host = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are run in the host environment.";
};
target = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are run in the host environment which produces code for the target environment.";
};
};
target = {
only = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are only used in the target environment.";
};
target = lib.options.create {
type = lib'.types.dependencies;
default.value = {};
description = "Dependencies which are run in the target environment.";
};
};
};
versions = lib.options.create {
type = lib.types.attrs.of lib'.types.package;
default.value = {};
description = "Available versions of the package.";
};
};
});
dependencies = lib.types.attrs.of (lib.types.nullish lib'.types.package);
packages = lib.types.attrs.of (lib.types.submodule {
freeform = lib.types.nullish lib'.types.package;
});
builder = lib.types.submodule {
freeform = lib.types.any;
options = {
build = lib.options.create {
type = lib.types.function lib.types.derivation;
description = "The function that creates the package derivation.";
}; };
}; };
}; };

View file

@ -3,24 +3,22 @@
config, config,
}: let }: let
lib' = config.lib; lib' = config.lib;
# configure = namespace: packages:
configure = namespace: packages: # builtins.mapAttrs
builtins.mapAttrs # (key: package: let
(key: package: let # name =
name = # if package.pname != null && package.version != null
if package.pname != null && package.version != null # then "${package.pname}-${package.version}"
then "${package.pname}-${package.version}" # else key;
else key; # in {
in { # name = lib.modules.overrides.default name;
name = lib.modules.overrides.default name; # package = lib.modules.overrides.default (package.builder package);
package = lib.modules.overrides.default (package.builder package); # })
}) # packages;
packages; # configs = builtins.mapAttrs configure config.packages;
configs = builtins.mapAttrs configure config.packages;
in { in {
includes = [ includes = [
./aux/foundation.nix # ./aux/foundation.nix
]; ];
options = { options = {
@ -29,5 +27,5 @@ in {
}; };
}; };
config = lib.modules.merge configs; # config = lib.modules.merge configs;
} }