• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# tools/pybind11NewTools.cmake -- Build system for the pybind11 modules
2#
3# Copyright (c) 2020 Wenzel Jakob <wenzel@inf.ethz.ch> and Henry Schreiner
4#
5# All rights reserved. Use of this source code is governed by a
6# BSD-style license that can be found in the LICENSE file.
7
8get_property(
9  is_config
10  TARGET pybind11::headers
11  PROPERTY IMPORTED)
12
13if(pybind11_FIND_QUIETLY)
14  set(_pybind11_quiet QUIET)
15else()
16  set(_pybind11_quiet "")
17endif()
18
19if(CMAKE_VERSION VERSION_LESS 3.12)
20  message(FATAL_ERROR "You cannot use the new FindPython module with CMake < 3.12")
21endif()
22
23if(NOT Python_FOUND
24   AND NOT Python3_FOUND
25   AND NOT Python2_FOUND)
26  if(NOT DEFINED Python_FIND_IMPLEMENTATIONS)
27    set(Python_FIND_IMPLEMENTATIONS CPython PyPy)
28  endif()
29
30  # GitHub Actions like activation
31  if(NOT DEFINED Python_ROOT_DIR AND DEFINED ENV{pythonLocation})
32    set(Python_ROOT_DIR "$ENV{pythonLocation}")
33  endif()
34
35  find_package(Python REQUIRED COMPONENTS Interpreter Development ${_pybind11_quiet})
36
37  # If we are in submodule mode, export the Python targets to global targets.
38  # If this behavior is not desired, FindPython _before_ pybind11.
39  if(NOT is_config)
40    set_property(TARGET Python::Python PROPERTY IMPORTED_GLOBAL TRUE)
41    set_property(TARGET Python::Interpreter PROPERTY IMPORTED_GLOBAL TRUE)
42    if(TARGET Python::Module)
43      set_property(TARGET Python::Module PROPERTY IMPORTED_GLOBAL TRUE)
44    endif()
45  endif()
46endif()
47
48if(Python_FOUND)
49  set(_Python
50      Python
51      CACHE INTERNAL "" FORCE)
52elseif(Python3_FOUND AND NOT Python2_FOUND)
53  set(_Python
54      Python3
55      CACHE INTERNAL "" FORCE)
56elseif(Python2_FOUND AND NOT Python3_FOUND)
57  set(_Python
58      Python2
59      CACHE INTERNAL "" FORCE)
60else()
61  message(AUTHOR_WARNING "Python2 and Python3 both present, pybind11 in "
62                         "PYBIND11_NOPYTHON mode (manually activate to silence warning)")
63  set(_pybind11_nopython ON)
64  return()
65endif()
66
67if(PYBIND11_MASTER_PROJECT)
68  if(${_Python}_INTERPRETER_ID MATCHES "PyPy")
69    message(STATUS "PyPy ${${_Python}_PyPy_VERSION} (Py ${${_Python}_VERSION})")
70  else()
71    message(STATUS "${_Python} ${${_Python}_VERSION}")
72  endif()
73endif()
74
75# If a user finds Python, they may forget to include the Interpreter component
76# and the following two steps require it. It is highly recommended by CMake
77# when finding development libraries anyway, so we will require it.
78if(NOT DEFINED ${_Python}_EXECUTABLE)
79  message(
80    FATAL_ERROR
81      "${_Python} was found without the Interpreter component. Pybind11 requires this component.")
82
83endif()
84
85if(NOT DEFINED PYTHON_IS_DEBUG)
86  # Debug check - see https://stackoverflow.com/questions/646518/python-how-to-detect-debug-Interpreter
87  execute_process(
88    COMMAND "${${_Python}_EXECUTABLE}" "-c"
89            "import sys; sys.exit(hasattr(sys, 'gettotalrefcount'))"
90    RESULT_VARIABLE _PYTHON_IS_DEBUG)
91  set(PYTHON_IS_DEBUG
92      "${_PYTHON_IS_DEBUG}"
93      CACHE INTERNAL "Python debug status")
94endif()
95
96# Get the suffix - SO is deprecated, should use EXT_SUFFIX, but this is
97# required for PyPy3 (as of 7.3.1)
98if(NOT DEFINED PYTHON_MODULE_EXTENSION)
99  execute_process(
100    COMMAND
101      "${${_Python}_EXECUTABLE}" "-c"
102      "from distutils import sysconfig as s;print(s.get_config_var('EXT_SUFFIX') or s.get_config_var('SO'))"
103    OUTPUT_VARIABLE _PYTHON_MODULE_EXTENSION
104    ERROR_VARIABLE _PYTHON_MODULE_EXTENSION_ERR
105    OUTPUT_STRIP_TRAILING_WHITESPACE)
106
107  if(_PYTHON_MODULE_EXTENSION STREQUAL "")
108    message(
109      FATAL_ERROR "pybind11 could not query the module file extension, likely the 'distutils'"
110                  "package is not installed. Full error message:\n${_PYTHON_MODULE_EXTENSION_ERR}")
111  endif()
112
113  # This needs to be available for the pybind11_extension function
114  set(PYTHON_MODULE_EXTENSION
115      "${_PYTHON_MODULE_EXTENSION}"
116      CACHE INTERNAL "")
117endif()
118
119# Python debug libraries expose slightly different objects before 3.8
120# https://docs.python.org/3.6/c-api/intro.html#debugging-builds
121# https://stackoverflow.com/questions/39161202/how-to-work-around-missing-pymodule-create2-in-amd64-win-python35-d-lib
122if(PYTHON_IS_DEBUG)
123  set_property(
124    TARGET pybind11::pybind11
125    APPEND
126    PROPERTY INTERFACE_COMPILE_DEFINITIONS Py_DEBUG)
127endif()
128
129# Check on every access - since Python2 and Python3 could have been used - do nothing in that case.
130
131if(DEFINED ${_Python}_INCLUDE_DIRS)
132  # Only add Python for build - must be added during the import for config
133  # since it has to be re-discovered.
134  #
135  # This needs to be a target to be included after the local pybind11
136  # directory, just in case there there is an installed pybind11 sitting
137  # next to Python's includes. It also ensures Python is a SYSTEM library.
138  add_library(pybind11::python_headers INTERFACE IMPORTED)
139  set_property(
140    TARGET pybind11::python_headers PROPERTY INTERFACE_INCLUDE_DIRECTORIES
141                                             "$<BUILD_INTERFACE:${${_Python}_INCLUDE_DIRS}>")
142  set_property(
143    TARGET pybind11::pybind11
144    APPEND
145    PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python_headers)
146  set(pybind11_INCLUDE_DIRS
147      "${pybind11_INCLUDE_DIR}" "${${_Python}_INCLUDE_DIRS}"
148      CACHE INTERNAL "Directories where pybind11 and possibly Python headers are located")
149endif()
150
151if(DEFINED ${_Python}_VERSION AND ${_Python}_VERSION VERSION_LESS 3)
152  set_property(
153    TARGET pybind11::pybind11
154    APPEND
155    PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python2_no_register)
156endif()
157
158# In CMake 3.18+, you can find these separately, so include an if
159if(TARGET ${_Python}::Python)
160  set_property(
161    TARGET pybind11::embed
162    APPEND
163    PROPERTY INTERFACE_LINK_LIBRARIES ${_Python}::Python)
164endif()
165
166# CMake 3.15+ has this
167if(TARGET ${_Python}::Module)
168  set_property(
169    TARGET pybind11::module
170    APPEND
171    PROPERTY INTERFACE_LINK_LIBRARIES ${_Python}::Module)
172else()
173  set_property(
174    TARGET pybind11::module
175    APPEND
176    PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python_link_helper)
177endif()
178
179# WITHOUT_SOABI and WITH_SOABI will disable the custom extension handling used by pybind11.
180# WITH_SOABI is passed on to python_add_library.
181function(pybind11_add_module target_name)
182  cmake_parse_arguments(PARSE_ARGV 1 ARG
183                        "STATIC;SHARED;MODULE;THIN_LTO;OPT_SIZE;NO_EXTRAS;WITHOUT_SOABI" "" "")
184
185  if(ARG_STATIC)
186    set(lib_type STATIC)
187  elseif(ARG_SHARED)
188    set(lib_type SHARED)
189  else()
190    set(lib_type MODULE)
191  endif()
192
193  if("${_Python}" STREQUAL "Python")
194    python_add_library(${target_name} ${lib_type} ${ARG_UNPARSED_ARGUMENTS})
195  elseif("${_Python}" STREQUAL "Python3")
196    python3_add_library(${target_name} ${lib_type} ${ARG_UNPARSED_ARGUMENTS})
197  elseif("${_Python}" STREQUAL "Python2")
198    python2_add_library(${target_name} ${lib_type} ${ARG_UNPARSED_ARGUMENTS})
199  else()
200    message(FATAL_ERROR "Cannot detect FindPython version: ${_Python}")
201  endif()
202
203  target_link_libraries(${target_name} PRIVATE pybind11::headers)
204
205  if(lib_type STREQUAL "MODULE")
206    target_link_libraries(${target_name} PRIVATE pybind11::module)
207  else()
208    target_link_libraries(${target_name} PRIVATE pybind11::embed)
209  endif()
210
211  if(MSVC)
212    target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
213  endif()
214
215  if(DEFINED ${_Python}_VERSION AND ${_Python}_VERSION VERSION_LESS 3)
216    target_link_libraries(${target_name} PRIVATE pybind11::python2_no_register)
217  endif()
218
219  # -fvisibility=hidden is required to allow multiple modules compiled against
220  # different pybind versions to work properly, and for some features (e.g.
221  # py::module_local).  We force it on everything inside the `pybind11`
222  # namespace; also turning it on for a pybind module compilation here avoids
223  # potential warnings or issues from having mixed hidden/non-hidden types.
224  if(NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET)
225    set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden")
226  endif()
227
228  if(NOT DEFINED CMAKE_CUDA_VISIBILITY_PRESET)
229    set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "hidden")
230  endif()
231
232  # If we don't pass a WITH_SOABI or WITHOUT_SOABI, use our own default handling of extensions
233  if(NOT ARG_WITHOUT_SOABI OR NOT "WITH_SOABI" IN_LIST ARG_UNPARSED_ARGUMENTS)
234    pybind11_extension(${target_name})
235  endif()
236
237  if(ARG_NO_EXTRAS)
238    return()
239  endif()
240
241  if(NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
242    if(ARG_THIN_LTO)
243      target_link_libraries(${target_name} PRIVATE pybind11::thin_lto)
244    else()
245      target_link_libraries(${target_name} PRIVATE pybind11::lto)
246    endif()
247  endif()
248
249  if(NOT MSVC AND NOT ${CMAKE_BUILD_TYPE} MATCHES Debug|RelWithDebInfo)
250    # Strip unnecessary sections of the binary on Linux/macOS
251    pybind11_strip(${target_name})
252  endif()
253
254  if(MSVC)
255    target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
256  endif()
257
258  if(ARG_OPT_SIZE)
259    target_link_libraries(${target_name} PRIVATE pybind11::opt_size)
260  endif()
261endfunction()
262
263function(pybind11_extension name)
264  # The extension is precomputed
265  set_target_properties(${name} PROPERTIES PREFIX "" SUFFIX "${PYTHON_MODULE_EXTENSION}")
266
267endfunction()
268