├── .editorconfig ├── .envrc ├── .github └── workflows │ ├── pr.yml │ └── update.yml ├── .gitignore ├── API_GUIDE.md ├── LICENSE ├── README.md ├── builtinModules ├── apps.nix ├── autoInputs.nix ├── builtinFormatters.nix ├── builtinOverlay.nix ├── bundlers.nix ├── checks.nix ├── core.nix ├── devShells.nix ├── editorconfig.nix ├── flakelightModules.nix ├── formatter.nix ├── functor.nix ├── homeConfigurations.nix ├── homeModules.nix ├── legacyPackages.nix ├── lib.nix ├── moduleArgs.nix ├── nixDir.nix ├── nixosConfigurations.nix ├── nixosModules.nix ├── overlays.nix ├── packages.nix ├── propagationModule.nix └── templates.nix ├── default.nix ├── flake.lock ├── flake.nix ├── misc ├── lock2inputs.nix └── nameMockedPkgs.nix ├── nix └── flakelightModules │ └── flakelightModule.nix ├── templates ├── basic │ ├── .envrc │ └── flake.nix └── default.nix └── tests ├── default.nix ├── editorconfig └── .editorconfig └── empty └── .keep /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | max_line_length = 80 11 | 12 | [{*.nix,flake.lock,*.yml}] 13 | indent_size = 2 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | indent_size = 2 18 | 19 | [COMMIT_EDITMSG] 20 | max_line_length = 72 21 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: PR checks 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | run-checks: 8 | name: Run checks 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: cachix/install-nix-action@master 13 | - run: nix flake check --all-systems 14 | run-tests: 15 | name: Run tests 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: cachix/install-nix-action@master 20 | - run: nix eval .#tests 21 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | name: Update flake inputs 2 | 3 | on: 4 | schedule: 5 | - cron: "0 12 ? * MON" 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | update-inputs: 13 | name: Update inputs 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: cachix/install-nix-action@master 18 | - name: Configure git 19 | run: | 20 | git config user.name "github-actions[bot]" 21 | git config user.email "41898282+github-actions[bot]@users.noreply.github.com" 22 | - run: nix flake update --commit-lock-file 23 | - run: nix flake check --all-systems 24 | - run: nix eval .#tests 25 | - run: git push 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.direnv 2 | result 3 | -------------------------------------------------------------------------------- /API_GUIDE.md: -------------------------------------------------------------------------------- 1 | # API Guide 2 | 3 | ## lib 4 | 5 | This section covers important functions available in Flakelight's lib attribute. 6 | 7 | ### mkFlake 8 | 9 | The outputs of a flake using Flakelight are created using the `mkFlake` 10 | function. When called directly, Flakelight invokes `mkFlake`, as follows: 11 | 12 | ```nix 13 | { 14 | inputs.flakelight.url = "github:nix-community/flakelight"; 15 | outputs = { flakelight, ... }: 16 | flakelight ./. { 17 | # Your flake configuration here 18 | }; 19 | } 20 | ``` 21 | 22 | To call `mkFlake` explicitly, you can do: 23 | 24 | ```nix 25 | { 26 | inputs.flakelight.url = "github:nix-community/flakelight"; 27 | outputs = { flakelight, ... }: 28 | flakelight.lib.mkFlake ./. { 29 | # Your flake configuration here 30 | }; 31 | } 32 | ``` 33 | 34 | `mkFlake` takes two parameters: the path to the flake's source and a Flakelight 35 | module. 36 | 37 | If you need access to module args, you can write it as bellow: 38 | 39 | ```nix 40 | { 41 | inputs.flakelight.url = "github:nix-community/flakelight"; 42 | outputs = { flakelight, ... }: 43 | flakelight ./. ({ lib, config, ... }: { 44 | # Your flake configuration here 45 | }); 46 | } 47 | ``` 48 | 49 | ## Module arguments 50 | 51 | The following module arguments are available: 52 | 53 | - `src`: The flake's source directory 54 | - `lib`: nixpkgs lib attribute 55 | - `config`: configured option values 56 | - `options`: available options 57 | - `flakelight`: flakelight lib attribute 58 | - `inputs`: value of inputs option 59 | - `outputs`: resulting output (i.e. final flake attributes) 60 | - `pkgsFor`: attrset mapping systems to the pkgs set for that system 61 | - `moduleArgs`: All of the available arguments (passed to auto-loaded files) 62 | 63 | ## Additional pkgs values 64 | 65 | Functions that take the package set as an argument, such as package definitions 66 | or `perSystem` values, have several additional values available in the package 67 | set. 68 | 69 | The `src`, `flakelight`, `inputs`, `outputs`, and `moduleArgs` attributes are 70 | the same as the above module arguments. 71 | 72 | `inputs'` and `outputs'` are transformed versions of `inputs` and `outputs` with 73 | system preselected. I.e., `inputs.emacs-overlay.packages.x86_64-linux.default` 74 | can be accessed as `inputs'.emacs-overlay.packages.default`. 75 | 76 | `defaultMeta` is a derivation meta attribute set generated from options. Modules 77 | setting `packages.default` should use this to allow meta attributes to be 78 | configured. 79 | 80 | ## Module options 81 | 82 | This section covers the options available to modules. 83 | 84 | ### inputs 85 | 86 | ``` 87 | Type: AttrsOf FlakeInput 88 | ``` 89 | 90 | The `inputs` option is an attrset of the flake inputs used by flakelight 91 | modules. These inputs get passed as the `inputs` module argument, and are used 92 | for `inputs` and `inputs'` in the package set. 93 | 94 | Default values are automatically initialized from your flake inputs by reading 95 | your `flake.lock`. Note that this does not include the `self` argument; for 96 | using `self`, use `inherit inputs` or otherwise define inputs. The default 97 | values also are not affected by nix command flags like `--override-input`, so 98 | inputs should be passed to enable full CLI functionality. 99 | 100 | Flakelight will add a recent `nixpkgs` input if your flake does not have one. 101 | Other flakelight modules may provide default inputs for their dependencies. 102 | 103 | To use a different nixpkgs from the built-in default (passing all inputs): 104 | 105 | ```nix 106 | { 107 | inputs = { 108 | flakelight.url = "github:nix-community/flakelight"; 109 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 110 | }; 111 | outputs = { flakelight, ... }@inputs: 112 | flakelight ./. { 113 | inherit inputs; 114 | }; 115 | } 116 | ``` 117 | 118 | Or to just pass just the nixpkgs input: 119 | 120 | ```nix 121 | { 122 | inputs = { 123 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 124 | flakelight.url = "github:nix-community/flakelight"; 125 | }; 126 | outputs = { flakelight, nixpkgs, ... }: 127 | flakelight ./. { 128 | inputs.nixpkgs = nixpkgs; 129 | }; 130 | } 131 | ``` 132 | 133 | ### systems 134 | 135 | ``` 136 | Type: [SystemStr] 137 | ``` 138 | 139 | The `systems` option sets which systems per-system outputs should be created 140 | for. 141 | 142 | If not set, the default is `x86_64-linux` and `aarch64-linux`. 143 | 144 | To also support `i686-linux` and `armv7l-linux`, you would configure `systems` 145 | as follows: 146 | 147 | ```nix 148 | { 149 | inputs.flakelight.url = "github:nix-community/flakelight"; 150 | outputs = { flakelight, ... }: 151 | flakelight ./. { 152 | systems = [ "x86_64-linux" "aarch64-linux" "i686-linux" "armv7l-linux" ]; 153 | }; 154 | } 155 | ``` 156 | 157 | To support all systems supported by flakes, set `systems` as follows: 158 | 159 | ```nix 160 | { 161 | inputs.flakelight.url = "github:nix-community/flakelight"; 162 | outputs = { flakelight, ... }: 163 | flakelight ./. ({ lib, ... }: { 164 | systems = lib.systems.flakeExposed; 165 | }); 166 | } 167 | ``` 168 | 169 | To support all Linux systems supported by flakes, set `systems` as follows: 170 | 171 | ```nix 172 | { 173 | inputs.flakelight.url = "github:nix-community/flakelight"; 174 | outputs = { flakelight, ... }: 175 | flakelight ./. ({ lib, ... }: { 176 | systems = lib.intersectLists 177 | lib.systems.doubles.linux 178 | lib.systems.flakeExposed; 179 | }); 180 | } 181 | ``` 182 | 183 | ### nixDir 184 | 185 | ``` 186 | Type: Path 187 | ``` 188 | 189 | The `nixDir` option is `./nix` by default and sets which directory to use to 190 | automatically load nix files to configure flake options from. 191 | 192 | For a given option, the following is checked in order: 193 | 194 | - If `${nixDir}/option.nix` exists, it is imported as the value 195 | - Else if `${nixDir}/option` is a directory with a `default.nix`, it is imported 196 | - Else if `${nixDir}/option` is a directory, it results in an attrset with an 197 | attr for each importable item in the directory for which the values are the 198 | corresponding items imported. An importable item is a file ending with `.nix` 199 | or a directory containing a `default.nix`. This is the same as the flakelight 200 | `importDir` function. 201 | 202 | To enable using a directory for an attrset that includes a `default` attribute, 203 | attr names can be escaped with an underscore. For example, 204 | `${nixDir}/nix/packages/_default.nix` will be loaded as `packages.default`. 205 | 206 | Aliases for options can be set with the `nixDirAliases` option. For example, by 207 | default `nixDirAliases.nixosConfigurations = [ "nixos" ];` is set which means 208 | "nixos" can be used instead of "nixosConfigurations" for loading the files as 209 | described above. 210 | 211 | All options except for `nixDir` and `_module` can be configured this way. 212 | 213 | To apply transformations on the output of an autoloaded directory, you can use 214 | `option/default.nix` and load the directory with `flakelight.importDir`. 215 | 216 | ### outputs 217 | 218 | ``` 219 | Type: AttrSet | (ModuleArgs -> AttrSet) 220 | ``` 221 | 222 | The `outputs` option allows you to directly configure flake outputs. This should 223 | be used for porting or for configuring output attrs not otherwise supported by 224 | Flakelight. 225 | 226 | The option value may be an attrset or a function that takes `moduleArgs` and 227 | returns and attrset. 228 | 229 | To add a `example.test` output to your flake you could do the following: 230 | 231 | ```nix 232 | { 233 | inputs.flakelight.url = "github:nix-community/flakelight"; 234 | outputs = { flakelight, ... }: 235 | flakelight ./. { 236 | outputs = { 237 | example.test = "hello"; 238 | }; 239 | }; 240 | } 241 | ``` 242 | 243 | With the above, `nix eval .#example.test` will output "hello". 244 | 245 | This can be used to configure any output, for example directly setting an 246 | overlay (though this can be configured with the `overlays` option): 247 | 248 | ```nix 249 | { 250 | inputs.flakelight.url = "github:nix-community/flakelight"; 251 | outputs = { flakelight, ... }: 252 | flakelight ./. { 253 | outputs.overlays.clang = final: prev: { stdenv = final.clangStdenv; }; 254 | }; 255 | } 256 | ``` 257 | 258 | ### perSystem 259 | 260 | ``` 261 | Type: Pkgs -> AttrSet 262 | ``` 263 | 264 | The `perSystem` option allows you to directly configure per-system flake 265 | outputs, and gives you access to packages. This should be used for porting or 266 | for configuring output attrs not otherwise supported by Flakelight. 267 | 268 | To add `example.${system}.test` outputs to your flake, you could do the 269 | following: 270 | 271 | ```nix 272 | { 273 | inputs.flakelight.url = "github:nix-community/flakelight"; 274 | outputs = { flakelight, ... }: 275 | flakelight ./. { 276 | perSystem = pkgs: { 277 | example.test = pkgs.writeShellScript "test" "echo hello"; 278 | }; 279 | }; 280 | } 281 | ``` 282 | 283 | The above, with default systems, will generate `example.x86_64-linux.test` and 284 | `example.aarch64-linux.test` attributes. 285 | 286 | ### nixpkgs.config 287 | 288 | ``` 289 | Type: AttrSet 290 | ``` 291 | 292 | This allows you to pass configuration options to the Nixpkgs instance used for 293 | building packages and calling perSystem. 294 | 295 | For example, to allow building broken or unsupported packages, you can set the 296 | option as follows: 297 | 298 | ```nix 299 | { 300 | inputs.flakelight.url = "github:nix-community/flakelight"; 301 | outputs = { flakelight, ... }: 302 | flakelight ./. { 303 | nixpkgs.config = { allowBroken = true; allowUnsupportedSystem = true; }; 304 | }; 305 | } 306 | ``` 307 | 308 | ### withOverlays 309 | 310 | ``` 311 | Type: [Overlay] | Overlay 312 | ``` 313 | 314 | This allows you to apply overlays to the Nixpkgs instance used for building 315 | packages and calling perSystem. 316 | 317 | It can be set to either a list of overlays or a single overlay. 318 | 319 | For example, to apply the Emacs overlay and change the Zig version, you can set 320 | the option as follows: 321 | 322 | ```nix 323 | { 324 | inputs = { 325 | flakelight.url = "github:nix-community/flakelight"; 326 | emacs-overlay.url = "github:nix-community/emacs-overlay"; 327 | }; 328 | outputs = { flakelight, emacs-overlay, ... }: 329 | flakelight ./. { 330 | withOverlays = [ 331 | emacs-overlay.overlays.default 332 | (final: prev: { zig = final.zig_0_9; }) 333 | ]; 334 | }; 335 | } 336 | ``` 337 | 338 | You can use the values from the overlays with other options: 339 | 340 | ```nix 341 | { 342 | inputs.flakelight.url = "github:nix-community/flakelight"; 343 | outputs = { flakelight, ... }: 344 | flakelight ./. { 345 | withOverlays = final: prev: { testValue = "hi"; }; 346 | 347 | package = { writeShellScript, testValue }: 348 | writeShellScript "test" "echo ${testValue}"; 349 | }; 350 | } 351 | ``` 352 | 353 | ### packages 354 | 355 | ``` 356 | Types: 357 | package: PackageDef 358 | packages: (AttrsOf PackageDef) | (ModuleArgs -> (AttrsOf PackageDef)) 359 | pname: Str 360 | ``` 361 | 362 | The `package` and `packages` options allow you to add packages. These are 363 | exported in the `packages.${system}` outputs, are included in 364 | `overlays.default`, and have build checks in `checks.${system}`. 365 | 366 | `package` can be set to a package definition, and will set `packages.default`. 367 | 368 | `packages` can be set to attrs of package definitions. If it is a function, it 369 | will additionally get a `system` arg in addition to module args, to allow 370 | conditionally including package definitions depending on the system. 371 | 372 | By default, the `packages.default` package's name (its attribute name in the 373 | package set and overlay) is automatically determined from the derivation's 374 | `pname`. In order to use a different attribute name from the package pname, to 375 | set it in cases where it cannot be automatically determined, or to speed up 376 | uncached evaluation, the flakelight `pname` option can be set. 377 | 378 | To set the default package, you can set the options as follows: 379 | 380 | ```nix 381 | { 382 | inputs.flakelight.url = "github:nix-community/flakelight"; 383 | outputs = { flakelight, ... }: 384 | flakelight ./. { 385 | package = { stdenv }: 386 | stdenv.mkDerivation { 387 | pname = "pkg1"; 388 | version = "0.0.1"; 389 | src = ./.; 390 | installPhase = "make DESTDIR=$out install"; 391 | }; 392 | }; 393 | } 394 | ``` 395 | 396 | The above will export `packages.${system}.default` attributes, add `pkg1` to 397 | `overlays.default`, and export `checks.${system}.packages-default`. 398 | 399 | You can also instead just directly set `packages.default`. 400 | 401 | To set multiple packages, you can set the options as follows: 402 | 403 | ```nix 404 | { 405 | inputs.flakelight.url = "github:nix-community/flakelight"; 406 | outputs = { flakelight, ... }: 407 | flakelight ./. { 408 | packages = { 409 | default = { stdenv }: 410 | stdenv.mkDerivation { 411 | name = "pkg1"; 412 | src = ./.; 413 | installPhase = "make DESTDIR=$out install"; 414 | }; 415 | pkg2 = { stdenv, pkg1, pkg3 }: 416 | stdenv.mkDerivation { 417 | name = "hello-world"; 418 | src = ./pkg2; 419 | nativeBuildInputs = [ pkg1 pkg3 ]; 420 | installPhase = "make DESTDIR=$out install"; 421 | }; 422 | pkg3 = { stdenv }: 423 | stdenv.mkDerivation { 424 | name = "hello-world"; 425 | src = ./pkg3; 426 | installPhase = "make DESTDIR=$out install"; 427 | }; 428 | }; 429 | }; 430 | } 431 | ``` 432 | 433 | The above will export `packages.${system}.default`, `packages.${system}.pkg2`, 434 | `packages.${system}.pkg3` attributes, add `pkg1`, `pkg2`, and `pkg3` to 435 | `overlays.default`, and export corresponding build checks. 436 | 437 | To use the first example, but manually specify the package name: 438 | 439 | ```nix 440 | { 441 | inputs.flakelight.url = "github:nix-community/flakelight"; 442 | outputs = { flakelight, ... }: 443 | flakelight ./. { 444 | pname = "pkgs-attribute-name"; 445 | package = { stdenv }: 446 | stdenv.mkDerivation { 447 | pname = "package-name"; 448 | version = "0.0.1"; 449 | src = ./.; 450 | installPhase = "make DESTDIR=$out install"; 451 | }; 452 | }; 453 | } 454 | ``` 455 | 456 | To add a package only for certain systems, you can take `system` as an arg as 457 | follows: 458 | 459 | ```nix 460 | { 461 | inputs.flakelight.url = "github:nix-community/flakelight"; 462 | outputs = { flakelight, ... }: 463 | flakelight ./. { 464 | packages = { system, ... }: if (system == "x86_64-linux") then { 465 | pkg1 = { stdenv }: 466 | stdenv.mkDerivation { 467 | name = "pkg1"; 468 | src = ./.; 469 | installPhase = "make DESTDIR=$out install"; 470 | }; 471 | } else { }; 472 | }; 473 | } 474 | ``` 475 | 476 | ### devShell 477 | 478 | ``` 479 | Type: 480 | devShell: Cfg | (Pkgs -> Cfg) | PackageDef | Derivation | (Pkgs -> Derivation) 481 | Cfg.packages: [Derivation] | (Pkgs -> [Derivation]) 482 | Cfg.inputsFrom: [Derivation] | (Pkgs -> [Derivation]) 483 | Cfg.shellHook: Str | (Pkgs -> Str) 484 | Cfg.env: (AttrsOf Str) | (Pkgs -> (AttrsOf Str)) 485 | Cfg.stdenv: Stdenv | (Pkgs -> Stdenv) 486 | ``` 487 | 488 | The devshell options allow you to configure `devShells.${system}.default`. It is 489 | split up into options in order to enable multiple modules to contribute to its 490 | configuration. 491 | 492 | `devShell` can alternatively be set to a package definition or derivation, which 493 | is then used as the default shell, overriding other options. 494 | 495 | `devShell` can also be set to a function that takes the package set and returns 496 | an attrSet of the devShell configuration options or a derivation. 497 | 498 | The options available are as follows: 499 | 500 | `devShell.packages` is a list of packages to add to the shell. It can optionally 501 | be a function taking the package set and returning such a list. 502 | 503 | `devShell.inputsFrom` is a list of packages whose deps should be in the shell. 504 | It can optionally be a function taking the package set and returning such a 505 | list. 506 | 507 | `devShell.shellHook` is a string that provides bash code to run in shell 508 | initialization. It can optionally be a function taking the package set and 509 | returning such a string. 510 | 511 | `devShell.hardeningDisable` is a list of hardening options to disable. Setting 512 | it to `["all"]` disables all Nix hardening. 513 | 514 | `devShell.env` is for setting environment variables in the shell. It is an 515 | attribute set mapping variables to values. It can optionally be a function 516 | taking the package set and returning such an attribute set. 517 | 518 | `devShell.stdenv` is the stdenv package used for the shell. It can optionally be 519 | a function takeing the package set and returning the stdenv to use. 520 | 521 | For example, these can be configured as follows: 522 | 523 | ```nix 524 | { 525 | inputs.flakelight.url = "github:nix-community/flakelight"; 526 | outputs = { flakelight, ... }: 527 | flakelight ./. { 528 | devShell = pkgs: { 529 | # Include build deps of emacs 530 | inputsFrom = [ pkgs.emacs ]; 531 | # Add coreutils to the shell 532 | packages = [ pkgs.coreutils ]; 533 | # Add shell hook. Can be a function if you need packages 534 | shellHook = '' 535 | echo Welcome to example shell! 536 | ''; 537 | # Set an environment var. `env` can be an be a function 538 | env.TEST_VAR = "test value"; 539 | stdenv = pkgs.clangStdenv; 540 | }; 541 | }; 542 | } 543 | ``` 544 | 545 | The above exports `devShells.${system}.default` outputs. 546 | 547 | To add the build inputs of one of your packages, you can do as follows: 548 | 549 | ```nix 550 | { 551 | inputs.flakelight.url = "github:nix-community/flakelight"; 552 | outputs = { flakelight, ... }: 553 | flakelight ./. { 554 | package = { stdenv }: 555 | stdenv.mkDerivation { 556 | pname = "pkg1"; 557 | version = "0.0.1"; 558 | src = ./.; 559 | installPhase = "make DESTDIR=$out install"; 560 | }; 561 | devShell = { 562 | inputsFrom = pkgs: [ pkgs.pkg1 ]; 563 | }; 564 | }; 565 | } 566 | ``` 567 | 568 | To override the devShell, you can use a package definition as such: 569 | 570 | ```nix 571 | { 572 | inputs.flakelight.url = "github:nix-community/flakelight"; 573 | outputs = { flakelight, ... }: 574 | flakelight ./. { 575 | devShell = { mkShell, hello }: mkShell { 576 | packages = [ hello ]; 577 | }; 578 | }; 579 | } 580 | ``` 581 | 582 | ### devShells 583 | 584 | ``` 585 | Type: 586 | devShells: (AttrsOf (PackageDef | Cfg | (Pkgs -> Cfg)) | 587 | (ModuleArgs -> (AttrsOf (PackageDef | Cfg | (Pkgs -> Cfg)))) 588 | Cfg.packages: [Derivation] | (Pkgs -> [Derivation]) 589 | Cfg.inputsFrom: [Derivation] | (Pkgs -> [Derivation]) 590 | Cfg.shellHook: Str | (Pkgs -> Str) 591 | Cfg.env: (AttrsOf Str) | (Pkgs -> (AttrsOf Str)) 592 | Cfg.stdenv: Stdenv | (Pkgs -> Stdenv) 593 | ``` 594 | 595 | The `devShells` option allows you to set additional `devShell` outputs. The 596 | values each shell can be set to are the same as described above for the 597 | `devShell` option. 598 | 599 | For example, using the configuration options: 600 | 601 | ```nix 602 | { 603 | inputs.flakelight.url = "github:nix-community/flakelight"; 604 | outputs = { flakelight, ... }: 605 | flakelight ./. { 606 | devShells.testing = { 607 | packages = pkgs: [ pkgs.coreutils ]; 608 | env.TEST_VAR = "in testing shell"; 609 | }; 610 | }; 611 | } 612 | ``` 613 | 614 | For example, using a package definition: 615 | 616 | ```nix 617 | { 618 | inputs.flakelight.url = "github:nix-community/flakelight"; 619 | outputs = { flakelight, ... }: 620 | flakelight ./. { 621 | devShells.testing = { mkShell, coreutils }: 622 | mkShell { 623 | packages = [ coreutils ]; 624 | env.TEST_VAR = "in testing shell"; 625 | }; 626 | }; 627 | } 628 | ``` 629 | 630 | The above flakes export `devShells.${system}.testing` outputs. 631 | 632 | ### overlays 633 | 634 | ``` 635 | Types: 636 | overlay: Overlay 637 | overlays: (AttrsOf Overlay) | (ModuleArgs -> (AttrsOf Overlay) 638 | ``` 639 | 640 | The `overlay` and `overlays` options allow you to configure `overlays` outputs. 641 | 642 | Multiple provided overlays for an output are merged. 643 | 644 | The `overlay` option adds the overlay to `overlays.default`. 645 | 646 | The `overlays` option allows you to add overlays to `overlays` outputs. 647 | 648 | For example, to add an overlay to `overlays.default`, do the following: 649 | 650 | ```nix 651 | { 652 | inputs.flakelight.url = "github:nix-community/flakelight"; 653 | outputs = { flakelight, ... }: 654 | flakelight ./. { 655 | overlay = final: prev: { testValue = "hello"; }; 656 | }; 657 | } 658 | ``` 659 | 660 | The above results in `overlays.default` output containing testValue. 661 | 662 | To configure other overlays: 663 | 664 | ```nix 665 | { 666 | inputs.flakelight.url = "github:nix-community/flakelight"; 667 | outputs = { flakelight, ... }: 668 | flakelight ./. { 669 | overlays.cool = final: prev: { testValue = "cool"; }; 670 | }; 671 | } 672 | ``` 673 | 674 | The above results in a `overlays.cool` output. 675 | 676 | ### checks 677 | 678 | ``` 679 | Types: 680 | checks: (AttrsOf Check) | (Pkgs -> (AttrsOf Check)) 681 | Check: Str | (Pkgs -> Str) | Derivation | (Pkgs -> Derivation) 682 | ``` 683 | 684 | The `checks` option allows you to add checks for `checks.${system}` attributes. 685 | 686 | It can be set to an attribute set of checks, which can be functions, 687 | derivations, or strings. 688 | 689 | If a check is a derivation, it will be used as is. 690 | 691 | If a check is a string, it will be included in a bash script that runs it in a 692 | copy of the source directory, and succeeds if the no command in the string 693 | errored. 694 | 695 | If a check is a function, it will be passed packages, and should return one of 696 | the above. 697 | 698 | For example: 699 | 700 | ```nix 701 | { 702 | inputs.flakelight.url = "github:nix-community/flakelight"; 703 | outputs = { flakelight, ... }: 704 | flakelight ./. { 705 | checks = { 706 | # Check that succeeds if the source contains the string "hi" 707 | hi = { rg, ... }: "${rg}/bin/rg hi"; 708 | # Check that emacs builds 709 | emacs = pkgs: pkgs.emacs; 710 | }; 711 | }; 712 | } 713 | ``` 714 | 715 | ### apps 716 | 717 | ``` 718 | Types: 719 | app: App' 720 | apps: (AttrsOf App') | (Pkgs -> (AttrsOf App')) 721 | App': Str | (Pkgs -> Str) | App | (Pkgs -> App) 722 | ``` 723 | 724 | The `app` and `apps` options allow you to set `apps.${system}` outputs. 725 | 726 | `apps` is an attribute set of apps or a function that takes packages and returns 727 | an attribute set of apps. If the app value is a function, it is passed packages. 728 | If the app value or function result is a string, it is converted to an app. 729 | 730 | `app` sets `apps.default`. 731 | 732 | For example: 733 | 734 | ```nix 735 | { 736 | inputs.flakelight.url = "github:nix-community/flakelight"; 737 | outputs = { flakelight, ... }: 738 | flakelight ./. { 739 | apps = { 740 | emacs = pkgs: "${pkgs.emacs}/bin/emacs"; 741 | bash = pkgs: { type = "app"; program = "${pkgs.bash}/bin/bash"; }; 742 | }; 743 | }; 744 | } 745 | ``` 746 | 747 | Alternatively, the above can be written as: 748 | 749 | ```nix 750 | { 751 | inputs.flakelight.url = "github:nix-community/flakelight"; 752 | outputs = { flakelight, ... }: 753 | flakelight ./. { 754 | apps = { emacs, bash, ... }: { 755 | emacs = "${emacs}/bin/emacs"; 756 | bash = { type = "app"; program = "${bash}/bin/bash"; }; 757 | }; 758 | }; 759 | } 760 | ``` 761 | 762 | ### templates 763 | 764 | ``` 765 | Types: 766 | template: Template | (ModuleArgs -> Template) 767 | templates: (AttrsOf (Template | (ModuleArgs -> Template))) | 768 | (ModuleArgs -> (AttrsOf (Template | (ModuleArgs -> Template)))) 769 | ``` 770 | 771 | The `template` and `templates` options allow you to set `templates` outputs. 772 | 773 | `templates` is an attribute set to template values. 774 | 775 | `template` sets `templates.default`. 776 | 777 | For example: 778 | 779 | ```nix 780 | { 781 | inputs.flakelight.url = "github:nix-community/flakelight"; 782 | outputs = { flakelight, ... }: 783 | flakelight ./. { 784 | templates.test-template = { 785 | path = ./test; 786 | description = "test template"; 787 | }; 788 | }; 789 | } 790 | ``` 791 | 792 | ### legacyPackages 793 | 794 | ``` 795 | Type: Pkgs -> Pkgs 796 | ``` 797 | 798 | The `legacyPackages` option allows you to configure the flake's `legacyPackages` 799 | output. It can be set to a function that takes the package set and returns the 800 | package set to be used as the corresponding system's legacyPackages output. 801 | 802 | For example: 803 | 804 | ```nix 805 | { 806 | inputs = { 807 | flakelight.url = "github:nix-community/flakelight"; 808 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 809 | }; 810 | outputs = { flakelight, nixpkgs, ... }: 811 | flakelight ./. { 812 | legacyPackages = pkgs: nixpkgs.legacyPackages.${pkgs.system}; 813 | }; 814 | } 815 | ``` 816 | 817 | To export the package set used for calling package definitions and other options 818 | that take functions passed the package set, you can do the following: 819 | 820 | ```nix 821 | { 822 | inputs.flakelight.url = "github:nix-community/flakelight"; 823 | outputs = { flakelight, ... }: 824 | flakelight ./. { 825 | legacyPackages = pkgs: pkgs; 826 | }; 827 | } 828 | ``` 829 | 830 | ### formatter 831 | 832 | ``` 833 | Type: Pkgs -> Derivation 834 | ``` 835 | 836 | The `formatter` option allows you to set `formatter.${system}` outputs. It can 837 | be set to a function that takes packages and returns the package to use. This 838 | overrides the `formatters` functionality described below though, so for 839 | configuring formatters for a file type, you likely want to use `formatters` 840 | instead. 841 | 842 | For example, to use a custom formatting command: 843 | 844 | ```nix 845 | { 846 | inputs.flakelight.url = "github:nix-community/flakelight"; 847 | outputs = { flakelight, ... }: 848 | flakelight ./. { 849 | formatter = pkgs: pkgs.writeShellScriptBin "format-script" '' 850 | # Perform formatting (`nix fmt` calls the script with `.` as arg) 851 | ''; 852 | }; 853 | } 854 | ``` 855 | 856 | ### formatters 857 | 858 | ``` 859 | Type: (AttrsOf Str) | (Pkgs -> (AttrsOf Str)) 860 | ``` 861 | 862 | The `formatters` option allows you to configure formatting tools that will be 863 | used by `nix fmt`. If formatters are set, Flakelight will export 864 | `formatter.${system}` outputs which apply all the configured formatters. 865 | 866 | By default, `nix` files are formatted with `nixpkgs-fmt` and `md`, `json`, and 867 | `yml` files are formatted with `prettier`. 868 | 869 | To disable default formatters, set the `flakelight.builtinFormatters` option to 870 | false. 871 | 872 | You can set `formatters` to an attribute set, for which the keys are a file name 873 | pattern and the value is the corresponding formatting command. `formatters` can 874 | optionally be a function that takes packages and returns the above. 875 | 876 | Formatting tools should be added to `devShell.packages`; this enables easier use 877 | as described below, as well as allowing flake users to use the tools directly 878 | when in the devShell. 879 | 880 | Formatters can be set to a plain string like `"zig fmt"` or a full path like 881 | `"${pkgs.zig}/bin/zig fmt"`. Formatters set as plain strings have access to all 882 | packages in `devShell.packages`. 883 | 884 | If building the formatter is slow due to building devShell packages, use full 885 | paths for the formatters; the devShell packages are only included if a 886 | formatting option is set to a plain string. 887 | 888 | ```nix 889 | { 890 | inputs.flakelight.url = "github:nix-community/flakelight"; 891 | outputs = { flakelight, ... }: 892 | flakelight ./. { 893 | devShell.packages = pkgs: [ pkgs.rustfmt pkgs.zig ]; 894 | formatters = { 895 | "*.rs" = "rustfmt"; 896 | "*.zig" = "zig fmt"; 897 | }; 898 | }; 899 | } 900 | ``` 901 | 902 | ### bundlers 903 | 904 | ``` 905 | Types: 906 | bundler: Bundler | (Pkgs -> Bundler) 907 | bundlers: (AttrsOf (Bundler | (Pkgs -> Bundler))) | 908 | (ModuleArgs -> (AttrsOf (Bundler | (Pkgs -> Bundler)))) 909 | ``` 910 | 911 | The `bundler` and `bundlers` options allow you to set `bundlers.${system}` 912 | outputs. 913 | 914 | Each bundler value can be either a bundler function or a function that takes the 915 | package set and returns a bundler function. 916 | 917 | `bundlers` is an attribute set of bundler values or a function that takes 918 | packages and returns an attribute set of bundler values. 919 | 920 | `bundler` sets `bundlers.default`. 921 | 922 | For example, a bundler that returns the passed package: 923 | 924 | ```nix 925 | { 926 | inputs.flakelight.url = "github:nix-community/flakelight"; 927 | outputs = { flakelight, ... }: 928 | flakelight ./. { 929 | bundler = x: x; 930 | }; 931 | } 932 | ``` 933 | 934 | As another example, a bundler that always returns `hello`: 935 | 936 | ```nix 937 | { 938 | inputs.flakelight.url = "github:nix-community/flakelight"; 939 | outputs = { flakelight, ... }: 940 | flakelight ./. { 941 | bundlers = { hello, ... }: { 942 | hello = x: hello; 943 | }; 944 | }; 945 | } 946 | ``` 947 | 948 | To write the above using autoloads, can use the following: 949 | 950 | ```nix 951 | # nix/bundlers/hello.nix 952 | { hello, ... }: x: hello; 953 | ``` 954 | 955 | ### nixosConfigurations 956 | 957 | ``` 958 | Type: (AttrsOf (NixOSArgs | NixOSConfig | 959 | (ModuleArgs -> (NixOSArgs | NixOSConfig)))) | 960 | (ModuleArgs -> (AttrsOf (NixOSArgs | NixOSConfig | 961 | (ModuleArgs -> (NixOSArgs | NixOSConfig))))) 962 | ``` 963 | 964 | The `nixosConfigurations` attribute lets you set outputs for NixOS systems and 965 | home-manager users. 966 | 967 | It should be set to an attribute set. Each value should be a set of 968 | `nixpkgs.lib.nixosSystem` args, the result of calling `nixpkgs.lib.nixosSystem`, 969 | or a function that takes `moduleArgs` and returns one of the prior. 970 | 971 | When using a set of `nixpkgs.lib.nixosSystem` args, NixOS modules will have 972 | access to a `flake` module arg equivalent to `moduleArgs` plus `inputs'` and 973 | `outputs'`. Flakelight's pkgs attributes, `withOverlays`, and `packages` will 974 | also be available in the NixOS instance's pkgs, and Flakelight's 975 | `nixpkgs.config` will apply to it as well. 976 | 977 | When using the result of calling `nixpkgs.lib.nixosSystem`, the 978 | `config.propagationModule` value can be used as a NixOS module to gain the above 979 | benefits. 980 | 981 | For example: 982 | 983 | ```nix 984 | { 985 | inputs.flakelight.url = "github:nix-community/flakelight"; 986 | outputs = { flakelight, ... }: 987 | flakelight ./. ({ lib, config, ... }: { 988 | nixosConfigurations.test-system = { 989 | system = "x86_64-linux"; 990 | modules = [{ system.stateVersion = "24.05"; }]; 991 | }; 992 | }); 993 | } 994 | ``` 995 | 996 | ### homeConfigurations 997 | 998 | ``` 999 | Type: (AttrsOf (HomeArgs | HomeConfig | 1000 | (ModuleArgs -> (HomeArgs | HomeConfig)))) | 1001 | (ModuleArgs -> (AttrsOf (HomeArgs | HomeConfig | 1002 | (ModuleArgs -> (HomeArgs | HomeConfig))))) 1003 | ``` 1004 | 1005 | The `homeConfigurations` attribute lets you set outputs for NixOS systems and 1006 | home-manager users. 1007 | 1008 | It should be set to an attribute set. Each value should be a set of 1009 | `home-manager.lib.homeManagerConfiguration` args, the result of calling 1010 | `home-manager.lib.homeManagerConfiguration`, or a function that takes 1011 | `moduleArgs` and returns one of the prior. 1012 | 1013 | When using a set of `homeManagerConfiguration` args, it is required to include 1014 | `system` (`pkgs` does not need to be included), and `inputs.home-manager` must 1015 | be set. home-manager modules will have access to a `flake` module arg equivalent 1016 | to `moduleArgs` plus `inputs'` and `outputs'`. Flakelight's pkgs attributes, 1017 | `withOverlays`, and `packages` will also be available in the home-manager 1018 | instance's pkgs. 1019 | 1020 | When using the result of calling `homeManagerConfiguration`, the 1021 | `config.propagationModule` value can be used as a home-manager module to gain 1022 | the above benefits. 1023 | 1024 | For example: 1025 | 1026 | ```nix 1027 | { 1028 | inputs = { 1029 | flakelight.url = "github:nix-community/flakelight"; 1030 | home-manger.url = "github:nix-community/home-manager"; 1031 | }; 1032 | outputs = { flakelight, home-manager, ... }@inputs: 1033 | flakelight ./. ({ config, ... }: { 1034 | inherit inputs; 1035 | homeConfigurations.username = { 1036 | system = "x86_64-linux"; 1037 | modules = [{ home.stateVersion = "24.05"; }]; 1038 | }; 1039 | }); 1040 | } 1041 | ``` 1042 | 1043 | ### nixosModules, homeModules, and flakelightModules 1044 | 1045 | ``` 1046 | Types: 1047 | nixosModule: Module 1048 | nixosModules: (AttrsOf Module) | (ModuleArgs -> (AttrsOf Module)) 1049 | homeModule: Module 1050 | homeModules: (AttrsOf Module) | (ModuleArgs -> (AttrsOf Module)) 1051 | flakelightModule: Module 1052 | flakelightModules: (AttrsOf Module) | (ModuleArgs -> (AttrsOf Module)) 1053 | ``` 1054 | 1055 | The `nixosModules`, `homeModules`, and `flakelightModules` options allow you to 1056 | configure the corresponding outputs. 1057 | 1058 | The `nixosModule`, `homeModule`, and `flakelightModule` options set the 1059 | `default` attribute of the corresponding above option. 1060 | 1061 | For example: 1062 | 1063 | ```nix 1064 | { 1065 | inputs.flakelight.url = "github:nix-community/flakelight"; 1066 | outputs = { flakelight, ... }: 1067 | flakelight ./. ({ lib, ... }: { 1068 | nixosModule = { system, lib, pkgs, ... }: { 1069 | # nixos module configuration 1070 | }; 1071 | }); 1072 | } 1073 | ``` 1074 | 1075 | These can be paths, which is preferred as it results in better debug output: 1076 | 1077 | ```nix 1078 | { 1079 | inputs.flakelight.url = "github:nix-community/flakelight"; 1080 | outputs = { flakelight, ... }: 1081 | flakelight ./. ({ lib, ... }: { 1082 | nixosModule = ./module.nix; 1083 | homeModules = { 1084 | default = ./home.nix; 1085 | emacs = ./emacs.nix; 1086 | } 1087 | }); 1088 | } 1089 | ``` 1090 | 1091 | ### lib 1092 | 1093 | ``` 1094 | Type: AttrSet | (ModuleArgs -> AttrSet) 1095 | ``` 1096 | 1097 | The `lib` option allows you to configure the flake's `lib` output. 1098 | 1099 | For example: 1100 | 1101 | ```nix 1102 | { 1103 | inputs.flakelight.url = "github:nix-community/flakelight"; 1104 | outputs = { flakelight, ... }: 1105 | flakelight ./. { 1106 | lib = { 1107 | addFive = x: x + 5; 1108 | addFour = x: x + 4; 1109 | }; 1110 | }; 1111 | } 1112 | ``` 1113 | 1114 | ### functor 1115 | 1116 | ``` 1117 | Type: Outputs -> Any -> Any 1118 | ``` 1119 | 1120 | The `functor` option allows you to make your flake callable. 1121 | 1122 | If it is set to a function, that function will be set as the `__functor` 1123 | attribute of your flake outputs. 1124 | 1125 | Flakelight uses it so that calling your `flakelight` input calls 1126 | `flakelight.lib.mkFlake`. 1127 | 1128 | As an example: 1129 | 1130 | ```nix 1131 | { 1132 | inputs.flakelight.url = "github:nix-community/flakelight"; 1133 | outputs = { flakelight, ... }: 1134 | flakelight ./. { 1135 | outputs.testvalue = 5; 1136 | functor = self: x: x + self.testvalue; 1137 | } 1138 | } 1139 | ``` 1140 | 1141 | With the above flake, another flake that has imports it with the name `addFive` 1142 | would be able to call `addFive 4` to get 9. 1143 | 1144 | ### meta 1145 | 1146 | ``` 1147 | Types: 1148 | description: Str 1149 | license: Str | [Str] 1150 | ``` 1151 | 1152 | The following options are available for configuring the meta attributes of the 1153 | default package for supported modules (such as flakelight-rust or 1154 | flakelight-zig) or for use in your own packages through the `defaultMeta` pkgs 1155 | value. 1156 | 1157 | `description` allows setting the package description. By default it uses the 1158 | flake description, if found. 1159 | 1160 | `license` lets you set the license or license. It may be a single string or list 1161 | of strings. These strings may be Spdx license identifiers or Nixpkgs license 1162 | attribute names. 1163 | 1164 | ### flakelight 1165 | 1166 | ``` 1167 | Types: 1168 | flakelight.editorconfig: Bool 1169 | flakelight.builtinFormatters: Bool 1170 | ``` 1171 | 1172 | This option has options for configuring Flakelight's defaults. 1173 | 1174 | `flakelight.editorconfig` can be set to false to disable the editorconfig check 1175 | that is added if editorconfig configuration is detected. 1176 | 1177 | `flakelight.builtinFormatters` can be set to false to disable the default 1178 | formatting configuration. 1179 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2023 Archit Gupta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the “Software”), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flakelight 2 | 3 | A modular Nix flake framework for simplifying flake definitions. 4 | 5 | ## Goals 6 | 7 | - Minimize boilerplate needed for flakes 8 | - Support straightforward configuration of all vanilla flake attributes 9 | - Allow sharing common configuration using modules 10 | - What can be done automatically, should be 11 | - Provide good defaults, but let them be changed/disabled 12 | 13 | ## Features 14 | 15 | - Handles generating per-system attributes 16 | - Extensible using the module system 17 | - Given package definitions, generates package and overlay outputs 18 | - Automatically import attributes from nix files in a directory (default 19 | `./nix`) 20 | - Builds formatter outputs that can format multiple file types 21 | - Provides outputs/perSystem options for easy migration 22 | 23 | ## Documentation 24 | 25 | See the [API docs](./API_GUIDE.md) for available options and example usage. 26 | 27 | ## Additional modules 28 | 29 | The following modules are also available: 30 | 31 | - [flakelight-rust][] for Rust projects 32 | - [flakelight-zig][] for Zig projects 33 | - [flakelight-elisp][] for flakes providing Emacs lisp package(s) 34 | - [flakelight-darwin][] for nix-darwin configs 35 | 36 | [flakelight-rust]: https://github.com/accelbread/flakelight-rust 37 | [flakelight-zig]: https://github.com/accelbread/flakelight-zig 38 | [flakelight-elisp]: https://github.com/accelbread/flakelight-elisp 39 | [flakelight-darwin]: https://github.com/cmacrae/flakelight-darwin 40 | 41 | ## Contact 42 | 43 | Feel free to ask for help or other questions in the issues/discussions, or reach 44 | out on Matrix at [#flakelight:nixos.org][matrix-flakelight]. 45 | 46 | [matrix-flakelight]: https://matrix.to/#/#flakelight:nixos.org 47 | 48 | ## Examples 49 | 50 | ### Shell 51 | 52 | The following is an example flake.nix for a devshell, using the passed in 53 | nixpkgs. It outputs `devShell.${system}.default` attributes for each configured 54 | system. `systems` can be set to change configured systems from the default. 55 | 56 | ```nix 57 | { 58 | inputs.flakelight.url = "github:nix-community/flakelight"; 59 | outputs = { flakelight, ... }: 60 | flakelight ./. { 61 | devShell.packages = pkgs: [ pkgs.hello pkgs.coreutils ]; 62 | }; 63 | } 64 | ``` 65 | 66 | With this flake, calling `nix develop` will make `hello` and `coreutils` 67 | available. 68 | 69 | To use a different nixpkgs, you can instead use: 70 | 71 | ```nix 72 | { 73 | inputs = { 74 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 75 | flakelight.url = "github:nix-community/flakelight"; 76 | }; 77 | outputs = { flakelight, ... }@inputs: 78 | flakelight ./. { 79 | inherit inputs; 80 | devShell.packages = pkgs: [ pkgs.hello pkgs.coreutils ]; 81 | }; 82 | } 83 | ``` 84 | 85 | ### Rust package 86 | 87 | The following is an example flake for a Rust project using `flakelight-rust`, 88 | invoked by using `flakelight-rust`'s wrapper. Package metadata is taken from the 89 | project's `Cargo.toml`. 90 | 91 | ```nix 92 | { 93 | inputs.flakelight-rust.url = "github:accelbread/flakelight-rust"; 94 | outputs = { flakelight-rust, ... }: flakelight-rust ./. { }; 95 | } 96 | ``` 97 | 98 | The above flake exports the following: 99 | 100 | - Per-system attributes for default systems (`x86_64-linux` and `aarch64-linux`) 101 | - `packages.${system}.default` attributes for each system 102 | - `overlays.default` providing an overlay with the package (built with the 103 | applied pkg set's dependencies) 104 | - `devShells.${system}.default` that provides `rust-analyzer`, `cargo`, 105 | `clippy`, `rustc`, and `rustfmt` as well as sets `RUST_SRC_PATH` 106 | - `checks.${system}.${check}` attributes for build, test, clippy, and formatting 107 | checks 108 | - `formatter.${system}` with additional support for formatting Rust files 109 | 110 | Equivalently, you can just import the `flakelight-rust` module as follows: 111 | 112 | ```nix 113 | { 114 | inputs = { 115 | flakelight.url = "github:nix-community/flakelight"; 116 | flakelight-rust.url = "github:accelbread/flakelight-rust"; 117 | }; 118 | outputs = { flakelight, flakelight-rust, ... }: flakelight ./. { 119 | imports = [ flakelight-rust.flakelightModules.default ]; 120 | }; 121 | } 122 | ``` 123 | 124 | See [flakelight-rust.nix][flakelight-rust] to see how you could configure it 125 | without the module. 126 | 127 | [flakelight-rust]: 128 | https://github.com/accelbread/flakelight-rust/blob/master/flakelight-rust.nix 129 | 130 | ### C application 131 | 132 | The following example flake is for a C project with a simple `make` setup. 133 | 134 | ```nix 135 | { 136 | description = "My C application."; 137 | inputs.flakelight.url = "github:nix-community/flakelight"; 138 | outputs = { flakelight, ... }: 139 | flakelight ./. { 140 | license = "AGPL-3.0-or-later"; 141 | 142 | package = { stdenv, defaultMeta }: 143 | stdenv.mkDerivation { 144 | name = "hello-world"; 145 | src = ./.; 146 | installPhase = '' 147 | runHook preInstall 148 | make DESTDIR=$out install 149 | runHook postInstall 150 | ''; 151 | meta = defaultMeta; 152 | }; 153 | 154 | devShell.packages = pkgs: with pkgs; [ clang-tools coreutils ]; 155 | 156 | formatters = { 157 | "*.h" = "clang-format -i"; 158 | "*.c" = "clang-format -i"; 159 | } 160 | }; 161 | } 162 | ``` 163 | 164 | This flake exports the following: 165 | 166 | - Per-system attributes for default systems (`x86_64-linux` and `aarch64-linux`) 167 | - `packages.${system}.default` attributes for each system, with license and 168 | description set 169 | - `overlays.default` providing an overlay with the package (built with the 170 | applied pkg set's dependencies) 171 | - `devShells.${system}.default` that provides `clang-tools` and `coreutils` 172 | - `checks.${system}.${check}` attributes for build and formatting checks. 173 | - `formatter.${system}` with additional support for formatting `c` and `h` files 174 | with `clang-format` 175 | 176 | ### C application using autoloads 177 | 178 | The above example can instead use the autoload directory feature for the package 179 | like the following. Most attributes can be autoloaded. 180 | 181 | `./flake.nix`: 182 | 183 | ```nix 184 | { 185 | description = "My C application."; 186 | inputs.flakelight.url = "github:nix-community/flakelight"; 187 | outputs = { flakelight, ... }: 188 | flakelight ./. { 189 | license = "AGPL-3.0-or-later"; 190 | 191 | devShell.packages = pkgs: with pkgs; [ clang-tools coreutils ]; 192 | 193 | formatters = { 194 | "*.h" = "clang-format -i"; 195 | "*.c" = "clang-format -i"; 196 | } 197 | }; 198 | } 199 | ``` 200 | 201 | `./nix/packages/_default.nix`: 202 | 203 | ```nix 204 | { stdenv, defaultMeta }: 205 | stdenv.mkDerivation { 206 | name = "hello-world"; 207 | src = ./.; 208 | installPhase = '' 209 | runHook preInstall 210 | make DESTDIR=$out install 211 | runHook postInstall 212 | ''; 213 | meta = defaultMeta; 214 | } 215 | ``` 216 | 217 | A leading underscore in filename is stripped (default needs to be escaped to not 218 | conflict with dir import). 219 | 220 | ## Related Resources 221 | 222 | - [Comparison to flake-parts](https://discourse.nixos.org/t/flakelight-a-new-modular-flake-framework/32395/3) 223 | -------------------------------------------------------------------------------- /builtinModules/apps.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, genSystems, ... }: 6 | let 7 | inherit (builtins) match storeDir; 8 | inherit (lib) defaultFunctor fix isFunction last mapAttrs mergeDefinitions 9 | mkIf mkMerge mkOption mkOptionType; 10 | inherit (lib.types) coercedTo enum lazyAttrsOf 11 | optionDescriptionPhrase pathInStore submoduleWith; 12 | inherit (flakelight.types) nullable optFunctionTo stringLike; 13 | 14 | isStorePath = s: match "${storeDir}/[^.][^ \n]*" s != null; 15 | 16 | app = submoduleWith { 17 | modules = [{ 18 | options = { 19 | type = mkOption { type = enum [ "app" ]; default = "app"; }; 20 | program = mkOption { type = pathInStore // { check = isStorePath; }; }; 21 | }; 22 | }]; 23 | }; 24 | 25 | mkApp = name: pkgs: s: 26 | let s' = "${s}"; in { 27 | program = 28 | if isStorePath s' then s' 29 | else "${pkgs.writeShellScript "app-${name}" s'}"; 30 | }; 31 | 32 | parameterize = value: fn: fix fn value; 33 | 34 | appType = parameterize app (self': app: (mkOptionType rec { 35 | name = "appType"; 36 | description = 37 | let 38 | targetDesc = optionDescriptionPhrase 39 | (class: class == "noun" || class == "composite") 40 | (coercedTo stringLike (abort "") app); 41 | in 42 | "${targetDesc} or function that evaluates to it"; 43 | descriptionClass = "composite"; 44 | check = x: isFunction x || app.check x || stringLike.check x; 45 | merge = loc: defs: pkgs: 46 | let 47 | targetType = coercedTo stringLike (mkApp (last loc) pkgs) app; 48 | in 49 | (mergeDefinitions loc targetType (map 50 | (fn: { 51 | inherit (fn) file; 52 | value = if isFunction fn.value then fn.value pkgs else fn.value; 53 | }) 54 | defs)).mergedValue; 55 | inherit (app) getSubOptions getSubModules; 56 | substSubModules = m: self' (app.substSubModules m); 57 | functor = (defaultFunctor name) // { wrapped = app; }; 58 | nestedTypes.coercedType = stringLike; 59 | nestedTypes.finalType = app; 60 | })); 61 | in 62 | { 63 | options = { 64 | app = mkOption { 65 | type = nullable appType; 66 | default = null; 67 | }; 68 | 69 | apps = mkOption { 70 | type = nullable (optFunctionTo (lazyAttrsOf appType)); 71 | default = null; 72 | }; 73 | }; 74 | 75 | config = mkMerge [ 76 | (mkIf (config.app != null) { 77 | apps.default = config.app; 78 | }) 79 | 80 | (mkIf (config.apps != null) { 81 | outputs.apps = genSystems (pkgs: 82 | mapAttrs (_: v: v pkgs) (config.apps pkgs)); 83 | }) 84 | ]; 85 | } 86 | -------------------------------------------------------------------------------- /builtinModules/autoInputs.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { lib, src, ... }: 6 | let 7 | inherit (builtins) mapAttrs pathExists; 8 | inherit (lib) mkOverride; 9 | lock2inputs = import ../misc/lock2inputs.nix { inherit lib; }; 10 | lockFound = pathExists (src + "/flake.lock"); 11 | autoInputs = if lockFound then lock2inputs src else { }; 12 | in 13 | { config.inputs = mapAttrs (_: mkOverride 950) autoInputs; } 14 | -------------------------------------------------------------------------------- /builtinModules/builtinFormatters.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, ... }: 6 | let 7 | inherit (lib) mkDefault mkEnableOption mkIf; 8 | in 9 | { 10 | options.flakelight.builtinFormatters = 11 | mkEnableOption "default formatters" // 12 | { default = config.formatter == null; }; 13 | 14 | config = mkIf config.flakelight.builtinFormatters { 15 | devShell.packages = pkgs: [ 16 | pkgs.nixpkgs-fmt 17 | pkgs.nodePackages.prettier 18 | ]; 19 | 20 | formatters = pkgs: 21 | let 22 | nixpkgs-fmt = "${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt"; 23 | # prefer-file would be better but does not work with prose-wrap 24 | prettier = "${pkgs.nodePackages.prettier}/bin/prettier --write" 25 | + " --cache-location=.prettiercache" 26 | + " --config-precedence file-override --prose-wrap always"; 27 | in 28 | { 29 | "*.nix" = mkDefault nixpkgs-fmt; 30 | "*.md" = mkDefault prettier; 31 | "*.json" = mkDefault prettier; 32 | "*.yaml" = mkDefault prettier; 33 | "*.yml" = mkDefault prettier; 34 | }; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /builtinModules/builtinOverlay.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, src, lib, inputs, outputs, flakelight, moduleArgs, ... }: 6 | let 7 | inherit (lib) isList mkOption mkOrder mapAttrs optionalAttrs; 8 | inherit (lib.types) listOf oneOf str; 9 | inherit (builtins) pathExists; 10 | inherit (flakelight) selectAttr; 11 | inherit (flakelight.types) nullable; 12 | in 13 | { 14 | options = { 15 | description = mkOption { 16 | type = nullable str; 17 | default = 18 | if pathExists (src + /flake.nix) 19 | then (import (src + /flake.nix)).description or null 20 | else null; 21 | }; 22 | 23 | license = mkOption { 24 | type = nullable (oneOf [ str (listOf str) ]); 25 | default = null; 26 | }; 27 | }; 28 | 29 | config.withOverlays = mkOrder 10 (final: prev: 30 | let inherit (prev.stdenv.hostPlatform) system; in { 31 | inherit system moduleArgs src inputs outputs flakelight; 32 | inputs' = mapAttrs (_: selectAttr system) inputs; 33 | outputs' = selectAttr system outputs; 34 | 35 | defaultMeta = { 36 | platforms = config.systems; 37 | } // optionalAttrs (config.description != null) { 38 | inherit (config) description; 39 | } // optionalAttrs (config.license != null) { 40 | license = 41 | let 42 | getLicense = license: final.lib.licenses.${license} or 43 | (final.lib.meta.getLicenseFromSpdxId license); 44 | in 45 | if isList config.license then map getLicense config.license 46 | else getLicense config.license; 47 | }; 48 | }); 49 | } 50 | -------------------------------------------------------------------------------- /builtinModules/bundlers.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, genSystems, ... }: 6 | let 7 | inherit (lib) isFunction mapAttrs mkMerge mkOption mkIf; 8 | inherit (lib.types) lazyAttrsOf; 9 | inherit (flakelight.types) function nullable optFunctionTo; 10 | 11 | wrapBundler = pkgs: bundler: drv: 12 | if isFunction (bundler (pkgs // drv)) 13 | then bundler pkgs drv 14 | else bundler drv; 15 | in 16 | { 17 | options = { 18 | bundler = mkOption { 19 | type = nullable function; 20 | default = null; 21 | }; 22 | 23 | bundlers = mkOption { 24 | type = nullable (optFunctionTo (lazyAttrsOf function)); 25 | default = null; 26 | }; 27 | }; 28 | 29 | config = mkMerge [ 30 | (mkIf (config.bundler != null) { 31 | bundlers.default = config.bundler; 32 | }) 33 | 34 | (mkIf (config.bundlers != null) { 35 | outputs.bundlers = genSystems (pkgs: 36 | mapAttrs (_: wrapBundler pkgs) (config.bundlers pkgs)); 37 | }) 38 | ]; 39 | } 40 | -------------------------------------------------------------------------------- /builtinModules/checks.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, src, lib, flakelight, genSystems, ... }: 6 | let 7 | inherit (lib) isFunction last mapAttrs mergeDefinitions mkIf mkOption 8 | mkOptionType; 9 | inherit (lib.types) lazyAttrsOf optionDescriptionPhrase; 10 | inherit (flakelight.types) coercedTo' drv nullable optFunctionTo stringLike; 11 | 12 | mkCheck = name: pkgs: cmd: 13 | pkgs.runCommand "check-${name}" 14 | { allowSubstitutes = false; } 15 | '' 16 | cp --no-preserve=mode -r ${src} src 17 | cd src 18 | ${cmd} 19 | touch $out 20 | ''; 21 | 22 | checkType = mkOptionType { 23 | name = "checkType"; 24 | description = 25 | let 26 | targetDesc = optionDescriptionPhrase 27 | (class: class == "noun" || class == "composite") 28 | (coercedTo' stringLike (abort "") drv); 29 | in 30 | "${targetDesc} or function that evaluates to it"; 31 | descriptionClass = "composite"; 32 | check = x: isFunction x || drv.check x || stringLike.check x; 33 | merge = loc: defs: pkgs: 34 | let 35 | targetType = coercedTo' stringLike (mkCheck (last loc) pkgs) drv; 36 | in 37 | (mergeDefinitions loc targetType (map 38 | (fn: { 39 | inherit (fn) file; 40 | value = if isFunction fn.value then fn.value pkgs else fn.value; 41 | }) 42 | defs)).mergedValue; 43 | }; 44 | in 45 | { 46 | options.checks = mkOption { 47 | type = nullable (optFunctionTo (lazyAttrsOf checkType)); 48 | default = null; 49 | }; 50 | 51 | config.outputs = mkIf (config.checks != null) { 52 | checks = genSystems (pkgs: mapAttrs (_: v: v pkgs) (config.checks pkgs)); 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /builtinModules/core.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, inputs, lib, flakelight, moduleArgs, ... }: 6 | let 7 | inherit (builtins) all head isAttrs length; 8 | inherit (lib) foldAttrs genAttrs getFiles getValues mapAttrs mergeAttrs 9 | mkOption mkOptionType showFiles showOption; 10 | inherit (lib.types) functionTo lazyAttrsOf listOf nonEmptyStr raw uniq; 11 | inherit (flakelight.types) optCallWith optListOf overlay; 12 | 13 | outputs = mkOptionType { 14 | name = "outputs"; 15 | description = "output values"; 16 | descriptionClass = "noun"; 17 | merge = loc: defs: 18 | if (length defs) == 1 then (head defs).value 19 | else if all isAttrs (getValues defs) then 20 | (lazyAttrsOf outputs).merge loc defs 21 | else 22 | throw ("The option `${showOption loc}' has conflicting definitions" + 23 | " in ${showFiles (getFiles defs)}"); 24 | }; 25 | 26 | pkgsFor = genAttrs config.systems (system: import inputs.nixpkgs { 27 | inherit system; 28 | inherit (config.nixpkgs) config; 29 | overlays = config.withOverlays ++ [ config.packageOverlay ]; 30 | }); 31 | 32 | genSystems = f: genAttrs config.systems (system: f pkgsFor.${system}); 33 | in 34 | { 35 | options = { 36 | inputs = mkOption { 37 | type = lazyAttrsOf raw; 38 | }; 39 | 40 | systems = mkOption { 41 | type = uniq (listOf nonEmptyStr); 42 | default = [ "x86_64-linux" "aarch64-linux" ]; 43 | }; 44 | 45 | outputs = mkOption { 46 | type = optCallWith moduleArgs (lazyAttrsOf outputs); 47 | default = { }; 48 | }; 49 | 50 | perSystem = mkOption { 51 | type = functionTo (lazyAttrsOf outputs); 52 | default = _: { }; 53 | }; 54 | 55 | nixpkgs.config = mkOption { 56 | type = lazyAttrsOf raw; 57 | default = { }; 58 | }; 59 | 60 | withOverlays = mkOption { 61 | type = optListOf overlay; 62 | default = [ ]; 63 | }; 64 | }; 65 | 66 | config = { 67 | _module.args = { 68 | inherit (config) inputs outputs; 69 | inherit pkgsFor genSystems; 70 | }; 71 | 72 | outputs = foldAttrs mergeAttrs { } (map 73 | (system: mapAttrs 74 | (_: v: { ${system} = v; }) 75 | (config.perSystem pkgsFor.${system})) 76 | config.systems); 77 | }; 78 | } 79 | -------------------------------------------------------------------------------- /builtinModules/devShells.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, genSystems, moduleArgs, ... }: 6 | let 7 | inherit (lib) functionArgs mapAttrs mkIf mkMerge mkOption; 8 | inherit (lib.types) coercedTo lazyAttrsOf lines listOf 9 | package str submoduleWith; 10 | inherit (flakelight.types) function nullable optCallWith optFunctionTo; 11 | 12 | devShellModule.options = { 13 | inputsFrom = mkOption { 14 | type = optFunctionTo (listOf package); 15 | default = [ ]; 16 | }; 17 | 18 | packages = mkOption { 19 | type = optFunctionTo (listOf package); 20 | default = [ ]; 21 | }; 22 | 23 | shellHook = mkOption { 24 | type = optFunctionTo lines; 25 | default = ""; 26 | }; 27 | 28 | hardeningDisable = mkOption { 29 | type = listOf str; 30 | default = [ ]; 31 | }; 32 | 33 | env = mkOption { 34 | type = optFunctionTo (lazyAttrsOf str); 35 | default = { }; 36 | }; 37 | 38 | stdenv = mkOption { 39 | type = optFunctionTo package; 40 | default = pkgs: pkgs.stdenv; 41 | }; 42 | 43 | overrideShell = mkOption { 44 | type = nullable package; 45 | internal = true; 46 | default = null; 47 | }; 48 | }; 49 | 50 | wrapFn = fn: pkgs: 51 | let val = pkgs.callPackage fn { }; in 52 | if (functionArgs fn == { }) || !(package.check val) 53 | then fn pkgs 54 | else val; 55 | 56 | packageOverride = p: { overrideShell = p; }; 57 | 58 | devShellType = coercedTo function wrapFn 59 | (optFunctionTo (coercedTo package packageOverride 60 | (submoduleWith { modules = [ devShellModule ]; }))); 61 | 62 | genDevShell = pkgs: cfg: 63 | if cfg.overrideShell != null then cfg.overrideShell 64 | else 65 | let cfg' = mapAttrs (_: v: v pkgs) cfg; in 66 | pkgs.mkShell.override { inherit (cfg') stdenv; } 67 | (cfg'.env // { 68 | inherit (cfg') inputsFrom packages shellHook; 69 | inherit (cfg) hardeningDisable; 70 | }); 71 | in 72 | { 73 | options = { 74 | devShell = mkOption { 75 | default = null; 76 | type = nullable devShellType; 77 | }; 78 | 79 | devShells = mkOption { 80 | type = optCallWith moduleArgs (lazyAttrsOf devShellType); 81 | default = { }; 82 | }; 83 | }; 84 | 85 | config = mkMerge [ 86 | (mkIf (config.devShell != null) { 87 | devShells.default = config.devShell; 88 | }) 89 | 90 | (mkIf (config.devShells != { }) { 91 | outputs.devShells = genSystems (pkgs: 92 | mapAttrs (_: v: genDevShell pkgs (v pkgs)) config.devShells); 93 | }) 94 | ]; 95 | } 96 | -------------------------------------------------------------------------------- /builtinModules/editorconfig.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, src, ... }: 6 | let 7 | inherit (lib) mkEnableOption mkIf optionalString pathExists; 8 | in 9 | { 10 | options.flakelight.editorconfig = 11 | mkEnableOption "editorconfig check" // { default = true; }; 12 | 13 | config.checks = mkIf 14 | (config.flakelight.editorconfig && (pathExists (src + /.editorconfig))) 15 | { 16 | # By default, high false-positive flags are disabled. 17 | editorconfig = { editorconfig-checker, ... }: 18 | "${editorconfig-checker}/bin/editorconfig-checker" 19 | + optionalString (!pathExists (src + /.ecrc)) 20 | " -disable-indent-size -disable-max-line-length"; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /builtinModules/flakelightModules.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, moduleArgs, ... }: 6 | let 7 | inherit (lib) mkOption mkIf mkMerge; 8 | inherit (lib.types) lazyAttrsOf; 9 | inherit (flakelight.types) module nullable optCallWith; 10 | in 11 | { 12 | options = { 13 | flakelightModule = mkOption { 14 | type = nullable module; 15 | default = null; 16 | }; 17 | 18 | flakelightModules = mkOption { 19 | type = optCallWith moduleArgs (lazyAttrsOf module); 20 | default = { }; 21 | }; 22 | }; 23 | 24 | config = mkMerge [ 25 | (mkIf (config.flakelightModule != null) { 26 | flakelightModules.default = config.flakelightModule; 27 | }) 28 | 29 | (mkIf (config.flakelightModules != { }) { 30 | outputs = { inherit (config) flakelightModules; }; 31 | }) 32 | ]; 33 | } 34 | -------------------------------------------------------------------------------- /builtinModules/formatter.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, src, lib, flakelight, genSystems, ... }: 6 | let 7 | inherit (builtins) all hasContext; 8 | inherit (lib) mkDefault mkMerge mkOption mkIf mapAttrsToList; 9 | inherit (lib.types) functionTo lazyAttrsOf package str; 10 | inherit (flakelight.types) nullable optFunctionTo; 11 | in 12 | { 13 | options = { 14 | formatter = mkOption { 15 | type = nullable (functionTo package); 16 | default = null; 17 | }; 18 | formatters = mkOption { 19 | type = nullable (optFunctionTo (lazyAttrsOf str)); 20 | default = null; 21 | }; 22 | }; 23 | 24 | config = mkMerge [ 25 | (mkIf (config.formatter != null) { 26 | outputs.formatter = genSystems config.formatter; 27 | }) 28 | 29 | (mkIf (config.formatters != null) { 30 | outputs.formatter = mkDefault (genSystems 31 | ({ pkgs, lib, fd, coreutils, ... }: 32 | let 33 | inherit (lib) attrValues makeBinPath; 34 | formatters = config.formatters pkgs; 35 | fullContext = all hasContext (attrValues formatters); 36 | packages = 37 | if config.devShell == null then [ ] 38 | else (config.devShell pkgs).packages pkgs; 39 | caseArms = toString (mapAttrsToList 40 | (n: v: "\n ${n}) ${v} \"$f\" & ;;") 41 | formatters); 42 | in 43 | pkgs.writeShellScriptBin "formatter" '' 44 | PATH=${if fullContext then "" else makeBinPath packages} 45 | if [ $# -eq 0 ]; then 46 | flakedir=. 47 | while [ "$(${coreutils}/bin/realpath "$flakedir")" != / ]; do 48 | if [ -e "$flakedir/flake.nix" ]; then 49 | exec "$0" "$flakedir" 50 | fi 51 | flakedir="$flakedir/.." 52 | done 53 | echo Failed to find flake root! >&2 54 | exit 1 55 | fi 56 | for f in "$@"; do 57 | if [ -d "$f" ]; then 58 | ${fd}/bin/fd "$f" -Htf -x "$0" & 59 | else 60 | case "$(${coreutils}/bin/basename "$f")" in${caseArms} 61 | esac 62 | fi 63 | done &>/dev/null 64 | wait 65 | '')); 66 | }) 67 | 68 | (mkIf ((config.formatters != null) || (config.formatter != null)) { 69 | checks.formatting = { lib, outputs', diffutils, ... }: '' 70 | ${lib.getExe outputs'.formatter} . 71 | ${diffutils}/bin/diff -qr ${src} . |\ 72 | sed 's/Files .* and \(.*\) differ/File \1 not formatted/g' 73 | ''; 74 | }) 75 | ]; 76 | } 77 | -------------------------------------------------------------------------------- /builtinModules/functor.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, ... }: 6 | let 7 | inherit (lib) mkOption mkIf; 8 | inherit (lib.types) functionTo raw uniq; 9 | inherit (flakelight.types) nullable; 10 | in 11 | { 12 | options.functor = mkOption { 13 | type = nullable (uniq (functionTo (functionTo raw))); 14 | default = null; 15 | }; 16 | 17 | config.outputs = mkIf (config.functor != null) (_: { 18 | __functor = config.functor; 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /builtinModules/homeConfigurations.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, inputs, flakelight, moduleArgs, ... }: 6 | let 7 | inherit (builtins) head mapAttrs match; 8 | inherit (lib) foldl mapAttrsToList mkOption mkIf recursiveUpdate; 9 | inherit (lib.types) attrs lazyAttrsOf; 10 | inherit (flakelight) selectAttr; 11 | inherit (flakelight.types) optCallWith; 12 | 13 | isHome = x: x ? activationPackage; 14 | 15 | mkHome = name: cfg: inputs.home-manager.lib.homeManagerConfiguration ( 16 | (removeAttrs cfg [ "system" ]) // { 17 | extraSpecialArgs = { 18 | inherit inputs; 19 | inputs' = mapAttrs (_: selectAttr cfg.system) inputs; 20 | } // cfg.extraSpecialArgs or { }; 21 | modules = [ 22 | ({ lib, ... }: { 23 | home.username = lib.mkDefault (head (match "([^@]*)(@.*)?" name)); 24 | }) 25 | config.propagationModule 26 | ] ++ cfg.modules or [ ]; 27 | pkgs = inputs.nixpkgs.legacyPackages.${cfg.system}; 28 | } 29 | ); 30 | 31 | configs = mapAttrs 32 | (name: cfg: if isHome cfg then cfg else mkHome name cfg) 33 | config.homeConfigurations; 34 | in 35 | { 36 | options.homeConfigurations = mkOption { 37 | type = optCallWith moduleArgs (lazyAttrsOf (optCallWith moduleArgs attrs)); 38 | default = { }; 39 | }; 40 | 41 | config = { 42 | outputs = mkIf (config.homeConfigurations != { }) { 43 | homeConfigurations = configs; 44 | checks = foldl recursiveUpdate { } (mapAttrsToList 45 | (n: v: { 46 | ${v.config.nixpkgs.system}."home-${n}" = v.activationPackage; 47 | }) 48 | configs); 49 | }; 50 | nixDirAliases.homeConfigurations = [ "home" ]; 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /builtinModules/homeModules.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, moduleArgs, ... }: 6 | let 7 | inherit (lib) mkOption mkIf mkMerge; 8 | inherit (lib.types) lazyAttrsOf; 9 | inherit (flakelight.types) module nullable optCallWith; 10 | in 11 | { 12 | options = { 13 | homeModule = mkOption { 14 | type = nullable module; 15 | default = null; 16 | }; 17 | 18 | homeModules = mkOption { 19 | type = optCallWith moduleArgs (lazyAttrsOf module); 20 | default = { }; 21 | }; 22 | }; 23 | 24 | config = mkMerge [ 25 | (mkIf (config.homeModule != null) { 26 | homeModules.default = config.homeModule; 27 | }) 28 | 29 | (mkIf (config.homeModules != { }) { 30 | outputs = { inherit (config) homeModules; }; 31 | }) 32 | ]; 33 | } 34 | -------------------------------------------------------------------------------- /builtinModules/legacyPackages.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, genSystems, ... }: 6 | let 7 | inherit (lib) mkIf mkOption; 8 | inherit (lib.types) functionTo pkgs; 9 | inherit (flakelight.types) nullable; 10 | in 11 | { 12 | options.legacyPackages = mkOption { 13 | type = nullable (functionTo pkgs); 14 | default = null; 15 | }; 16 | 17 | config.outputs = mkIf (config.legacyPackages != null) { 18 | legacyPackages = genSystems config.legacyPackages; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /builtinModules/lib.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, moduleArgs, ... }: 6 | let 7 | inherit (lib) mkOption mkIf; 8 | inherit (lib.types) attrsOf raw; 9 | inherit (flakelight.types) optCallWith; 10 | in 11 | { 12 | options.lib = mkOption { 13 | type = optCallWith moduleArgs (attrsOf raw); 14 | default = { }; 15 | }; 16 | 17 | config.outputs = mkIf (config.lib != { }) { 18 | inherit (config) lib; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /builtinModules/moduleArgs.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, ... }@args: 6 | { 7 | _module.args.moduleArgs = args // config._module.args; 8 | } 9 | -------------------------------------------------------------------------------- /builtinModules/nixDir.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, options, src, lib, flakelight, ... }: 6 | let 7 | inherit (builtins) attrNames; 8 | inherit (lib) findFirst genAttrs mkIf mkOption pathExists subtractLists; 9 | inherit (lib.types) attrsOf listOf str; 10 | inherit (flakelight) importDir; 11 | inherit (flakelight.types) path; 12 | 13 | inherit (config) nixDir; 14 | 15 | importName = name: 16 | if pathExists (nixDir + "/${name}.nix") 17 | then { success = true; value = import (nixDir + "/${name}.nix"); } 18 | else if pathExists (nixDir + "/${name}/default.nix") 19 | then { success = true; value = import (nixDir + "/${name}"); } 20 | else if pathExists (nixDir + "/${name}") 21 | then { success = true; value = importDir (nixDir + "/${name}"); } 22 | else { success = false; }; 23 | 24 | importNames = names: 25 | findFirst (x: x.success) { success = false; } (map importName names); 26 | in 27 | { 28 | options = { 29 | nixDir = mkOption { 30 | type = path; 31 | default = src + /nix; 32 | }; 33 | 34 | nixDirAliases = mkOption { 35 | type = attrsOf (listOf str); 36 | default = { }; 37 | }; 38 | }; 39 | 40 | config = genAttrs (subtractLists [ "_module" "nixDir" ] (attrNames options)) 41 | (name: 42 | let 43 | internal = options.${name}.internal or false; 44 | val = importNames 45 | (if name == "nixDirAliases" then [ name ] else 46 | ([ name ] ++ config.nixDirAliases.${name} or [ ])); 47 | cond = !internal && val.success; 48 | in 49 | mkIf cond (if cond then val.value else { })); 50 | } 51 | -------------------------------------------------------------------------------- /builtinModules/nixosConfigurations.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, inputs, flakelight, moduleArgs, ... }: 6 | let 7 | inherit (builtins) mapAttrs; 8 | inherit (lib) foldl mapAttrsToList mkIf mkOption recursiveUpdate; 9 | inherit (lib.types) attrs lazyAttrsOf; 10 | inherit (flakelight) selectAttr; 11 | inherit (flakelight.types) optCallWith; 12 | 13 | # Avoid checking if toplevel is a derivation as it causes the nixos modules 14 | # to be evaluated. 15 | isNixos = x: x ? config.system.build.toplevel; 16 | 17 | mkNixos = hostname: cfg: inputs.nixpkgs.lib.nixosSystem (cfg // { 18 | specialArgs = { 19 | inherit inputs hostname; 20 | inputs' = mapAttrs (_: selectAttr cfg.system) inputs; 21 | } // cfg.specialArgs or { }; 22 | modules = [ config.propagationModule ] ++ cfg.modules or [ ]; 23 | }); 24 | 25 | configs = mapAttrs 26 | (hostname: cfg: if isNixos cfg then cfg else mkNixos hostname cfg) 27 | config.nixosConfigurations; 28 | in 29 | { 30 | options.nixosConfigurations = mkOption { 31 | type = optCallWith moduleArgs (lazyAttrsOf (optCallWith moduleArgs attrs)); 32 | default = { }; 33 | }; 34 | 35 | config = { 36 | outputs = mkIf (config.nixosConfigurations != { }) { 37 | nixosConfigurations = configs; 38 | checks = foldl recursiveUpdate { } (mapAttrsToList 39 | (n: v: { 40 | # Wrapping the drv is needed as computing its name is expensive 41 | # If not wrapped, it slows down `nix flake show` significantly 42 | ${v.config.nixpkgs.system}."nixos-${n}" = v.pkgs.runCommand 43 | "check-nixos-${n}" 44 | { } "echo ${v.config.system.build.toplevel} > $out"; 45 | }) 46 | configs); 47 | }; 48 | nixDirAliases.nixosConfigurations = [ "nixos" ]; 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /builtinModules/nixosModules.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, moduleArgs, ... }: 6 | let 7 | inherit (lib) mkOption mkIf mkMerge; 8 | inherit (lib.types) lazyAttrsOf; 9 | inherit (flakelight.types) module nullable optCallWith; 10 | in 11 | { 12 | options = { 13 | nixosModule = mkOption { 14 | type = nullable module; 15 | default = null; 16 | }; 17 | 18 | nixosModules = mkOption { 19 | type = optCallWith moduleArgs (lazyAttrsOf module); 20 | default = { }; 21 | }; 22 | }; 23 | 24 | config = mkMerge [ 25 | (mkIf (config.nixosModule != null) { 26 | nixosModules.default = config.nixosModule; 27 | }) 28 | 29 | (mkIf (config.nixosModules != { }) { 30 | outputs = { inherit (config) nixosModules; }; 31 | }) 32 | ]; 33 | } 34 | -------------------------------------------------------------------------------- /builtinModules/overlays.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, moduleArgs, ... }: 6 | let 7 | inherit (lib) mkMerge mkOption mkIf; 8 | inherit (lib.types) lazyAttrsOf; 9 | inherit (flakelight.types) nullable optCallWith overlay; 10 | in 11 | { 12 | options = { 13 | overlay = mkOption { 14 | type = nullable overlay; 15 | default = null; 16 | }; 17 | 18 | overlays = mkOption { 19 | type = optCallWith moduleArgs (lazyAttrsOf overlay); 20 | default = { }; 21 | }; 22 | }; 23 | 24 | config = mkMerge [ 25 | (mkIf (config.overlay != null) { 26 | overlays.default = config.overlay; 27 | }) 28 | 29 | (mkIf (config.overlays != { }) { 30 | outputs = { inherit (config) overlays; }; 31 | }) 32 | ]; 33 | } 34 | -------------------------------------------------------------------------------- /builtinModules/packages.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, inputs, flakelight, genSystems, moduleArgs, ... }: 6 | let 7 | inherit (builtins) hasAttr parseDrvName tryEval; 8 | inherit (lib) findFirst functionArgs mapAttrs' mapAttrs mkIf mkMerge mkOption 9 | nameValuePair optionalAttrs optionals; 10 | inherit (lib.types) lazyAttrsOf str uniq; 11 | inherit (flakelight.types) nullable optFunctionTo overlay packageDef; 12 | 13 | genPkg = final: prev: name: pkg: 14 | let 15 | args = functionArgs pkg; 16 | noArgs = args == { }; 17 | pkg' = if noArgs then { pkgs }: pkg pkgs else pkg; 18 | dependsOnSelf = hasAttr name (functionArgs pkg); 19 | dependsOnPkgs = noArgs || (args ? pkgs); 20 | selfOverride = { 21 | ${name} = prev.${name} or 22 | (throw "${name} depends on ${name}, but no existing ${name}."); 23 | }; 24 | overrides = optionalAttrs dependsOnSelf selfOverride 25 | // optionalAttrs dependsOnPkgs { pkgs = final.pkgs // selfOverride; }; 26 | in 27 | final.callPackage pkg' overrides; 28 | genPkgs = final: prev: pkgs: 29 | mapAttrs (name: genPkg final prev name) pkgs; 30 | 31 | getPkgDefs = pkgs: config.packages (moduleArgs // { inherit (pkgs) system; }); 32 | in 33 | { 34 | options = { 35 | package = mkOption { 36 | type = nullable packageDef; 37 | default = null; 38 | }; 39 | 40 | packages = mkOption { 41 | type = nullable (optFunctionTo (lazyAttrsOf packageDef)); 42 | default = null; 43 | }; 44 | 45 | pname = mkOption { 46 | type = nullable str; 47 | default = null; 48 | }; 49 | 50 | packageOverlay = mkOption { 51 | internal = true; 52 | type = uniq overlay; 53 | default = _: _: { }; 54 | }; 55 | }; 56 | 57 | config = mkMerge [ 58 | (mkIf (config.package != null) { 59 | packages.default = config.package; 60 | }) 61 | 62 | (mkIf (config.packages != null) { 63 | packageOverlay = final: prev: 64 | let 65 | pkgDefs = getPkgDefs prev; 66 | getName = pkg: pkg.pname or (parseDrvName pkg.name).name; 67 | mockPkgs = import ../misc/nameMockedPkgs.nix prev; 68 | 69 | defaultPkgName = findFirst (x: (tryEval x).success) 70 | (throw ("Could not determine the name of the default package; " + 71 | "please set the `pname` flakelight option to the intended name.")) 72 | [ 73 | (assert config.pname != null; config.pname) 74 | (getName (mockPkgs.callPackage pkgDefs.default { })) 75 | (getName (import inputs.nixpkgs { 76 | inherit (prev.stdenv.hostPlatform) system; 77 | inherit (config.nixpkgs) config; 78 | overlays = config.withOverlays ++ 79 | [ (final: prev: genPkgs final prev pkgDefs) ]; 80 | }).default) 81 | ]; 82 | in 83 | (optionalAttrs (pkgDefs ? default) rec { 84 | default = genPkg final prev defaultPkgName pkgDefs.default; 85 | ${defaultPkgName} = default; 86 | }) // genPkgs final prev (removeAttrs pkgDefs [ "default" ]); 87 | 88 | overlay = final: prev: removeAttrs 89 | (config.packageOverlay (final.appendOverlays config.withOverlays) prev) 90 | [ "default" ]; 91 | 92 | outputs = rec { 93 | packages = genSystems (pkgs: 94 | mapAttrs (k: _: pkgs.${k}) (getPkgDefs pkgs)); 95 | 96 | checks = mapAttrs 97 | (_: mapAttrs' (n: nameValuePair ("packages-" + n))) 98 | packages; 99 | }; 100 | 101 | devShell.inputsFrom = pkgs: 102 | optionals ((getPkgDefs pkgs) ? default) [ pkgs.default ]; 103 | }) 104 | ]; 105 | } 106 | -------------------------------------------------------------------------------- /builtinModules/propagationModule.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | # This provides a module that can be added to module systems nested inside of 6 | # flakelight, for example NixOS or home-manager configurations. 7 | 8 | { lib, config, flakelight, moduleArgs, inputs, outputs, ... }: 9 | let 10 | inherit (lib) mapAttrs mkOption optional optionalAttrs; 11 | inherit (flakelight) selectAttr; 12 | inherit (flakelight.types) module; 13 | flakeConfig = config; 14 | in 15 | { 16 | options.propagationModule = mkOption { type = module; internal = true; }; 17 | 18 | config.propagationModule = 19 | { lib, pkgs, options, config, ... }: 20 | let inherit (pkgs.stdenv.hostPlatform) system; in { 21 | config = (optionalAttrs (options ? nixpkgs) { 22 | nixpkgs = (optionalAttrs (options ? nixpkgs.overlays) { 23 | # Forward overlays to NixOS/home-manager configurations 24 | overlays = lib.mkOrder 10 25 | (flakeConfig.withOverlays ++ [ flakeConfig.packageOverlay ]); 26 | }) 27 | // (optionalAttrs (options ? nixpkgs.config) { 28 | # Forward nixpkgs.config to NixOS/home-manager configurations 29 | inherit (flakeConfig.nixpkgs) config; 30 | }); 31 | }) 32 | // (optionalAttrs (options ? home-manager.sharedModules) { 33 | # Propagate module to home-manager when using its nixos module 34 | home-manager.sharedModules = 35 | optional (! config.home-manager.useGlobalPkgs) 36 | [ flakeConfig.propagationModule ]; 37 | }) 38 | // { 39 | # Give access to flakelight module args under `flake` arg. 40 | # Also include inputs'/outputs' which depend on `pkgs`. 41 | _module.args.flake = { 42 | inputs' = mapAttrs (_: selectAttr system) inputs; 43 | outputs' = selectAttr system outputs; 44 | } // moduleArgs; 45 | }; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /builtinModules/templates.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { config, lib, flakelight, moduleArgs, ... }: 6 | let 7 | inherit (builtins) isPath isString; 8 | inherit (lib) mkOption mkOptionType mkIf mkMerge; 9 | inherit (lib.types) lazyAttrsOf; 10 | inherit (lib.options) mergeEqualOption; 11 | inherit (flakelight.types) nullable optCallWith; 12 | 13 | template = mkOptionType { 14 | name = "template"; 15 | description = "template definition"; 16 | descriptionClass = "noun"; 17 | check = x: (x ? path) && (isPath x.path) && 18 | (x ? description) && (isString x.description) && 19 | ((! x ? welcomeText) || (isString x.welcomeText)); 20 | merge = mergeEqualOption; 21 | }; 22 | in 23 | { 24 | options = { 25 | template = mkOption { 26 | type = nullable (optCallWith moduleArgs template); 27 | default = null; 28 | }; 29 | 30 | templates = mkOption { 31 | type = optCallWith moduleArgs 32 | (lazyAttrsOf (optCallWith moduleArgs template)); 33 | default = { }; 34 | }; 35 | }; 36 | 37 | config = mkMerge [ 38 | (mkIf (config.template != null) { 39 | templates.default = config.template; 40 | }) 41 | 42 | (mkIf (config.templates != { }) { 43 | outputs = { inherit (config) templates; }; 44 | }) 45 | ]; 46 | } 47 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | inputs: 6 | let 7 | inherit (inputs) nixpkgs; 8 | inherit (builtins) isAttrs isPath readDir; 9 | inherit (nixpkgs.lib) all attrNames composeManyExtensions evalModules filter 10 | findFirst fix genAttrs getValues hasSuffix isDerivation isFunction isList 11 | isStringLike mapAttrs mapAttrsToList mkDefault mkOptionType pathExists pipe 12 | removePrefix removeSuffix singleton warn; 13 | inherit (nixpkgs.lib.types) coercedTo defaultFunctor functionTo listOf 14 | optionDescriptionPhrase; 15 | inherit (nixpkgs.lib.options) mergeEqualOption mergeOneOption; 16 | 17 | builtinModules = mapAttrsToList (k: _: ./builtinModules + ("/" + k)) 18 | (readDir ./builtinModules); 19 | 20 | mkFlake = { 21 | __functor = self: src: root: (evalModules { 22 | specialArgs.modulesPath = ./builtinModules; 23 | modules = builtinModules ++ self.extraModules ++ [ 24 | { inputs.nixpkgs = mkDefault nixpkgs; } 25 | { inputs.flakelight = mkDefault inputs.self; } 26 | { _module.args = { inherit src flakelight; }; } 27 | root 28 | ]; 29 | }).config.outputs; 30 | 31 | # Attributes to allow module flakes to extend mkFlake 32 | extraModules = [ ]; 33 | extend = (fix (extend': mkFlake': modules: fix (self: mkFlake' // { 34 | extraModules = mkFlake'.extraModules ++ modules; 35 | extend = extend' self; 36 | }))) mkFlake; 37 | }; 38 | 39 | flakelight = { 40 | inherit autoImport autoImportArgs importDir mkFlake selectAttr types; 41 | }; 42 | 43 | types = rec { 44 | overlay = mkOptionType { 45 | name = "overlay"; 46 | description = "nixpkgs overlay"; 47 | descriptionClass = "noun"; 48 | check = isFunction; 49 | merge = _: defs: composeManyExtensions (getValues defs); 50 | }; 51 | 52 | packageDef = mkOptionType { 53 | name = "packageDef"; 54 | description = "package definition"; 55 | descriptionClass = "noun"; 56 | check = isFunction; 57 | merge = mergeOneOption; 58 | }; 59 | 60 | path = mkOptionType { 61 | name = "path"; 62 | description = "path"; 63 | descriptionClass = "noun"; 64 | check = isPath; 65 | merge = mergeEqualOption; 66 | }; 67 | 68 | function = mkOptionType { 69 | name = "function"; 70 | description = "function"; 71 | descriptionClass = "noun"; 72 | check = isFunction; 73 | merge = mergeOneOption; 74 | }; 75 | 76 | drv = mkOptionType { 77 | name = "drv"; 78 | description = "derivation"; 79 | descriptionClass = "noun"; 80 | check = isDerivation; 81 | merge = mergeOneOption; 82 | }; 83 | 84 | stringLike = mkOptionType { 85 | name = "stringLike"; 86 | description = "string-convertible value"; 87 | descriptionClass = "noun"; 88 | check = isStringLike; 89 | merge = mergeEqualOption; 90 | }; 91 | 92 | module = mkOptionType { 93 | name = "module"; 94 | description = "module"; 95 | descriptionClass = "noun"; 96 | check = x: isPath x || isFunction x || isAttrs x; 97 | merge = _: defs: { imports = getValues defs; }; 98 | }; 99 | 100 | fileset = mkOptionType { 101 | name = "fileset"; 102 | description = "fileset"; 103 | descriptionClass = "noun"; 104 | check = x: isPath x || x._type or null == "fileset"; 105 | }; 106 | 107 | optListOf = elemType: coercedTo elemType singleton (listOf elemType); 108 | 109 | coercedTo' = coercedType: coerceFunc: finalType: 110 | (coercedTo coercedType coerceFunc finalType) // { 111 | merge = loc: defs: 112 | let 113 | coerceVal = val: 114 | if finalType.check val then val 115 | else coerceFunc val; 116 | in 117 | finalType.merge loc 118 | (map (def: def // { value = coerceVal def.value; }) defs); 119 | }; 120 | 121 | optFunctionTo = 122 | let 123 | nonFunction = mkOptionType { 124 | name = "nonFunction"; 125 | description = "non-function"; 126 | descriptionClass = "noun"; 127 | check = x: ! isFunction x; 128 | merge = mergeOneOption; 129 | }; 130 | in 131 | elemType: coercedTo nonFunction (x: _: x) 132 | (functionTo elemType); 133 | 134 | optCallWith = args: elemType: coercedTo function (x: x args) elemType; 135 | 136 | nullable = elemType: mkOptionType { 137 | name = "nullable"; 138 | description = "nullable ${optionDescriptionPhrase 139 | (class: class == "noun" || class == "composite") elemType}"; 140 | descriptionClass = "noun"; 141 | check = x: x == null || elemType.check x; 142 | merge = loc: defs: 143 | if all (def: def.value == null) defs then null 144 | else elemType.merge loc (filter (def: def.value != null) defs); 145 | emptyValue.value = null; 146 | inherit (elemType) getSubOptions getSubModules; 147 | substSubModules = m: nullable (elemType.substSubModules m); 148 | functor = (defaultFunctor "nullable") // { 149 | type = nullable; 150 | wrapped = elemType; 151 | }; 152 | nestedTypes = { inherit elemType; }; 153 | }; 154 | }; 155 | 156 | importDir = path: genAttrs 157 | (pipe (readDir path) [ 158 | attrNames 159 | (filter (s: s != "default.nix")) 160 | (filter (s: (hasSuffix ".nix" s) 161 | || pathExists (path + "/${s}/default.nix"))) 162 | (map (removeSuffix ".nix")) 163 | (map (removePrefix "_")) 164 | ]) 165 | (p: import (path + 166 | (if pathExists (path + "/_${p}.nix") then "/_${p}.nix" 167 | else if pathExists (path + "/${p}.nix") then "/${p}.nix" 168 | else "/${p}"))); 169 | 170 | autoImport = dir: name: warn 171 | ("The autoImport function is deprecated. " + 172 | "All options are now automatically auto-loaded.") 173 | (if isList name 174 | then findFirst (x: x != null) null (map (autoImport dir) name) 175 | else 176 | if pathExists (dir + "/${name}.nix") 177 | then import (dir + "/${name}.nix") 178 | else if pathExists (dir + "/${name}/default.nix") 179 | then import (dir + "/${name}") 180 | else if pathExists (dir + "/${name}") 181 | then importDir (dir + "/${name}") 182 | else null); 183 | 184 | autoImportArgs = dir: args: name: warn 185 | ("The autoImportArgs function is deprecated. " + 186 | "Wrap the target type in flakelight.types.optCallWith instead.") 187 | ( 188 | let v = autoImport dir name; in 189 | if isFunction v then v args else v 190 | ); 191 | 192 | selectAttr = attr: mapAttrs (_: v: v.${attr} or { }); 193 | in 194 | flakelight 195 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1748693115, 6 | "narHash": "sha256-StSrWhklmDuXT93yc3GrTlb0cKSS0agTAxMGjLKAsY8=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "910796cabe436259a29a72e8d3f5e180fc6dfacc", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "ref": "nixos-unstable", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | { 6 | description = 7 | "A modular Nix flake framework for simplifying flake definitions"; 8 | inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 9 | outputs = inputs: 10 | let lib = import ./. inputs; in 11 | lib.mkFlake ./. { 12 | inherit lib; 13 | functor = _: lib.mkFlake; 14 | templates = import ./templates; 15 | checks.statix = pkgs: "${pkgs.statix}/bin/statix check"; 16 | outputs.tests = import ./tests inputs; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /misc/lock2inputs.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | # Get a flakes inputs 6 | { lib, ... }: 7 | src: 8 | let 9 | inherit (builtins) fromJSON head isString mapAttrs readFile tail; 10 | inherit (lib) fix; 11 | 12 | json = fromJSON (readFile (src + "/flake.lock")); 13 | inherit (json) nodes; 14 | rootNode = nodes.${json.root}; 15 | 16 | getInputName = base: ref: 17 | let next = getInputName json.root nodes.${base}.inputs.${head ref}; in 18 | if isString ref then ref 19 | else if ref == [ ] then base 20 | else getInputName next (tail ref); 21 | 22 | getInput = ref: resolved.${getInputName json.root ref}; 23 | 24 | fetchNode = node: fetchTree (node.info or { } // 25 | removeAttrs node.locked [ "dir" ]); 26 | 27 | resolveFlakeNode = node: fix (self: 28 | let 29 | sourceInfo = fetchNode node; 30 | outPath = sourceInfo + 31 | (if node.locked ? dir then "/${node.locked.dir}" else ""); 32 | inputs = (mapAttrs (_: getInput) (node.inputs or { })) // 33 | { inherit self; }; 34 | outputs = (import (outPath + "/flake.nix")).outputs inputs; 35 | in 36 | outputs // sourceInfo // { 37 | _type = "flake"; 38 | inherit outPath inputs outputs sourceInfo; 39 | }); 40 | 41 | resolveNode = node: 42 | if node.flake or true then resolveFlakeNode node else fetchNode node; 43 | 44 | resolved = mapAttrs (_: resolveNode) nodes; 45 | in 46 | mapAttrs (_: getInput) rootNode.inputs 47 | -------------------------------------------------------------------------------- /misc/nameMockedPkgs.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | # This is a fake pkgs set to enable efficiently extracting a derivation's name 6 | 7 | real: 8 | let 9 | inherit (real) lib; 10 | 11 | callPackageWith = autoArgs: fn: args: 12 | let 13 | f = if lib.isFunction fn then fn else import fn; 14 | fargs = lib.functionArgs f; 15 | mock = lib.mapAttrs (_: _: throw "") (lib.filterAttrs (_: v: !v) fargs); 16 | in 17 | assert fargs != { }; 18 | f (mock // builtins.intersectAttrs fargs autoArgs // args); 19 | 20 | mockStdenv = builtins.mapAttrs (_: _: throw "") real.stdenv // { 21 | mkDerivation = args: 22 | if lib.isFunction args then lib.fix args else args; 23 | }; 24 | in 25 | lib.fix (self: { 26 | lib = lib // { inherit callPackageWith; }; 27 | 28 | callPackage = callPackageWith self; 29 | 30 | stdenv = mockStdenv; 31 | stdenvNoCC = mockStdenv; 32 | stdenv_32bit = mockStdenv; 33 | stdenvNoLibs = mockStdenv; 34 | libcxxStdenv = mockStdenv; 35 | gccStdenv = mockStdenv; 36 | gccStdenvNoLibs = mockStdenv; 37 | gccMultiStdenv = mockStdenv; 38 | clangStdenv = mockStdenv; 39 | clangStdenvNoLibs = mockStdenv; 40 | clangMultiStdenv = mockStdenv; 41 | ccacheStdenv = mockStdenv; 42 | 43 | runCommandWith = args: _: args; 44 | runCommand = name: _: _: { inherit name; }; 45 | runCommandLocal = name: _: _: { inherit name; }; 46 | runCommandCC = name: _: _: { inherit name; }; 47 | writeTextFile = args: args; 48 | writeText = name: _: { inherit name; }; 49 | writeTextDir = path: _: { name = builtins.baseNameOf path; }; 50 | writeScript = name: _: { inherit name; }; 51 | writeScriptBin = name: _: { inherit name; }; 52 | writeShellScript = name: _: { inherit name; }; 53 | writeShellScriptBin = name: _: { inherit name; }; 54 | writeShellApplication = args: args; 55 | writeCBin = pname: _: { inherit pname; }; 56 | concatTextFile = args: args; 57 | concatText = name: _: { inherit name; }; 58 | concatScript = name: _: { inherit name; }; 59 | symlinkJoin = args: args; 60 | linkFarm = name: _: { inherit name; }; 61 | linkFarmFromDrvs = name: _: { inherit name; }; 62 | }) 63 | -------------------------------------------------------------------------------- /nix/flakelightModules/flakelightModule.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | # A Flakelight module for Flakelight module flakes 6 | 7 | { flakelight, outputs, src, ... }: { 8 | nixDir = src; 9 | lib.mkFlake = flakelight.mkFlake.extend [ outputs.flakelightModules.default ]; 10 | functor = self: self.lib.mkFlake; 11 | } 12 | -------------------------------------------------------------------------------- /templates/basic/.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /templates/basic/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 4 | flakelight.url = "github:nix-community/flakelight"; 5 | }; 6 | outputs = { flakelight, ... }@inputs: 7 | flakelight ./. { 8 | inherit inputs; 9 | devShell.packages = pkgs: with pkgs; [ hello ]; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /templates/default.nix: -------------------------------------------------------------------------------- 1 | # flakelight -- Framework for simplifying flake setup 2 | # Copyright (C) 2023 Archit Gupta 3 | # SPDX-License-Identifier: MIT 4 | 5 | rec { 6 | default = basic; 7 | basic = { path = ./basic; description = "Minimal Flakelight flake."; }; 8 | } 9 | -------------------------------------------------------------------------------- /tests/default.nix: -------------------------------------------------------------------------------- 1 | { self, nixpkgs, ... }: 2 | let 3 | flakelight = self; 4 | test = flake: test: assert test flake; true; 5 | inherit (nixpkgs) lib; 6 | in 7 | { 8 | call-flakelight = test 9 | (flakelight ./empty { outputs.test = true; }) 10 | (f: f.test); 11 | 12 | explicit-mkFlake = test 13 | (flakelight.lib.mkFlake ./empty { outputs.test = true; }) 14 | (f: f.test); 15 | 16 | module-with-args = test 17 | (flakelight ./empty ({ lib, config, ... }: { outputs.test = true; })) 18 | (f: f.test); 19 | 20 | src-arg = test 21 | (flakelight ./test-path ({ src, ... }: { 22 | outputs = { inherit src; }; 23 | })) 24 | (f: f.src == ./test-path); 25 | 26 | lib-arg = test 27 | (flakelight ./empty ({ lib, ... }: { 28 | outputs = { inherit lib; }; 29 | })) 30 | (f: f.lib ? fix); 31 | 32 | config-arg = test 33 | (flakelight ./empty ({ config, ... }: { 34 | lib = { a = true; }; 35 | outputs = { inherit config; }; 36 | })) 37 | (f: f.config.lib.a); 38 | 39 | options-arg = test 40 | (flakelight ./empty ({ options, ... }: { 41 | outputs = { inherit options; }; 42 | })) 43 | (f: f.options ? package && f.options ? overlays); 44 | 45 | flakelight-arg = test 46 | (flakelight ./empty ({ flakelight, ... }: { 47 | outputs = { inherit flakelight; }; 48 | })) 49 | (f: f.flakelight ? mkFlake); 50 | 51 | inputs-arg = test 52 | (flakelight ./empty ({ inputs, ... }: { 53 | inputs.test = true; 54 | outputs = { inherit inputs; }; 55 | })) 56 | (f: f.inputs.test); 57 | 58 | overridden-nixpkgs = test 59 | (flakelight ./empty ({ inputs, ... }: { 60 | inputs.nixpkgs = nixpkgs // { testValue = true; }; 61 | outputs = { inherit inputs; }; 62 | })) 63 | (f: f.inputs.nixpkgs.testValue); 64 | 65 | outputs-arg = test 66 | (flakelight ./empty ({ outputs, ... }: { 67 | lib.test = true; 68 | outputs.test = outputs.lib.test; 69 | })) 70 | (f: f.test); 71 | 72 | moduleArgs = test 73 | (flakelight ./empty ({ moduleArgs, ... }: { 74 | outputs = { inherit moduleArgs; }; 75 | })) 76 | (f: f.moduleArgs ? config 77 | && f.moduleArgs ? options 78 | && f.moduleArgs ? src 79 | && f.moduleArgs ? lib 80 | && f.moduleArgs ? flakelight 81 | && f.moduleArgs ? inputs 82 | && f.moduleArgs ? outputs 83 | && f.moduleArgs ? pkgsFor 84 | && f.moduleArgs ? specialArgs 85 | && f.moduleArgs ? modulesPath 86 | && f.moduleArgs ? moduleArgs 87 | ); 88 | 89 | moduleArgs-add = test 90 | (flakelight ./empty { 91 | _module.args.test-val = true; 92 | outputs = { test-val, ... }: { 93 | test = test-val; 94 | }; 95 | }) 96 | (f: f.test); 97 | 98 | extra-pkgs-vals = test 99 | (flakelight ./empty { 100 | package = 101 | { src 102 | , inputs 103 | , outputs 104 | , flakelight 105 | , inputs' 106 | , outputs' 107 | , defaultMeta 108 | , writeText 109 | }: 110 | writeText "test" ""; 111 | }) 112 | (f: f.packages.x86_64-linux.default.name == "test"); 113 | 114 | inputs' = test 115 | (flakelight ./empty { 116 | systems = [ "x86_64-linux" ]; 117 | inputs.a.attr.x86_64-linux = true; 118 | perSystem = { inputs', ... }: { test = inputs'.a.attr && true; }; 119 | }) 120 | (f: f.test.x86_64-linux); 121 | 122 | outputs' = test 123 | (flakelight ./empty { 124 | systems = [ "x86_64-linux" ]; 125 | outputs.attr.x86_64-linux = true; 126 | perSystem = { outputs', ... }: { test = outputs'.attr && true; }; 127 | }) 128 | (f: f.test.x86_64-linux); 129 | 130 | systems = test 131 | (flakelight ./empty { 132 | systems = [ "i686-linux" "armv7l-linux" ]; 133 | perSystem = _: { test = true; }; 134 | }) 135 | (f: (builtins.attrNames f.test) == [ "armv7l-linux" "i686-linux" ]); 136 | 137 | all-flakes-systems = test 138 | (flakelight ./empty ({ lib, ... }: { 139 | systems = lib.systems.flakeExposed; 140 | perSystem = _: { test = true; }; 141 | })) 142 | (f: builtins.deepSeq f.test f.test.x86_64-linux); 143 | 144 | all-linux-systems = test 145 | (flakelight ./empty ({ lib, ... }: { 146 | systems = lib.intersectLists 147 | lib.systems.doubles.linux 148 | lib.systems.flakeExposed; 149 | perSystem = _: { test = true; }; 150 | })) 151 | (f: builtins.deepSeq f.test f.test.x86_64-linux); 152 | 153 | outputs = test 154 | (flakelight ./empty { 155 | outputs.example.test = true; 156 | }) 157 | (f: f.example.test); 158 | 159 | outputs-handled-attr = test 160 | (flakelight ./empty { 161 | outputs.overlays.test = final: prev: { testVal = true; }; 162 | }) 163 | (f: (nixpkgs.legacyPackages.x86_64-linux.extend f.overlays.test).testVal); 164 | 165 | perSystem = test 166 | (flakelight ./empty { 167 | perSystem = _: { test = true; }; 168 | }) 169 | (f: (builtins.attrNames f.test) == [ "aarch64-linux" "x86_64-linux" ]); 170 | 171 | withOverlays = test 172 | (flakelight ./empty { 173 | withOverlays = final: prev: { testValue = "true"; }; 174 | package = { writeText, testValue }: writeText "test" "${testValue}"; 175 | }) 176 | (f: import f.packages.x86_64-linux.default); 177 | 178 | withOverlays-multiple = test 179 | (flakelight ./empty { 180 | withOverlays = [ 181 | (final: prev: { testValue = "tr"; }) 182 | (final: prev: { testValue2 = "ue"; }) 183 | ]; 184 | package = { writeText, testValue, testValue2 }: 185 | writeText "test" "${testValue}${testValue2}"; 186 | }) 187 | (f: import f.packages.x86_64-linux.default); 188 | 189 | package-no-named-args = test 190 | (flakelight ./empty { 191 | package = pkgs: pkgs.hello; 192 | }) 193 | (f: f.packages.aarch64-linux.default.pname == "hello"); 194 | 195 | package-prevent-recursion = test 196 | (flakelight ./empty { 197 | package = { hello }: hello; 198 | }) 199 | (f: f.packages.aarch64-linux.default.pname == "hello"); 200 | 201 | package = test 202 | (flakelight ./empty { 203 | package = { stdenv }: 204 | stdenv.mkDerivation { 205 | pname = "pkg1"; 206 | version = "0.0.1"; 207 | src = ./empty; 208 | installPhase = "echo true > $out"; 209 | }; 210 | }) 211 | (f: (import f.packages.x86_64-linux.default) 212 | && (f ? packages.aarch64-linux.default) 213 | && ((nixpkgs.legacyPackages.x86_64-linux.extend f.overlays.default) ? pkg1) 214 | && (f ? checks.x86_64-linux.packages-default) 215 | && (f ? checks.aarch64-linux.packages-default)); 216 | 217 | packages = test 218 | (flakelight ./empty { 219 | packages = { 220 | default = { stdenv }: 221 | stdenv.mkDerivation { 222 | name = "pkg1"; 223 | src = ./empty; 224 | installPhase = "echo true > $out"; 225 | }; 226 | pkg2 = { stdenv, pkg1, pkg3 }: 227 | stdenv.mkDerivation { 228 | name = "hello-world"; 229 | src = ./empty; 230 | nativeBuildInputs = [ pkg1 pkg3 ]; 231 | installPhase = "echo true > $out"; 232 | }; 233 | pkg3 = { stdenv }: 234 | stdenv.mkDerivation { 235 | name = "hello-world"; 236 | src = ./empty; 237 | installPhase = "echo true > $out"; 238 | }; 239 | }; 240 | }) 241 | (f: 242 | (import f.packages.x86_64-linux.default) 243 | && (import f.packages.x86_64-linux.pkg2) 244 | && (import f.packages.x86_64-linux.pkg3) 245 | && ( 246 | let 247 | pkgs' = nixpkgs.legacyPackages.x86_64-linux.extend f.overlays.default; 248 | in 249 | (pkgs' ? pkg1) && (pkgs' ? pkg2) && (pkgs' ? pkg3) 250 | ) 251 | && (f ? checks.x86_64-linux.packages-default) 252 | && (f ? checks.x86_64-linux.packages-pkg2) 253 | && (f ? checks.x86_64-linux.packages-pkg3) 254 | ); 255 | 256 | package-overlay-no-default = test 257 | (flakelight ./empty { 258 | package = { stdenv }: 259 | stdenv.mkDerivation { 260 | name = "pkg1"; 261 | src = ./empty; 262 | installPhase = "echo true > $out"; 263 | }; 264 | }) 265 | (f: !((nixpkgs.legacyPackages.x86_64-linux.extend f.overlays.default) 266 | ? default)); 267 | 268 | packages-refer-default-as-default = test 269 | (flakelight ./empty { 270 | packages = { 271 | default = { stdenv }: 272 | stdenv.mkDerivation { 273 | name = "pkg1"; 274 | src = ./empty; 275 | installPhase = "echo true > $out"; 276 | }; 277 | pkg2 = { stdenv, default }: 278 | stdenv.mkDerivation { 279 | name = "hello-world"; 280 | src = ./empty; 281 | installPhase = "cat ${default} > $out"; 282 | }; 283 | }; 284 | }) 285 | (f: (import f.packages.x86_64-linux.pkg2)); 286 | 287 | packages-refer-default-as-name = test 288 | (flakelight ./empty { 289 | packages = { 290 | default = { stdenv }: 291 | stdenv.mkDerivation { 292 | name = "pkg1"; 293 | src = ./empty; 294 | installPhase = "echo true > $out"; 295 | }; 296 | pkg2 = { stdenv, pkg1 }: 297 | stdenv.mkDerivation { 298 | name = "hello-world"; 299 | src = ./empty; 300 | installPhase = "cat ${pkg1} > $out"; 301 | }; 302 | }; 303 | }) 304 | (f: (import f.packages.x86_64-linux.pkg2)); 305 | 306 | packages-fn-has-system = test 307 | (flakelight ./empty { 308 | packages = { system, ... }: (if system == "x86_64-linux" then { 309 | default = { stdenv }: 310 | stdenv.mkDerivation { 311 | name = "pkg1"; 312 | src = ./empty; 313 | installPhase = "echo true > $out"; 314 | }; 315 | } else { }); 316 | }) 317 | (f: (import f.packages.x86_64-linux.default) 318 | && !(f.packages.aarch64-linux ? default)); 319 | 320 | legacyPackages-set-pkgs = test 321 | (flakelight ./empty { 322 | inputs = { inherit nixpkgs; }; 323 | legacyPackages = pkgs: pkgs; 324 | }) 325 | (f: f.legacyPackages.x86_64-linux.hello 326 | == nixpkgs.legacyPackages.x86_64-linux.hello); 327 | 328 | legacyPackages-set-nixpkgs = test 329 | (flakelight ./empty { 330 | inputs = { inherit nixpkgs; }; 331 | legacyPackages = pkgs: nixpkgs.legacyPackages.${pkgs.system}; 332 | }) 333 | (f: f.legacyPackages.x86_64-linux.hello 334 | == nixpkgs.legacyPackages.x86_64-linux.hello); 335 | 336 | devShell = test 337 | (flakelight ./empty { 338 | devShell = { 339 | inputsFrom = pkgs: [ pkgs.emacs ]; 340 | packages = pkgs: [ pkgs.coreutils ]; 341 | shellHook = '' 342 | echo Welcome to example shell! 343 | ''; 344 | env.TEST_VAR = "test value"; 345 | stdenv = pkgs: pkgs.clangStdenv; 346 | hardeningDisable = [ "all" ]; 347 | }; 348 | }) 349 | (f: lib.isDerivation f.devShells.x86_64-linux.default); 350 | 351 | devShell-empty = test 352 | (flakelight ./empty { 353 | disabledModules = [ "builtinFormatters.nix" ]; 354 | devShell = { }; 355 | }) 356 | (f: lib.isDerivation f.devShells.x86_64-linux.default); 357 | 358 | devShell-pkgDef = test 359 | (flakelight ./empty { 360 | devShell = { mkShell }: mkShell { }; 361 | }) 362 | (f: lib.isDerivation f.devShells.x86_64-linux.default); 363 | 364 | devShell-pkgDef-empty = test 365 | (flakelight ./empty { 366 | disabledModules = [ "builtinFormatters.nix" ]; 367 | devShell = { mkShell }: mkShell { }; 368 | }) 369 | (f: lib.isDerivation f.devShells.x86_64-linux.default); 370 | 371 | devShell-pkgs-arg = test 372 | (flakelight ./empty { 373 | devShell = pkgs: { 374 | inputsFrom = [ pkgs.emacs ]; 375 | packages = [ pkgs.coreutils ]; 376 | shellHook = '' 377 | echo Welcome to example shell! 378 | ''; 379 | env.TEST_VAR = "test value"; 380 | stdenv = pkgs.clangStdenv; 381 | }; 382 | }) 383 | (f: lib.isDerivation f.devShells.x86_64-linux.default); 384 | 385 | devShell-pkgs-arg-set = test 386 | (flakelight ./empty { 387 | devShell = { emacs, coreutils, clangStdenv, ... }: { 388 | inputsFrom = [ emacs ]; 389 | packages = [ coreutils ]; 390 | shellHook = '' 391 | echo Welcome to example shell! 392 | ''; 393 | env.TEST_VAR = "test value"; 394 | stdenv = clangStdenv; 395 | }; 396 | }) 397 | (f: lib.isDerivation f.devShells.x86_64-linux.default); 398 | 399 | devShell-pkg = test 400 | (flakelight ./empty ({ inputs, ... }: { 401 | systems = [ "x86_64-linux" ]; 402 | devShell = inputs.nixpkgs.legacyPackages.x86_64-linux.hello; 403 | })) 404 | (f: lib.isDerivation f.devShells.x86_64-linux.default); 405 | 406 | devShell-pkg-fn = test 407 | (flakelight ./empty { 408 | devShell = pkgs: pkgs.hello; 409 | }) 410 | (f: lib.isDerivation f.devShells.x86_64-linux.default); 411 | 412 | devShells = test 413 | (flakelight ./empty { 414 | devShell.inputsFrom = pkgs: [ pkgs.emacs ]; 415 | devShells = { 416 | shell1 = { mkShell }: mkShell { }; 417 | shell2 = { packages = pkgs: [ pkgs.emacs ]; }; 418 | shell3 = pkgs: { packages = [ pkgs.emacs ]; }; 419 | shell4 = { emacs, ... }: { packages = [ emacs ]; }; 420 | }; 421 | }) 422 | (f: (lib.isDerivation f.devShells.x86_64-linux.default) 423 | && (lib.isDerivation f.devShells.x86_64-linux.shell1) 424 | && (lib.isDerivation f.devShells.x86_64-linux.shell2) 425 | && (lib.isDerivation f.devShells.x86_64-linux.shell3) 426 | && (lib.isDerivation f.devShells.x86_64-linux.shell4)); 427 | 428 | devShells-override = test 429 | (flakelight ./empty { 430 | devShells.default = { mkShell }: mkShell { }; 431 | }) 432 | (f: f ? devShells.x86_64-linux.default); 433 | 434 | devShells-import = test 435 | (flakelight ./empty ({ config, ... }: { 436 | devShell.inputsFrom = pkgs: [ pkgs.emacs ]; 437 | devShells.shell1 = pkgs: { imports = [ (config.devShell pkgs) ]; }; 438 | })) 439 | (f: (lib.isDerivation f.devShells.x86_64-linux.default) 440 | && (lib.isDerivation f.devShells.x86_64-linux.shell1)); 441 | 442 | overlay = test 443 | (flakelight ./empty { 444 | overlay = final: prev: { testValue = "hello"; }; 445 | }) 446 | (f: 447 | (lib.fix (self: f.overlays.default self { })) == 448 | { testValue = "hello"; } 449 | ); 450 | 451 | overlays = test 452 | (flakelight ./empty { 453 | overlay = final: prev: { testValue = "hello"; }; 454 | overlays.cool = final: prev: { testValue = "cool"; }; 455 | }) 456 | (f: 457 | ((lib.fix (self: f.overlays.default self { })) == 458 | { testValue = "hello"; }) 459 | && ((lib.fix (self: f.overlays.cool self { })) == 460 | { testValue = "cool"; })); 461 | 462 | overlay-merge = test 463 | (flakelight ./empty { 464 | imports = [ 465 | { overlay = final: prev: { testValue = "hello"; }; } 466 | { overlay = final: prev: { testValue2 = "hello2"; }; } 467 | ]; 468 | }) 469 | (f: ((lib.fix (self: f.overlays.default self { })) == 470 | { testValue = "hello"; testValue2 = "hello2"; })); 471 | 472 | overlays-merge = test 473 | (flakelight ./empty { 474 | imports = [ 475 | { overlays.test = final: prev: { testValue = "hello"; }; } 476 | { overlays.test = final: prev: { testValue2 = "hello2"; }; } 477 | ]; 478 | }) 479 | (f: ((lib.fix (self: f.overlays.test self { })) == 480 | { testValue = "hello"; testValue2 = "hello2"; })); 481 | 482 | checks = test 483 | (flakelight ./empty { 484 | checks = { 485 | test-fail = pkgs: "exit 1"; 486 | test-success = pkgs: pkgs.hello; 487 | }; 488 | }) 489 | (f: (f ? checks.x86_64-linux.test-fail) 490 | && (lib.isDerivation f.checks.x86_64-linux.test-success) 491 | && (f ? checks.x86_64-linux.test-success) 492 | && (lib.isDerivation f.checks.x86_64-linux.test-success)); 493 | 494 | app = test 495 | (flakelight ./empty { 496 | app = { 497 | type = "app"; 498 | program = "${nixpkgs.legacyPackages.x86_64-linux.hello}/bin/hello"; 499 | }; 500 | }) 501 | (f: (f.apps.x86_64-linux.default == { 502 | type = "app"; 503 | program = "${nixpkgs.legacyPackages.x86_64-linux.hello}/bin/hello"; 504 | })); 505 | 506 | app-fn = test 507 | (flakelight ./empty { 508 | app = pkgs: { 509 | type = "app"; 510 | program = "${pkgs.hello}/bin/hello"; 511 | }; 512 | }) 513 | (f: (f.apps.x86_64-linux.default == { 514 | type = "app"; 515 | program = "${nixpkgs.legacyPackages.x86_64-linux.hello}/bin/hello"; 516 | })); 517 | 518 | app-string = test 519 | (flakelight ./empty { 520 | inputs = { inherit nixpkgs; }; 521 | app = "${nixpkgs.legacyPackages.x86_64-linux.hello}/bin/hello"; 522 | }) 523 | (f: (f.apps.x86_64-linux.default == { 524 | type = "app"; 525 | program = "${nixpkgs.legacyPackages.x86_64-linux.hello}/bin/hello"; 526 | })); 527 | 528 | app-string-fn = test 529 | (flakelight ./empty { 530 | inputs = { inherit nixpkgs; }; 531 | app = pkgs: "${pkgs.hello}/bin/hello"; 532 | }) 533 | (f: (f.apps.x86_64-linux.default == { 534 | type = "app"; 535 | program = "${nixpkgs.legacyPackages.x86_64-linux.hello}/bin/hello"; 536 | })); 537 | 538 | apps = test 539 | (flakelight ./empty { 540 | inputs = { inherit nixpkgs; }; 541 | apps = { 542 | emacs = pkgs: "${pkgs.emacs}/bin/emacs"; 543 | bash = pkgs: { type = "app"; program = "${pkgs.bash}/bin/bash"; }; 544 | }; 545 | }) 546 | (f: f.apps.x86_64-linux == { 547 | emacs = { 548 | type = "app"; 549 | program = "${nixpkgs.legacyPackages.x86_64-linux.emacs}/bin/emacs"; 550 | }; 551 | bash = { 552 | type = "app"; 553 | program = "${nixpkgs.legacyPackages.x86_64-linux.bash}/bin/bash"; 554 | }; 555 | }); 556 | 557 | apps-fn = test 558 | (flakelight ./empty { 559 | inputs = { inherit nixpkgs; }; 560 | apps = { emacs, bash, ... }: { 561 | emacs = "${emacs}/bin/emacs"; 562 | bash = { type = "app"; program = "${bash}/bin/bash"; }; 563 | }; 564 | }) 565 | (f: f.apps.x86_64-linux == { 566 | emacs = { 567 | type = "app"; 568 | program = "${nixpkgs.legacyPackages.x86_64-linux.emacs}/bin/emacs"; 569 | }; 570 | bash = { 571 | type = "app"; 572 | program = "${nixpkgs.legacyPackages.x86_64-linux.bash}/bin/bash"; 573 | }; 574 | }); 575 | 576 | template = test 577 | (flakelight ./empty { 578 | template = { 579 | path = ./test; 580 | description = "test template"; 581 | }; 582 | }) 583 | (f: f.templates.default == { 584 | path = ./test; 585 | description = "test template"; 586 | }); 587 | 588 | templates = test 589 | (flakelight ./empty { 590 | templates.test-template = { 591 | path = ./test; 592 | description = "test template"; 593 | }; 594 | }) 595 | (f: f.templates.test-template == { 596 | path = ./test; 597 | description = "test template"; 598 | }); 599 | 600 | templates-welcomeText = test 601 | (flakelight ./empty { 602 | templates.test-template = { 603 | path = ./test; 604 | description = "test template"; 605 | welcomeText = "hi"; 606 | }; 607 | }) 608 | (f: f.templates.test-template == { 609 | path = ./test; 610 | description = "test template"; 611 | welcomeText = "hi"; 612 | }); 613 | 614 | formatter = test 615 | (flakelight ./empty { 616 | formatter = pkgs: pkgs.hello; 617 | }) 618 | (f: lib.isDerivation f.formatter.x86_64-linux); 619 | 620 | formatters = test 621 | (flakelight ./empty { 622 | devShell.packages = pkgs: [ pkgs.rustfmt ]; 623 | formatters = { 624 | "*.rs" = "rustfmt"; 625 | }; 626 | }) 627 | (f: lib.isDerivation f.formatter.x86_64-linux); 628 | 629 | formatters-fn = test 630 | (flakelight ./empty { 631 | formatters = { rustfmt, ... }: { 632 | "*.rs" = "${rustfmt}"; 633 | }; 634 | }) 635 | (f: lib.isDerivation f.formatter.x86_64-linux); 636 | 637 | formatters-no-devshell = test 638 | (flakelight ./empty { 639 | devShell = lib.mkForce null; 640 | formatters = { rustfmt, ... }: { 641 | "*.rs" = "${rustfmt}"; 642 | }; 643 | }) 644 | (f: lib.isDerivation f.formatter.x86_64-linux); 645 | 646 | formatters-disable = test 647 | (flakelight ./empty { 648 | flakelight.builtinFormatters = false; 649 | }) 650 | (f: ! f ? formatter.x86_64-linux); 651 | 652 | formatters-disable-only-builtin = test 653 | (flakelight ./empty { 654 | flakelight.builtinFormatters = false; 655 | formatters = { rustfmt, ... }: { 656 | "*.rs" = "rustfmt"; 657 | }; 658 | }) 659 | (f: f ? formatter.x86_64-linux); 660 | 661 | bundler = test 662 | (flakelight ./empty { 663 | bundler = x: x; 664 | }) 665 | (f: (f.bundlers.x86_64-linux.default 666 | nixpkgs.legacyPackages.x86_64-linux.hello) 667 | == nixpkgs.legacyPackages.x86_64-linux.hello); 668 | 669 | bundler-fn = test 670 | (flakelight ./empty { 671 | bundler = pkgs: x: pkgs.hello; 672 | }) 673 | (f: (f.bundlers.x86_64-linux.default 674 | nixpkgs.legacyPackages.x86_64-linux.emacs) 675 | == nixpkgs.legacyPackages.x86_64-linux.hello); 676 | 677 | bundlers = test 678 | (flakelight ./empty { 679 | bundlers = { 680 | hello = x: x; 681 | }; 682 | }) 683 | (f: (f.bundlers.x86_64-linux.hello 684 | nixpkgs.legacyPackages.x86_64-linux.hello) 685 | == nixpkgs.legacyPackages.x86_64-linux.hello); 686 | 687 | bundlers-fn = test 688 | (flakelight ./empty { 689 | bundlers = { hello, ... }: { 690 | hello = x: hello; 691 | }; 692 | }) 693 | (f: (f.bundlers.x86_64-linux.hello 694 | nixpkgs.legacyPackages.x86_64-linux.emacs) 695 | == nixpkgs.legacyPackages.x86_64-linux.hello); 696 | 697 | nixosConfigurations = test 698 | (flakelight ./empty ({ lib, ... }: { 699 | nixosConfigurations.test = { 700 | system = "x86_64-linux"; 701 | modules = [{ system.stateVersion = "24.05"; }]; 702 | }; 703 | })) 704 | (f: f ? nixosConfigurations.test.config.system.build.toplevel); 705 | 706 | nixosConfigurationsManual = test 707 | (flakelight ./empty ({ lib, ... }: { 708 | nixosConfigurations.test = nixpkgs.lib.nixosSystem { 709 | system = "x86_64-linux"; 710 | modules = [{ system.stateVersion = "24.05"; }]; 711 | }; 712 | })) 713 | (f: f ? nixosConfigurations.test.config.system.build.toplevel); 714 | 715 | nixosConfigurationsManualWithProp = test 716 | (flakelight ./empty ({ lib, config, ... }: { 717 | nixosConfigurations.test = nixpkgs.lib.nixosSystem { 718 | system = "x86_64-linux"; 719 | modules = [ 720 | config.propagationModule 721 | ({ flake, ... }: { 722 | system.stateVersion = "24.05"; 723 | environment.variables = { 724 | TEST1 = flake.inputs.nixpkgs.legacyPackages.x86_64-linux.hello; 725 | TEST2 = flake.inputs'.nixpkgs.legacyPackages.hello; 726 | }; 727 | }) 728 | ]; 729 | }; 730 | })) 731 | (f: (f ? nixosConfigurations.test.config.system.build.toplevel) 732 | && (f.nixosConfigurations.test.config.environment.variables.TEST1 == 733 | f.nixosConfigurations.test.config.environment.variables.TEST2)); 734 | 735 | nixosModule = test 736 | (flakelight ./empty { 737 | nixosModule = _: { }; 738 | }) 739 | (f: f ? nixosModules.default); 740 | 741 | nixosModules = test 742 | (flakelight ./empty { 743 | nixosModules.test = _: { }; 744 | }) 745 | (f: f ? nixosModules.test); 746 | 747 | homeModule = test 748 | (flakelight ./empty { 749 | homeModule = _: { }; 750 | }) 751 | (f: f ? homeModules.default); 752 | 753 | homeModules = test 754 | (flakelight ./empty { 755 | homeModules.test = _: { }; 756 | }) 757 | (f: f ? homeModules.test); 758 | 759 | flakelightModule = test 760 | (flakelight ./empty { 761 | flakelightModule = _: { }; 762 | }) 763 | (f: f ? flakelightModules.default); 764 | 765 | flakelightModules = test 766 | (flakelight ./empty { 767 | flakelightModules.test = _: { }; 768 | }) 769 | (f: f ? flakelightModules.test); 770 | 771 | lib = test 772 | (flakelight ./empty { 773 | lib.addFive = x: x + 5; 774 | }) 775 | (f: f.lib.addFive 4 == 9); 776 | 777 | functor = test 778 | (flakelight ./empty { 779 | outputs.testvalue = 5; 780 | functor = self: x: x + self.testvalue; 781 | }) 782 | (f: f 4 == 9); 783 | 784 | meta = test 785 | (flakelight ./empty { 786 | description = "aaa"; 787 | license = "AGPL-3.0-only"; 788 | packages.test = { writeTextFile, defaultMeta }: 789 | writeTextFile { 790 | name = "test"; 791 | text = ""; 792 | meta = defaultMeta; 793 | }; 794 | }) 795 | (f: (f.packages.x86_64-linux.test.meta.description == "aaa") 796 | && (f.packages.x86_64-linux.test.meta.license.spdxId 797 | == "AGPL-3.0-only")); 798 | 799 | meta-license-attrname = test 800 | (flakelight ./empty { 801 | license = "agpl3Only"; 802 | packages.test = { writeTextFile, defaultMeta }: 803 | writeTextFile { 804 | name = "test"; 805 | text = ""; 806 | meta = defaultMeta; 807 | }; 808 | }) 809 | (f: f.packages.x86_64-linux.test.meta.license.spdxId == "AGPL-3.0-only"); 810 | 811 | meta-licenses = test 812 | (flakelight ./empty { 813 | license = [ "agpl3Only" "AGPL-3.0-or-later" ]; 814 | packages.test = { writeTextFile, defaultMeta }: 815 | writeTextFile { 816 | name = "test"; 817 | text = ""; 818 | meta = defaultMeta; 819 | }; 820 | }) 821 | (f: builtins.isList f.packages.x86_64-linux.test.meta.license); 822 | 823 | editorconfig = test 824 | (flakelight ./editorconfig { }) 825 | (f: f ? checks.x86_64-linux.editorconfig); 826 | 827 | editorconfig-disabled = test 828 | (flakelight ./editorconfig { 829 | flakelight.editorconfig = false; 830 | }) 831 | (f: ! f ? checks.x86_64-linux.editorconfig); 832 | 833 | modulesPath = test 834 | (flakelight ./empty { 835 | disabledModules = [ "functor.nix" "nixDir.nix" ]; 836 | functor = _: _: true; 837 | }) 838 | (f: !(builtins.tryEval f).success); 839 | 840 | empty-flake = test 841 | (flakelight ./empty { 842 | disabledModules = [ "builtinFormatters.nix" ]; 843 | }) 844 | (f: f == { }); 845 | 846 | default-nixpkgs = test 847 | (flakelight ./empty ({ inputs, ... }: { 848 | outputs = { inherit inputs; }; 849 | })) 850 | (f: f.inputs ? nixpkgs.lib); 851 | 852 | extend-mkFlake = 853 | let 854 | extended = flakelight.lib.mkFlake.extend [{ outputs.test = true; }]; 855 | in 856 | test 857 | (extended ./empty { }) 858 | (f: f.test); 859 | 860 | extend-mkFlake-nested = 861 | let 862 | extended = flakelight.lib.mkFlake.extend [{ outputs.test = true; }]; 863 | extended2 = extended.extend [{ outputs.test2 = true; }]; 864 | extended3 = extended2.extend [{ outputs.test3 = true; }]; 865 | in 866 | test 867 | (extended3 ./empty { }) 868 | (f: f.test && f.test2 && f.test3); 869 | } 870 | -------------------------------------------------------------------------------- /tests/editorconfig/.editorconfig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nix-community/flakelight/dfbecd12d99c1bf82906521a6a7d5b75d2aa1ca2/tests/editorconfig/.editorconfig -------------------------------------------------------------------------------- /tests/empty/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nix-community/flakelight/dfbecd12d99c1bf82906521a6a7d5b75d2aa1ca2/tests/empty/.keep --------------------------------------------------------------------------------