tests: avoid putting build products into source directory (#2353)
* tests: keep source dir clean
* ci: make first build inplace
* ci: drop dev setting (wasn't doing anything)
* tests: warn if source directory is dirty
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4f9ebac..0f01b1d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -17,7 +17,6 @@
runs-on: [ubuntu-latest, windows-latest, macos-latest]
arch: [x64]
max-cxx-std: [17]
- dev: [false]
python:
- 2.7
- 3.5
@@ -30,41 +29,34 @@
python: 3.6
arch: x64
max-cxx-std: 17
- dev: false
args: "-DPYBIND11_FINDPYTHON=ON"
- runs-on: macos-latest
python: 3.7
arch: x64
max-cxx-std: 17
- dev: false
args: "-DPYBIND11_FINDPYTHON=ON"
- runs-on: windows-2016
python: 3.7
arch: x86
max-cxx-std: 14
- dev: false
- runs-on: windows-latest
python: 3.6
arch: x64
max-cxx-std: 17
- dev: false
args: "-DPYBIND11_FINDPYTHON=ON"
- runs-on: windows-latest
python: 3.7
arch: x64
max-cxx-std: 17
- dev: false
- runs-on: ubuntu-latest
python: 3.9-dev
arch: x64
max-cxx-std: 17
- dev: true
- runs-on: macos-latest
python: 3.9-dev
arch: x64
max-cxx-std: 17
- dev: true
exclude:
# Currently 32bit only, and we build 64bit
@@ -72,29 +64,24 @@
python: pypy2
arch: x64
max-cxx-std: 17
- dev: false
- runs-on: windows-latest
python: pypy3
arch: x64
max-cxx-std: 17
- dev: false
# Currently broken on embed_test
- runs-on: windows-latest
python: 3.8
arch: x64
max-cxx-std: 17
- dev: false
- runs-on: windows-latest
python: 3.9-dev
arch: x64
max-cxx-std: 17
- dev: false
name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • ${{ matrix.arch }} ${{ matrix.args }}"
runs-on: ${{ matrix.runs-on }}
- continue-on-error: ${{ matrix.dev }}
steps:
- uses: actions/checkout@v2
@@ -129,7 +116,7 @@
- name: Configure C++11 ${{ matrix.args }}
shell: bash
run: >
- cmake -S . -B build
+ cmake -S . -B .
-DPYBIND11_WERROR=ON
-DDOWNLOAD_CATCH=ON
-DDOWNLOAD_EIGEN=ON
@@ -137,16 +124,19 @@
${{ matrix.args }}
- name: Build C++11
- run: cmake --build build -j 2
+ run: cmake --build . -j 2
- name: Python tests C++11
- run: cmake --build build --target pytest -j 2
+ run: cmake --build . --target pytest -j 2
- name: C++11 tests
- run: cmake --build build --target cpptest -j 2
+ run: cmake --build . --target cpptest -j 2
- name: Interface test C++11
- run: cmake --build build --target test_cmake_build -v
+ run: cmake --build . --target test_cmake_build
+
+ - name: Clean directory
+ run: git clean -fdx
- name: Configure C++${{ matrix.max-cxx-std }} ${{ matrix.args }}
shell: bash
diff --git a/.gitignore b/.gitignore
index 6d65838..47e010c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,7 +32,7 @@
.*.swp
.DS_Store
/dist
-/build*
+/*build*
.cache/
sosize-*.txt
pybind11Config*.cmake
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4279752..00e39bc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,7 +46,17 @@
endif()
# Check if pybind11 is being used directly or via add_subdirectory
-if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+if(CMAKE_CURRENT_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ ### Warn if not an out-of-source builds
+ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
+ set(lines
+ "You are building in-place. If that is not what you intended to "
+ "do, you can clean the source directory with:\n"
+ "rm -r CMakeCache.txt CMakeFiles/ cmake_uninstall.cmake pybind11Config.cmake "
+ "pybind11ConfigVersion.cmake tests/CMakeFiles/\n")
+ message(AUTHOR_WARNING ${lines})
+ endif()
+
set(PYBIND11_MASTER_PROJECT ON)
if(OSX AND CMAKE_VERSION VERSION_LESS 3.7)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 895cfe7..72de210 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -239,7 +239,6 @@
endif()
endforeach()
-set(testdir ${CMAKE_CURRENT_SOURCE_DIR})
foreach(target ${test_targets})
set(test_files ${PYBIND11_TEST_FILES})
if(NOT "${target}" STREQUAL "pybind11_tests")
@@ -250,6 +249,18 @@
pybind11_add_module(${target} THIN_LTO ${target}.cpp ${test_files} ${PYBIND11_HEADERS})
pybind11_enable_warnings(${target})
+ if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
+ get_property(
+ suffix
+ TARGET ${target}
+ PROPERTY SUFFIX)
+ set(source_output "${CMAKE_CURRENT_SOURCE_DIR}/${target}${suffix}")
+ if(suffix AND EXISTS "${source_output}")
+ message(WARNING "Output file also in source directory; "
+ "please remove to avoid confusion: ${source_output}")
+ endif()
+ endif()
+
if(MSVC)
target_compile_options(${target} PRIVATE /utf-8)
endif()
@@ -266,10 +277,12 @@
# Always write the output file directly into the 'tests' directory (even on MSVC)
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
- set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${testdir}")
+ set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY
+ "${CMAKE_CURRENT_BINARY_DIR}")
foreach(config ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${config} config)
- set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${config} "${testdir}")
+ set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${config}
+ "${CMAKE_CURRENT_BINARY_DIR}")
endforeach()
endif()
endforeach()
@@ -293,12 +306,26 @@
CACHE INTERNAL "")
endif()
+if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
+ # This is not used later in the build, so it's okay to regenerate each time.
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/pytest.ini" "${CMAKE_CURRENT_BINARY_DIR}/pytest.ini"
+ COPYONLY)
+ file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/pytest.ini"
+ "\ntestpaths = \"${CMAKE_CURRENT_SOURCE_DIR}\"")
+
+endif()
+
+# cmake 3.12 added list(transform <list> prepend
+# but we can't use it yet
+string(REPLACE "test_" "${CMAKE_CURRENT_BINARY_DIR}/test_" PYBIND11_BINARY_TEST_FILES
+ "${PYBIND11_PYTEST_FILES}")
+
# A single command to compile and run the tests
add_custom_target(
pytest
- COMMAND ${PYTHON_EXECUTABLE} -m pytest ${PYBIND11_PYTEST_FILES}
+ COMMAND ${PYTHON_EXECUTABLE} -m pytest ${PYBIND11_BINARY_PYTEST_FILES}
DEPENDS ${test_targets}
- WORKING_DIRECTORY ${testdir}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
USES_TERMINAL)
if(PYBIND11_TEST_OVERRIDE)
diff --git a/tests/conftest.py b/tests/conftest.py
index 8b6e47d..a2350d0 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -13,6 +13,8 @@
import pytest
+import env
+
# Early diagnostic for failed imports
import pybind11_tests # noqa: F401
@@ -20,6 +22,11 @@
_long_marker = re.compile(r'([0-9])L')
_hexadecimal = re.compile(r'0x[0-9a-fA-F]+')
+# Avoid collecting Python3 only files
+collect_ignore = []
+if env.PY2:
+ collect_ignore.append("test_async.py")
+
def _strip_and_dedent(s):
"""For triple-quote strings"""
diff --git a/tests/test_embed/CMakeLists.txt b/tests/test_embed/CMakeLists.txt
index 1495c77..2e298fa 100644
--- a/tests/test_embed/CMakeLists.txt
+++ b/tests/test_embed/CMakeLists.txt
@@ -21,18 +21,22 @@
target_link_libraries(test_embed PRIVATE pybind11::embed Catch2::Catch2 Threads::Threads)
+if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
+ file(COPY test_interpreter.py DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
+endif()
+
add_custom_target(
cpptest
COMMAND "$<TARGET_FILE:test_embed>"
- WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
pybind11_add_module(external_module THIN_LTO external_module.cpp)
set_target_properties(external_module PROPERTIES LIBRARY_OUTPUT_DIRECTORY
- "${CMAKE_CURRENT_SOURCE_DIR}")
+ "${CMAKE_CURRENT_BINARY_DIR}")
foreach(config ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${config} config)
set_target_properties(external_module PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${config}
- "${CMAKE_CURRENT_SOURCE_DIR}")
+ "${CMAKE_CURRENT_BINARY_DIR}")
endforeach()
add_dependencies(cpptest external_module)