diff options
author | Ryan Volz <ryan.volz@gmail.com> | 2021-01-08 15:43:41 -0500 |
---|---|---|
committer | Martin Braun <martin@gnuradio.org> | 2021-01-14 04:08:21 -0800 |
commit | 51d3ad973292763a6fc0cf8e971faa3cf89029e9 (patch) | |
tree | ac7e74ccc60615b700f693241379dedd77abbd4e /cmake | |
parent | 518dc7eda3a2575292dc67374cad62c887f83d12 (diff) |
cmake: python: Fix linking when runtime py interpreter != build time.
This fixes a segmentation fault with the Pybind11 bindings when trying
to load any Python module on OSX with a different interpreter than
was used at build time (relevant to at least conda and homebrew). This
fix was already in place for the prior Swig bindings, but the Pybind11
changes do not incorporate it since they link with ${PYTHON_LIBRARIES}
instead of the (fixed) Python::Python target.
For clearer separation and to adopt the approach used by the new-ish
(3.12) builtin CMake FindPython module, this commit creates a separate
Python::Module target to be used when creating a Python extension module
(which includes "-undefined" and "dynamic_lookup" for macOS instead of
linking directly to the Python library). The Python::Python target
that does link to the Python library is still necessary for use as a
PRIVATE target (e.g. for runtime and qtgui).
For future reference and a general description of best practices for
linking Python extension modules, see
https://blog.tim-smith.us/2015/09/python-extension-modules-os-x.
Signed-off-by: Ryan Volz <ryan.volz@gmail.com>
Diffstat (limited to 'cmake')
-rw-r--r-- | cmake/Modules/GrPybind.cmake | 6 | ||||
-rw-r--r-- | cmake/Modules/GrPython.cmake | 36 |
2 files changed, 33 insertions, 9 deletions
diff --git a/cmake/Modules/GrPybind.cmake b/cmake/Modules/GrPybind.cmake index 3eb01c8cdc..bc92a5af3e 100644 --- a/cmake/Modules/GrPybind.cmake +++ b/cmake/Modules/GrPybind.cmake @@ -39,7 +39,7 @@ target_include_directories(${name}_python PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/${updir}/include ${PYBIND11_INCLUDE_DIR} ) -target_link_libraries(${name}_python PUBLIC ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} gnuradio-${MODULE_NAME}) +target_link_libraries(${name}_python PUBLIC ${Boost_LIBRARIES} Python::Module gnuradio-${MODULE_NAME}) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") target_compile_options(${name}_python PRIVATE -Wno-unused-variable) # disable warnings for docstring templates @@ -156,7 +156,7 @@ target_include_directories(${name}_python PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/${updir}/include ${PYBIND11_INCLUDE_DIR} ) -target_link_libraries(${name}_python PUBLIC ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} gnuradio-${MODULE_NAME}) +target_link_libraries(${name}_python PUBLIC ${Boost_LIBRARIES} Python::Module gnuradio-${MODULE_NAME}) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") target_compile_options(${name}_python PRIVATE -Wno-unused-variable) # disable warnings for docstring templates @@ -289,7 +289,7 @@ target_include_directories(${name}_python PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/${updir}/include ${PYBIND11_INCLUDE_DIR} ) -target_link_libraries(${name}_python PUBLIC ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} gnuradio-${MODULE_NAME}) +target_link_libraries(${name}_python PUBLIC ${Boost_LIBRARIES} Python::Module gnuradio-${MODULE_NAME}) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") target_compile_options(${name}_python PRIVATE -Wno-unused-variable) # disable warnings for docstring templates diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake index ff7927c05a..8149cb5cbe 100644 --- a/cmake/Modules/GrPython.cmake +++ b/cmake/Modules/GrPython.cmake @@ -37,14 +37,9 @@ set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter") set(QA_PYTHON_EXECUTABLE ${QA_PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter for QA tests") add_library(Python::Python INTERFACE IMPORTED) -if(APPLE) - set_target_properties(Python::Python PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "-undefined dynamic_lookup" - ) # Need to handle special cases where both debug and release # libraries are available (in form of debug;A;optimized;B) in PYTHON_LIBRARIES -elseif(PYTHON_LIBRARY_DEBUG AND PYTHON_LIBRARY_RELEASE) +if(PYTHON_LIBRARY_DEBUG AND PYTHON_LIBRARY_RELEASE) set_target_properties(Python::Python PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}" INTERFACE_LINK_LIBRARIES "$<$<NOT:$<CONFIG:Debug>>:${PYTHON_LIBRARY_RELEASE}>;$<$<CONFIG:Debug>:${PYTHON_LIBRARY_DEBUG}>" @@ -56,6 +51,35 @@ else() ) endif() +# separate target when linking to make an extension module, which should not +# link explicitly to the python library on Unix-like platforms +add_library(Python::Module INTERFACE IMPORTED) +if(WIN32) + # identical to Python::Python, cannot be an alias because Python::Python is imported + # Need to handle special cases where both debug and release + # libraries are available (in form of debug;A;optimized;B) in PYTHON_LIBRARIES + if(PYTHON_LIBRARY_DEBUG AND PYTHON_LIBRARY_RELEASE) + set_target_properties(Python::Module PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "$<$<NOT:$<CONFIG:Debug>>:${PYTHON_LIBRARY_RELEASE}>;$<$<CONFIG:Debug>:${PYTHON_LIBRARY_DEBUG}>" + ) + else() + set_target_properties(Python::Module PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${PYTHON_LIBRARIES}" + ) + endif() +else() + set_target_properties(Python::Module PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}" + ) + if(APPLE) + set_target_properties(Python::Module PROPERTIES + INTERFACE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup" + ) + endif(APPLE) +endif(WIN32) + ######################################################################## # Check for the existence of a python module: |