{ description = "A framework for 2nix tools"; inputs = { nixpkgs.url = "nixpkgs/nixos-unstable"; ### dev dependencies alejandra.url = github:kamadorueda/alejandra; alejandra.inputs.nixpkgs.follows = "nixpkgs"; pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix"; pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs"; # upstream flake-utils dep not supporting `aarch64-darwin` yet flake-utils-pre-commit.url = "github:numtide/flake-utils"; pre-commit-hooks.inputs.flake-utils.follows = "flake-utils-pre-commit"; ### framework dependencies # required for builder go/gomod2nix gomod2nix = { url = "github:tweag/gomod2nix"; flake = false; }; # required for translator pip mach-nix = { url = "mach-nix"; flake = false; }; # required for builder nodejs/node2nix node2nix = { url = "github:svanderburg/node2nix"; flake = false; }; # required for utils.satisfiesSemver poetry2nix = { url = "github:nix-community/poetry2nix/1.21.0"; flake = false; }; # required for builder rust/crane crane = { url = "github:ipetkov/crane"; flake = false; }; }; outputs = { self, alejandra, gomod2nix, mach-nix, nixpkgs, node2nix, poetry2nix, pre-commit-hooks, crane, ... } @ inp: let b = builtins; l = lib // builtins; lib = nixpkgs.lib; # dream2nix lib (system independent utils) dlib = import ./src/lib {inherit lib;}; supportedSystems = ["x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin"]; forSystems = systems: f: lib.genAttrs systems (system: f system nixpkgs.legacyPackages.${system}); forAllSystems = forSystems supportedSystems; # To use dream2nix in non-flake + non-IFD enabled repos, the source code of dream2nix # must be installed into these repos (using nix run dream2nix#install). # The problem is, all of dream2nix' dependecies need to be installed as well. # Therefore 'externalPaths' contains all relevant files of external projects # which dream2nix depends on. Exactly these files will be installed. externalPaths = { mach-nix = [ "lib/extractor/default.nix" "lib/extractor/distutils.patch" "lib/extractor/setuptools.patch" "LICENSE" ]; node2nix = [ "nix/node-env.nix" "LICENSE" ]; poetry2nix = [ "semver.nix" "LICENSE" ]; crane = [ "lib/buildDepsOnly.nix" "lib/buildPackage.nix" "lib/cargoBuild.nix" "lib/cleanCargoToml.nix" "lib/findCargoFiles.nix" "lib/mkCargoDerivation.nix" "lib/mkDummySrc.nix" "lib/writeTOML.nix" "pkgs/configureCargoCommonVarsHook.sh" "pkgs/configureCargoVendoredDepsHook.sh" "pkgs/installFromCargoBuildLogHook.sh" "pkgs/inheritCargoArtifactsHook.sh" "pkgs/installCargoArtifactsHook.sh" "pkgs/remapSourcePathPrefixHook.sh" "LICENSE" ]; }; # create a directory containing the files listed in externalPaths makeExternalDir = import ./src/utils/external-dir.nix; externalDirFor = forAllSystems (system: pkgs: makeExternalDir { inherit externalPaths externalSources pkgs; }); # An interface to access files of external projects. # This implementation accesses the flake inputs directly, # but if dream2nix is used without flakes, it defaults # to another implementation of that function which # uses the installed external paths instead (see default.nix) externalSources = lib.genAttrs (lib.attrNames externalPaths) (inputName: inp."${inputName}"); overridesDirs = ["${./overrides}"]; # system specific dream2nix api dream2nixFor = forAllSystems (system: pkgs: import ./src rec { externalDir = externalDirFor."${system}"; inherit dlib externalPaths externalSources lib pkgs; config = { inherit overridesDirs; }; }); pre-commit-check = forAllSystems ( system: pkgs: pre-commit-hooks.lib.${system}.run { src = ./.; hooks = { treefmt = { enable = true; name = "treefmt"; pass_filenames = true; entry = l.toString (pkgs.writeScript "treefmt" '' #!${pkgs.bash}/bin/bash export PATH="$PATH:${alejandra.defaultPackage.${system}}/bin" ${pkgs.treefmt}/bin/treefmt --fail-on-change "$@" ''); }; }; } ); in { # System independent dream2nix api. # Similar to drem2nixFor but will require 'system(s)' or 'pkgs' as an argument. # Produces flake-like output schema. lib = (import ./src/lib.nix { inherit dlib externalPaths externalSources overridesDirs lib; nixpkgsSrc = "${nixpkgs}"; }) # system specific dream2nix library // (forAllSystems (system: pkgs: dream2nixFor."${system}")); # with project discovery enabled lib2 = self.lib; # all apps including cli, install, etc. apps = forAllSystems ( system: pkgs: dream2nixFor."${system}".apps.flakeApps // { tests-unit.type = "app"; tests-unit.program = b.toString (dream2nixFor."${system}".callPackageDream ./tests/unit { inherit self; }); tests-examples.type = "app"; tests-examples.program = b.toString (dream2nixFor."${system}".callPackageDream ./tests/examples { inherit self; }); tests-all.type = "app"; tests-all.program = l.toString (dream2nixFor.${system}.utils.writePureShellScript [ alejandra.defaultPackage.${system} pkgs.coreutils pkgs.gitMinimal pkgs.nix ] '' echo "check for correct formatting" cp -r $WORKDIR ./repo cd ./repo ${self.apps.${system}.format.program} --fail-on-change cd - echo "running unit tests" ${self.apps.${system}.tests-unit.program} echo "checking flakes under ./examples" ${self.apps.${system}.tests-examples.program} echo "running nix flake check" cd $WORKDIR nix flake show >/dev/null nix flake check ''); # passes through extra flags to treefmt format.type = "app"; format.program = l.toString (pkgs.writeScript "format" '' export PATH="${alejandra.defaultPackage.${system}}/bin" ${pkgs.treefmt}/bin/treefmt --clear-cache "$@" ''); } ); # a dev shell for working on dream2nix # use via 'nix develop . -c $SHELL' devShell = forAllSystems (system: pkgs: pkgs.mkShell { buildInputs = (with pkgs; [ nix treefmt ]) ++ [ alejandra.defaultPackage."${system}" ] # using linux is highly recommended as cntr is amazing for debugging builds ++ lib.optionals pkgs.stdenv.isLinux [pkgs.cntr]; shellHook = self.checks.${system}.pre-commit-check.shellHook + '' export NIX_PATH=nixpkgs=${nixpkgs} export d2nExternalDir=${externalDirFor."${system}"} export dream2nixWithExternals=${dream2nixFor."${system}".dream2nixWithExternals} if [ -e ./overrides ]; then export d2nOverridesDir=$(realpath ./overrides) else export d2nOverridesDir=${./overrides} echo -e "\nManually execute 'export d2nOverridesDir={path to your dream2nix overrides dir}'" fi if [ -e ../dream2nix ]; then export dream2nixWithExternals=$(realpath ./src) else export dream2nixWithExternals=${./src} echo -e "\nManually execute 'export dream2nixWithExternals={path to your dream2nix checkout}'" fi ''; }); checks = forAllSystems (system: pkgs: { pre-commit-check = pre-commit-hooks.lib.${system}.run { src = ./.; hooks = { treefmt = { enable = true; name = "treefmt"; pass_filenames = false; entry = l.toString (pkgs.writeScript "treefmt" '' #!${pkgs.bash}/bin/bash export PATH="$PATH:${alejandra.defaultPackage.${system}}/bin" ${pkgs.treefmt}/bin/treefmt --clear-cache --fail-on-change ''); }; }; }; }); templates = { simple = { description = "Simple dream2nix flake"; path = ./templates/simple; }; }; }; }