Skip to content

Commit fdfdae1

Browse files
chore: setup CMake presets (#998)
* chore: setup CMake presets Signed-off-by: Henry Schreiner <[email protected]> * style: pre-commit fixes * chore: auto-discover a .venv directory Signed-off-by: Henry Schreiner <[email protected]> * fixup! style: pre-commit fixes * style: pre-commit fixes --------- Signed-off-by: Henry Schreiner <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent cfb55c2 commit fdfdae1

File tree

6 files changed

+75
-29
lines changed

6 files changed

+75
-29
lines changed

.github/CONTRIBUTING.md

+15-20
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ pip-install-dependency-groups dev
6464
pip install -ve.
6565
```
6666

67+
Or if you use uv:
68+
69+
```bash
70+
uv sync
71+
```
72+
6773
<details><summary>Optional: External Jupyter kernel (click to expand)</summary>
6874

6975
You can set up a kernel for external Jupyter then deactivate your environment:
@@ -87,16 +93,11 @@ a rebuild.
8793
CMake is common for C++ development, and ties nicely to many C++ tools, like
8894
IDEs. If you want to use it for building, you can. Make a build directory and
8995
run CMake. If you have a specific Python you want to use, add
90-
`-DPYTHON_EXECUTABLE=$(which python)` or similar to the CMake line. If you need
96+
`-DPython_EXECUTABLE=$(which python)` or similar to the CMake line. If you need
9197
help installing the latest CMake version, [visit this
9298
page](https://cliutils.gitlab.io/modern-cmake/chapters/intro/installing.html);
9399
one option is to use pip to install CMake.
94100

95-
> Note: Since setuptools uses a subdirectory called `build`, it is _slightly_
96-
> better to avoid making your CMake directory `build` as well. Also, you will
97-
> often have multiple CMake directories (`build-release`, `build-debug`, etc.),
98-
> so avoiding the descriptive name `build` is not a bad idea.
99-
100101
You have three options for running code in python:
101102

102103
1. Run from the build directory (only works with some commands, like `python -m
@@ -105,25 +106,20 @@ pytest`, and not others, like `pytest`
105106
3. Set `CMAKE_INSTALL_PREFIX` to your site-packages and install (recommended
106107
for virtual environments).
107108

108-
Here is the recommendation for a CMake install:
109+
Here is the recommendation for a CMake install, using uv:
109110

110111
```bash
111-
python3 -m venv env_cmake
112-
source ./env_cmake/bin/activate
113-
pip install dependency-groups
114-
pip-install-dependency-groups dev
115-
cmake -S . -B build-debug \
116-
-GNinja \
117-
-DCMAKE_INSTALL_PREFIX=$(python -c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False))")
118-
cmake --build build-debug -j4
119-
cmake --install build-debug # Option 3 only
112+
uv venv
113+
uv pip install --group dev
114+
cmake --workflow default
115+
116+
# Option 3 only:
117+
cmake --install --preset default --prefix $(python -c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False))")
120118
```
121119

122120
Note that option 3 will require reinstalling if the python files change, while
123121
options 1-2 will not if you have a recent version of CMake (symlinks are made).
124122

125-
This could be simplified if pybind11 supported the new CMake FindPython tools.
126-
127123
## Testing
128124

129125
Run the unit tests (requires pytest and NumPy).
@@ -132,8 +128,7 @@ Run the unit tests (requires pytest and NumPy).
132128
python3 -m pytest
133129
```
134130

135-
For CMake, you can also use the `test` target from anywhere, or use `python3 -m
136-
pytest` or `ctest` from the build directory.
131+
For CMake, you can use `ctest --preset default` (the workflow above will run the tests).
137132

138133
The build requires `setuptools_scm`. The tests require `numpy`, `pytest`, and
139134
`pytest-benchmark`. `pytest-sugar` adds some nice formatting.

.github/workflows/tests.yml

