Henry Schreiner | 1729aae | 2020-08-19 12:26:26 -0400 | [diff] [blame] | 1 | #[======================================================[.rst |
| 2 | |
| 3 | Adds 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 |
Wenzel Jakob | 36c666f | 2020-09-04 23:31:05 +0200 | [diff] [blame^] | 13 | pybind11::opt_size - avoid optimizations that increase code size |
Henry Schreiner | 1729aae | 2020-08-19 12:26:26 -0400 | [diff] [blame] | 14 | |
| 15 | Adds the following functions:: |
| 16 | |
| 17 | pybind11_strip(target) - strip target after building on linux/macOS |
| 18 | |
| 19 | |
| 20 | #]======================================================] |
| 21 | |
| 22 | # CMake 3.10 has an include_guard command, but we can't use that yet |
| 23 | if(TARGET pybind11::lto) |
| 24 | return() |
| 25 | endif() |
| 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. |
| 31 | get_property( |
| 32 | is_config |
| 33 | TARGET pybind11::headers |
| 34 | PROPERTY IMPORTED) |
| 35 | if(NOT is_config) |
| 36 | set(optional_global GLOBAL) |
| 37 | endif() |
| 38 | |
| 39 | # --------------------- Shared targets ---------------------------- |
| 40 | |
| 41 | # Build an interface library target: |
| 42 | add_library(pybind11::pybind11 IMPORTED INTERFACE ${optional_global}) |
| 43 | set_property( |
| 44 | TARGET pybind11::pybind11 |
| 45 | APPEND |
| 46 | PROPERTY INTERFACE_LINK_LIBRARIES pybind11::headers) |
| 47 | |
| 48 | # Build a module target: |
| 49 | add_library(pybind11::module IMPORTED INTERFACE ${optional_global}) |
| 50 | set_property( |
| 51 | TARGET pybind11::module |
| 52 | APPEND |
| 53 | PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11) |
| 54 | |
| 55 | # Build an embed library target: |
| 56 | add_library(pybind11::embed IMPORTED INTERFACE ${optional_global}) |
| 57 | set_property( |
| 58 | TARGET pybind11::embed |
| 59 | APPEND |
| 60 | PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11) |
| 61 | |
| 62 | # ----------------------- no register ---------------------- |
| 63 | |
| 64 | # Workaround for Python 2.7 and C++17 (C++14 as a warning) incompatibility |
| 65 | # This adds the flags -Wno-register and -Wno-deprecated-register if the compiler |
| 66 | # is Clang 3.9+ or AppleClang and the compile language is CXX, or /wd5033 for MSVC (all languages, |
| 67 | # since MSVC didn't recognize COMPILE_LANGUAGE until CMake 3.11+). |
| 68 | |
| 69 | add_library(pybind11::python2_no_register INTERFACE IMPORTED ${optional_global}) |
| 70 | set(clang_4plus |
| 71 | "$<AND:$<CXX_COMPILER_ID:Clang>,$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,3.9>>>") |
| 72 | set(no_register "$<OR:${clang_4plus},$<CXX_COMPILER_ID:AppleClang>>") |
| 73 | |
| 74 | if(MSVC AND CMAKE_VERSION VERSION_LESS 3.11) |
| 75 | set(cxx_no_register "${no_register}") |
| 76 | else() |
| 77 | set(cxx_no_register "$<AND:$<COMPILE_LANGUAGE:CXX>,${no_register}>") |
| 78 | endif() |
| 79 | |
| 80 | set(msvc "$<CXX_COMPILER_ID:MSVC>") |
| 81 | |
| 82 | set_property( |
| 83 | TARGET pybind11::python2_no_register |
| 84 | PROPERTY INTERFACE_COMPILE_OPTIONS |
| 85 | "$<${cxx_no_register}:-Wno-register;-Wno-deprecated-register>" "$<${msvc}:/wd5033>") |
| 86 | |
| 87 | # --------------------------- link helper --------------------------- |
| 88 | |
| 89 | add_library(pybind11::python_link_helper IMPORTED INTERFACE ${optional_global}) |
| 90 | |
| 91 | if(CMAKE_VERSION VERSION_LESS 3.13) |
| 92 | # In CMake 3.11+, you can set INTERFACE properties via the normal methods, and |
| 93 | # this would be simpler. |
| 94 | set_property( |
| 95 | TARGET pybind11::python_link_helper |
| 96 | APPEND |
| 97 | PROPERTY INTERFACE_LINK_LIBRARIES "$<$<PLATFORM_ID:Darwin>:-undefined dynamic_lookup>") |
| 98 | else() |
| 99 | # link_options was added in 3.13+ |
| 100 | # This is safer, because you are ensured the deduplication pass in CMake will not consider |
| 101 | # these separate and remove one but not the other. |
| 102 | set_property( |
| 103 | TARGET pybind11::python_link_helper |
| 104 | APPEND |
| 105 | PROPERTY INTERFACE_LINK_OPTIONS "$<$<PLATFORM_ID:Darwin>:LINKER:-undefined,dynamic_lookup>") |
| 106 | endif() |
| 107 | |
| 108 | # ------------------------ Windows extras ------------------------- |
| 109 | |
| 110 | add_library(pybind11::windows_extras IMPORTED INTERFACE ${optional_global}) |
| 111 | |
| 112 | if(MSVC) |
| 113 | # /MP enables multithreaded builds (relevant when there are many files), /bigobj is |
| 114 | # needed for bigger binding projects due to the limit to 64k addressable sections |
| 115 | set_property( |
| 116 | TARGET pybind11::windows_extras |
| 117 | APPEND |
| 118 | PROPERTY INTERFACE_COMPILE_OPTIONS /bigobj) |
| 119 | |
| 120 | if(CMAKE_VERSION VERSION_LESS 3.11) |
| 121 | set_property( |
| 122 | TARGET pybind11::windows_extras |
| 123 | APPEND |
| 124 | PROPERTY INTERFACE_COMPILE_OPTIONS $<$<NOT:$<CONFIG:Debug>>:/MP>) |
| 125 | else() |
| 126 | # Only set these options for C++ files. This is important so that, for |
| 127 | # instance, projects that include other types of source files like CUDA |
| 128 | # .cu files don't get these options propagated to nvcc since that would |
| 129 | # cause the build to fail. |
| 130 | set_property( |
| 131 | TARGET pybind11::windows_extras |
| 132 | APPEND |
| 133 | PROPERTY INTERFACE_COMPILE_OPTIONS $<$<NOT:$<CONFIG:Debug>>:$<$<COMPILE_LANGUAGE:CXX>:/MP>>) |
| 134 | endif() |
| 135 | endif() |
| 136 | |
Wenzel Jakob | 36c666f | 2020-09-04 23:31:05 +0200 | [diff] [blame^] | 137 | # ----------------------- Optimize binary size -------------------------- |
| 138 | |
| 139 | add_library(pybind11::opt_size IMPORTED INTERFACE ${optional_global}) |
| 140 | |
| 141 | if(MSVC) |
| 142 | set(PYBIND11_OPT_SIZE /Os) |
| 143 | else() |
| 144 | set(PYBIND11_OPT_SIZE -Os) |
| 145 | endif() |
| 146 | |
| 147 | set_property( |
| 148 | TARGET pybind11::opt_size |
| 149 | APPEND |
| 150 | PROPERTY INTERFACE_COMPILE_OPTIONS $<$<CONFIG:Release>:${PYBIND11_OPT_SIZE}> |
| 151 | $<$<CONFIG:MinSizeRel>:${PYBIND11_OPT_SIZE}> |
| 152 | $<$<CONFIG:RelWithDebInfo>:${PYBIND11_OPT_SIZE}>) |
| 153 | |
Henry Schreiner | 1729aae | 2020-08-19 12:26:26 -0400 | [diff] [blame] | 154 | # ----------------------- Legacy option -------------------------- |
| 155 | |
| 156 | # Warn or error if old variable name used |
| 157 | if(PYBIND11_CPP_STANDARD) |
| 158 | string(REGEX MATCH [[..$]] VAL "${PYBIND11_CPP_STANDARD}") |
| 159 | if(CMAKE_CXX_STANDARD) |
| 160 | if(NOT CMAKE_CXX_STANDARD STREQUAL VAL) |
| 161 | message(WARNING "CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} does not match " |
| 162 | "PYBIND11_CPP_STANDARD=${PYBIND11_CPP_STANDARD}, " |
| 163 | "please remove PYBIND11_CPP_STANDARD from your cache") |
| 164 | endif() |
| 165 | else() |
| 166 | set(supported_standards 11 14 17 20) |
| 167 | if("${VAL}" IN_LIST supported_standards) |
Henry Schreiner | 9b8cb02 | 2020-08-26 09:07:30 -0400 | [diff] [blame] | 168 | message(WARNING "USE -DCMAKE_CXX_STANDARD=${VAL} instead of PYBIND11_CPP_STANDARD") |
Henry Schreiner | 1729aae | 2020-08-19 12:26:26 -0400 | [diff] [blame] | 169 | set(CMAKE_CXX_STANDARD |
| 170 | ${VAL} |
| 171 | CACHE STRING "From PYBIND11_CPP_STANDARD") |
| 172 | else() |
| 173 | message(FATAL_ERROR "PYBIND11_CPP_STANDARD should be replaced with CMAKE_CXX_STANDARD " |
| 174 | "(last two chars: ${VAL} not understood as a valid CXX std)") |
| 175 | endif() |
| 176 | endif() |
| 177 | endif() |
| 178 | |
| 179 | # --------------------- Python specifics ------------------------- |
| 180 | |
| 181 | # Check to see which Python mode we are in, new, old, or no python |
| 182 | if(PYBIND11_NOPYTHON) |
| 183 | set(_pybind11_nopython ON) |
| 184 | elseif( |
| 185 | PYBIND11_FINDPYTHON |
| 186 | OR Python_FOUND |
| 187 | OR Python2_FOUND |
| 188 | OR Python3_FOUND) |
| 189 | # New mode |
| 190 | include("${CMAKE_CURRENT_LIST_DIR}/pybind11NewTools.cmake") |
| 191 | |
| 192 | else() |
| 193 | |
| 194 | # Classic mode |
| 195 | include("${CMAKE_CURRENT_LIST_DIR}/pybind11Tools.cmake") |
| 196 | |
| 197 | endif() |
| 198 | |
| 199 | # --------------------- LTO ------------------------------- |
| 200 | |
| 201 | include(CheckCXXCompilerFlag) |
| 202 | |
| 203 | # Checks whether the given CXX/linker flags can compile and link a cxx file. |
| 204 | # cxxflags and linkerflags are lists of flags to use. The result variable is a |
| 205 | # unique variable name for each set of flags: the compilation result will be |
| 206 | # cached base on the result variable. If the flags work, sets them in |
| 207 | # cxxflags_out/linkerflags_out internal cache variables (in addition to |
| 208 | # ${result}). |
| 209 | function(_pybind11_return_if_cxx_and_linker_flags_work result cxxflags linkerflags cxxflags_out |
| 210 | linkerflags_out) |
| 211 | set(CMAKE_REQUIRED_LIBRARIES ${linkerflags}) |
| 212 | check_cxx_compiler_flag("${cxxflags}" ${result}) |
| 213 | if(${result}) |
| 214 | set(${cxxflags_out} |
| 215 | "${cxxflags}" |
| 216 | PARENT_SCOPE) |
| 217 | set(${linkerflags_out} |
| 218 | "${linkerflags}" |
| 219 | PARENT_SCOPE) |
| 220 | endif() |
| 221 | endfunction() |
| 222 | |
| 223 | function(_pybind11_generate_lto target prefer_thin_lto) |
| 224 | if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") |
| 225 | set(cxx_append "") |
| 226 | set(linker_append "") |
| 227 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT APPLE) |
| 228 | # Clang Gold plugin does not support -Os; append -O3 to MinSizeRel builds to override it |
| 229 | set(linker_append ";$<$<CONFIG:MinSizeRel>:-O3>") |
| 230 | elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") |
| 231 | set(cxx_append ";-fno-fat-lto-objects") |
| 232 | endif() |
| 233 | |
| 234 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND prefer_thin_lto) |
| 235 | _pybind11_return_if_cxx_and_linker_flags_work( |
| 236 | HAS_FLTO_THIN "-flto=thin${cxx_append}" "-flto=thin${linker_append}" |
| 237 | PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) |
| 238 | endif() |
| 239 | |
| 240 | if(NOT HAS_FLTO_THIN) |
| 241 | _pybind11_return_if_cxx_and_linker_flags_work( |
| 242 | HAS_FLTO "-flto${cxx_append}" "-flto${linker_append}" PYBIND11_LTO_CXX_FLAGS |
| 243 | PYBIND11_LTO_LINKER_FLAGS) |
| 244 | endif() |
| 245 | elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") |
| 246 | # Intel equivalent to LTO is called IPO |
| 247 | _pybind11_return_if_cxx_and_linker_flags_work(HAS_INTEL_IPO "-ipo" "-ipo" |
| 248 | PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) |
| 249 | elseif(MSVC) |
| 250 | # cmake only interprets libraries as linker flags when they start with a - (otherwise it |
| 251 | # converts /LTCG to \LTCG as if it was a Windows path). Luckily MSVC supports passing flags |
| 252 | # with - instead of /, even if it is a bit non-standard: |
| 253 | _pybind11_return_if_cxx_and_linker_flags_work(HAS_MSVC_GL_LTCG "/GL" "-LTCG" |
| 254 | PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) |
| 255 | endif() |
| 256 | |
| 257 | # Enable LTO flags if found, except for Debug builds |
| 258 | if(PYBIND11_LTO_CXX_FLAGS) |
| 259 | set(not_debug "$<NOT:$<CONFIG:Debug>>") |
| 260 | set(cxx_lang "$<COMPILE_LANGUAGE:CXX>") |
| 261 | if(MSVC AND CMAKE_VERSION VERSION_LESS 3.11) |
| 262 | set(genex "${not_debug}") |
| 263 | else() |
| 264 | set(genex "$<AND:${not_debug},${cxx_lang}>") |
| 265 | endif() |
| 266 | set_property( |
| 267 | TARGET ${target} |
| 268 | APPEND |
| 269 | PROPERTY INTERFACE_COMPILE_OPTIONS "$<${genex}:${PYBIND11_LTO_CXX_FLAGS}>") |
| 270 | if(CMAKE_PROJECT_NAME STREQUAL "pybind11") |
| 271 | message(STATUS "${target} enabled") |
| 272 | endif() |
| 273 | else() |
| 274 | if(CMAKE_PROJECT_NAME STREQUAL "pybind11") |
| 275 | message(STATUS "${target} disabled (not supported by the compiler and/or linker)") |
| 276 | endif() |
| 277 | endif() |
| 278 | |
| 279 | if(PYBIND11_LTO_LINKER_FLAGS) |
| 280 | if(CMAKE_VERSION VERSION_LESS 3.11) |
| 281 | set_property( |
| 282 | TARGET ${target} |
| 283 | APPEND |
| 284 | PROPERTY INTERFACE_LINK_LIBRARIES "$<${not_debug}:${PYBIND11_LTO_LINKER_FLAGS}>") |
| 285 | else() |
| 286 | set_property( |
| 287 | TARGET ${target} |
| 288 | APPEND |
| 289 | PROPERTY INTERFACE_LINK_OPTIONS "$<${not_debug}:${PYBIND11_LTO_LINKER_FLAGS}>") |
| 290 | endif() |
| 291 | endif() |
| 292 | endfunction() |
| 293 | |
| 294 | add_library(pybind11::lto IMPORTED INTERFACE ${optional_global}) |
| 295 | _pybind11_generate_lto(pybind11::lto FALSE) |
| 296 | |
| 297 | add_library(pybind11::thin_lto IMPORTED INTERFACE ${optional_global}) |
| 298 | _pybind11_generate_lto(pybind11::thin_lto TRUE) |
| 299 | |
| 300 | # ---------------------- pybind11_strip ----------------------------- |
| 301 | |
| 302 | function(pybind11_strip target_name) |
| 303 | # Strip unnecessary sections of the binary on Linux/Mac OS |
| 304 | if(CMAKE_STRIP) |
| 305 | if(APPLE) |
| 306 | set(x_opt -x) |
| 307 | endif() |
| 308 | |
| 309 | add_custom_command( |
| 310 | TARGET ${target_name} |
| 311 | POST_BUILD |
| 312 | COMMAND ${CMAKE_STRIP} ${x_opt} $<TARGET_FILE:${target_name}>) |
| 313 | endif() |
| 314 | endfunction() |