Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nix dev shell #2166

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use_flake
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ gdb.txt
# venv
.venv/

# Nix build stuff
result-*
# Nix build and dev shell
result*
.direnv/

# Vim
*.swp
16 changes: 16 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
);
};
}
47 changes: 47 additions & 0 deletions nix/devshell.nix
Original file line number Diff line number Diff line change
@@ -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/"
'';
};
}
51 changes: 16 additions & 35 deletions nix/pwndbg.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
python3 ? pkgs.python3,
gdb ? pkgs.gdb,
inputs ? null,
isDev ? false,
}:
let
binPath = pkgs.lib.makeBinPath (
Expand All @@ -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 (
Expand Down Expand Up @@ -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\
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sys.path.insert(0, '$out/share/pwndbg/')
🤔 why is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pyEnv only provides the dependencies of pwndbg, whereas for gdbinit.py to import pwndbg, it needs to import from share/pwndbg/ as that is where the pwndbg python module is installed to.

This is without that line:

(gdb) source result/pwndbg/share/gdbinit.py
result/pwndbg/share/gdbinit.py: No such file or directory.
(gdb) source result/share/pwndbg/gdbinit.py
Traceback (most recent call last):
  File "result/share/pwndbg/gdbinit.py", line 65, in <module>
    import pwndbg  # noqa: F401
    ^^^^^^^^^^^^^
ModuleNotFoundError: No module named 'pwndbg'

If there's some better way, happy to change it.

Reminds me even though pwndbg.nix links the .venv/ folder, there is no activation script created by the poetry derivation in .venv/bin/. Is anyone actually using the venv on nix? Since it won't include pwndbg (as it only links the poetry sitePackages) I think it might not work? Maybe I'm missing something.

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 = {
Expand Down
57 changes: 57 additions & 0 deletions nix/pyenv.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
pkgs ? import <nixpkgs> { },
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; };
}
);
}
Loading