Skip to content

chore(cmake): add CMake presets #5655

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

Merged
merged 4 commits into from
May 14, 2025
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
39 changes: 14 additions & 25 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,25 +220,20 @@ jobs:
with:
fetch-depth: 0

- name: Prepare venv
run: python3.13t -m venv .venv
- name: Prepare uv's path
run: echo "$HOME/.local/bin" >> $GITHUB_PATH

- name: Install Python deps
run: .venv/bin/pip install -r tests/requirements.txt
- name: Install ninja
run: uv tool install ninja

- name: Configure C++11
run: >
cmake -S. -Bbuild
-DPYBIND11_WERROR=ON
-DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON
-DPython_ROOT_DIR=.venv
- name: Configure via preset
run: cmake --preset venv -DPYBIND11_CREATE_WITH_UV=python3.13t

- name: Build C++11
run: cmake --build build -j2
run: cmake --build --preset venv

- name: Python tests C++11
run: cmake --build build --target pytest -j2
run: cmake --build --preset testsvenv -t pytest

deadsnakes:
strategy:
Expand Down Expand Up @@ -292,33 +287,27 @@ jobs:
run: |
sudo make install
sudo apt-get update
sudo apt-get install libc6-dbg # Needed by Valgrind
sudo apt-get install ninja-build libc6-dbg

- name: Prepare env
run: |
python -m pip install -r tests/requirements.txt

- name: Configure
run: >
cmake -S . -B build
-DCMAKE_BUILD_TYPE=Debug
-DPYBIND11_WERROR=ON
-DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON
-DCMAKE_CXX_STANDARD=17
run: cmake --preset default -DCMAKE_CXX_STANDARD=17

- name: Build
run: cmake --build build -j 2
run: cmake --build --preset default

- name: Python tests
run: cmake --build build --target pytest
run: cmake --build --preset default --target pytest

- name: C++ tests
run: cmake --build build --target cpptest
run: cmake --build --preset default --target cpptest

- name: Run Valgrind on Python tests
if: matrix.valgrind
run: cmake --build build --target memcheck
run: cmake --build --preset default --target memcheck


# Testing on clang using the excellent silkeh clang docker images
Expand Down
61 changes: 54 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,60 @@ set(PYBIND11_FINDPYTHON
${_pybind11_findpython_default}
CACHE STRING "Force new FindPython - NEW, OLD, COMPAT")

# Allow PYTHON_EXECUTABLE if in FINDPYTHON mode and building pybind11's tests
# (makes transition easier while we support both modes).
if(PYBIND11_MASTER_PROJECT
AND PYBIND11_FINDPYTHON
AND DEFINED PYTHON_EXECUTABLE
AND NOT DEFINED Python_EXECUTABLE)
set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
if(PYBIND11_MASTER_PROJECT)

# Allow PYTHON_EXECUTABLE if in FINDPYTHON mode and building pybind11's tests
# (makes transition easier while we support both modes).
if(PYBIND11_FINDPYTHON
AND DEFINED PYTHON_EXECUTABLE
AND NOT DEFINED Python_EXECUTABLE)
set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
endif()

if(NOT DEFINED Python3_EXECUTABLE
AND NOT DEFINED Python_EXECUTABLE
AND NOT DEFINED Python_ROOT_DIR
AND NOT DEFINED ENV{VIRTUALENV}
AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.venv")
message(STATUS "Autodetecting Python in virtual environment")
set(Python_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.venv")
endif()

# This is a shortcut that is primarily for the venv cmake preset,
# but can be used to quickly setup tests manually, too
set(PYBIND11_CREATE_WITH_UV
""
CACHE STRING "Create a virtualenv in Python_ROOT_DIR with uv if it doesn't exist")

if(NOT PYBIND11_CREATE_WITH_UV STREQUAL "")
if(NOT DEFINED Python_ROOT_DIR)
message(FATAL_ERROR "Python_ROOT_DIR must be defined to use PYBIND11_CREATE_WITH_UV")
endif()
if(EXISTS "${Python_ROOT_DIR}")
message(STATUS "Using existing venv at ${Python_ROOT_DIR}, remove to recreate")
else()
find_program(UV uv REQUIRED)
# CMake 3.19+ would be able to use COMMAND_ERROR_IS_FATAL
message(
STATUS "Creating venv with ${UV} venv -p ${PYBIND11_CREATE_WITH_UV} '${Python_ROOT_DIR}'")
execute_process(COMMAND ${UV} venv -p ${PYBIND11_CREATE_WITH_UV} "${Python_ROOT_DIR}"
RESULT_VARIABLE _venv_result)
if(_venv_result AND NOT _venv_result EQUAL 0)
message(FATAL_ERROR "uv venv failed with '${_venv_result}'")
endif()
message(
STATUS
"Installing deps with ${UV} pip install -p '${Python_ROOT_DIR}' -r tests/requirements.txt"
)
execute_process(
COMMAND ${UV} pip install -p "${Python_ROOT_DIR}" -r
"${CMAKE_CURRENT_SOURCE_DIR}/tests/requirements.txt" RESULT_VARIABLE _pip_result)
if(_pip_result AND NOT _pip_result EQUAL 0)
message(FATAL_ERROR "uv pip install failed with '${_pip_result}'")
endif()
endif()
endif()

endif()

# NB: when adding a header don't forget to also add it to setup.py
Expand Down
80 changes: 80 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"version": 6,
"configurePresets": [
{
"name": "default",
"displayName": "Default",
"binaryDir": "build",
"generator": "Ninja",
"errors": {
"dev": true,
"deprecated": true
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"PYBIND11_FINDPYTHON": "NEW",
"PYBIND11_WERROR": true,
"DOWNLOAD_CATCH": true,
"DOWNLOAD_EIGEN": true
}
},
{
"name": "venv",
"displayName": "Venv",
"inherits": "default",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"PYBIND11_CREATE_WITH_UV": "python3",
"Python_ROOT_DIR": ".venv",
"PYBIND11_WERROR": true,
"PYBIND11_FINDPYTHON": "NEW",
"DOWNLOAD_CATCH": true,
"DOWNLOAD_EIGEN": true
}
}
],
"buildPresets": [
{
"name": "default",
"displayName": "Default Build",
"configurePreset": "default"
},
{
"name": "venv",
"displayName": "Venv Build",
"configurePreset": "venv"
},
{
"name": "tests",
"displayName": "Tests (for workflow)",
"configurePreset": "default",
"targets": ["pytest", "cpptest", "test_cmake_build"]
},
{
"name": "testsvenv",
"displayName": "Tests Venv (for workflow)",
"configurePreset": "venv",
"targets": ["pytest", "cpptest", "test_cmake_build"]
}
],
"workflowPresets": [
{
"name": "default",
"displayName": "Default Workflow",
"steps": [
{ "type": "configure", "name": "default" },
{ "type": "build", "name": "default" },
{ "type": "build", "name": "tests" }
]
},
{
"name": "venv",
"displayName": "Default Workflow",
"steps": [
{ "type": "configure", "name": "venv" },
{ "type": "build", "name": "venv" },
{ "type": "build", "name": "testsvenv" }
]
}
]
}
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ ignore = [
"pybind11/include/**",
"pybind11/share/**",
"CMakeLists.txt",
"CMakePresets.json",
"noxfile.py",
]

Expand Down