about summary refs log tree commit diff stats
path: root/flake.nix
diff options
context:
space:
mode:
Diffstat (limited to 'flake.nix')
-rw-r--r--flake.nix187
1 files changed, 187 insertions, 0 deletions
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 00000000..89818257
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,187 @@
+{
+	description = "Focaccia: A Symbolic Tester for QEMU";
+
+	inputs = {
+		self.submodules = true;
+
+		nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+
+		flake-utils.url = "github:numtide/flake-utils";
+
+		pyproject-nix = {
+			url = "github:pyproject-nix/pyproject.nix";
+			inputs.nixpkgs.follows = "nixpkgs";
+		};
+
+		uv2nix = {
+			url = "github:pyproject-nix/uv2nix";
+			inputs.nixpkgs.follows = "nixpkgs";
+			inputs.pyproject-nix.follows = "pyproject-nix";
+		};
+
+		pyproject-build-systems = {
+			url = "github:pyproject-nix/build-system-pkgs";
+			inputs.uv2nix.follows = "uv2nix";
+			inputs.nixpkgs.follows = "nixpkgs";
+			inputs.pyproject-nix.follows = "pyproject-nix";
+		};
+	};
+
+	outputs = {
+		uv2nix,
+		nixpkgs,
+		flake-utils,
+		pyproject-nix,
+		pyproject-build-systems,
+		...
+	}:
+	flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ] (system:
+	let
+		# Refine nixpkgs used in flake to system arch
+		pkgs = import nixpkgs {
+			inherit system;
+		};
+
+		# Pin Python version
+		python = pkgs.python312;
+
+		# Define workspace root and load uv workspace metadata
+		workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; };
+
+		# Create an overlay for Nix that includes extracted Python packages declared as dependencies
+		# in uv
+		overlay = workspace.mkPyprojectOverlay { sourcePreference = "wheel"; };
+
+		editableOverlay = workspace.mkEditablePyprojectOverlay {
+			# Use environment variable
+			root = "$REPO_ROOT";
+
+			members = [ "miasm" ];
+		};
+
+		# Another overlay layer for flake-specific overloads
+		# This might be needed because uv does not have sufficient metadata
+		# Here, uv does include metadata about build systems used by each dependency
+		# Ergo we need to add a nativeBuildInput to miasm because it depends on setuptools for its
+		# installation
+		pyprojectOverrides = self: super: {
+			miasm = super.miasm.overrideAttrs (old: {
+				nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ self.setuptools ];
+			});
+
+			z3-solver = super.z3-solver.overrideAttrs (old: {
+				nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ self.setuptools self.cmake ];
+			});
+		};
+
+		pyprojectOverridesEditable = self: super: {
+			miasm = super.miasm.overrideAttrs (old: {
+				nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ self.setuptools ];
+
+				src = pkgs.lib.fileset.toSource {
+					root = old.src;
+					fileset = pkgs.lib.fileset.unions [
+						(old.src + "/pyproject.toml")
+						(old.src + "/README.md")
+						(old.src + "/miasm/__init__.py")
+					];
+				};
+			});
+
+			z3-solver = super.z3-solver.overrideAttrs (old: {
+				nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ self.setuptools self.cmake ];
+			});
+		};
+
+		# Build a set of Python packages
+		# The call to callPackage here uses the base package set from pyproject.nix
+		# We inherit the Python version to ensure that the packages have the same version
+		#
+		# The overrideScope here customizes the Python package set with an overlay defined by the
+		# composition of three overlay functions
+		pythonSet = (pkgs.callPackage pyproject-nix.build.packages { inherit python; }).
+					 overrideScope (pkgs.lib.composeManyExtensions [
+						 pyproject-build-systems.overlays.default
+						 overlay
+						 pyprojectOverrides 
+					 ]);
+
+		pythonSetEditable = pythonSet.overrideScope (
+			pkgs.lib.composeManyExtensions [
+				editableOverlay
+				pyprojectOverridesEditable
+			]
+		);
+
+		 # Create a Python venv with the default dependency group
+		 pythonEnv = pythonSet.mkVirtualEnv "miasm-env" workspace.deps.default;
+
+		 # Create a Python venv with the default dependency group
+		 pythonDevEnv = pythonSetEditable.mkVirtualEnv "miasm-env" workspace.deps.all;
+
+		 uvEnv = {
+			UV_NO_SYNC = "1";
+			UV_PYTHON = python.interpreter;
+			UV_PYTHON_DOWNLOADS = "never";
+		};
+
+		uvShellHook = ''
+			unset PYTHONPATH
+
+			export REPO_ROOT=$(git rev-parse --show-toplevel)
+		'';
+	in rec {
+		# Default package just builds Focaccia
+		packages = rec {
+			miasm = pythonEnv;
+
+			dev = pythonDevEnv.overrideAttrs (old: {
+				propagatedBuildInputs = (old.propagatedBuildInputs or []) ++ [ 
+					pkgs.uv
+				];
+			});
+
+			default = miasm;
+		};
+
+		devShells = {
+			default = pkgs.mkShell {
+				packages = [ packages.dev ];
+
+				env = uvEnv;
+				shellHook = uvShellHook;
+			};
+			
+			basic = pkgs.mkShell {
+				packages = [ pkgs.uv packages.miasm ];
+
+				env = uvEnv;
+				shellHook = uvShellHook;
+			};
+		};
+
+		# TODO
+		checks = {
+			miasm-tests = pkgs.stdenv.mkDerivation {
+				name = "miasm-tests";
+				src = ./.;
+
+				doCheck = true;
+				dontBuild = true;
+
+				nativeCheckInputs = [ packages.dev pythonDevEnv ];
+
+				checkPhase = ''
+					set -euo pipefail
+					export REPO_ROOT="$PWD"
+					${packages.dev}/bin/python -m 'pytest' -q tests
+					touch $out
+				'';
+
+				env = uvEnv;
+				shellHook = uvShellHook;
+			};
+		};
+	});
+}
+