Skip to content

pybind11Tools: Use interface target library when able #1367

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

Closed
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
5 changes: 5 additions & 0 deletions docs/compiling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ to an independently constructed (through ``add_library``, not
Studio (``/bigobj``). The :ref:`FAQ <faq:symhidden>` contains an
explanation on why these are needed.

.. note::

``pybind11_add_module`` will use this interface library target in addition
to the above compiler flags if using a version of CMake greater than 3.0.

Embedding the Python interpreter
--------------------------------

Expand Down
88 changes: 48 additions & 40 deletions tools/pybind11Tools.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -130,50 +130,58 @@ function(pybind11_add_module target_name)

add_library(${target_name} ${lib_type} ${exclude_from_all} ${ARG_UNPARSED_ARGUMENTS})

target_include_directories(${target_name}
PRIVATE ${PYBIND11_INCLUDE_DIR} # from project CMakeLists.txt
PRIVATE ${pybind11_INCLUDE_DIR} # from pybind11Config
PRIVATE ${PYTHON_INCLUDE_DIRS})

# The prefix and extension are provided by FindPythonLibsNew.cmake
set_target_properties(${target_name} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}")
set_target_properties(${target_name} PROPERTIES SUFFIX "${PYTHON_MODULE_EXTENSION}")
if(TARGET pybind11::module)
# Use interface target library.
target_link_libraries(${target_name} PRIVATE pybind11::module)
else()
target_include_directories(${target_name}
PRIVATE ${PYBIND11_INCLUDE_DIR} # from project CMakeLists.txt
PRIVATE ${pybind11_INCLUDE_DIR} # from pybind11Config
PRIVATE ${PYTHON_INCLUDE_DIRS})

# -fvisibility=hidden is required to allow multiple modules compiled against
# different pybind versions to work properly, and for some features (e.g.
# py::module_local). We force it on everything inside the `pybind11`
# namespace; also turning it on for a pybind module compilation here avoids
# potential warnings or issues from having mixed hidden/non-hidden types.
set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden")

if(WIN32 OR CYGWIN)
# Link against the Python shared library on Windows
target_link_libraries(${target_name} PRIVATE ${PYTHON_LIBRARIES})
endif()

# -fvisibility=hidden is required to allow multiple modules compiled against
# different pybind versions to work properly, and for some features (e.g.
# py::module_local). We force it on everything inside the `pybind11`
# namespace; also turning it on for a pybind module compilation here avoids
# potential warnings or issues from having mixed hidden/non-hidden types.
set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden")

if(WIN32 OR CYGWIN)
# Link against the Python shared library on Windows
target_link_libraries(${target_name} PRIVATE ${PYTHON_LIBRARIES})
elseif(APPLE)
# It's quite common to have multiple copies of the same Python version
# installed on one's system. E.g.: one copy from the OS and another copy
# that's statically linked into an application like Blender or Maya.
# If we link our plugin library against the OS Python here and import it
# into Blender or Maya later on, this will cause segfaults when multiple
# conflicting Python instances are active at the same time (even when they
# are of the same version).

# Windows is not affected by this issue since it handles DLL imports
# differently. The solution for Linux and Mac OS is simple: we just don't
# link against the Python library. The resulting shared library will have
# missing symbols, but that's perfectly fine -- they will be resolved at
# import time.

target_link_libraries(${target_name} PRIVATE "-undefined dynamic_lookup")

if(ARG_SHARED)
# Suppress CMake >= 3.0 warning for shared libraries
set_target_properties(${target_name} PROPERTIES MACOSX_RPATH ON)
# Make sure C++11/14 are enabled
target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD})

if(APPLE)
# It's quite common to have multiple copies of the same Python version
# installed on one's system. E.g.: one copy from the OS and another copy
# that's statically linked into an application like Blender or Maya.
# If we link our plugin library against the OS Python here and import it
# into Blender or Maya later on, this will cause segfaults when multiple
# conflicting Python instances are active at the same time (even when they
# are of the same version).

# Windows is not affected by this issue since it handles DLL imports
# differently. The solution for Linux and Mac OS is simple: we just don't
# link against the Python library. The resulting shared library will have
# missing symbols, but that's perfectly fine -- they will be resolved at
# import time.

target_link_libraries(${target_name} PRIVATE "-undefined dynamic_lookup")

if(ARG_SHARED)
# Suppress CMake >= 3.0 warning for shared libraries
set_target_properties(${target_name} PROPERTIES MACOSX_RPATH ON)
endif()
endif()

endif()

# Make sure C++11/14 are enabled
target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD})
# The prefix and extension are provided by FindPythonLibsNew.cmake
set_target_properties(${target_name} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}")
set_target_properties(${target_name} PROPERTIES SUFFIX "${PYTHON_MODULE_EXTENSION}")

if(ARG_NO_EXTRAS)
return()
Expand Down