+8-8
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,16 @@ jobs:
5555
cmake:
5656
name: CMake 🐍 ${{ matrix.python-version }}
5757
runs-on: ubuntu-latest
58-
env:
59-
PIP_ONLY_BINARY: numpy
6058
strategy:
6159
fail-fast: false
6260
matrix:
63-
python-version: ["3.11", "3.13", "pypy3.10"]
6461
include:
6562
- python-version: "3.9"
6663
cmake-extras: "-DCMAKE_CXX_STANDARD=17"
64+
- python-version: "3.11"
65+
- python-version: "3.13"
6766
- python-version: "3.13t"
67+
- python-version: "pypy3.10"
6868

6969
steps:
7070
- uses: actions/checkout@v4
@@ -87,17 +87,17 @@ jobs:
8787
create-symlink: true
8888

8989
- name: Install python tools
90-
run: uv pip install --system --python=python --group dev pytest-github-actions-annotate-failures
90+
run: |
91+
uv pip install --system --python=python --group dev --only-binary numpy pytest-github-actions-annotate-failures
9192
9293
- name: Configure
93-
run: cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Debug -DBOOST_HISTOGRAM_ERRORS=ON ${{ matrix.cmake-extras }}
94+
run: cmake --preset default -DCMAKE_BUILD_TYPE=Debug ${{ matrix.cmake-extras }}
9495

9596
- name: Build
96-
run: cmake --build build -j 4
97+
run: cmake --build --preset default -j 4
9798

9899
- name: Test
99-
working-directory: ./build
100-
run: python -m pytest -ra
100+
run: ctest --preset default -j 4
101101

102102
build_wheels:
103103
name: ${{ matrix.only }}

CMakeLists.txt

+8
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
3737
"RelWithDebInfo")
3838
endif()
3939

40+
# If no Python venv set, and .venv exists, use it.
41+
if(NOT DEFINED ENV{VIRTUALENV}
42+
AND NOT DEFINED Python_ROOT_DIR
43+
AND NOT DEFINED Python_EXECUTABLE
44+
AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.venv")
45+
set(Python_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.venv")
46+
endif()
47+
4048
# Adding pybind11 and setting up Python
4149
# Will display pybind11 version
4250
set(PYBIND11_FINDPYTHON TRUE)

CMakePresets.json

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"version": 6,
3+
"configurePresets": [
4+
{
5+
"name": "default",
6+
"generator": "Ninja",
7+
"binaryDir": "${sourceDir}/build/default",
8+
"warnings": { "dev": true },
9+
"cacheVariables": {
10+
"BOOST_HISTOGRAM_ERRORS": "ON"
11+
}
12+
}
13+
],
14+
"buildPresets": [
15+
{
16+
"name": "default",
17+
"verbose": true,
18+
"configurePreset": "default"
19+
}
20+
],
21+
"testPresets": [
22+
{
23+
"name": "default",
24+
"displayName": "Default Test",
25+
"configurePreset": "default",
26+
"output": {
27+
"outputOnFailure": true
28+
}
29+
}
30+
],
31+
"workflowPresets": [
32+
{
33+
"name": "default",
34+
"displayName": "Default workflow",
35+
"steps": [
36+
{ "type": "configure", "name": "default" },
37+
{ "type": "build", "name": "default" },
38+
{ "type": "test", "name": "default" }
39+
]
40+
}
41+
]
42+
}

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ dev = [
6565
{ include-group = "test" },
6666
"ipykernel",
6767
"nbconvert",
68-
"numpy",
6968
"setuptools_scm",
7069
"typer",
7170
"uhi",
@@ -93,6 +92,7 @@ test = [
9392
"pytest-benchmark",
9493
"pytest>=6.0",
9594
"pytest-xdist",
95+
"numpy",
9696
]
9797

9898

tests/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ foreach(TEST_FILE IN LISTS BOOST_HIST_PY_TESTS)
2323
NAME ${TEST_NAME}
2424
COMMAND ${Python_EXECUTABLE} -m pytest "${TEST_FILE}" --rootdir=.
2525
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}")
26+
set_tests_properties(${TEST_NAME} PROPERTIES SKIP_RETURN_CODE 5)
2627
endforeach()

0 commit comments

Comments
 (0)