fix(cmake): respect explicit PYBIND11_USE_CROSSCOMPILING under CMP0190 (#6094)
* fix(cmake): respect explicit PYBIND11_USE_CROSSCOMPILING under CMP0190
PR #5829 added `AND NOT DEFINED CMAKE_CROSSCOMPILING_EMULATOR` to the
condition setting `_PYBIND11_CROSSCOMPILING`. That gate was meant to only
control the auto-default of `PYBIND11_USE_CROSSCOMPILING`, but it ended up
overriding a value the project set explicitly. Emscripten/Pyodide defines
`CMAKE_CROSSCOMPILING_EMULATOR` (node) yet still wants cross-compiling
mode, so the flag was forced OFF and the build failed with a spurious
"Cannot run the interpreter" / pointer-size mismatch.
Move the emulator check up so it only guards the auto-default, and never
override an explicitly set `PYBIND11_USE_CROSSCOMPILING`.
Fixes #6043
Assisted-by: ClaudeCode:claude-opus-4.8
* fix(cmake): keep CMP0190 auto-default in add_subdirectory builds
The previous commit's `NOT DEFINED PYBIND11_USE_CROSSCOMPILING` guard
broke the intended auto-default for top-level / add_subdirectory builds:
CMakeLists.txt runs `option(PYBIND11_USE_CROSSCOMPILING ... OFF)` before
including pybind11Common.cmake, so the variable is already defined (OFF)
and the CMP0190 default never applied.
Capture, before the option() call, whether the project set the value
itself, and let pybind11Common.cmake apply its default unless the value
was set explicitly. This keeps both the emulator override fix and the
CMP0190 auto-default for subdirectory consumers.
Assisted-by: ClaudeCode:claude-opus-4.8
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5e72afc..6f3f8be 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -102,6 +102,11 @@
set(PYBIND11_INTERNALS_VERSION
""
CACHE STRING "Override the ABI version, may be used to enable the unstable ABI.")
+# Record whether the project set this before option() supplies its OFF default, so
+# pybind11Common.cmake can apply its CMP0190-aware default without clobbering an explicit value.
+if(NOT DEFINED PYBIND11_USE_CROSSCOMPILING)
+ set(_PYBIND11_USE_CROSSCOMPILING_DEFAULTED ON)
+endif()
option(PYBIND11_USE_CROSSCOMPILING "Respect CMAKE_CROSSCOMPILING" OFF)
if(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
diff --git a/tools/pybind11Common.cmake b/tools/pybind11Common.cmake
index f525270..d75fb67 100644
--- a/tools/pybind11Common.cmake
+++ b/tools/pybind11Common.cmake
@@ -43,16 +43,21 @@
# CMP0190 prohibits calling FindPython with both Interpreter and Development components
# when cross-compiling, unless the CMAKE_CROSSCOMPILING_EMULATOR variable is defined.
-if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.1")
+# Default PYBIND11_USE_CROSSCOMPILING to ON in that case, but never override a value the
+# project set explicitly (e.g. Emscripten/Pyodide defines an emulator yet still wants it ON).
+# PYBIND11_USE_CROSSCOMPILING is undefined for find_package() consumers, but our own
+# CMakeLists.txt always defines it via option(); _PYBIND11_USE_CROSSCOMPILING_DEFAULTED tells
+# us whether that came from the project or from the option() default.
+if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.1"
+ AND NOT DEFINED CMAKE_CROSSCOMPILING_EMULATOR
+ AND (NOT DEFINED PYBIND11_USE_CROSSCOMPILING OR _PYBIND11_USE_CROSSCOMPILING_DEFAULTED))
cmake_policy(GET CMP0190 _pybind11_cmp0190)
if(_pybind11_cmp0190 STREQUAL "NEW")
set(PYBIND11_USE_CROSSCOMPILING "ON")
endif()
endif()
-if(CMAKE_CROSSCOMPILING
- AND PYBIND11_USE_CROSSCOMPILING
- AND NOT DEFINED CMAKE_CROSSCOMPILING_EMULATOR)
+if(CMAKE_CROSSCOMPILING AND PYBIND11_USE_CROSSCOMPILING)
set(_PYBIND11_CROSSCOMPILING
ON
CACHE INTERNAL "")