Skip to content

fix(cmake): respect explicit PYBIND11_USE_CROSSCOMPILING under CMP0190#6094

Open
henryiii wants to merge 2 commits into
masterfrom
fix-crosscompiling-emulator-6043
Open

fix(cmake): respect explicit PYBIND11_USE_CROSSCOMPILING under CMP0190#6094
henryiii wants to merge 2 commits into
masterfrom
fix-crosscompiling-emulator-6043

Conversation

@henryiii

@henryiii henryiii commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Implemented with Claude Code Opus 4.8 (see linux kernel style trailer in commit messages)

🤖 AI text below 🤖

Description

Fixes #6043.

Cross-compiling to Emscripten/Pyodide (and any target that defines CMAKE_CROSSCOMPILING_EMULATOR) broke with CMake ≥ 4.1 and pybind11 ≥ 3.0.2, failing with a spurious Cannot run the interpreter / pointer-size mismatch.

PR #5829 added AND NOT DEFINED CMAKE_CROSSCOMPILING_EMULATOR to the condition that sets the internal _PYBIND11_CROSSCOMPILING flag. That check was meant only to gate whether pybind11 auto-defaults PYBIND11_USE_CROSSCOMPILING to ON, but it ended up overriding a value the project had set explicitly. Emscripten defines CMAKE_CROSSCOMPILING_EMULATOR (node) while still wanting cross-compiling mode, so the flag was forced OFF.

This moves the emulator check up so it only guards the auto-default (which also no longer fires if the project already set the variable), and restores the second condition to CMAKE_CROSSCOMPILING AND PYBIND11_USE_CROSSCOMPILING. This is the fix proposed by the original PR author (@mhsmith) in the issue thread.

Behavior preserved across all cases:

  • Emscripten/Pyodide — sets PYBIND11_USE_CROSSCOMPILING=ON explicitly → respected → ON
  • Android (CMake ≥ 4.1, CMP0190 NEW, no emulator, variable unset) → still auto-defaults to ON
  • Explicit OFF → respected

Suggested changelog entry:

  • Fixed cross-compilation to Emscripten/Pyodide with CMake ≥ 4.1 by no longer overriding an explicitly set PYBIND11_USE_CROSSCOMPILING when CMAKE_CROSSCOMPILING_EMULATOR is defined.

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
@henryiii

Copy link
Copy Markdown
Collaborator Author

GPT 5.5 review in Codex:

🤖 AI text below 🤖

The change fixes respecting explicit cross-compiling settings with an emulator, but it regresses the intended CMP0190 default in normal top-level/add_subdirectory builds because the option default makes the variable defined before this file is included.

Review comment:

  • [P2] Restore CMP0190 auto-default for subdirectory builds — /Users/henryfs/git/pybind/pybind11/tools/pybind11Common.cmake:49-49
    When pybind11 is used as the top-level project or via add_subdirectory, CMakeLists.txt has already run option(PYBIND11_USE_CROSSCOMPILING ... OFF), so this NOT DEFINED check is false even when the user did not explicitly choose a value. With CMake 4.1+ / CMP0190 NEW cross-compiling without CMAKE_CROSSCOMPILING_EMULATOR, _PYBIND11_CROSSCOMPILING now stays OFF and find_package(Python ... Interpreter ... Development...) fails with the CMP0190 error instead of omitting the interpreter component.

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
@henryiii

henryiii commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator Author

Claude Opus 4.8:

🤖 AI text below 🤖

Good catch — fixed in 692b031.

The NOT DEFINED PYBIND11_USE_CROSSCOMPILING guard worked for find_package() consumers but, as you noted, broke top-level / add_subdirectory builds: CMakeLists.txt runs option(PYBIND11_USE_CROSSCOMPILING ... OFF) before including pybind11Common.cmake, so the variable was already defined (OFF) and the CMP0190 auto-default never applied.

The fix records, right before the option() call, whether the project had already set the value:

if(NOT DEFINED PYBIND11_USE_CROSSCOMPILING)
  set(_PYBIND11_USE_CROSSCOMPILING_DEFAULTED ON)
endif()
option(PYBIND11_USE_CROSSCOMPILING "Respect CMAKE_CROSSCOMPILING" OFF)

and pybind11Common.cmake now applies the CMP0190 default when either the variable is undefined (the find_package case) or it was only defaulted by option():

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))

This preserves all cases: explicit user value (any flow) respected; CMP0190 auto-default restored for add_subdirectory/top-level and find_package; and the original emulator override fix (Emscripten/Pyodide sets the var explicitly) intact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: Cannot compile emscripten/pyodide project

1 participant