From 2989fdc4fe153f13e7b6b476476805b03c419f0c Mon Sep 17 00:00:00 2001 From: Jake Hamilton Date: Sat, 15 Jun 2024 02:35:37 -0700 Subject: [PATCH] refactor: more elegant shorthand support --- lib/src/modules/default.nix | 2 +- lib/src/modules/default.test.nix | 108 ++++ lib/src/types/default.nix | 25 +- tidepool/flake.lock | 16 +- tidepool/src/builders/basic.nix | 11 +- tidepool/src/export.nix | 2 +- tidepool/src/exports/lib.nix | 2 +- tidepool/src/exports/packages.nix | 26 +- tidepool/src/lib/default.nix | 4 + tidepool/src/lib/packages.nix | 117 ++-- tidepool/src/lib/types.nix | 702 ++++++----------------- tidepool/src/packages/aux/foundation.nix | 39 +- tidepool/src/packages/default.nix | 41 +- 13 files changed, 418 insertions(+), 677 deletions(-) diff --git a/lib/src/modules/default.nix b/lib/src/modules/default.nix index 6aa4bcf..eb7573f 100644 --- a/lib/src/modules/default.nix +++ b/lib/src/modules/default.nix @@ -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); diff --git a/lib/src/modules/default.test.nix b/lib/src/modules/default.test.nix index 5b1cea6..788e2fa 100644 --- a/lib/src/modules/default.test.nix +++ b/lib/src/modules/default.test.nix @@ -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; }; } diff --git a/lib/src/types/default.nix b/lib/src/types/default.nix index 6e6a8ed..b83fad3 100644 --- a/lib/src/types/default.nix +++ b/lib/src/types/default.nix @@ -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]; diff --git a/tidepool/flake.lock b/tidepool/flake.lock index f783170..e3e3dc6 100644 --- a/tidepool/flake.lock +++ b/tidepool/flake.lock @@ -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" }, diff --git a/tidepool/src/builders/basic.nix b/tidepool/src/builders/basic.nix index ae09616..0a939ba 100644 --- a/tidepool/src/builders/basic.nix +++ b/tidepool/src/builders/basic.nix @@ -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 '') ]; - }); + } + ); }; }; } diff --git a/tidepool/src/export.nix b/tidepool/src/export.nix index 1d879f8..afb6e36 100644 --- a/tidepool/src/export.nix +++ b/tidepool/src/export.nix @@ -12,7 +12,7 @@ in { modules = import ./modules.nix; packages = { - example = lib'.packages.export "example.x"; + example-x = config.packages.example.x; }; }; }; diff --git a/tidepool/src/exports/lib.nix b/tidepool/src/exports/lib.nix index c168f44..89da50c 100644 --- a/tidepool/src/exports/lib.nix +++ b/tidepool/src/exports/lib.nix @@ -1,6 +1,6 @@ { - config, lib, + config, }: let in { options = { diff --git a/tidepool/src/exports/packages.nix b/tidepool/src/exports/packages.nix index 5dfd22e..c58b846 100644 --- a/tidepool/src/exports/packages.nix +++ b/tidepool/src/exports/packages.nix @@ -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 = diff --git a/tidepool/src/lib/default.nix b/tidepool/src/lib/default.nix index c418935..573c40e 100644 --- a/tidepool/src/lib/default.nix +++ b/tidepool/src/lib/default.nix @@ -19,4 +19,8 @@ in { apply = value: lib.extend (final: prev: prev.attrs.mergeRecursive prev value); }; }; + + config = { + __module__.args.dynamic.lib' = config.lib; + }; } diff --git a/tidepool/src/lib/packages.nix b/tidepool/src/lib/packages.nix index 617a400..ca677f2 100644 --- a/tidepool/src/lib/packages.nix +++ b/tidepool/src/lib/packages.nix @@ -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; }; }; } diff --git a/tidepool/src/lib/types.nix b/tidepool/src/lib/types.nix index c1c34c0..bb3d00a 100644 --- a/tidepool/src/lib/types.nix +++ b/tidepool/src/lib/types.nix @@ -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. - targeted = lib.types.attrs.of (lib.types.submodule ({name}: let - system = name; - in { - # packages.. - freeform = lib.types.attrs.of (lib.types.submodule ({name}: let - namespace = name; - in { - # packages... - 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.. - options.cross = lib.attrs.generate lib'.systems.doubles.all (cross: - lib.options.create { - description = "A cross-compiling package set."; - default.value = {}; - # packages... - type = lib.types.attrs.of (lib.types.submodule ( - {name}: let - namespace = name; - in { - # packages.... - 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 = " 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 = " 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 = " 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; }; }; - }; + }); }; }; } diff --git a/tidepool/src/packages/aux/foundation.nix b/tidepool/src/packages/aux/foundation.nix index 5470462..d61a3d1 100644 --- a/tidepool/src/packages/aux/foundation.nix +++ b/tidepool/src/packages/aux/foundation.nix @@ -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 + ''; + }; + }; }; }; }; diff --git a/tidepool/src/packages/default.nix b/tidepool/src/packages/default.nix index c4352bf..df5b01f 100644 --- a/tidepool/src/packages/default.nix +++ b/tidepool/src/packages/default.nix @@ -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"; + }; }; }; }