1#[======================================================[.rst 2 3Adds the following targets:: 4 5 pybind11::pybind11 - link to headers and pybind11 6 pybind11::module - Adds module links 7 pybind11::embed - Adds embed links 8 pybind11::lto - Link time optimizations (manual selection) 9 pybind11::thin_lto - Link time optimizations (manual selection) 10 pybind11::python_link_helper - Adds link to Python libraries 11 pybind11::python2_no_register - Avoid warning/error with Python 2 + C++14/7 12 pybind11::windows_extras - MSVC bigobj and mp for building multithreaded 13 pybind11::opt_size - avoid optimizations that increase code size 14 15Adds the following functions:: 16 17 pybind11_strip(target) - strip target after building on linux/macOS 18 pybind11_find_import(module) - See if a module is installed. 19 20#]======================================================] 21 22# CMake 3.10 has an include_guard command, but we can't use that yet 23if(TARGET pybind11::lto) 24 return() 25endif() 26 27# If we are in subdirectory mode, all IMPORTED targets must be GLOBAL. If we 28# are in CONFIG mode, they should be "normal" targets instead. 29# In CMake 3.11+ you can promote a target to global after you create it, 30# which might be simpler than this check. 31get_property( 32 is_config 33 TARGET pybind11::headers 34 PROPERTY IMPORTED) 35if(NOT is_config) 36 set(optional_global GLOBAL) 37endif() 38 39# If not run in Python mode, we still would like this to at least 40# include pybind11's include directory: 41set(pybind11_INCLUDE_DIRS 42 "${pybind11_INCLUDE_DIR}" 43 CACHE INTERNAL "Include directory for pybind11 (Python not requested)") 44 45# --------------------- Shared targets ---------------------------- 46 47# Build an interface library target: 48add_library(pybind11::pybind11 IMPORTED INTERFACE ${optional_global}) 49set_property( 50 TARGET pybind11::pybind11 51 APPEND 52 PROPERTY INTERFACE_LINK_LIBRARIES pybind11::headers) 53 54# Build a module target: 55add_library(pybind11::module IMPORTED INTERFACE ${optional_global}) 56set_property( 57 TARGET pybind11::module 58 APPEND 59 PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11) 60 61# Build an embed library target: 62add_library(pybind11::embed IMPORTED INTERFACE ${optional_global}) 63set_property( 64 TARGET pybind11::embed 65 APPEND 66 PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11) 67 68# ----------------------- no register ---------------------- 69 70# Workaround for Python 2.7 and C++17 (C++14 as a warning) incompatibility 71# This adds the flags -Wno-register and -Wno-deprecated-register if the compiler 72# is Clang 3.9+ or AppleClang and the compile language is CXX, or /wd5033 for MSVC (all languages, 73# since MSVC didn't recognize COMPILE_LANGUAGE until CMake 3.11+). 74 75add_library(pybind11::python2_no_register INTERFACE IMPORTED ${optional_global}) 76set(clang_4plus 77 "$<AND:$<CXX_COMPILER_ID:Clang>,$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,3.9>>>") 78set(no_register "$<OR:${clang_4plus},$<CXX_COMPILER_ID:AppleClang>>") 79 80if(MSVC AND CMAKE_VERSION VERSION_LESS 3.11) 81 set(cxx_no_register "${no_register}") 82else() 83 set(cxx_no_register "$<AND:$<COMPILE_LANGUAGE:CXX>,${no_register}>") 84endif() 85 86set(msvc "$<CXX_COMPILER_ID:MSVC>") 87 88set_property( 89 TARGET pybind11::python2_no_register 90 PROPERTY INTERFACE_COMPILE_OPTIONS 91 "$<${cxx_no_register}:-Wno-register;-Wno-deprecated-register>" "$<${msvc}:/wd5033>") 92 93# --------------------------- link helper --------------------------- 94 95add_library(pybind11::python_link_helper IMPORTED INTERFACE ${optional_global}) 96 97if(CMAKE_VERSION VERSION_LESS 3.13) 98 # In CMake 3.11+, you can set INTERFACE properties via the normal methods, and 99 # this would be simpler. 100 set_property( 101 TARGET pybind11::python_link_helper 102 APPEND 103 PROPERTY INTERFACE_LINK_LIBRARIES "$<$<PLATFORM_ID:Darwin>:-undefined dynamic_lookup>") 104else() 105 # link_options was added in 3.13+ 106 # This is safer, because you are ensured the deduplication pass in CMake will not consider 107 # these separate and remove one but not the other. 108 set_property( 109 TARGET pybind11::python_link_helper 110 APPEND 111 PROPERTY INTERFACE_LINK_OPTIONS "$<$<PLATFORM_ID:Darwin>:LINKER:-undefined,dynamic_lookup>") 112endif() 113 114# ------------------------ Windows extras ------------------------- 115 116add_library(pybind11::windows_extras IMPORTED INTERFACE ${optional_global}) 117 118if(MSVC) 119 # /MP enables multithreaded builds (relevant when there are many files), /bigobj is 120 # needed for bigger binding projects due to the limit to 64k addressable sections 121 set_property( 122 TARGET pybind11::windows_extras 123 APPEND 124 PROPERTY INTERFACE_COMPILE_OPTIONS /bigobj) 125 126 if(CMAKE_VERSION VERSION_LESS 3.11) 127 set_property( 128 TARGET pybind11::windows_extras 129 APPEND 130 PROPERTY INTERFACE_COMPILE_OPTIONS $<$<NOT:$<CONFIG:Debug>>:/MP>) 131 else() 132 # Only set these options for C++ files. This is important so that, for 133 # instance, projects that include other types of source files like CUDA 134 # .cu files don't get these options propagated to nvcc since that would 135 # cause the build to fail. 136 set_property( 137 TARGET pybind11::windows_extras 138 APPEND 139 PROPERTY INTERFACE_COMPILE_OPTIONS $<$<NOT:$<CONFIG:Debug>>:$<$<COMPILE_LANGUAGE:CXX>:/MP>>) 140 endif() 141endif() 142 143# ----------------------- Optimize binary size -------------------------- 144 145add_library(pybind11::opt_size IMPORTED INTERFACE ${optional_global}) 146 147if(MSVC) 148 set(PYBIND11_OPT_SIZE /Os) 149else() 150 set(PYBIND11_OPT_SIZE -Os) 151endif() 152 153set_property( 154 TARGET pybind11::opt_size 155 APPEND 156 PROPERTY INTERFACE_COMPILE_OPTIONS $<$<CONFIG:Release>:${PYBIND11_OPT_SIZE}> 157 $<$<CONFIG:MinSizeRel>:${PYBIND11_OPT_SIZE}> 158 $<$<CONFIG:RelWithDebInfo>:${PYBIND11_OPT_SIZE}>) 159 160# ----------------------- Legacy option -------------------------- 161 162# Warn or error if old variable name used 163if(PYBIND11_CPP_STANDARD) 164 string(REGEX MATCH [[..$]] VAL "${PYBIND11_CPP_STANDARD}") 165 if(CMAKE_CXX_STANDARD) 166 if(NOT CMAKE_CXX_STANDARD STREQUAL VAL) 167 message(WARNING "CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} does not match " 168 "PYBIND11_CPP_STANDARD=${PYBIND11_CPP_STANDARD}, " 169 "please remove PYBIND11_CPP_STANDARD from your cache") 170 endif() 171 else() 172 set(supported_standards 11 14 17 20) 173 if("${VAL}" IN_LIST supported_standards) 174 message(WARNING "USE -DCMAKE_CXX_STANDARD=${VAL} instead of PYBIND11_CPP_STANDARD") 175 set(CMAKE_CXX_STANDARD 176 ${VAL} 177 CACHE STRING "From PYBIND11_CPP_STANDARD") 178 else() 179 message(FATAL_ERROR "PYBIND11_CPP_STANDARD should be replaced with CMAKE_CXX_STANDARD " 180 "(last two chars: ${VAL} not understood as a valid CXX std)") 181 endif() 182 endif() 183endif() 184 185# --------------------- Python specifics ------------------------- 186 187# Check to see which Python mode we are in, new, old, or no python 188if(PYBIND11_NOPYTHON) 189 set(_pybind11_nopython ON) 190elseif( 191 PYBIND11_FINDPYTHON 192 OR Python_FOUND 193 OR Python2_FOUND 194 OR Python3_FOUND) 195 # New mode 196 include("${CMAKE_CURRENT_LIST_DIR}/pybind11NewTools.cmake") 197 198else() 199 200 # Classic mode 201 include("${CMAKE_CURRENT_LIST_DIR}/pybind11Tools.cmake") 202 203endif() 204 205# --------------------- pybind11_find_import ------------------------------- 206 207if(NOT _pybind11_nopython) 208 # Check to see if modules are importable. Use REQUIRED to force an error if 209 # one of the modules is not found. <package_name>_FOUND will be set if the 210 # package was found (underscores replace dashes if present). QUIET will hide 211 # the found message, and VERSION will require a minimum version. A successful 212 # find will cache the result. 213 function(pybind11_find_import PYPI_NAME) 214 # CMake variables need underscores (PyPI doesn't care) 215 string(REPLACE "-" "_" NORM_PYPI_NAME "${PYPI_NAME}") 216 217 # Return if found previously 218 if(${NORM_PYPI_NAME}_FOUND) 219 return() 220 endif() 221 222 set(options "REQUIRED;QUIET") 223 set(oneValueArgs "VERSION") 224 cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "" ${ARGN}) 225 226 if(ARG_REQUIRED) 227 set(status_level FATAL_ERROR) 228 else() 229 set(status_level WARNING) 230 endif() 231 232 execute_process( 233 COMMAND 234 ${${_Python}_EXECUTABLE} -c 235 "from pkg_resources import get_distribution; print(get_distribution('${PYPI_NAME}').version)" 236 RESULT_VARIABLE RESULT_PRESENT 237 OUTPUT_VARIABLE PKG_VERSION 238 ERROR_QUIET) 239 240 string(STRIP "${PKG_VERSION}" PKG_VERSION) 241 242 # If a result is present, this failed 243 if(RESULT_PRESENT) 244 set(${NORM_PYPI_NAME}_FOUND 245 ${NORM_PYPI_NAME}-NOTFOUND 246 CACHE INTERNAL "") 247 # Always warn or error 248 message( 249 ${status_level} 250 "Missing: ${PYPI_NAME} ${ARG_VERSION}\nTry: ${${_Python}_EXECUTABLE} -m pip install ${PYPI_NAME}" 251 ) 252 else() 253 if(ARG_VERSION AND PKG_VERSION VERSION_LESS ARG_VERSION) 254 message( 255 ${status_level} 256 "Version incorrect: ${PYPI_NAME} ${PKG_VERSION} found, ${ARG_VERSION} required - try upgrading" 257 ) 258 else() 259 set(${NORM_PYPI_NAME}_FOUND 260 YES 261 CACHE INTERNAL "") 262 set(${NORM_PYPI_NAME}_VERSION 263 ${PKG_VERSION} 264 CACHE INTERNAL "") 265 endif() 266 if(NOT ARG_QUIET) 267 message(STATUS "Found ${PYPI_NAME} ${PKG_VERSION}") 268 endif() 269 endif() 270 if(NOT ARG_VERSION OR (NOT PKG_VERSION VERSION_LESS ARG_VERSION)) 271 # We have successfully found a good version, cache to avoid calling again. 272 endif() 273 endfunction() 274endif() 275 276# --------------------- LTO ------------------------------- 277 278include(CheckCXXCompilerFlag) 279 280# Checks whether the given CXX/linker flags can compile and link a cxx file. 281# cxxflags and linkerflags are lists of flags to use. The result variable is a 282# unique variable name for each set of flags: the compilation result will be 283# cached base on the result variable. If the flags work, sets them in 284# cxxflags_out/linkerflags_out internal cache variables (in addition to 285# ${result}). 286function(_pybind11_return_if_cxx_and_linker_flags_work result cxxflags linkerflags cxxflags_out 287 linkerflags_out) 288 set(CMAKE_REQUIRED_LIBRARIES ${linkerflags}) 289 check_cxx_compiler_flag("${cxxflags}" ${result}) 290 if(${result}) 291 set(${cxxflags_out} 292 "${cxxflags}" 293 PARENT_SCOPE) 294 set(${linkerflags_out} 295 "${linkerflags}" 296 PARENT_SCOPE) 297 endif() 298endfunction() 299 300function(_pybind11_generate_lto target prefer_thin_lto) 301 if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") 302 set(cxx_append "") 303 set(linker_append "") 304 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT APPLE) 305 # Clang Gold plugin does not support -Os; append -O3 to MinSizeRel builds to override it 306 set(linker_append ";$<$<CONFIG:MinSizeRel>:-O3>") 307 elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") 308 set(cxx_append ";-fno-fat-lto-objects") 309 endif() 310 311 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND prefer_thin_lto) 312 _pybind11_return_if_cxx_and_linker_flags_work( 313 HAS_FLTO_THIN "-flto=thin${cxx_append}" "-flto=thin${linker_append}" 314 PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) 315 endif() 316 317 if(NOT HAS_FLTO_THIN) 318 _pybind11_return_if_cxx_and_linker_flags_work( 319 HAS_FLTO "-flto${cxx_append}" "-flto${linker_append}" PYBIND11_LTO_CXX_FLAGS 320 PYBIND11_LTO_LINKER_FLAGS) 321 endif() 322 elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") 323 # Intel equivalent to LTO is called IPO 324 _pybind11_return_if_cxx_and_linker_flags_work(HAS_INTEL_IPO "-ipo" "-ipo" 325 PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) 326 elseif(MSVC) 327 # cmake only interprets libraries as linker flags when they start with a - (otherwise it 328 # converts /LTCG to \LTCG as if it was a Windows path). Luckily MSVC supports passing flags 329 # with - instead of /, even if it is a bit non-standard: 330 _pybind11_return_if_cxx_and_linker_flags_work(HAS_MSVC_GL_LTCG "/GL" "-LTCG" 331 PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) 332 endif() 333 334 # Enable LTO flags if found, except for Debug builds 335 if(PYBIND11_LTO_CXX_FLAGS) 336 # CONFIG takes multiple values in CMake 3.19+, until then we have to use OR 337 set(is_debug "$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>") 338 set(not_debug "$<NOT:${is_debug}>") 339 set(cxx_lang "$<COMPILE_LANGUAGE:CXX>") 340 if(MSVC AND CMAKE_VERSION VERSION_LESS 3.11) 341 set(genex "${not_debug}") 342 else() 343 set(genex "$<AND:${not_debug},${cxx_lang}>") 344 endif() 345 set_property( 346 TARGET ${target} 347 APPEND 348 PROPERTY INTERFACE_COMPILE_OPTIONS "$<${genex}:${PYBIND11_LTO_CXX_FLAGS}>") 349 if(CMAKE_PROJECT_NAME STREQUAL "pybind11") 350 message(STATUS "${target} enabled") 351 endif() 352 else() 353 if(CMAKE_PROJECT_NAME STREQUAL "pybind11") 354 message(STATUS "${target} disabled (not supported by the compiler and/or linker)") 355 endif() 356 endif() 357 358 if(PYBIND11_LTO_LINKER_FLAGS) 359 if(CMAKE_VERSION VERSION_LESS 3.11) 360 set_property( 361 TARGET ${target} 362 APPEND 363 PROPERTY INTERFACE_LINK_LIBRARIES "$<${not_debug}:${PYBIND11_LTO_LINKER_FLAGS}>") 364 else() 365 set_property( 366 TARGET ${target} 367 APPEND 368 PROPERTY INTERFACE_LINK_OPTIONS "$<${not_debug}:${PYBIND11_LTO_LINKER_FLAGS}>") 369 endif() 370 endif() 371endfunction() 372 373add_library(pybind11::lto IMPORTED INTERFACE ${optional_global}) 374_pybind11_generate_lto(pybind11::lto FALSE) 375 376add_library(pybind11::thin_lto IMPORTED INTERFACE ${optional_global}) 377_pybind11_generate_lto(pybind11::thin_lto TRUE) 378 379# ---------------------- pybind11_strip ----------------------------- 380 381function(pybind11_strip target_name) 382 # Strip unnecessary sections of the binary on Linux/macOS 383 if(CMAKE_STRIP) 384 if(APPLE) 385 set(x_opt -x) 386 endif() 387 388 add_custom_command( 389 TARGET ${target_name} 390 POST_BUILD 391 COMMAND ${CMAKE_STRIP} ${x_opt} $<TARGET_FILE:${target_name}>) 392 endif() 393endfunction() 394