Skip to content

Commit ae6ed96

Browse files
committed
add CMake exported interface library and Config detection file
1 parent 6a8c13d commit ae6ed96

File tree

5 files changed

+191
-0
lines changed

5 files changed

+191
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ MANIFEST
3333
/cmake/
3434
.cache/
3535
sosize-*.txt
36+
pybind11Config*.cmake
37+
pybind11Targets.cmake

CMakeLists.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ if (PYBIND11_TEST)
180180
endif()
181181

182182
include(GNUInstallDirs)
183+
include(CMakePackageConfigHelpers)
183184

184185
# extract project version from source
185186
file(STRINGS "${PYBIND11_INCLUDE_DIR}/pybind11/common.h" pybind11_version_defines
@@ -191,10 +192,40 @@ foreach(ver ${pybind11_version_defines})
191192
endforeach()
192193
set(${PROJECT_NAME}_VERSION ${PYBIND11_VERSION_MAJOR}.${PYBIND11_VERSION_MINOR}.${PYBIND11_VERSION_PATCH})
193194

195+
if(NOT (CMAKE_VERSION VERSION_LESS 3.0)) # CMake >= 3.0
196+
# Build an interface library target:
197+
add_library(pybind11 INTERFACE)
198+
target_include_directories(pybind11 INTERFACE $<BUILD_INTERFACE:${PYBIND11_INCLUDE_DIR}>
199+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
200+
if(APPLE)
201+
target_link_libraries(pybind11 INTERFACE "-undefined dynamic_lookup")
202+
endif()
203+
endif()
204+
194205
if (PYBIND11_INSTALL)
195206
install(FILES ${PYBIND11_HEADERS}
196207
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pybind11)
197208
# GNUInstallDirs "DATADIR" wrong here; CMake search path wants "share".
198209
set(PYBIND11_CMAKECONFIG_INSTALL_DIR "share/cmake/${PROJECT_NAME}" CACHE STRING "install path for pybind11Config.cmake")
199210

211+
configure_package_config_file(tools/${PROJECT_NAME}Config.cmake.in
212+
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
213+
INSTALL_DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
214+
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
215+
VERSION ${${PROJECT_NAME}_VERSION}
216+
COMPATIBILITY AnyNewerVersion)
217+
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
218+
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
219+
tools/FindPythonLibsNew.cmake
220+
tools/pybind11Tools.cmake
221+
DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
222+
223+
if(NOT (CMAKE_VERSION VERSION_LESS 3.0))
224+
install(TARGETS pybind11
225+
EXPORT "${PROJECT_NAME}Targets")
226+
install(EXPORT "${PROJECT_NAME}Targets"
227+
NAMESPACE "${PROJECT_NAME}::"
228+
DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
229+
message(STATUS "Exporting ${PROJECT_NAME}::pybind11 interface library target version ${${PROJECT_NAME}_VERSION}")
230+
endif()
200231
endif()

docs/compiling.rst

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,67 @@ A working sample project, including a way to invoke CMake from :file:`setup.py`
5151
PyPI integration, can be found in the [cmake_example]_ repository.
5252

5353
.. [cmake_example] https://github.com/pybind/cmake_example
54+
55+
For CMake-based projects that don't include the pybind11
56+
repository internally, an external installation can be detected
57+
through `find_package(pybind11 ... CONFIG ...)`. See the `Config file
58+
<https://github.com/pybind/pybind11/blob/master/tools/pybind11Config.cmake.in>`_
59+
docstring for details of relevant CMake variables.
60+
61+
Once detected, and after setting any variables to guide Python and C++
62+
standard detection, the aforementioned ``pybind11_add_module``
63+
wrapper to ``add_library`` can
64+
be employed as described above (after ``include(pybind11Tools)``). This
65+
procedure is available when using CMake >= 2.8.12. A
66+
working example can be found at [test_installed_module]_ .
67+
68+
.. code-block:: cmake
69+
70+
cmake_minimum_required(VERSION 2.8.12)
71+
project(example)
72+
73+
find_package(pybind11 REQUIRED)
74+
pybind11_add_module(example example.cpp)
75+
76+
.. [test_installed_module] https://github.com/pybind/pybind11/blob/master/tests/test_installed_module/CMakeLists.txt
77+
78+
When using a version of CMake greater than 3.0, pybind11 can
79+
additionally be used as a special *interface library* following the call
80+
to ``find_package``. CMake
81+
variables to guide Python and C++ standard detection should be set
82+
*before* ``find_package``. When ``find_package`` returns, the target
83+
``pybind11::pybind11`` is available with pybind11 headers, Python headers
84+
and libraries as needed, and C++ compile definitions attached. This
85+
target is suitable for linking to an independently constructed (through
86+
``add_library``, not ``pybind11_add_module``) target in the consuming
87+
project. A working example can be found at [test_installed_target]_ .
88+
89+
.. code-block:: cmake
90+
91+
cmake_minimum_required(VERSION 3.0)
92+
project(example)
93+
94+
add_library(example MODULE main.cpp)
95+
96+
find_package(pybind11 REQUIRED)
97+
target_link_libraries(example PRIVATE pybind11::pybind11)
98+
set_target_properties(example PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
99+
SUFFIX "${PYTHON_MODULE_EXTENSION}")
100+
101+
.. warning::
102+
103+
Since pybind11 is a metatemplate library, it is crucial that certain
104+
compiler flags are provided to ensure high quality code generation. In
105+
contrast to the ``pybind11_add_module()`` command, the CMake interface
106+
library only provides the *minimal* set of parameters to ensure that the
107+
code using pybind11 compiles, but it does **not** pass these extra compiler
108+
flags (i.e. this is up to you).
109+
110+
These include Link Time Optimization (``-flto`` on GCC/Clang/ICPC, ``/GL``
111+
and ``/LTCG`` on Visual Studio). Default-hidden symbols on GCC/Clang/ICPC
112+
(``-fvisibility=hidden``) and .OBJ files with many sections on Visual Studio
113+
(``/bigobj``). The :ref:`FAQ <faq:symhidden>` contains an
114+
explanation on why these are needed.
115+
116+
.. [test_installed_target] https://github.com/pybind/pybind11/blob/master/tests/test_installed_target/CMakeLists.txt
117+

docs/faq.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ culprit is generally the generation of function signatures at compile time
162162
using C++14 template metaprogramming.
163163

164164

165+
.. _`faq:symhidden`:
166+
165167
How can I create smaller binaries?
166168
==================================
167169

tools/pybind11Config.cmake.in

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# pybind11Config.cmake
2+
# --------------------
3+
#
4+
# PYBIND11 cmake module.
5+
# This module sets the following variables in your project::
6+
#
7+
# pybind11_FOUND - true if pybind11 and all required components found on the system
8+
# pybind11_VERSION - pybind11 version in format Major.Minor.Release
9+
# pybind11_INCLUDE_DIRS - Directories where pybind11 and python headers are located.
10+
# pybind11_INCLUDE_DIR - Directory where pybind11 headers are located.
11+
# pybind11_DEFINITIONS - Definitions necessary to use pybind11, namely USING_pybind11.
12+
# pybind11_LIBRARIES - compile flags and python libraries (as needed) to link against.
13+
# pybind11_LIBRARY - empty.
14+
# CMAKE_MODULE_PATH - appends location of accompanying FindPythonLibsNew.cmake and
15+
# pybind11Tools.cmake modules.
16+
#
17+
#
18+
# Available components: None
19+
#
20+
#
21+
# Exported targets::
22+
#
23+
# If pybind11 is found, this module defines the following :prop_tgt:`IMPORTED`
24+
# target. Python headers, libraries (as needed by platform), and C++ standard
25+
# are attached to the target. Set PythonLibsNew variables to influence
26+
# python detection and PYBIND11_CPP_STANDARD (-std=c++11 or -std=c++14) to
27+
# influence standard setting. ::
28+
#
29+
# pybind11::pybind11 - the main pybind11 interface library (i.e., headers)
30+
#
31+
# find_package(pybind11 CONFIG REQUIRED)
32+
# message(STATUS "Found pybind11: ${pybind11_INCLUDE_DIR} (found version ${pybind11_VERSION} & Py${PYTHON_VERSION_STRING})")
33+
# add_library(mylib MODULE main.cpp)
34+
# target_link_libraries(mylib pybind11::pybind11)
35+
#
36+
# Suggested usage::
37+
#
38+
# find_package with version info is not recommended except for release versions. ::
39+
#
40+
# find_package(pybind11 CONFIG)
41+
# find_package(pybind11 2.0 EXACT CONFIG REQUIRED)
42+
#
43+
#
44+
# The following variables can be set to guide the search for this package::
45+
#
46+
# pybind11_DIR - CMake variable, set to directory containing this Config file
47+
# CMAKE_PREFIX_PATH - CMake variable, set to root directory of this package
48+
# PATH - environment variable, set to bin directory of this package
49+
# CMAKE_DISABLE_FIND_PACKAGE_pybind11 - CMake variable, disables
50+
# find_package(pybind11) when not REQUIRED, perhaps to force internal build
51+
52+
@PACKAGE_INIT@
53+
54+
set(PN pybind11)
55+
56+
# location of pybind11/pybind11.h
57+
set(${PN}_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@")
58+
59+
set(${PN}_LIBRARY "")
60+
set(${PN}_DEFINITIONS USING_${PN})
61+
62+
check_required_components(${PN})
63+
64+
# make detectable the FindPythonLibsNew.cmake module
65+
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
66+
67+
include(pybind11Tools)
68+
69+
if(NOT (CMAKE_VERSION VERSION_LESS 3.0))
70+
#-----------------------------------------------------------------------------
71+
# Don't include targets if this file is being picked up by another
72+
# project which has already built this as a subproject
73+
#-----------------------------------------------------------------------------
74+
if(NOT TARGET ${PN}::pybind11)
75+
include("${CMAKE_CURRENT_LIST_DIR}/${PN}Targets.cmake")
76+
77+
find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} MODULE REQUIRED)
78+
set_property(TARGET ${PN}::pybind11 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_DIRS})
79+
if(WIN32 OR CYGWIN)
80+
set_property(TARGET ${PN}::pybind11 APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${PYTHON_LIBRARIES})
81+
endif()
82+
83+
select_cxx_standard()
84+
set_property(TARGET ${PN}::pybind11 APPEND PROPERTY INTERFACE_COMPILE_OPTIONS "${PYBIND11_CPP_STANDARD}")
85+
86+
get_property(_iid TARGET ${PN}::pybind11 PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
87+
get_property(_ill TARGET ${PN}::pybind11 PROPERTY INTERFACE_LINK_LIBRARIES)
88+
get_property(_ico TARGET ${PN}::pybind11 PROPERTY INTERFACE_COMPILE_OPTIONS)
89+
set(${PN}_INCLUDE_DIRS ${_iid})
90+
set(${PN}_LIBRARIES ${_ico} ${_ill})
91+
endif()
92+
endif()

0 commit comments

Comments
 (0)