diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..c4b17d79 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use_flake diff --git a/.gitignore b/.gitignore index 3ed40d38..eb6eed49 100644 --- a/.gitignore +++ b/.gitignore @@ -91,8 +91,9 @@ gdb.txt # venv .venv/ -# Nix build stuff -result-* +# Nix build and dev shell +result* +.direnv/ # Vim *.swp diff --git a/flake.nix b/flake.nix index e6e3c46c..be403067 100644 --- a/flake.nix +++ b/flake.nix @@ -64,9 +64,25 @@ inputs.pwndbg = self; }; default = self.packages.${system}.pwndbg; + pwndbg-dev = import ./nix/pwndbg.nix { + pkgs = pkgsBySystem.${system}; + python3 = pkgsBySystem.${system}.python3; + gdb = pkgsBySystem.${system}.gdb; + inputs.pwndbg = self; + isDev = true; + }; } // (portableDrvs system) // (tarballDrv system) ); + + devShells = forAllSystems ( + system: + import ./nix/devshell.nix { + pkgs = pkgsBySystem.${system}; + python3 = pkgsBySystem.${system}.python3; + inputs.pwndbg = self; + } + ); }; } diff --git a/nix/devshell.nix b/nix/devshell.nix new file mode 100644 index 00000000..7ef27d86 --- /dev/null +++ b/nix/devshell.nix @@ -0,0 +1,47 @@ +# This should be kept in sync with setup-dev.sh and lint.sh requirements +{ + pkgs ? + # If pkgs is not defined, instantiate nixpkgs from locked commit + let + lock = (builtins.fromJSON (builtins.readFile ./flake.lock)).nodes.nixpkgs.locked; + nixpkgs = fetchTarball { + url = "https://github.com/nixos/nixpkgs/archive/${lock.rev}.tar.gz"; + sha256 = lock.narHash; + }; + in + import nixpkgs { overlays = [ ]; }, + python3 ? pkgs.python3, + inputs ? null, + ... +}: +let + pyEnv = import ./pyenv.nix { + inherit pkgs python3 inputs; + lib = pkgs.lib; + isDev = true; + }; +in +{ + default = pkgs.mkShell { + NIX_CONFIG = "extra-experimental-features = nix-command flakes repl-flake"; + # Anything not handled by the poetry env + nativeBuildInputs = with pkgs; [ + # from setup-dev.sh + nasm + gcc + curl + gdb + parallel + qemu + netcat-openbsd + zig_0_10 # matches setup-dev.sh + go + + pyEnv + ]; + shellHook = '' + export PWNDBG_VENV_PATH="PWNDBG_PLEASE_SKIP_VENV" + export ZIGPATH="${pkgs.lib.getBin pkgs.zig_0_10}/bin/" + ''; + }; +} diff --git a/nix/pwndbg.nix b/nix/pwndbg.nix index 48e8ceaf..16328efc 100644 --- a/nix/pwndbg.nix +++ b/nix/pwndbg.nix @@ -3,6 +3,7 @@ python3 ? pkgs.python3, gdb ? pkgs.gdb, inputs ? null, + isDev ? false, }: let binPath = pkgs.lib.makeBinPath ( @@ -15,38 +16,14 @@ let ] ); - pyEnv = pkgs.poetry2nix.mkPoetryEnv { - groups = [ ]; # put [ "dev" ] to build "dev" dependencies - checkGroups = [ ]; # put [ "dev" ] to build "dev" dependencies - projectDir = inputs.pwndbg; - python = python3; - overrides = pkgs.poetry2nix.overrides.withDefaults ( - self: super: { - pip = python3.pkgs.pip; # fix infinite loop in nix, look here: https://github.com/nix-community/poetry2nix/issues/1184#issuecomment-1644878841 - unicorn = python3.pkgs.unicorn; # fix build for aarch64 (but it will use same version like in nixpkgs) - - # disable build from source, because rust's hash had to be repaired many times, see: PR https://github.com/pwndbg/pwndbg/pull/2024 - cryptography = super.cryptography.override { preferWheel = true; }; - - unix-ar = super.unix-ar.overridePythonAttrs (old: { - nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ self.setuptools ]; - }); - - pt = super.pt.overridePythonAttrs (old: { - buildInputs = (old.buildInputs or [ ]) ++ [ super.poetry-core ]; - }); - capstone = super.capstone.overridePythonAttrs (old: { - # fix darwin - preBuild = pkgs.lib.optionalString pkgs.stdenv.isDarwin '' - sed -i 's/^IS_APPLE := .*$/IS_APPLE := 1/' ./src/Makefile - ''; - # fix build for aarch64: https://github.com/capstone-engine/capstone/issues/2102 - postPatch = pkgs.lib.optionalString pkgs.stdenv.isLinux '' - substituteInPlace setup.py --replace manylinux1 manylinux2014 - ''; - }); - } - ); + pyEnv = import ./pyenv.nix { + inherit + pkgs + python3 + inputs + isDev + ; + lib = pkgs.lib; }; pwndbgVersion = pkgs.lib.readFile ( @@ -74,13 +51,17 @@ let mkdir -p $out/share/pwndbg cp -r gdbinit.py pwndbg $out/share/pwndbg + # Build self-contained init script for lazy loading from vanilla gdb + # I purposely use insert() so I can re-import during development without having to restart gdb + sed "2 i import sys, os\n\ + sys.path.insert(0, '${pyEnv}/${pyEnv.sitePackages}')\n\ + sys.path.insert(0, '$out/share/pwndbg/')\n\ + os.environ['PATH'] += ':${binPath}'\n" -i $out/share/pwndbg/gdbinit.py ln -s ${pyEnv} $out/share/pwndbg/.venv makeWrapper ${gdb}/bin/gdb $out/bin/pwndbg \ - --add-flags "--quiet --early-init-eval-command=\"set charset UTF-8\" --early-init-eval-command=\"set auto-load safe-path /\" --command=$out/share/pwndbg/gdbinit.py" \ - --prefix PATH : ${binPath} \ - --set LC_CTYPE C.UTF-8 + --add-flags "--quiet --early-init-eval-command=\"set auto-load safe-path /\" --command=$out/share/pwndbg/gdbinit.py" ''; meta = { diff --git a/nix/pyenv.nix b/nix/pyenv.nix new file mode 100644 index 00000000..5a464b8c --- /dev/null +++ b/nix/pyenv.nix @@ -0,0 +1,57 @@ +{ + pkgs ? import { }, + python3 ? pkgs.python3, + inputs ? null, + isDev ? false, + lib, + ... +}: +pkgs.poetry2nix.mkPoetryEnv { + groups = lib.optionals isDev [ "dev" ]; + checkGroups = lib.optionals isDev [ "dev" ]; + projectDir = inputs.pwndbg; + python = python3; + overrides = pkgs.poetry2nix.overrides.withDefaults ( + self: super: { + pip = python3.pkgs.pip; # fix infinite loop in nix, look here: https://github.com/nix-community/poetry2nix/issues/1184#issuecomment-1644878841 + unicorn = python3.pkgs.unicorn; # fix build for aarch64 (but it will use same version like in nixpkgs) + + # disable build from source, because rust's hash had to be repaired many times, see: PR https://github.com/pwndbg/pwndbg/pull/2024 + cryptography = super.cryptography.override { preferWheel = true; }; + + unix-ar = super.unix-ar.overridePythonAttrs (old: { + nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ self.setuptools ]; + }); + + pt = super.pt.overridePythonAttrs (old: { + buildInputs = (old.buildInputs or [ ]) ++ [ super.poetry-core ]; + }); + capstone = super.capstone.overridePythonAttrs (old: { + # fix darwin + preBuild = pkgs.lib.optionalString pkgs.stdenv.isDarwin '' + sed -i 's/^IS_APPLE := .*$/IS_APPLE := 1/' ./src/Makefile + ''; + # fix build for aarch64: https://github.com/capstone-engine/capstone/issues/2102 + postPatch = pkgs.lib.optionalString pkgs.stdenv.isLinux '' + substituteInPlace setup.py --replace manylinux1 manylinux2014 + ''; + }); + sortedcontainers-stubs = super.sortedcontainers-stubs.overridePythonAttrs (old: { + buildInputs = (old.buildInputs or [ ]) ++ [ super.poetry-core ]; + }); + + # Dev-only dependencies + + # Because compiling mypy is slow + mypy = super.mypy.override { preferWheel = true; }; + types-gdb = super.types-gdb.overridePythonAttrs (old: { + buildInputs = (old.buildInputs or [ ]) ++ [ super.setuptools ]; + }); + vermin = super.vermin.overridePythonAttrs (old: { + buildInputs = (old.buildInputs or [ ]) ++ [ super.setuptools ]; + }); + # Hash issues, so just wheel + ruff = super.ruff.override { preferWheel = true; }; + } + ); +}