Skip to content

Commit f966792

Browse files
tiptenbrinkmaartenflippo
authored andcommitted
fix: make pumpkin-py build without any additional installs (#113)
Running `cargo build` in the project root directory (not necessarily useful, I did it by accident) means you also build `pumpkin-py`. However, I have a new laptop so I didn't yet have need to install the development headers for Python (`python3-dev` package on APT). This causes the the build to fail with the below linker error: ``` = note: /usr/bin/ld: cannot find -lpython3.13: No such file or directory collect2: error: ld returned 1 exit status ``` This confused me (I've used PyO3 before), it's just an extension module (you're calling Rust from Python so you always have an interpreter) so why would you need the dev headers, which you usually only need if you're calling Python from a Rust executable (https://pyo3.rs/v0.22.6/index.html?highlight=python3-dev#using-python-from-rust). I then noticed the `extension-module` feature is not enabled in the `Cargo.toml`. It is enabled in the `pyproject.toml` so it works fine if you build from `maturin`. However I think it's useful (to prevent confusion) to have `cargo build` when invoked on the whole workspace to still not fail. Plus, I think it's nice you can still just run `cargo build` even in `pumpkin-py` without needing a global package that isn't really required under these circumstances. It also means the dependencies in the `Cargo.toml` don't really match what you are actually building when you use `maturin`. There's a tiny wrinkle, though. Maybe it's the reason you removed the feature from the `Cargo.toml` in the first place. When using workspaces and an IDE that runs `cargo check` on save, probably the Python interpreter will not match the one in the virtualenv that you use for maturin. This causes PyO3 to recompile on most builds. Thankfully I've had this problem and this can be fixed, see PyO3/pyo3#1708. This does mean that by default someone who will develop the python interface will need to add something to their config manually. The alternative solution however means that cargo build will also fail without some manual work by the user (installing a venv to the right place). When testing, I found that the current version of the Python script actually fails, so I fixed that and updated the README with the correct path to the file to run. So even if you disagree with the main change that part is definitely useful.
1 parent a1be6b9 commit f966792

File tree

3 files changed

+22
-3
lines changed

3 files changed

+22
-3
lines changed

pumpkin-py/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ name = "pumpkin_py"
1212
crate-type = ["cdylib"]
1313

1414
[dependencies]
15-
pyo3 = "0.23.0"
15+
pyo3 = { version = "0.23.3", features= ["extension-module"] }
1616
pumpkin-solver = { path = "../pumpkin-solver" }

pumpkin-py/README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,24 @@ again.
2222

2323
Then, the examples (for example `nqueens`) can be run with
2424
```
25-
python python/examples/nqueens.py 5
25+
python examples/nqueens.py 5
2626
```
27+
28+
### PyO3 rebuilds
29+
30+
When developing in an IDE that runs `cargo check` on save, the PyO3 build
31+
cache can get invalidated unnecessarily. See https://github.com/PyO3/pyo3/issues/1708
32+
for more details. One way to fix this is by making `rust-analyzer` use a
33+
different directory. In VSCode, you could fix this by adding the following
34+
to your `.vscode/settings.json` (in the main project directory):
35+
36+
```json
37+
{
38+
"rust-analyzer.server.extraEnv": {
39+
"CARGO_TARGET_DIR": "target/analyzer"
40+
},
41+
"rust-analyzer.check.extraArgs": [
42+
"--target-dir=target/analyzer"
43+
]
44+
}
45+
```

pumpkin-py/examples/nqueens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def main(n: int, proof: Path | None):
2626
for row in range(n):
2727
print(f"{row_separator}");
2828

29-
queen_col = solution.value(variables[row])
29+
queen_col = solution.int_value(variables[row])
3030

3131
for col in range(n):
3232
string = "| * " if queen_col == col else "| "

0 commit comments

Comments
 (0)