You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

423 lines
16 KiB

  1. # CMakeLists.txt -- Build system for the pybind11 modules
  2. #
  3. # Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
  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. # Propagate this policy (FindPythonInterp removal) so it can be detected later
  8. if(NOT CMAKE_VERSION VERSION_LESS "3.27")
  9. cmake_policy(GET CMP0148 _pybind11_cmp0148)
  10. endif()
  11. cmake_minimum_required(VERSION 3.15...4.0)
  12. if(_pybind11_cmp0148)
  13. cmake_policy(SET CMP0148 ${_pybind11_cmp0148})
  14. unset(_pybind11_cmp0148)
  15. endif()
  16. # Avoid infinite recursion if tests include this as a subdirectory
  17. include_guard(GLOBAL)
  18. # Extract project version from source
  19. file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/pybind11/detail/common.h"
  20. pybind11_version_defines REGEX "#define PYBIND11_VERSION_(MAJOR|MINOR|PATCH) ")
  21. foreach(ver ${pybind11_version_defines})
  22. if(ver MATCHES [[#define PYBIND11_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$]])
  23. set(PYBIND11_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}")
  24. endif()
  25. endforeach()
  26. if(PYBIND11_VERSION_PATCH MATCHES [[\.([a-zA-Z0-9]+)$]])
  27. set(pybind11_VERSION_TYPE "${CMAKE_MATCH_1}")
  28. endif()
  29. string(REGEX MATCH "^[0-9]+" PYBIND11_VERSION_PATCH "${PYBIND11_VERSION_PATCH}")
  30. project(
  31. pybind11
  32. LANGUAGES CXX
  33. VERSION "${PYBIND11_VERSION_MAJOR}.${PYBIND11_VERSION_MINOR}.${PYBIND11_VERSION_PATCH}")
  34. # Standard includes
  35. include(GNUInstallDirs)
  36. include(CMakePackageConfigHelpers)
  37. include(CMakeDependentOption)
  38. if(NOT pybind11_FIND_QUIETLY)
  39. message(STATUS "pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}")
  40. endif()
  41. # Check if pybind11 is being used directly or via add_subdirectory
  42. if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
  43. ### Warn if not an out-of-source builds
  44. if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
  45. set(lines
  46. "You are building in-place. If that is not what you intended to "
  47. "do, you can clean the source directory with:\n"
  48. "rm -r CMakeCache.txt CMakeFiles/ cmake_uninstall.cmake pybind11Config.cmake "
  49. "pybind11ConfigVersion.cmake tests/CMakeFiles/\n")
  50. message(AUTHOR_WARNING ${lines})
  51. endif()
  52. set(PYBIND11_MASTER_PROJECT ON)
  53. message(STATUS "CMake ${CMAKE_VERSION}")
  54. if(DEFINED SKBUILD AND DEFINED ENV{PYBIND11_GLOBAL_SDIST})
  55. message(
  56. FATAL_ERROR
  57. "PYBIND11_GLOBAL_SDIST is not supported, use nox -s build_global or a pybind11-global SDist instead."
  58. )
  59. endif()
  60. if(CMAKE_CXX_STANDARD)
  61. set(CMAKE_CXX_EXTENSIONS OFF)
  62. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  63. endif()
  64. set(pybind11_system "")
  65. set_property(GLOBAL PROPERTY USE_FOLDERS ON)
  66. if(CMAKE_VERSION VERSION_LESS "3.18")
  67. set(_pybind11_findpython_default OFF)
  68. else()
  69. set(_pybind11_findpython_default ON)
  70. endif()
  71. else()
  72. set(PYBIND11_MASTER_PROJECT OFF)
  73. set(pybind11_system SYSTEM)
  74. set(_pybind11_findpython_default COMPAT)
  75. endif()
  76. # Options
  77. option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT})
  78. option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT})
  79. option(PYBIND11_NOPYTHON "Disable search for Python" OFF)
  80. option(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION
  81. "To enforce that a handle_type_name<> specialization exists" OFF)
  82. option(PYBIND11_SIMPLE_GIL_MANAGEMENT
  83. "Use simpler GIL management logic that does not support disassociation" OFF)
  84. set(PYBIND11_INTERNALS_VERSION
  85. ""
  86. CACHE STRING "Override the ABI version, may be used to enable the unstable ABI.")
  87. option(PYBIND11_USE_CROSSCOMPILING "Respect CMAKE_CROSSCOMPILING" OFF)
  88. if(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
  89. add_compile_definitions(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
  90. endif()
  91. if(PYBIND11_SIMPLE_GIL_MANAGEMENT)
  92. add_compile_definitions(PYBIND11_SIMPLE_GIL_MANAGEMENT)
  93. endif()
  94. cmake_dependent_option(
  95. USE_PYTHON_INCLUDE_DIR
  96. "Install pybind11 headers in Python include directory instead of default installation prefix"
  97. OFF "PYBIND11_INSTALL" OFF)
  98. set(PYBIND11_FINDPYTHON
  99. ${_pybind11_findpython_default}
  100. CACHE STRING "Force new FindPython - NEW, OLD, COMPAT")
  101. if(PYBIND11_MASTER_PROJECT)
  102. # Allow PYTHON_EXECUTABLE if in FINDPYTHON mode and building pybind11's tests
  103. # (makes transition easier while we support both modes).
  104. if(PYBIND11_FINDPYTHON
  105. AND DEFINED PYTHON_EXECUTABLE
  106. AND NOT DEFINED Python_EXECUTABLE)
  107. set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
  108. endif()
  109. # This is a shortcut that is primarily for the venv cmake preset,
  110. # but can be used to quickly setup tests manually, too
  111. set(PYBIND11_CREATE_WITH_UV
  112. ""
  113. CACHE STRING "Create a virtualenv if it doesn't exist")
  114. if(NOT PYBIND11_CREATE_WITH_UV STREQUAL "")
  115. set(Python_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/.venv")
  116. if(EXISTS "${Python_ROOT_DIR}")
  117. if(EXISTS "${CMAKE_BINARY_DIR}/CMakeCache.txt")
  118. message(STATUS "Using existing venv at ${Python_ROOT_DIR}, remove or --fresh to recreate")
  119. else()
  120. # --fresh used to remove the cache
  121. file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/.venv")
  122. endif()
  123. endif()
  124. if(NOT EXISTS "${Python_ROOT_DIR}")
  125. find_program(UV uv REQUIRED)
  126. # CMake 3.19+ would be able to use COMMAND_ERROR_IS_FATAL
  127. message(
  128. STATUS "Creating venv with ${UV} venv -p ${PYBIND11_CREATE_WITH_UV} '${Python_ROOT_DIR}'")
  129. execute_process(COMMAND ${UV} venv -p ${PYBIND11_CREATE_WITH_UV} "${Python_ROOT_DIR}"
  130. RESULT_VARIABLE _venv_result)
  131. if(_venv_result AND NOT _venv_result EQUAL 0)
  132. message(FATAL_ERROR "uv venv failed with '${_venv_result}'")
  133. endif()
  134. message(
  135. STATUS
  136. "Installing deps with ${UV} pip install -p '${Python_ROOT_DIR}' -r tests/requirements.txt"
  137. )
  138. execute_process(
  139. COMMAND ${UV} pip install -p "${Python_ROOT_DIR}" -r
  140. "${CMAKE_CURRENT_SOURCE_DIR}/tests/requirements.txt" RESULT_VARIABLE _pip_result)
  141. if(_pip_result AND NOT _pip_result EQUAL 0)
  142. message(FATAL_ERROR "uv pip install failed with '${_pip_result}'")
  143. endif()
  144. endif()
  145. else()
  146. if(NOT DEFINED Python3_EXECUTABLE
  147. AND NOT DEFINED Python_EXECUTABLE
  148. AND NOT DEFINED Python_ROOT_DIR
  149. AND NOT DEFINED ENV{VIRTUALENV}
  150. AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.venv")
  151. message(STATUS "Autodetecting Python in virtual environment")
  152. set(Python_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.venv")
  153. endif()
  154. endif()
  155. endif()
  156. set(PYBIND11_HEADERS
  157. include/pybind11/detail/class.h
  158. include/pybind11/detail/common.h
  159. include/pybind11/detail/cpp_conduit.h
  160. include/pybind11/detail/descr.h
  161. include/pybind11/detail/dynamic_raw_ptr_cast_if_possible.h
  162. include/pybind11/detail/exception_translation.h
  163. include/pybind11/detail/function_record_pyobject.h
  164. include/pybind11/detail/init.h
  165. include/pybind11/detail/internals.h
  166. include/pybind11/detail/native_enum_data.h
  167. include/pybind11/detail/pybind11_namespace_macros.h
  168. include/pybind11/detail/struct_smart_holder.h
  169. include/pybind11/detail/type_caster_base.h
  170. include/pybind11/detail/typeid.h
  171. include/pybind11/detail/using_smart_holder.h
  172. include/pybind11/detail/value_and_holder.h
  173. include/pybind11/attr.h
  174. include/pybind11/buffer_info.h
  175. include/pybind11/cast.h
  176. include/pybind11/chrono.h
  177. include/pybind11/common.h
  178. include/pybind11/complex.h
  179. include/pybind11/conduit/pybind11_conduit_v1.h
  180. include/pybind11/conduit/pybind11_platform_abi_id.h
  181. include/pybind11/conduit/wrap_include_python_h.h
  182. include/pybind11/critical_section.h
  183. include/pybind11/options.h
  184. include/pybind11/eigen.h
  185. include/pybind11/eigen/common.h
  186. include/pybind11/eigen/matrix.h
  187. include/pybind11/eigen/tensor.h
  188. include/pybind11/embed.h
  189. include/pybind11/eval.h
  190. include/pybind11/gil.h
  191. include/pybind11/gil_safe_call_once.h
  192. include/pybind11/gil_simple.h
  193. include/pybind11/iostream.h
  194. include/pybind11/functional.h
  195. include/pybind11/native_enum.h
  196. include/pybind11/numpy.h
  197. include/pybind11/operators.h
  198. include/pybind11/pybind11.h
  199. include/pybind11/pytypes.h
  200. include/pybind11/subinterpreter.h
  201. include/pybind11/stl.h
  202. include/pybind11/stl_bind.h
  203. include/pybind11/stl/filesystem.h
  204. include/pybind11/trampoline_self_life_support.h
  205. include/pybind11/type_caster_pyobject_ptr.h
  206. include/pybind11/typing.h
  207. include/pybind11/warnings.h)
  208. # Compare with grep and warn if mismatched
  209. if(PYBIND11_MASTER_PROJECT)
  210. file(
  211. GLOB_RECURSE _pybind11_header_check
  212. LIST_DIRECTORIES false
  213. RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
  214. CONFIGURE_DEPENDS "include/pybind11/*.h")
  215. set(_pybind11_here_only ${PYBIND11_HEADERS})
  216. set(_pybind11_disk_only ${_pybind11_header_check})
  217. list(REMOVE_ITEM _pybind11_here_only ${_pybind11_header_check})
  218. list(REMOVE_ITEM _pybind11_disk_only ${PYBIND11_HEADERS})
  219. if(_pybind11_here_only)
  220. message(AUTHOR_WARNING "PYBIND11_HEADERS has extra files:" ${_pybind11_here_only})
  221. endif()
  222. if(_pybind11_disk_only)
  223. message(AUTHOR_WARNING "PYBIND11_HEADERS is missing files:" ${_pybind11_disk_only})
  224. endif()
  225. endif()
  226. list(TRANSFORM PYBIND11_HEADERS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/")
  227. # Cache variable so this can be used in parent projects
  228. set(pybind11_INCLUDE_DIR
  229. "${CMAKE_CURRENT_LIST_DIR}/include"
  230. CACHE INTERNAL "Directory where pybind11 headers are located")
  231. # Backward compatible variable for add_subdirectory mode
  232. if(NOT PYBIND11_MASTER_PROJECT)
  233. set(PYBIND11_INCLUDE_DIR
  234. "${pybind11_INCLUDE_DIR}"
  235. CACHE INTERNAL "")
  236. endif()
  237. # Note: when creating targets, you cannot use if statements at configure time -
  238. # you need generator expressions, because those will be placed in the target file.
  239. # You can also place ifs *in* the Config.in, but not here.
  240. # This section builds targets, but does *not* touch Python
  241. # Non-IMPORT targets cannot be defined twice
  242. if(NOT TARGET pybind11_headers)
  243. # Build the headers-only target (no Python included):
  244. # (long name used here to keep this from clashing in subdirectory mode)
  245. add_library(pybind11_headers INTERFACE)
  246. add_library(pybind11::pybind11_headers ALIAS pybind11_headers) # to match exported target
  247. add_library(pybind11::headers ALIAS pybind11_headers) # easier to use/remember
  248. target_include_directories(
  249. pybind11_headers ${pybind11_system} INTERFACE $<BUILD_INTERFACE:${pybind11_INCLUDE_DIR}>
  250. $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
  251. target_compile_features(pybind11_headers INTERFACE cxx_inheriting_constructors cxx_user_literals
  252. cxx_right_angle_brackets)
  253. if(NOT "${PYBIND11_INTERNALS_VERSION}" STREQUAL "")
  254. target_compile_definitions(
  255. pybind11_headers INTERFACE "PYBIND11_INTERNALS_VERSION=${PYBIND11_INTERNALS_VERSION}")
  256. endif()
  257. else()
  258. # It is invalid to install a target twice, too.
  259. set(PYBIND11_INSTALL OFF)
  260. endif()
  261. include("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11Common.cmake")
  262. # https://github.com/jtojnar/cmake-snips/#concatenating-paths-when-building-pkg-config-files
  263. # TODO: cmake 3.20 adds the cmake_path() function, which obsoletes this snippet
  264. include("${CMAKE_CURRENT_SOURCE_DIR}/tools/JoinPaths.cmake")
  265. # Relative directory setting
  266. if(USE_PYTHON_INCLUDE_DIR AND DEFINED Python_INCLUDE_DIRS)
  267. file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${Python_INCLUDE_DIRS})
  268. elseif(USE_PYTHON_INCLUDE_DIR AND DEFINED PYTHON_INCLUDE_DIR)
  269. file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${PYTHON_INCLUDE_DIRS})
  270. endif()
  271. if(PYBIND11_INSTALL)
  272. if(DEFINED SKBUILD_PROJECT_NAME AND SKBUILD_PROJECT_NAME STREQUAL "pybind11_global")
  273. install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION "${SKBUILD_HEADERS_DIR}")
  274. endif()
  275. install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
  276. set(PYBIND11_CMAKECONFIG_INSTALL_DIR
  277. "${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}"
  278. CACHE STRING "install path for pybind11Config.cmake")
  279. if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
  280. set(pybind11_INCLUDEDIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
  281. else()
  282. set(pybind11_INCLUDEDIR "\$\{PACKAGE_PREFIX_DIR\}/${CMAKE_INSTALL_INCLUDEDIR}")
  283. endif()
  284. configure_package_config_file(
  285. tools/${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
  286. INSTALL_DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
  287. # CMake natively supports header-only libraries
  288. write_basic_package_version_file(
  289. ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
  290. VERSION ${PROJECT_VERSION}
  291. COMPATIBILITY AnyNewerVersion ARCH_INDEPENDENT)
  292. install(
  293. FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
  294. ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
  295. tools/FindPythonLibsNew.cmake
  296. tools/pybind11Common.cmake
  297. tools/pybind11Tools.cmake
  298. tools/pybind11NewTools.cmake
  299. tools/pybind11GuessPythonExtSuffix.cmake
  300. DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
  301. if(NOT PYBIND11_EXPORT_NAME)
  302. set(PYBIND11_EXPORT_NAME "${PROJECT_NAME}Targets")
  303. endif()
  304. install(TARGETS pybind11_headers EXPORT "${PYBIND11_EXPORT_NAME}")
  305. install(
  306. EXPORT "${PYBIND11_EXPORT_NAME}"
  307. NAMESPACE "pybind11::"
  308. DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
  309. # pkg-config support
  310. if(NOT prefix_for_pc_file)
  311. if(IS_ABSOLUTE "${CMAKE_INSTALL_DATAROOTDIR}")
  312. set(prefix_for_pc_file "${CMAKE_INSTALL_PREFIX}")
  313. else()
  314. set(pc_datarootdir "${CMAKE_INSTALL_DATAROOTDIR}")
  315. if(CMAKE_VERSION VERSION_LESS 3.20)
  316. set(prefix_for_pc_file "\${pcfiledir}/..")
  317. while(pc_datarootdir)
  318. get_filename_component(pc_datarootdir "${pc_datarootdir}" DIRECTORY)
  319. string(APPEND prefix_for_pc_file "/..")
  320. endwhile()
  321. else()
  322. cmake_path(RELATIVE_PATH CMAKE_INSTALL_PREFIX BASE_DIRECTORY CMAKE_INSTALL_DATAROOTDIR
  323. OUTPUT_VARIABLE prefix_for_pc_file)
  324. endif()
  325. endif()
  326. endif()
  327. join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
  328. configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11.pc.in"
  329. "${CMAKE_CURRENT_BINARY_DIR}/pybind11.pc" @ONLY)
  330. install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pybind11.pc"
  331. DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")
  332. # When building a wheel, include __init__.py's for modules
  333. # (see https://github.com/pybind/pybind11/pull/5552)
  334. if(DEFINED SKBUILD_PROJECT_NAME AND SKBUILD_PROJECT_NAME STREQUAL "pybind11")
  335. file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/empty")
  336. file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py")
  337. install(FILES "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py"
  338. DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/")
  339. install(FILES "${CMAKE_CURRENT_BINARY_DIR}/empty/__init__.py"
  340. DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")
  341. endif()
  342. # Uninstall target
  343. if(PYBIND11_MASTER_PROJECT)
  344. configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake_uninstall.cmake.in"
  345. "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
  346. add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P
  347. ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
  348. endif()
  349. endif()
  350. # BUILD_TESTING takes priority, but only if this is the master project
  351. if(PYBIND11_MASTER_PROJECT AND DEFINED BUILD_TESTING)
  352. if(BUILD_TESTING)
  353. if(_pybind11_nopython)
  354. message(FATAL_ERROR "Cannot activate tests in NOPYTHON mode")
  355. else()
  356. add_subdirectory(tests)
  357. endif()
  358. endif()
  359. else()
  360. if(PYBIND11_TEST)
  361. if(_pybind11_nopython)
  362. message(FATAL_ERROR "Cannot activate tests in NOPYTHON mode")
  363. else()
  364. add_subdirectory(tests)
  365. endif()
  366. endif()
  367. endif()
  368. # Better symmetry with find_package(pybind11 CONFIG) mode.
  369. if(NOT PYBIND11_MASTER_PROJECT)
  370. set(pybind11_FOUND
  371. TRUE
  372. CACHE INTERNAL "True if pybind11 and all required components found on the system")
  373. endif()