Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support system-independent flake outputs #86

Open
sellout opened this issue Aug 12, 2024 · 0 comments
Open

Support system-independent flake outputs #86

sellout opened this issue Aug 12, 2024 · 0 comments

Comments

@sellout
Copy link
Owner

sellout commented Aug 12, 2024

Currently, a flake has projectConfigurations.${system}, which provides many utilities for a flake, but all necessarily dependent on system.

Ideally, you would be able to extract overlays, schemas, and other things that are system-independent from a project configuration.

The configuration constructor could perhaps be provided a map of systems to package sets, then internally handle providing the per-system attributes. Something like:

{
  outputs = {flake-utils, nixpkgs, project-manager, self}: let
    supportedSystems = ["aarch64-darwin" "x86_64-linux"];
    pkgsFor = system: import nixpkgs {inherit system;};
  in
    {
      projectConfigurations = project-manager.lib.defaultConfiguration {
        inherit self;
        pkgSets = builtins.listToAttrs (map (system: {name = system; value = pkgsFor system}) supportedSystems);
      };

      overlays = self.projectConfigurations.overlays;
    }
    // flake-utils.lib.eachSystem supportedSystems (system: let
      pkgs = pkgsFor system;
    in {
      checks = self.projectConfigurations.${system}.checks;
    });
  };
}

I think the trickier part is the modules – maybe modules have to be partitioned into ones that don’t have access to pkgs and ones that do (ones that do can reference ones that don’t, but not vice-versa). But annoying to have to split things along this dimension, especially for modules that define options, where we don’t want to have to split, say, the treefmt module into two separate ones.

Alternatively, maybe we don’t provide pkgs to the configuration constructor at all, but let that be passed later somehow:

{
  outputs = {flake-utils, nixpkgs, project-manager, self}: let
    supportedSystems = ["aarch64-darwin" "x86_64-linux"];
  in
    {
      projectConfigurations = project-manager.lib.defaultConfiguration {inherit self;};

      overlays = self.projectConfigurations.overlays;
    }
    // flake-utils.lib.eachSystem supportedSystems (system: let
      pkgs = import nixpkgs {inherit system;};
    in {
      # This now extracts `system` from pkgs
      checks = self.projectConfigurations.checks pkgs;
    });
  };
}

Modules may now be called without a pkgs value in some cases, so modules need to conditionalize on that, like

{
  config,
  pkgs ? null,
  ...
}: {
  config = {
    config.devPackages = if pkgs then [cfg.package] else [];
  };
}

And configuration modules need to do this as well in some cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant