Flakelight

repository·master·Indexed 19 days ago

https://github.com/nix-community/flakelight

A modular Nix flake framework designed to simplify the creation of complex flakes by minimizing boilerplate. It provides sensible defaults, automatic per-system attribute generation, and a module system for sharing configurations. Flakelight supports various flake types, including projects, shells, NixOS configurations, and config monorepos, with built-in support for multi-file type formatters and automatic importing of attributes from a specified directory.

Tokens
4.9K
Snippets
19
Records
22
Agent score
15%

What's inside flakelight

  1. Overview of Flakelight

    master

    Flakelight is a modular Nix flake framework designed to simplify flake definitions by minimizing boilerplate. It supports various flake types including projects, shells, NixOS configurations, and config monorepos.

    Key capabilities include:

    • Automatic generation of per-system attributes.
    • Extensibility via a module system.
    • Automatic generation of package and overlay outputs from package definitions.
    • Automatic importing of attributes from .nix files located in a ./nix directory.
    • Built-in support for multi-file type formatters.
    • Easy migration via outputs/perSystem options.
  2. Use autoloads for Flakelight attributes

    master

    Flakelight can automatically import attributes from .nix files located in a ./nix directory. For example, you can move your package definition to ./nix/package.nix to keep your flake.nix clean.

    # ./flake.nix
    {
      description = "My C application.";
      inputs.flakelight.url = "github:nix-community/flakelight";
      outputs = { flakelight, ... }: 
        flakelight ./. {
          license = "AGPL-3.0-or-later";
          devShell.packages = pkgs: with pkgs; [ clang-tools coreutils ];
          formatters = {
            "*.h" = "clang-format -i";
            "*.c" = "clang-format -i";
          };
        };
    }
    
    # ./nix/package.nix
    {
      stdenv, defaultMeta 
    }: stdenv.mkDerivation {
      name = "hello-world";
      src = ./.;
      installPhase = ''
        runHook preInstall
        make DESTDIR=$out install
        runHook postInstall
      '';
      meta = defaultMeta;
    }
  3. Access module arguments in Flakelight configuration

    master

    If your Flakelight configuration requires access to module arguments (like lib or config), you can pass a function instead of a static attribute set. This function receives the module arguments as its parameters.

    {
      inputs.flakelight.url = "github:nix-community/flakelight";
      outputs = { flakelight, ... }: 
        flakelight ./. ({ lib, config, ... }: {
          # Your flake configuration here
        });
    }
  4. Use Flakelight to generate flake outputs

    master

    Flakelight allows you to define your flake outputs using a module-based configuration. You can use Flakelight by calling it directly in your outputs function, which implicitly invokes mkFlake.

    {
      inputs.flakelight.url = "github:nix-community/flakelight";
      outputs = { flakelight, ... }: 
        flakelight ./. {
          # Your flake configuration here
        };
    }
  5. Create a basic development shell with Flakelight

    master

    To create a devshell, use the flakelight function in your outputs. You can define the packages required for the shell using the devShell.packages option, which provides access to the pkgs set. By default, Flakelight generates devShell.${system}.default attributes for configured systems.

    {
      inputs.flakelight.url = "github:nix-community/flakelight";
      outputs = { flakelight, ... }: 
        flakelight ./. {
          devShell.packages = pkgs: [ pkgs.hello pkgs.coreutils ];
        };
    }
  6. Set up a Rust project using flakelight-rust

    master

    For Rust projects, you can use the flakelight-rust wrapper or import it as a module. The wrapper automatically extracts metadata from Cargo.toml and provides:

    • Per-system packages.${system}.default.
    • overlays.default for the package.
    • devShells.${system}.default containing rust-analyzer, cargo, clippy, rustc, and rustfmt, with RUST_SRC_PATH set.
    • checks.${system}.${check} for build, test, clippy, and formatting.
    • formatter.${system} for Rust files.
    # Option 1: Using the wrapper
    {
      inputs.flakelight-rust.url = "github:accelbread/flakelight-rust";
      outputs = { flakelight-rust, ... }: flakelight-rust ./. { };
    }
    
    # Option 2: Importing as a module
    {
      inputs = {
        flakelight.url = "github:nix-community/flakelight";
        flakelight-rust.url = "github:accelbread/flakelight-rust";
      };
      outputs = { flakelight, flakelight-rust, ... }: flakelight ./. {
        imports = [ flakelight-rust.flakelightModules.default ];
      };
    }
  7. Make your flake callable with the functor option

    master

    The functor option allows you to make your flake callable. If set to a function, that function is assigned to the __functor attribute of your flake outputs. Flakelight uses this so that calling your flakelight input invokes flakelight.lib.mkFlake.

    Example of a callable flake:

    {
      inputs.flakelight.url = "github:nix-community/flakelight";
      outputs = { flakelight, ... }: 
        flakelight ./. {
          outputs.testvalue = 5;
          functor = self: x: x + self.testvalue;
        }
    }
  8. Add packages to the flake

    master

    The package and packages options allow you to define packages that will be exported in packages.${system}, included in overlays.default, and checked via checks.${system}.

    • package: Sets packages.default.
    • packages: An attribute set of package definitions. If a function, it receives system as an argument.
    • pname: Use this to manually specify the attribute name in the package set to avoid automatic derivation from the derivation's pname.
    {
      inputs.flakelight.url = "github:nix-community/flakelight";
      outputs = { flakelight, ... }: 
        flakelight ./. {
          packages = { system, ... }: if (system == "x86_64-linux") then {
            pkg1 = { stdenv }: stdenv.mkDerivation { ... };
          } else { };
        };
    }
  9. Configure NixOS and Home Manager configurations

    master

    Use nixosConfigurations and homeConfigurations to define system and user configurations.

    NixOS: Each value should be a set of nixosSystem arguments, the result of calling nixosSystem, or a function returning one. NixOS modules gain access to a flake argument containing moduleArgs, inputs', and outputs'.

    Home Manager: Each value should be a set of homeManagerConfiguration arguments, the result of calling homeManagerConfiguration, or a function returning one. You must include system and set inputs.home-manager.

    {
      inputs = {
        flakelight.url = "github:nix-community/flakelight";
        home-manger.url = "github:nix-community/home-manager";
      };
      outputs = { flakelight, home-manager, ... }@inputs: 
        flakelight ./. ({ config, ... }: {
          inherit inputs;
          homeConfigurations.username = {
            system = "x86_64-linux";
            modules = [{ home.stateVersion = "24.05"; }];
          };
        });
    }
  10. Configure devShells

    master

    The devShell option configures the default devShells.${system}.default. It can be a configuration object, a package definition, or a function returning a configuration or derivation.

    Available devShell configuration options:

    • devShell.packages: List of packages to include.
    • devShell.inputsFrom: List of packages whose dependencies should be included.
    • devShell.shellHook: Bash code to run on initialization.
    • devShell.env: Attribute set of environment variables.
    • devShell.stdenv: The stdenv to use.
    • devShell.hardeningDisable: List of hardening options to disable (e.g., ["all"]).

    To configure a custom shell:

    {
      inputs.flakelight.url = "github:nix-community/flakelight";
      outputs = { flakelight, ... }: 
        flakelight ./. {
          devShell = pkgs: {
            inputsFrom = [ pkgs.emacs ];
            packages = [ pkgs.coreutils ];
            shellHook = "echo Welcome!";
            env.TEST_VAR = "test value";
            stdenv = pkgs.clangStdenv;
          };
        };
    }
  11. Configure supported systems

    master

    The systems option defines which per-system outputs are generated. If omitted, it defaults to x86_64-linux and aarch64-linux.

    To support specific additional systems:

    {
      inputs.flakelight.url = "github:nix-community/flakelight";
      outputs = { flakelight, ... }: 
        flakelight ./. { 
          systems = [ "x86_64-linux" "aarch64-linux" "i686-linux" "armv7l-linux" ]; 
        };
    }
  12. Configure flake inputs

    master

    The inputs option allows you to pass flake inputs to Flakelight modules. These are available as inputs and inputs' in the package set. By default, Flakelight initializes these from your flake.lock, but this excludes the self argument. To ensure full CLI functionality (including --override-input support), you should pass inputs explicitly.

    To pass all inputs (including a custom nixpkgs):

    {
      inputs = {
        flakelight.url = "github:nix-community/flakelight";
        nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
      };
      outputs = { flakelight, ... }@inputs:
        flakelight ./. {
          inherit inputs;
        };
    }