forked from auxolotl/labs
refactor: more elegant shorthand support
This commit is contained in:
parent
aa1c58f6ee
commit
2989fdc4fe
|
@ -358,7 +358,7 @@ lib: {
|
|||
in
|
||||
if builtins.isAttrs subtree
|
||||
then builtins.mapAttrs (name: f module) subtree
|
||||
else builtins.throw "Value for `${builtins.concatStringsSep "." prefix} is of type `${builtins.typeOf subtree}` but an attribute set was expected."
|
||||
else builtins.throw "Value for `${builtins.concatStringsSep "." prefix}` is of type `${builtins.typeOf subtree}` but an attribute set was expected."
|
||||
)
|
||||
modules);
|
||||
|
||||
|
|
|
@ -493,5 +493,113 @@ in {
|
|||
};
|
||||
in
|
||||
evaluated.config.aux.message == evaluated.config.aux.message2;
|
||||
|
||||
"function submodules" = let
|
||||
expected = "Hello, World!";
|
||||
evaluated = lib.modules.run {
|
||||
modules = [
|
||||
{
|
||||
options = {
|
||||
aux = lib.options.create {
|
||||
type = lib.types.submodules.of {
|
||||
shorthand = false;
|
||||
modules = [
|
||||
{
|
||||
options.message = lib.options.create {
|
||||
type = lib.types.string;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
config = {
|
||||
aux = args: {
|
||||
config.message = expected;
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
in
|
||||
evaluated.config.aux.message == expected;
|
||||
|
||||
"merges submodules" = let
|
||||
expected = "Hello, World!";
|
||||
evaluated = lib.modules.run {
|
||||
modules = [
|
||||
{
|
||||
options = {
|
||||
aux = lib.options.create {
|
||||
type = lib.types.submodules.of {
|
||||
shorthand = false;
|
||||
modules = [
|
||||
{
|
||||
options.message = lib.options.create {
|
||||
type = lib.types.string;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
config = {
|
||||
aux = args: {
|
||||
options.message2 = lib.options.create {
|
||||
type = lib.types.string;
|
||||
};
|
||||
|
||||
config.message = expected;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
config = {
|
||||
aux.config.message2 = expected;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
in
|
||||
evaluated.config.aux.message == evaluated.config.aux.message2;
|
||||
|
||||
"flexible shorthand" = let
|
||||
expected = "Hello, World!";
|
||||
evaluated = lib.modules.run {
|
||||
modules = [
|
||||
{
|
||||
options = {
|
||||
aux = lib.options.create {
|
||||
type = lib.types.submodules.of {
|
||||
shorthand = true;
|
||||
modules = [
|
||||
{
|
||||
options.message = lib.options.create {
|
||||
type = lib.types.string;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
config = {
|
||||
aux = args: {
|
||||
options.message2 = lib.options.create {
|
||||
type = lib.types.string;
|
||||
};
|
||||
|
||||
config.message = expected;
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
config = {
|
||||
aux.message2 = expected;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
in
|
||||
evaluated.config.aux.message == evaluated.config.aux.message2;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -756,7 +756,7 @@ lib: {
|
|||
## with helpers like `lib.types.attrs.of` in order to produce more complex,
|
||||
## dynamic types.
|
||||
##
|
||||
## @type { modules :: List Module, args? :: Attrs, description? :: String | Null } -> Attrs
|
||||
## @type { modules :: List Module, args? :: Attrs, description? :: String | Null, shorthand? :: Bool } -> Attrs
|
||||
of = settings @ {
|
||||
modules,
|
||||
args ? {},
|
||||
|
@ -765,11 +765,24 @@ lib: {
|
|||
}: let
|
||||
getModules = builtins.map (
|
||||
definition:
|
||||
if shorthand && builtins.isAttrs definition
|
||||
then {
|
||||
__file__ = definition.__file__;
|
||||
config = definition.value;
|
||||
}
|
||||
if shorthand && builtins.isAttrs definition.value
|
||||
then let
|
||||
config =
|
||||
definition.value.config
|
||||
or (
|
||||
builtins.removeAttrs definition.value
|
||||
(builtins.filter (key: key != "config") lib.modules.VALID_KEYS)
|
||||
);
|
||||
rest =
|
||||
if definition.value ? config
|
||||
then builtins.removeAttrs definition.value ["config"]
|
||||
else lib.attrs.filter (name: value: builtins.elem name lib.modules.VALID_KEYS) definition.value;
|
||||
in
|
||||
rest
|
||||
// {
|
||||
__file__ = definition.__file__;
|
||||
config = config;
|
||||
}
|
||||
else {
|
||||
__file__ = definition.__file__;
|
||||
includes = [definition.value];
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
},
|
||||
"locked": {
|
||||
"dir": "foundation",
|
||||
"dirtyRev": "b3f9fe574e6ff545e4a6fe6ad5e90fc71baeece3-dirty",
|
||||
"dirtyShortRev": "b3f9fe5-dirty",
|
||||
"lastModified": 1718366115,
|
||||
"narHash": "sha256-/ktNtlY/usvE1YaathJ0f6y60cv3gQjc32SMKApsp7Y=",
|
||||
"dirtyRev": "aa1c58f6ee8a3ad6ad569f34477192462533c16b-dirty",
|
||||
"dirtyShortRev": "aa1c58f-dirty",
|
||||
"lastModified": 1718411218,
|
||||
"narHash": "sha256-LOzQGGygC2U08zNwg1YNljjrJKJxnJ8S4RkX2v81yRw=",
|
||||
"type": "git",
|
||||
"url": "file:../?dir=foundation"
|
||||
},
|
||||
|
@ -24,10 +24,10 @@
|
|||
"lib": {
|
||||
"locked": {
|
||||
"dir": "lib",
|
||||
"dirtyRev": "b3f9fe574e6ff545e4a6fe6ad5e90fc71baeece3-dirty",
|
||||
"dirtyShortRev": "b3f9fe5-dirty",
|
||||
"lastModified": 1718366115,
|
||||
"narHash": "sha256-/ktNtlY/usvE1YaathJ0f6y60cv3gQjc32SMKApsp7Y=",
|
||||
"dirtyRev": "aa1c58f6ee8a3ad6ad569f34477192462533c16b-dirty",
|
||||
"dirtyShortRev": "aa1c58f-dirty",
|
||||
"lastModified": 1718411218,
|
||||
"narHash": "sha256-LOzQGGygC2U08zNwg1YNljjrJKJxnJ8S4RkX2v81yRw=",
|
||||
"type": "git",
|
||||
"url": "file:../?dir=lib"
|
||||
},
|
||||
|
|
|
@ -26,11 +26,9 @@ in {
|
|||
sorted.result;
|
||||
|
||||
system = package.platform.build;
|
||||
|
||||
deps = lib'.packages.dependencies.resolve package.deps system;
|
||||
in
|
||||
(builtins.trace script)
|
||||
builtins.derivation (package.env
|
||||
builtins.derivation (
|
||||
package.env
|
||||
// {
|
||||
inherit (package) name;
|
||||
inherit script system;
|
||||
|
@ -40,7 +38,7 @@ in {
|
|||
SHELL = cfg.executable;
|
||||
|
||||
PATH = lib.paths.bin (
|
||||
(lib'.packages.dependencies.getPackages "build.host" deps)
|
||||
(lib'.packages.dependencies.getPackages package.deps.build.host)
|
||||
++ [
|
||||
foundation.stage2-bash
|
||||
foundation.stage2-coreutils
|
||||
|
@ -67,7 +65,8 @@ in {
|
|||
bash -eux $scriptPath
|
||||
'')
|
||||
];
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ in {
|
|||
modules = import ./modules.nix;
|
||||
|
||||
packages = {
|
||||
example = lib'.packages.export "example.x";
|
||||
example-x = config.packages.example.x;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
config,
|
||||
}: let
|
||||
in {
|
||||
options = {
|
||||
|
|
|
@ -3,12 +3,10 @@
|
|||
lib,
|
||||
}: let
|
||||
lib' = config.lib;
|
||||
|
||||
cfg = config.exports;
|
||||
in {
|
||||
options = {
|
||||
exports.packages = lib.options.create {
|
||||
type = lib.types.attrs.of (lib.types.function (lib.types.nullish lib.types.derivation));
|
||||
type = lib.types.attrs.of (lib'.types.raw);
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
|
@ -22,17 +20,27 @@ in {
|
|||
exported.packages = let
|
||||
all = lib.attrs.generate lib'.systems.doubles.all (
|
||||
system: let
|
||||
packages =
|
||||
all =
|
||||
builtins.mapAttrs
|
||||
(name: resolve: resolve system)
|
||||
cfg.packages;
|
||||
(
|
||||
name: package: let
|
||||
result = lib'.packages.build package system system;
|
||||
in
|
||||
result
|
||||
)
|
||||
config.exports.packages;
|
||||
|
||||
available =
|
||||
lib.attrs.filter
|
||||
(name: package: package != null)
|
||||
packages;
|
||||
(name: package: builtins.elem system package.meta.platforms)
|
||||
all;
|
||||
|
||||
packages =
|
||||
builtins.mapAttrs
|
||||
(name: package: package.package)
|
||||
available;
|
||||
in
|
||||
available
|
||||
packages
|
||||
);
|
||||
|
||||
available =
|
||||
|
|
|
@ -19,4 +19,8 @@ in {
|
|||
apply = value: lib.extend (final: prev: prev.attrs.mergeRecursive prev value);
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
__module__.args.dynamic.lib' = config.lib;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,82 +1,65 @@
|
|||
{
|
||||
lib,
|
||||
lib',
|
||||
config,
|
||||
}: let
|
||||
lib' = config.lib;
|
||||
in {
|
||||
}: {
|
||||
config = {
|
||||
lib.packages = {
|
||||
dependencies = {
|
||||
getPackages = path: dependencies: let
|
||||
resolved =
|
||||
if builtins.isList path
|
||||
then path
|
||||
else lib.strings.split "." path;
|
||||
|
||||
attrs = lib.attrs.select resolved {} dependencies;
|
||||
getPackages = dependencies: let
|
||||
available =
|
||||
builtins.filter
|
||||
(dependency: !(builtins.isNull dependency))
|
||||
(builtins.attrValues dependencies);
|
||||
in
|
||||
lib.attrs.mapToList (name: value: value.package) attrs;
|
||||
|
||||
resolve = dependencies: system:
|
||||
builtins.mapAttrs
|
||||
# Note that this does not correspond to the "host" and "target" platforms, but rather
|
||||
# where the code is used and where it is intended to end up.
|
||||
(
|
||||
host: platforms:
|
||||
builtins.mapAttrs
|
||||
(
|
||||
target: deps:
|
||||
builtins.mapAttrs
|
||||
(
|
||||
name: dependency:
|
||||
assert lib.errors.trace (dependency.namespace != null) "Namespace unknown for dependency `${name}`."; let
|
||||
targeted = lib'.packages.export [dependency.namespace name] system;
|
||||
in
|
||||
if targeted == null
|
||||
then builtins.throw "Dependency `${dependency.namespace}.${name}` does not support system `${system}`."
|
||||
else targeted
|
||||
)
|
||||
deps
|
||||
)
|
||||
platforms
|
||||
)
|
||||
dependencies;
|
||||
builtins.map (dependency: dependency.package) available;
|
||||
};
|
||||
|
||||
## Get a package from the package set by its path. The path can be either
|
||||
## a string or a list of strings that is used to access `config.packages.generic`.
|
||||
##
|
||||
## @type String | List String -> Package
|
||||
get = path: let
|
||||
resolved =
|
||||
if builtins.isList path
|
||||
then path
|
||||
else lib.strings.split "." path;
|
||||
|
||||
package = lib.attrs.selectOrThrow resolved config.packages.generic;
|
||||
getLatest = alias: let
|
||||
versions = builtins.attrNames alias.versions;
|
||||
sorted = builtins.sort (builtins.compareVersions) versions;
|
||||
in
|
||||
assert lib.errors.trace (builtins.length resolved > 1) "Cannot get package without a namespace.";
|
||||
package
|
||||
// {
|
||||
namespace = lib.modules.override 99 (builtins.head resolved);
|
||||
builtins.head sorted;
|
||||
|
||||
build = package: system: cross: let
|
||||
resolved =
|
||||
if package ? versions
|
||||
then package.versions.${config.preferences.packages.version} or (lib'.packages.getLatest package)
|
||||
else package;
|
||||
|
||||
buildDependencies = builtins.mapAttrs (name: dep: lib'.packages.build dep system cross);
|
||||
|
||||
result = resolved.extend ({config}: {
|
||||
config = {
|
||||
platform = {
|
||||
build = system;
|
||||
host = cross;
|
||||
target = cross;
|
||||
};
|
||||
|
||||
deps = {
|
||||
build = {
|
||||
only = buildDependencies resolved.deps.build.only;
|
||||
build = buildDependencies resolved.deps.build.build;
|
||||
host = buildDependencies resolved.deps.build.host;
|
||||
target = buildDependencies resolved.deps.build.target;
|
||||
};
|
||||
host = {
|
||||
only = buildDependencies resolved.deps.host.only;
|
||||
host = buildDependencies resolved.deps.host.host;
|
||||
target = buildDependencies resolved.deps.host.target;
|
||||
};
|
||||
target = {
|
||||
only = buildDependencies resolved.deps.target.only;
|
||||
target = buildDependencies resolved.deps.target.target;
|
||||
};
|
||||
};
|
||||
|
||||
package = config.builder.build config;
|
||||
};
|
||||
|
||||
## Export a package by its path. Use this function with the `config.exports.packages.*`
|
||||
## options.
|
||||
##
|
||||
## @type String | List String -> String -> Package
|
||||
export = path: system: let
|
||||
resolved =
|
||||
if builtins.isList path
|
||||
then path
|
||||
else lib.strings.split "." path;
|
||||
|
||||
package = lib'.packages.get resolved;
|
||||
targeted = lib.attrs.selectOrThrow resolved config.packages.targeted.${system};
|
||||
});
|
||||
in
|
||||
if builtins.elem system package.meta.platforms
|
||||
then targeted.package
|
||||
else null;
|
||||
result.config;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
{
|
||||
lib,
|
||||
lib',
|
||||
config,
|
||||
}: let
|
||||
lib' = config.lib;
|
||||
in {
|
||||
}: {
|
||||
config = {
|
||||
lib.types = {
|
||||
license = let
|
||||
|
@ -51,58 +50,6 @@ in {
|
|||
in
|
||||
lib.types.either type (lib.types.list.of type);
|
||||
|
||||
meta = lib.types.submodule {
|
||||
options = {
|
||||
description = lib.options.create {
|
||||
description = "The description for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
homepage = lib.options.create {
|
||||
description = "The homepage for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
license = lib.options.create {
|
||||
description = "The license for the package.";
|
||||
type = lib.types.nullish config.lib.types.license;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
free = lib.options.create {
|
||||
description = "Whether the package is free.";
|
||||
type = lib.types.bool;
|
||||
default.value = true;
|
||||
};
|
||||
|
||||
insecure = lib.options.create {
|
||||
description = "Whether the package is insecure.";
|
||||
type = lib.types.bool;
|
||||
default.value = false;
|
||||
};
|
||||
|
||||
broken = lib.options.create {
|
||||
description = "Whether the package is broken.";
|
||||
type = lib.types.bool;
|
||||
default.value = false;
|
||||
};
|
||||
|
||||
main = lib.options.create {
|
||||
description = "The main entry point for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
platforms = lib.options.create {
|
||||
description = "The platforms the package supports.";
|
||||
type = lib.types.list.of lib.types.string;
|
||||
default.value = [];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
builder = lib.types.submodule {
|
||||
freeform = lib.types.any;
|
||||
|
||||
|
@ -114,523 +61,220 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
packages = {
|
||||
generic = lib.types.attrs.of (lib.types.submodule ({name}: {
|
||||
freeform = lib.types.attrs.of (lib.types.submodule [
|
||||
lib'.types.package.generic'
|
||||
]);
|
||||
}));
|
||||
packages = lib.types.attrs.of (lib'.types.alias);
|
||||
|
||||
versioned = lib.types.attrs.of (lib.types.submodule ({name}: {
|
||||
freeform = lib.types.attrs.of (lib.types.submodule [
|
||||
lib'.types.package.versioned'
|
||||
]);
|
||||
}));
|
||||
|
||||
# packages.<system>
|
||||
targeted = lib.types.attrs.of (lib.types.submodule ({name}: let
|
||||
system = name;
|
||||
in {
|
||||
# packages.<system>.<namespace>
|
||||
freeform = lib.types.attrs.of (lib.types.submodule ({name}: let
|
||||
namespace = name;
|
||||
in {
|
||||
# packages.<system>.<namespace>.<name>
|
||||
freeform = lib.types.attrs.of (lib.types.submodule [
|
||||
lib'.types.package.targeted'
|
||||
{
|
||||
config = {
|
||||
namespace = lib.modules.override 99 namespace;
|
||||
|
||||
platform = {
|
||||
build = system;
|
||||
host = lib.modules.overrides.default system;
|
||||
target = lib.modules.overrides.default system;
|
||||
};
|
||||
};
|
||||
}
|
||||
]);
|
||||
}));
|
||||
|
||||
# packages.<system>.<cross>
|
||||
options.cross = lib.attrs.generate lib'.systems.doubles.all (cross:
|
||||
lib.options.create {
|
||||
description = "A cross-compiling package set.";
|
||||
default.value = {};
|
||||
# packages.<system>.<cross>.<namespace>
|
||||
type = lib.types.attrs.of (lib.types.submodule (
|
||||
{name}: let
|
||||
namespace = name;
|
||||
in {
|
||||
# packages.<system>.<cross>.<namespace>.<name>
|
||||
freeform = lib.types.attrs.of (lib.types.submodule [
|
||||
lib'.types.package.targeted'
|
||||
{
|
||||
config = {
|
||||
namespace = lib.modules.override 99 namespace;
|
||||
|
||||
platform = {
|
||||
build = system;
|
||||
host = cross;
|
||||
target = lib.modules.overrides.default cross;
|
||||
};
|
||||
};
|
||||
}
|
||||
]);
|
||||
}
|
||||
));
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
dependencies = {
|
||||
generic = lib.types.attrs.of (lib.types.nullish lib'.types.package.generic);
|
||||
targeted = lib.types.attrs.of (lib.types.nullish lib'.types.package.targeted);
|
||||
};
|
||||
|
||||
package = {
|
||||
generic = lib.types.submodule lib'.types.package.generic';
|
||||
|
||||
generic' = args @ {
|
||||
name ? assert false; null,
|
||||
config,
|
||||
}: {
|
||||
freeform = lib.types.any;
|
||||
|
||||
options = {
|
||||
namespace = lib.options.create {
|
||||
description = "The namespace for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
pname = lib.options.create {
|
||||
description = "The program name for the package";
|
||||
type = lib.types.string;
|
||||
default = {
|
||||
text = "<name> or \"unknown\"";
|
||||
value =
|
||||
if args ? name
|
||||
then args.name
|
||||
else "unknown";
|
||||
};
|
||||
};
|
||||
|
||||
version = lib.options.create {
|
||||
description = "The version for the package.";
|
||||
type = lib.types.nullish lib.types.version;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
meta = lib.options.create {
|
||||
description = "Metadata for the package.";
|
||||
type = lib'.types.meta;
|
||||
default.value = {
|
||||
name = config.pname;
|
||||
};
|
||||
};
|
||||
|
||||
phases = lib.options.create {
|
||||
description = "The phases for the package.";
|
||||
type = lib.types.dag.of (
|
||||
lib.types.either
|
||||
lib.types.string
|
||||
(lib.types.function lib.types.string)
|
||||
);
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
env = lib.options.create {
|
||||
description = "The environment for the package.";
|
||||
type = lib.types.attrs.of lib.types.string;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
builder = lib.options.create {
|
||||
description = "The builder for the package.";
|
||||
type = lib'.types.builder;
|
||||
};
|
||||
|
||||
deps = {
|
||||
build = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the build environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
build = lib.options.create {
|
||||
description = "Dependencies which are created in the build environment and are executed in the build environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
host = lib.options.create {
|
||||
description = "Dependencies which are created in the build environment and are executed in the host environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are created in the build environment and are executed in the target environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
};
|
||||
|
||||
host = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the host environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
host = lib.options.create {
|
||||
description = "Dependencies which are executed in the host environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are executed in the host environment which produces code for the target environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
};
|
||||
|
||||
target = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the target environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are executed in the target environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
versions = lib.options.create {
|
||||
description = "Available package versions.";
|
||||
type = lib.types.attrs.of lib'.types.package.versioned;
|
||||
default.value = {};
|
||||
};
|
||||
alias = lib.types.attrs.of (lib.types.submodule {
|
||||
options = {
|
||||
versions = lib.options.create {
|
||||
description = "All available package versions.";
|
||||
type = lib.types.attrs.of lib'.types.package;
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
versioned = lib.types.submodule lib'.types.package.versioned';
|
||||
dependencies = lib.types.attrs.of (lib.types.nullish (lib.types.either lib'.types.alias lib'.types.package));
|
||||
|
||||
versioned' = args @ {
|
||||
name ? assert false; null,
|
||||
config,
|
||||
}: {
|
||||
freeform = lib.types.any;
|
||||
|
||||
options = {
|
||||
namespace = lib.options.create {
|
||||
description = "The namespace for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
pname = lib.options.create {
|
||||
description = "The program name for the package";
|
||||
type = lib.types.string;
|
||||
default = {
|
||||
text = "<name> or \"unknown\"";
|
||||
value =
|
||||
if args ? name
|
||||
then args.name
|
||||
else "unknown";
|
||||
package = lib.types.submodule ({
|
||||
config,
|
||||
meta,
|
||||
}: {
|
||||
options = {
|
||||
extend = lib.options.create {
|
||||
description = "Extend the package's submodules with additional configuration.";
|
||||
type = lib.types.function lib.types.raw;
|
||||
default.value = value:
|
||||
meta.extend {
|
||||
modules =
|
||||
if builtins.isAttrs value
|
||||
then [{config = value;}]
|
||||
else lib.lists.from.any value;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
version = lib.options.create {
|
||||
description = "The version for the package.";
|
||||
type = lib.types.nullish lib.types.version;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
meta = lib.options.create {
|
||||
type = lib'.types.meta;
|
||||
default.value = {
|
||||
name = config.pname;
|
||||
};
|
||||
};
|
||||
|
||||
phases = lib.options.create {
|
||||
description = "The phases for the package.";
|
||||
type = lib.types.dag.of (
|
||||
lib.types.either
|
||||
lib.types.string
|
||||
(lib.types.function lib.types.string)
|
||||
);
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
env = lib.options.create {
|
||||
description = "The environment for the package.";
|
||||
type = lib.types.attrs.of lib.types.string;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
builder = lib.options.create {
|
||||
description = "The builder for the package.";
|
||||
type = lib'.types.builder;
|
||||
};
|
||||
|
||||
deps = {
|
||||
build = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the build environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
build = lib.options.create {
|
||||
description = "Dependencies which are created in the build environment and are executed in the build environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
host = lib.options.create {
|
||||
description = "Dependencies which are created in the build environment and are executed in the host environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are created in the build environment and are executed in the target environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
};
|
||||
|
||||
host = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the host environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
host = lib.options.create {
|
||||
description = "Dependencies which are executed in the host environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are executed in the host environment which produces code for the target environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
};
|
||||
|
||||
target = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the target environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are executed in the target environment.";
|
||||
type = lib'.types.dependencies.generic;
|
||||
default.value = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
versions = lib.options.create {
|
||||
description = "Available package versions.";
|
||||
type = lib.types.attrs.of lib'.types.package.versioned;
|
||||
default.value = {};
|
||||
name = lib.options.create {
|
||||
description = "The name of the package.";
|
||||
type = lib.types.string;
|
||||
default = {
|
||||
text = "\${config.pname}-\${config.version}";
|
||||
value =
|
||||
if config.pname != null && config.version != null
|
||||
then "${config.pname}-${config.version}"
|
||||
else "";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
targeted = lib.types.submodule lib'.types.package.targeted';
|
||||
pname = lib.options.create {
|
||||
description = "The program name for the package";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
targeted' = args @ {
|
||||
name ? assert false; null,
|
||||
config,
|
||||
}: {
|
||||
options = {
|
||||
freeform = lib.types.any;
|
||||
version = lib.options.create {
|
||||
description = "The version for the package.";
|
||||
type = lib.types.nullish lib.types.version;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
name = lib.options.create {
|
||||
description = "The name of the package.";
|
||||
type = lib.types.string;
|
||||
default = {
|
||||
text = "\${namespace}-\${pname}-\${version} or \${pname}-\${version}";
|
||||
value = let
|
||||
namespace =
|
||||
if config.namespace == null
|
||||
then ""
|
||||
else "${config.namespace}-";
|
||||
version =
|
||||
if config.version == null
|
||||
then ""
|
||||
else "-${config.version}";
|
||||
in "${namespace}${config.pname}${version}";
|
||||
};
|
||||
};
|
||||
|
||||
namespace = lib.options.create {
|
||||
description = "The namespace for the package.";
|
||||
meta = {
|
||||
description = lib.options.create {
|
||||
description = "The description for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
pname = lib.options.create {
|
||||
description = "The program name for the package.";
|
||||
type = lib.types.string;
|
||||
default = {
|
||||
text = "<name> or \"unknown\"";
|
||||
value =
|
||||
if args ? name
|
||||
then args.name
|
||||
else "unknown";
|
||||
};
|
||||
};
|
||||
|
||||
version = lib.options.create {
|
||||
description = "The version for the package.";
|
||||
type = lib.types.nullish lib.types.version;
|
||||
homepage = lib.options.create {
|
||||
description = "The homepage for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
meta = lib.options.create {
|
||||
description = "Metadata for the package.";
|
||||
type = lib'.types.meta;
|
||||
default.value = {
|
||||
name = config.pname;
|
||||
};
|
||||
license = lib.options.create {
|
||||
description = "The license for the package.";
|
||||
type = lib.types.nullish lib'.types.license;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
platform = {
|
||||
free = lib.options.create {
|
||||
description = "Whether the package is free.";
|
||||
type = lib.types.bool;
|
||||
default.value = true;
|
||||
};
|
||||
|
||||
insecure = lib.options.create {
|
||||
description = "Whether the package is insecure.";
|
||||
type = lib.types.bool;
|
||||
default.value = false;
|
||||
};
|
||||
|
||||
broken = lib.options.create {
|
||||
description = "Whether the package is broken.";
|
||||
type = lib.types.bool;
|
||||
default.value = false;
|
||||
};
|
||||
|
||||
main = lib.options.create {
|
||||
description = "The main entry point for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
};
|
||||
|
||||
platforms = lib.options.create {
|
||||
description = "The platforms the package supports.";
|
||||
type = lib.types.list.of lib.types.string;
|
||||
default.value = [];
|
||||
};
|
||||
};
|
||||
|
||||
platform = {
|
||||
build = lib.options.create {
|
||||
description = "The build platform for the package.";
|
||||
type = lib.types.string;
|
||||
default.value = "unknown";
|
||||
};
|
||||
|
||||
host = lib.options.create {
|
||||
description = "The host platform for the package.";
|
||||
type = lib.types.string;
|
||||
default.value = "unknown";
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "The target platform for the package.";
|
||||
type = lib.types.string;
|
||||
default.value = "unknown";
|
||||
};
|
||||
};
|
||||
|
||||
phases = lib.options.create {
|
||||
description = "The phases for the package.";
|
||||
type = lib.types.dag.of (
|
||||
lib.types.either
|
||||
lib.types.string
|
||||
(lib.types.function lib.types.string)
|
||||
);
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
env = lib.options.create {
|
||||
description = "The environment for the package.";
|
||||
type = lib.types.attrs.of lib.types.string;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
builder = lib.options.create {
|
||||
description = "The builder for the package.";
|
||||
type = lib'.types.builder;
|
||||
};
|
||||
|
||||
deps = {
|
||||
build = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the build environment.";
|
||||
type = lib'.types.dependencies;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
build = lib.options.create {
|
||||
description = "The build platform for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
description = "Dependencies which are created in the build environment and are executed in the build environment.";
|
||||
type = lib'.types.dependencies;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
host = lib.options.create {
|
||||
description = "The host platform for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
description = "Dependencies which are created in the build environment and are executed in the host environment.";
|
||||
type = lib'.types.dependencies;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "The target platform for the package.";
|
||||
type = lib.types.nullish lib.types.string;
|
||||
default.value = null;
|
||||
description = "Dependencies which are created in the build environment and are executed in the target environment.";
|
||||
type = lib'.types.dependencies;
|
||||
default.value = {};
|
||||
};
|
||||
};
|
||||
|
||||
phases = lib.options.create {
|
||||
description = "Build phases for the package.";
|
||||
type = lib.types.dag.of (
|
||||
lib.types.either
|
||||
lib.types.string
|
||||
(lib.types.function lib.types.string)
|
||||
);
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
env = lib.options.create {
|
||||
description = "The environment for the package.";
|
||||
type = lib.types.attrs.of lib.types.string;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
builder = lib.options.create {
|
||||
description = "The builder for the package.";
|
||||
type = lib'.types.builder;
|
||||
};
|
||||
|
||||
package = lib.options.create {
|
||||
description = "The built derivation.";
|
||||
type = lib.types.derivation;
|
||||
};
|
||||
|
||||
deps = {
|
||||
build = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the build environment.";
|
||||
type = lib'.types.dependencies.targeted;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
build = lib.options.create {
|
||||
description = "Dependencies which are created in the build environment and are executed in the build environment.";
|
||||
type = lib'.types.dependencies.targeted;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
host = lib.options.create {
|
||||
description = "Dependencies which are created in the build environment and are executed in the host environment.";
|
||||
type = lib'.types.dependencies.targeted;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are created in the build environment and are executed in the target environment.";
|
||||
type = lib'.types.dependencies.targeted;
|
||||
default.value = {};
|
||||
};
|
||||
host = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the host environment.";
|
||||
type = lib'.types.dependencies;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
host = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the host environment.";
|
||||
type = lib'.types.dependencies.targeted;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
host = lib.options.create {
|
||||
description = "Dependencies which are executed in the host environment.";
|
||||
type = lib'.types.dependencies.targeted;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are executed in the host environment which produces code for the target environment.";
|
||||
type = lib'.types.dependencies.targeted;
|
||||
default.value = {};
|
||||
};
|
||||
host = lib.options.create {
|
||||
description = "Dependencies which are executed in the host environment.";
|
||||
type = lib'.types.dependencies;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the target environment.";
|
||||
type = lib'.types.dependencies.targeted;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are executed in the target environment.";
|
||||
type = lib'.types.dependencies.targeted;
|
||||
default.value = {};
|
||||
};
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are executed in the host environment which produces code for the target environment.";
|
||||
type = lib'.types.dependencies;
|
||||
default.value = {};
|
||||
};
|
||||
};
|
||||
|
||||
versions = lib.options.create {
|
||||
description = "Available package versions.";
|
||||
type = lib.types.attrs.of lib'.types.package.versioned;
|
||||
default.value = {};
|
||||
target = {
|
||||
only = lib.options.create {
|
||||
description = "Dependencies which are only used in the target environment.";
|
||||
type = lib'.types.dependencies;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
target = lib.options.create {
|
||||
description = "Dependencies which are executed in the target environment.";
|
||||
type = lib'.types.dependencies;
|
||||
default.value = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
package = config.builder.build config;
|
||||
package = lib.options.create {
|
||||
description = "The built derivation.";
|
||||
type = lib.types.derivation;
|
||||
default.value = config.builder.build config;
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,32 +1,37 @@
|
|||
{
|
||||
lib,
|
||||
lib',
|
||||
config,
|
||||
options,
|
||||
}: let
|
||||
lib' = config.lib;
|
||||
builders = config.builders;
|
||||
in {
|
||||
config = {
|
||||
packages = {
|
||||
generic = {
|
||||
example = {
|
||||
x = {
|
||||
meta.platforms = ["i686-linux" "x86_64-linux"];
|
||||
version = "1.0.0";
|
||||
example = {
|
||||
x = {
|
||||
versions = {
|
||||
"latest" = {config}: {
|
||||
config = {
|
||||
meta = {
|
||||
platforms = ["i686-linux" "x86_64-linux"];
|
||||
};
|
||||
|
||||
builder = config.builders.basic;
|
||||
pname = "x";
|
||||
version = "1.0.0";
|
||||
|
||||
phases = {
|
||||
build = package: ''
|
||||
make --build ${package.platform.build} --host ${package.platform.host}
|
||||
'';
|
||||
builder = builders.basic;
|
||||
|
||||
install = lib.dag.entry.after ["build"] ''
|
||||
make install DESTDIR=$out
|
||||
'';
|
||||
};
|
||||
phases = {
|
||||
build = ''
|
||||
make --build ${config.platform.build} --host ${config.platform.host}
|
||||
'';
|
||||
|
||||
versions = {
|
||||
"latest" = config.packages.generic.example.x;
|
||||
install = lib.dag.entry.after ["build"] ''
|
||||
make install DESTDIR=$out
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -5,46 +5,23 @@
|
|||
lib' = config.lib;
|
||||
|
||||
doubles = lib'.systems.doubles.all;
|
||||
|
||||
generic = config.packages.generic;
|
||||
|
||||
getPackages = system:
|
||||
builtins.mapAttrs
|
||||
(
|
||||
namespace: packages:
|
||||
lib.attrs.filter
|
||||
(name: package: builtins.elem system package.meta.platforms)
|
||||
packages
|
||||
);
|
||||
|
||||
targeted = lib.attrs.generate lib'.systems.doubles.all (system:
|
||||
getPackages system generic
|
||||
// {
|
||||
cross = lib.attrs.generate doubles (
|
||||
host: getPackages host generic
|
||||
);
|
||||
});
|
||||
in {
|
||||
includes = [
|
||||
./aux/foundation.nix
|
||||
];
|
||||
|
||||
options = {
|
||||
packages = {
|
||||
generic = lib.options.create {
|
||||
type = lib'.types.packages.generic;
|
||||
default.value = {};
|
||||
};
|
||||
|
||||
targeted = lib.options.create {
|
||||
type = lib'.types.packages.targeted;
|
||||
};
|
||||
packages = lib.options.create {
|
||||
description = "The package set.";
|
||||
type = lib'.types.packages;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
packages = {
|
||||
inherit targeted;
|
||||
preferences.packages = {
|
||||
version = lib.options.create {
|
||||
description = "The preferred package version when using aliases.";
|
||||
type = lib.types.enum ["latest" "stable"];
|
||||
default.value = "latest";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue