• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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