forked from extern/flakelight
Initial commit
This commit is contained in:
commit
4ec111408e
17
.editorconfig
Normal file
17
.editorconfig
Normal file
@ -0,0 +1,17 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
max_line_length = 80
|
||||
|
||||
[{*.nix,flake.lock}]
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
indent_size = 2
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/.direnv
|
||||
result
|
20
LICENSE
Normal file
20
LICENSE
Normal file
@ -0,0 +1,20 @@
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2023 Archit Gupta
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the “Software”), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# flakelite
|
||||
|
||||
An opinionated Nix flake framework for making flakes simple.
|
268
default.nix
Normal file
268
default.nix
Normal file
@ -0,0 +1,268 @@
|
||||
# flakelite -- Framework for making flakes simple
|
||||
# Copyright (C) 2023 Archit Gupta <archit@accelbread.com>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
nixpkgs:
|
||||
let
|
||||
inherit (builtins) readDir;
|
||||
inherit (nixpkgs.lib) attrNames attrVals composeManyExtensions filter
|
||||
filterAttrs foldAttrs foldl genAttrs hasSuffix isFunction isList listToAttrs
|
||||
mapAttrs mapAttrsToList mapAttrs' mergeAttrs nameValuePair optional
|
||||
optionalAttrs optionalString parseDrvName pathExists pipe recursiveUpdate
|
||||
removeSuffix zipAttrsWith;
|
||||
|
||||
baseModule = src: inputs: root: {
|
||||
withOverlay = final: prev: {
|
||||
flakelite.meta = {
|
||||
platforms = root.systems;
|
||||
} // optionalAttrs (root ? description) {
|
||||
inherit (root) description;
|
||||
} // optionalAttrs (root ? license) {
|
||||
license =
|
||||
if isList root.license
|
||||
then attrVals root.license final.lib.licenses
|
||||
else final.lib.licenses.${root.license};
|
||||
};
|
||||
};
|
||||
checks = { pkgs, lib, ... }:
|
||||
(optionalAttrs (pathExists (src + /.editorconfig)) {
|
||||
editorconfig = "${lib.getExe pkgs.editorconfig-checker}"
|
||||
+ optionalString (!pathExists (src + /.ecrc))
|
||||
" -disable-indent-size -disable-max-line-length";
|
||||
});
|
||||
devTools = { pkgs, ... }: with pkgs; [
|
||||
nixpkgs-fmt
|
||||
nodePackages.prettier
|
||||
];
|
||||
formatters = {
|
||||
"*.nix" = "nixpkgs-fmt";
|
||||
"*.md" = "prettier --write";
|
||||
};
|
||||
};
|
||||
|
||||
mkFlake = src: inputs: root:
|
||||
let
|
||||
modules = root.modules or pipe (inputs // { self = { }; }) [
|
||||
(filterAttrs (_: v: v ? flakeliteModule))
|
||||
(mapAttrsToList (_: v: v.flakeliteModule))
|
||||
];
|
||||
|
||||
defaultModule = {
|
||||
withOverlays = [ ];
|
||||
packages = { };
|
||||
devTools = _: [ ];
|
||||
env = _: { };
|
||||
overlays = { };
|
||||
apps = _: { };
|
||||
checks = _: { };
|
||||
nixosModules = { };
|
||||
nixosConfigurations = { };
|
||||
templates = { };
|
||||
formatters = _: { };
|
||||
};
|
||||
|
||||
mergeListFns = f1: f2: args: (f1 args) ++ (f2 args);
|
||||
mergeAttrFns = f1: f2: args: (f1 args) // (f2 args);
|
||||
|
||||
mkFunc = v: if isFunction v then v else _: v;
|
||||
|
||||
normalizeModule = module:
|
||||
let
|
||||
module' = defaultModule // module;
|
||||
in
|
||||
module' // {
|
||||
withOverlays = module'.withOverlays
|
||||
++ optional (module' ? withOverlay) module'.withOverlay;
|
||||
packages = module'.packages // optionalAttrs (module' ? package) {
|
||||
default = module'.package;
|
||||
};
|
||||
devTools = mkFunc module'.devTools;
|
||||
env = mkFunc module'.env;
|
||||
overlays = module'.overlays // optionalAttrs (module' ? overlay) {
|
||||
default = module'.overlay;
|
||||
};
|
||||
apps = mkFunc module'.apps;
|
||||
checks = mkFunc module'.checks;
|
||||
formatters = mkFunc module'.formatters;
|
||||
};
|
||||
|
||||
mergeModules = m1: m2: {
|
||||
withOverlays = m1.withOverlays ++ m2.withOverlays;
|
||||
packages = m1.packages // m2.packages;
|
||||
devTools = mergeListFns m1.devTools m2.devTools;
|
||||
env = mergeAttrFns m1.env m2.env;
|
||||
overlays = zipAttrsWith (_: composeManyExtensions)
|
||||
[ m1.overlays m2.overlays ];
|
||||
apps = mergeAttrFns m1.apps m2.apps;
|
||||
checks = mergeAttrFns m1.checks m2.checks;
|
||||
nixosModules = m1.nixosModules // m2.nixosModules;
|
||||
nixosConfigurations = m1.nixosConfigurations // m2.nixosConfigurations;
|
||||
templates = m1.templates // m2.templates;
|
||||
formatters = mergeAttrFns m1.formatters m2.formatters;
|
||||
};
|
||||
|
||||
root' = normalizeModule root // {
|
||||
systems = root.systems or systems.linuxDefault;
|
||||
perSystem = mkFunc root.perSystem or (_: { });
|
||||
outputs = root.outputs or { };
|
||||
};
|
||||
|
||||
merged = foldl mergeModules defaultModule
|
||||
((map (m: normalizeModule (m src inputs root'))
|
||||
([ baseModule ] ++ modules)) ++ [ root' ]);
|
||||
|
||||
pkgsFor = system: import (inputs.nixpkgs or nixpkgs) {
|
||||
inherit system;
|
||||
overlays = merged.withOverlays;
|
||||
};
|
||||
|
||||
systemPkgs = listToAttrs (map
|
||||
(system: nameValuePair system (pkgsFor system))
|
||||
root'.systems);
|
||||
|
||||
genPackages = pkgs: mapAttrs (_: v: pkgs.callPackage v { });
|
||||
|
||||
genMutualPackages = pkgs: packageSet:
|
||||
let
|
||||
overlay = final: _: genPackages final packageSet;
|
||||
pkgs' = pkgs.extend overlay;
|
||||
in
|
||||
genAttrs (attrNames packageSet) (p: pkgs'.${p});
|
||||
|
||||
mkCheck = pkgs: name: cmd: pkgs.runCommand "check-${name}" { } ''
|
||||
cp --no-preserve=mode -r ${src} src
|
||||
cd src
|
||||
${cmd}
|
||||
touch $out
|
||||
'';
|
||||
|
||||
mkApp = lib: program: {
|
||||
type = "app";
|
||||
program =
|
||||
if lib.isDerivation program
|
||||
then lib.getExe program
|
||||
else program;
|
||||
};
|
||||
|
||||
eachSystem = fn: foldAttrs mergeAttrs { } (map
|
||||
(system: mapAttrs
|
||||
(_: v: { ${system} = v; })
|
||||
(fn systemPkgs.${system}))
|
||||
root'.systems);
|
||||
|
||||
mergeOutputs = foldl
|
||||
(acc: new: recursiveUpdate acc ((mkFunc new) acc))
|
||||
{ };
|
||||
|
||||
getName = pkg: root.name or pkg.pname or (parseDrvName pkg).name;
|
||||
|
||||
replaceDefault = set:
|
||||
if set ? default
|
||||
then (removeAttrs set [ "default" ]) //
|
||||
{ ${getName set.default} = set.default; }
|
||||
else set;
|
||||
|
||||
supportedSystem = { lib, stdenv, ... }: pkg:
|
||||
if pkg ? meta.platforms
|
||||
then lib.meta.availableOn stdenv.hostPlatform pkg
|
||||
else true;
|
||||
in
|
||||
mergeOutputs [
|
||||
|
||||
(optionalAttrs (merged.packages != { }) ({
|
||||
overlays.default = final: _: genPackages
|
||||
(final.appendOverlays merged.withOverlays)
|
||||
(replaceDefault merged.packages);
|
||||
} // eachSystem (pkgs: rec {
|
||||
packages = filterAttrs (_: supportedSystem pkgs)
|
||||
(genMutualPackages pkgs merged.packages);
|
||||
checks = mapAttrs' (k: nameValuePair ("packages-" + k)) packages;
|
||||
})))
|
||||
|
||||
(prev: optionalAttrs (merged.overlays != { }) ({
|
||||
overlays = zipAttrsWith (_: composeManyExtensions)
|
||||
[ (prev.overlays or { }) merged.overlays ];
|
||||
}))
|
||||
|
||||
(eachSystem ({ pkgs, lib, ... }:
|
||||
optionalAttrs (merged.formatters pkgs != { }) rec {
|
||||
formatter = pkgs.writeShellScriptBin "formatter" ''
|
||||
PATH=${lib.makeBinPath (merged.devTools pkgs)}
|
||||
for f in "$@"; do
|
||||
if [ -d "$f" ]; then
|
||||
${pkgs.fd}/bin/fd "$f" -Htf -x "$0"
|
||||
else
|
||||
case "$(${pkgs.coreutils}/bin/basename "$f")" in
|
||||
${toString (mapAttrsToList (k: v: "${k}) ${v} \"$f\";;")
|
||||
(merged.formatters pkgs))}
|
||||
esac
|
||||
fi
|
||||
done &>/dev/null
|
||||
'';
|
||||
checks.formatting = mkCheck pkgs "formatting" ''
|
||||
${lib.getExe formatter} .
|
||||
${pkgs.diffutils}/bin/diff -qr ${src} . |\
|
||||
sed 's/Files .* and \(.*\) differ/File \1 not formatted/g'
|
||||
'';
|
||||
}))
|
||||
|
||||
(eachSystem ({ pkgs, lib, ... }:
|
||||
let
|
||||
checks = mapAttrs
|
||||
(k: v: if lib.isDerivation v then v else mkCheck pkgs k v)
|
||||
(merged.checks pkgs);
|
||||
in
|
||||
optionalAttrs (checks != { }) { inherit checks; }))
|
||||
|
||||
(eachSystem ({ pkgs, lib, ... }:
|
||||
let
|
||||
apps = mapAttrs (_: mkApp lib) (merged.apps pkgs);
|
||||
in
|
||||
optionalAttrs (apps != { }) { inherit apps; }))
|
||||
|
||||
(optionalAttrs (merged.nixosModules != { }) {
|
||||
inherit (merged) nixosModules;
|
||||
})
|
||||
|
||||
(optionalAttrs (merged.nixosConfigurations != { }) {
|
||||
inherit (merged) nixosConfigurations;
|
||||
})
|
||||
|
||||
(optionalAttrs (merged.templates != { }) {
|
||||
inherit (merged) templates;
|
||||
})
|
||||
|
||||
(prev: eachSystem ({ pkgs, system, mkShell, ... }: {
|
||||
devShells.default = mkShell (merged.env pkgs // {
|
||||
inputsFrom = optional (prev ? packages.${system}.default)
|
||||
prev.packages.${system}.default;
|
||||
packages = merged.devTools pkgs;
|
||||
});
|
||||
}))
|
||||
|
||||
(eachSystem root'.perSystem)
|
||||
|
||||
root'.outputs
|
||||
];
|
||||
|
||||
loadNixDir = path: genAttrs
|
||||
(pipe (readDir path) [
|
||||
attrNames
|
||||
(filter (hasSuffix ".nix"))
|
||||
(map (removeSuffix ".nix"))
|
||||
])
|
||||
(p: import (path + "/${p}.nix"));
|
||||
|
||||
systems = rec {
|
||||
linuxDefault = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
linuxAll = linuxDefault ++ [
|
||||
"armv6l-linux"
|
||||
"armv7l-linux"
|
||||
"i686-linux"
|
||||
];
|
||||
};
|
||||
in
|
||||
{ inherit mkFlake loadNixDir systems; }
|
26
flake.lock
Normal file
26
flake.lock
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1680665430,
|
||||
"narHash": "sha256-MTVhTukwza1Jlq2gECITZPFnhROmylP2uv3O3cSqQCE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5233fd2ba76a3accb5aaa999c00509a11fd0793c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-22.11",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
14
flake.nix
Normal file
14
flake.nix
Normal file
@ -0,0 +1,14 @@
|
||||
# flakelite -- Framework for making flakes simple
|
||||
# Copyright (C) 2023 Archit Gupta <archit@accelbread.com>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
{
|
||||
inputs.nixpkgs.url = "nixpkgs/nixos-22.11";
|
||||
outputs = { self, nixpkgs }@inputs:
|
||||
let
|
||||
lib = import ./. nixpkgs;
|
||||
in
|
||||
lib.mkFlake ./. inputs {
|
||||
outputs = { inherit lib; };
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user