111986Sandreas.sandberg@arm.com# tools/pybind11Tools.cmake -- Build system for the pybind11 modules 211986Sandreas.sandberg@arm.com# 311986Sandreas.sandberg@arm.com# Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch> 411986Sandreas.sandberg@arm.com# 511986Sandreas.sandberg@arm.com# All rights reserved. Use of this source code is governed by a 611986Sandreas.sandberg@arm.com# BSD-style license that can be found in the LICENSE file. 711986Sandreas.sandberg@arm.com 811986Sandreas.sandberg@arm.comcmake_minimum_required(VERSION 2.8.12) 911986Sandreas.sandberg@arm.com 1011986Sandreas.sandberg@arm.com# Add a CMake parameter for choosing a desired Python version 1112037Sandreas.sandberg@arm.comif(NOT PYBIND11_PYTHON_VERSION) 1212037Sandreas.sandberg@arm.com set(PYBIND11_PYTHON_VERSION "" CACHE STRING "Python version to use for compiling modules") 1312037Sandreas.sandberg@arm.comendif() 1411986Sandreas.sandberg@arm.com 1511986Sandreas.sandberg@arm.comset(Python_ADDITIONAL_VERSIONS 3.7 3.6 3.5 3.4) 1611986Sandreas.sandberg@arm.comfind_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} REQUIRED) 1711986Sandreas.sandberg@arm.com 1811986Sandreas.sandberg@arm.cominclude(CheckCXXCompilerFlag) 1912037Sandreas.sandberg@arm.cominclude(CMakeParseArguments) 2011986Sandreas.sandberg@arm.com 2112391Sjason@lowepower.comif(NOT PYBIND11_CPP_STANDARD AND NOT CMAKE_CXX_STANDARD) 2212391Sjason@lowepower.com if(NOT MSVC) 2311986Sandreas.sandberg@arm.com check_cxx_compiler_flag("-std=c++14" HAS_CPP14_FLAG) 2411986Sandreas.sandberg@arm.com 2511986Sandreas.sandberg@arm.com if (HAS_CPP14_FLAG) 2611986Sandreas.sandberg@arm.com set(PYBIND11_CPP_STANDARD -std=c++14) 2711986Sandreas.sandberg@arm.com else() 2812391Sjason@lowepower.com check_cxx_compiler_flag("-std=c++11" HAS_CPP11_FLAG) 2912391Sjason@lowepower.com if (HAS_CPP11_FLAG) 3012391Sjason@lowepower.com set(PYBIND11_CPP_STANDARD -std=c++11) 3112391Sjason@lowepower.com else() 3212391Sjason@lowepower.com message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!") 3312391Sjason@lowepower.com endif() 3411986Sandreas.sandberg@arm.com endif() 3512391Sjason@lowepower.com elseif(MSVC) 3612391Sjason@lowepower.com set(PYBIND11_CPP_STANDARD /std:c++14) 3712391Sjason@lowepower.com endif() 3811986Sandreas.sandberg@arm.com 3912391Sjason@lowepower.com set(PYBIND11_CPP_STANDARD ${PYBIND11_CPP_STANDARD} CACHE STRING 4012391Sjason@lowepower.com "C++ standard flag, e.g. -std=c++11, -std=c++14, /std:c++14. Defaults to C++14 mode." FORCE) 4112391Sjason@lowepower.comendif() 4211986Sandreas.sandberg@arm.com 4312037Sandreas.sandberg@arm.com# Checks whether the given CXX/linker flags can compile and link a cxx file. cxxflags and 4412037Sandreas.sandberg@arm.com# linkerflags are lists of flags to use. The result variable is a unique variable name for each set 4512037Sandreas.sandberg@arm.com# of flags: the compilation result will be cached base on the result variable. If the flags work, 4612037Sandreas.sandberg@arm.com# sets them in cxxflags_out/linkerflags_out internal cache variables (in addition to ${result}). 4712037Sandreas.sandberg@arm.comfunction(_pybind11_return_if_cxx_and_linker_flags_work result cxxflags linkerflags cxxflags_out linkerflags_out) 4812037Sandreas.sandberg@arm.com set(CMAKE_REQUIRED_LIBRARIES ${linkerflags}) 4912037Sandreas.sandberg@arm.com check_cxx_compiler_flag("${cxxflags}" ${result}) 5012037Sandreas.sandberg@arm.com if (${result}) 5112037Sandreas.sandberg@arm.com set(${cxxflags_out} "${cxxflags}" CACHE INTERNAL "" FORCE) 5212037Sandreas.sandberg@arm.com set(${linkerflags_out} "${linkerflags}" CACHE INTERNAL "" FORCE) 5312037Sandreas.sandberg@arm.com endif() 5412037Sandreas.sandberg@arm.comendfunction() 5512037Sandreas.sandberg@arm.com 5612037Sandreas.sandberg@arm.com# Internal: find the appropriate link time optimization flags for this compiler 5712037Sandreas.sandberg@arm.comfunction(_pybind11_add_lto_flags target_name prefer_thin_lto) 5812037Sandreas.sandberg@arm.com if (NOT DEFINED PYBIND11_LTO_CXX_FLAGS) 5912037Sandreas.sandberg@arm.com set(PYBIND11_LTO_CXX_FLAGS "" CACHE INTERNAL "") 6012037Sandreas.sandberg@arm.com set(PYBIND11_LTO_LINKER_FLAGS "" CACHE INTERNAL "") 6112037Sandreas.sandberg@arm.com 6212037Sandreas.sandberg@arm.com if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") 6312037Sandreas.sandberg@arm.com set(cxx_append "") 6412037Sandreas.sandberg@arm.com set(linker_append "") 6512037Sandreas.sandberg@arm.com if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT APPLE) 6612037Sandreas.sandberg@arm.com # Clang Gold plugin does not support -Os; append -O3 to MinSizeRel builds to override it 6712037Sandreas.sandberg@arm.com set(linker_append ";$<$<CONFIG:MinSizeRel>:-O3>") 6812037Sandreas.sandberg@arm.com elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") 6912037Sandreas.sandberg@arm.com set(cxx_append ";-fno-fat-lto-objects") 7012037Sandreas.sandberg@arm.com endif() 7112037Sandreas.sandberg@arm.com 7212037Sandreas.sandberg@arm.com if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND prefer_thin_lto) 7312037Sandreas.sandberg@arm.com _pybind11_return_if_cxx_and_linker_flags_work(HAS_FLTO_THIN 7412037Sandreas.sandberg@arm.com "-flto=thin${cxx_append}" "-flto=thin${linker_append}" 7512037Sandreas.sandberg@arm.com PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) 7612037Sandreas.sandberg@arm.com endif() 7712037Sandreas.sandberg@arm.com 7812037Sandreas.sandberg@arm.com if (NOT HAS_FLTO_THIN) 7912037Sandreas.sandberg@arm.com _pybind11_return_if_cxx_and_linker_flags_work(HAS_FLTO 8012037Sandreas.sandberg@arm.com "-flto${cxx_append}" "-flto${linker_append}" 8112037Sandreas.sandberg@arm.com PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) 8212037Sandreas.sandberg@arm.com endif() 8312037Sandreas.sandberg@arm.com elseif (CMAKE_CXX_COMPILER_ID MATCHES "Intel") 8412037Sandreas.sandberg@arm.com # Intel equivalent to LTO is called IPO 8512037Sandreas.sandberg@arm.com _pybind11_return_if_cxx_and_linker_flags_work(HAS_INTEL_IPO 8612037Sandreas.sandberg@arm.com "-ipo" "-ipo" PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) 8712037Sandreas.sandberg@arm.com elseif(MSVC) 8812037Sandreas.sandberg@arm.com # cmake only interprets libraries as linker flags when they start with a - (otherwise it 8912037Sandreas.sandberg@arm.com # converts /LTCG to \LTCG as if it was a Windows path). Luckily MSVC supports passing flags 9012037Sandreas.sandberg@arm.com # with - instead of /, even if it is a bit non-standard: 9112037Sandreas.sandberg@arm.com _pybind11_return_if_cxx_and_linker_flags_work(HAS_MSVC_GL_LTCG 9212037Sandreas.sandberg@arm.com "/GL" "-LTCG" PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) 9312037Sandreas.sandberg@arm.com endif() 9412037Sandreas.sandberg@arm.com 9512037Sandreas.sandberg@arm.com if (PYBIND11_LTO_CXX_FLAGS) 9612037Sandreas.sandberg@arm.com message(STATUS "LTO enabled") 9712037Sandreas.sandberg@arm.com else() 9812037Sandreas.sandberg@arm.com message(STATUS "LTO disabled (not supported by the compiler and/or linker)") 9912037Sandreas.sandberg@arm.com endif() 10012037Sandreas.sandberg@arm.com endif() 10112037Sandreas.sandberg@arm.com 10212037Sandreas.sandberg@arm.com # Enable LTO flags if found, except for Debug builds 10312037Sandreas.sandberg@arm.com if (PYBIND11_LTO_CXX_FLAGS) 10412037Sandreas.sandberg@arm.com target_compile_options(${target_name} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:${PYBIND11_LTO_CXX_FLAGS}>") 10512037Sandreas.sandberg@arm.com endif() 10612037Sandreas.sandberg@arm.com if (PYBIND11_LTO_LINKER_FLAGS) 10712037Sandreas.sandberg@arm.com target_link_libraries(${target_name} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:${PYBIND11_LTO_LINKER_FLAGS}>") 10812037Sandreas.sandberg@arm.com endif() 10912037Sandreas.sandberg@arm.comendfunction() 11012037Sandreas.sandberg@arm.com 11111986Sandreas.sandberg@arm.com# Build a Python extension module: 11212037Sandreas.sandberg@arm.com# pybind11_add_module(<name> [MODULE | SHARED] [EXCLUDE_FROM_ALL] 11314299Sbbruce@ucdavis.edu# [NO_EXTRAS] [SYSTEM] [THIN_LTO] source1 [source2 ...]) 11411986Sandreas.sandberg@arm.com# 11511986Sandreas.sandberg@arm.comfunction(pybind11_add_module target_name) 11614299Sbbruce@ucdavis.edu set(options MODULE SHARED EXCLUDE_FROM_ALL NO_EXTRAS SYSTEM THIN_LTO) 11712037Sandreas.sandberg@arm.com cmake_parse_arguments(ARG "${options}" "" "" ${ARGN}) 11811986Sandreas.sandberg@arm.com 11912037Sandreas.sandberg@arm.com if(ARG_MODULE AND ARG_SHARED) 12012037Sandreas.sandberg@arm.com message(FATAL_ERROR "Can't be both MODULE and SHARED") 12112037Sandreas.sandberg@arm.com elseif(ARG_SHARED) 12212037Sandreas.sandberg@arm.com set(lib_type SHARED) 12312037Sandreas.sandberg@arm.com else() 12412037Sandreas.sandberg@arm.com set(lib_type MODULE) 12512037Sandreas.sandberg@arm.com endif() 12611986Sandreas.sandberg@arm.com 12712037Sandreas.sandberg@arm.com if(ARG_EXCLUDE_FROM_ALL) 12812037Sandreas.sandberg@arm.com set(exclude_from_all EXCLUDE_FROM_ALL) 12912037Sandreas.sandberg@arm.com endif() 13012037Sandreas.sandberg@arm.com 13112037Sandreas.sandberg@arm.com add_library(${target_name} ${lib_type} ${exclude_from_all} ${ARG_UNPARSED_ARGUMENTS}) 13211986Sandreas.sandberg@arm.com 13314299Sbbruce@ucdavis.edu if(ARG_SYSTEM) 13414299Sbbruce@ucdavis.edu set(inc_isystem SYSTEM) 13514299Sbbruce@ucdavis.edu endif() 13614299Sbbruce@ucdavis.edu 13714299Sbbruce@ucdavis.edu target_include_directories(${target_name} ${inc_isystem} 13811986Sandreas.sandberg@arm.com PRIVATE ${PYBIND11_INCLUDE_DIR} # from project CMakeLists.txt 13911986Sandreas.sandberg@arm.com PRIVATE ${pybind11_INCLUDE_DIR} # from pybind11Config 14011986Sandreas.sandberg@arm.com PRIVATE ${PYTHON_INCLUDE_DIRS}) 14111986Sandreas.sandberg@arm.com 14214299Sbbruce@ucdavis.edu # Python debug libraries expose slightly different objects 14314299Sbbruce@ucdavis.edu # https://docs.python.org/3.6/c-api/intro.html#debugging-builds 14414299Sbbruce@ucdavis.edu # https://stackoverflow.com/questions/39161202/how-to-work-around-missing-pymodule-create2-in-amd64-win-python35-d-lib 14514299Sbbruce@ucdavis.edu if(PYTHON_IS_DEBUG) 14614299Sbbruce@ucdavis.edu target_compile_definitions(${target_name} PRIVATE Py_DEBUG) 14714299Sbbruce@ucdavis.edu endif() 14814299Sbbruce@ucdavis.edu 14911986Sandreas.sandberg@arm.com # The prefix and extension are provided by FindPythonLibsNew.cmake 15011986Sandreas.sandberg@arm.com set_target_properties(${target_name} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}") 15111986Sandreas.sandberg@arm.com set_target_properties(${target_name} PROPERTIES SUFFIX "${PYTHON_MODULE_EXTENSION}") 15211986Sandreas.sandberg@arm.com 15312391Sjason@lowepower.com # -fvisibility=hidden is required to allow multiple modules compiled against 15412391Sjason@lowepower.com # different pybind versions to work properly, and for some features (e.g. 15512391Sjason@lowepower.com # py::module_local). We force it on everything inside the `pybind11` 15612391Sjason@lowepower.com # namespace; also turning it on for a pybind module compilation here avoids 15712391Sjason@lowepower.com # potential warnings or issues from having mixed hidden/non-hidden types. 15812391Sjason@lowepower.com set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET "hidden") 15914299Sbbruce@ucdavis.edu set_target_properties(${target_name} PROPERTIES CUDA_VISIBILITY_PRESET "hidden") 16012391Sjason@lowepower.com 16111986Sandreas.sandberg@arm.com if(WIN32 OR CYGWIN) 16211986Sandreas.sandberg@arm.com # Link against the Python shared library on Windows 16311986Sandreas.sandberg@arm.com target_link_libraries(${target_name} PRIVATE ${PYTHON_LIBRARIES}) 16411986Sandreas.sandberg@arm.com elseif(APPLE) 16511986Sandreas.sandberg@arm.com # It's quite common to have multiple copies of the same Python version 16611986Sandreas.sandberg@arm.com # installed on one's system. E.g.: one copy from the OS and another copy 16711986Sandreas.sandberg@arm.com # that's statically linked into an application like Blender or Maya. 16811986Sandreas.sandberg@arm.com # If we link our plugin library against the OS Python here and import it 16911986Sandreas.sandberg@arm.com # into Blender or Maya later on, this will cause segfaults when multiple 17011986Sandreas.sandberg@arm.com # conflicting Python instances are active at the same time (even when they 17111986Sandreas.sandberg@arm.com # are of the same version). 17211986Sandreas.sandberg@arm.com 17311986Sandreas.sandberg@arm.com # Windows is not affected by this issue since it handles DLL imports 17411986Sandreas.sandberg@arm.com # differently. The solution for Linux and Mac OS is simple: we just don't 17511986Sandreas.sandberg@arm.com # link against the Python library. The resulting shared library will have 17611986Sandreas.sandberg@arm.com # missing symbols, but that's perfectly fine -- they will be resolved at 17711986Sandreas.sandberg@arm.com # import time. 17811986Sandreas.sandberg@arm.com 17911986Sandreas.sandberg@arm.com target_link_libraries(${target_name} PRIVATE "-undefined dynamic_lookup") 18012037Sandreas.sandberg@arm.com 18112037Sandreas.sandberg@arm.com if(ARG_SHARED) 18212037Sandreas.sandberg@arm.com # Suppress CMake >= 3.0 warning for shared libraries 18312037Sandreas.sandberg@arm.com set_target_properties(${target_name} PROPERTIES MACOSX_RPATH ON) 18412037Sandreas.sandberg@arm.com endif() 18511986Sandreas.sandberg@arm.com endif() 18611986Sandreas.sandberg@arm.com 18712391Sjason@lowepower.com # Make sure C++11/14 are enabled 18814299Sbbruce@ucdavis.edu if(CMAKE_VERSION VERSION_LESS 3.3) 18914299Sbbruce@ucdavis.edu target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD}) 19014299Sbbruce@ucdavis.edu else() 19114299Sbbruce@ucdavis.edu target_compile_options(${target_name} PUBLIC $<$<COMPILE_LANGUAGE:CXX>:${PYBIND11_CPP_STANDARD}>) 19214299Sbbruce@ucdavis.edu endif() 19311986Sandreas.sandberg@arm.com 19412037Sandreas.sandberg@arm.com if(ARG_NO_EXTRAS) 19512037Sandreas.sandberg@arm.com return() 19612037Sandreas.sandberg@arm.com endif() 19711986Sandreas.sandberg@arm.com 19812037Sandreas.sandberg@arm.com _pybind11_add_lto_flags(${target_name} ${ARG_THIN_LTO}) 19911986Sandreas.sandberg@arm.com 20014299Sbbruce@ucdavis.edu if (NOT MSVC AND NOT ${CMAKE_BUILD_TYPE} MATCHES Debug|RelWithDebInfo) 20112037Sandreas.sandberg@arm.com # Strip unnecessary sections of the binary on Linux/Mac OS 20212037Sandreas.sandberg@arm.com if(CMAKE_STRIP) 20312037Sandreas.sandberg@arm.com if(APPLE) 20412037Sandreas.sandberg@arm.com add_custom_command(TARGET ${target_name} POST_BUILD 20512037Sandreas.sandberg@arm.com COMMAND ${CMAKE_STRIP} -x $<TARGET_FILE:${target_name}>) 20612037Sandreas.sandberg@arm.com else() 20712037Sandreas.sandberg@arm.com add_custom_command(TARGET ${target_name} POST_BUILD 20812037Sandreas.sandberg@arm.com COMMAND ${CMAKE_STRIP} $<TARGET_FILE:${target_name}>) 20911986Sandreas.sandberg@arm.com endif() 21011986Sandreas.sandberg@arm.com endif() 21112037Sandreas.sandberg@arm.com endif() 21212037Sandreas.sandberg@arm.com 21312037Sandreas.sandberg@arm.com if(MSVC) 21411986Sandreas.sandberg@arm.com # /MP enables multithreaded builds (relevant when there are many files), /bigobj is 21511986Sandreas.sandberg@arm.com # needed for bigger binding projects due to the limit to 64k addressable sections 21614299Sbbruce@ucdavis.edu target_compile_options(${target_name} PRIVATE /bigobj) 21714299Sbbruce@ucdavis.edu if(CMAKE_VERSION VERSION_LESS 3.11) 21814299Sbbruce@ucdavis.edu target_compile_options(${target_name} PRIVATE $<$<NOT:$<CONFIG:Debug>>:/MP>) 21914299Sbbruce@ucdavis.edu else() 22014299Sbbruce@ucdavis.edu # Only set these options for C++ files. This is important so that, for 22114299Sbbruce@ucdavis.edu # instance, projects that include other types of source files like CUDA 22214299Sbbruce@ucdavis.edu # .cu files don't get these options propagated to nvcc since that would 22314299Sbbruce@ucdavis.edu # cause the build to fail. 22414299Sbbruce@ucdavis.edu target_compile_options(${target_name} PRIVATE $<$<NOT:$<CONFIG:Debug>>:$<$<COMPILE_LANGUAGE:CXX>:/MP>>) 22514299Sbbruce@ucdavis.edu endif() 22611986Sandreas.sandberg@arm.com endif() 22711986Sandreas.sandberg@arm.comendfunction() 228