Skip to content

Commit 924c34b

Browse files
committed
CMake compiler features now used on CMake 3.8+
1 parent 9bb3313 commit 924c34b

File tree

5 files changed

+144
-26
lines changed

5 files changed

+144
-26
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ if(NOT (CMAKE_VERSION VERSION_LESS 3.0)) # CMake >= 3.0
100100
target_include_directories(pybind11 INTERFACE $<BUILD_INTERFACE:${PYBIND11_INCLUDE_DIR}>
101101
$<BUILD_INTERFACE:${PYTHON_INCLUDE_DIRS}>
102102
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
103-
target_compile_options(pybind11 INTERFACE $<BUILD_INTERFACE:${PYBIND11_CPP_STANDARD}>)
103+
104+
_pybind11_target_cxx_std(pybind11)
104105

105106
add_library(module INTERFACE)
106107
add_library(pybind11::module ALIAS module)

docs/changelog.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ v2.2.3 (April 29, 2018)
113113
* Fixed an endianness-related fault in the test suite.
114114
`#1287 <https://github.com/pybind/pybind11/pull/1287>`_.
115115

116+
* Improved CMake C++ standard discovery for CMake 3.8+, and allow compiler features
117+
to be used on CMake 3.1+. Added C++17 standard check.
118+
`#1098 <https://github.com/pybind/pybind11/pull/1098>`_.
119+
116120
v2.2.2 (February 7, 2018)
117121
-----------------------------------------------------
118122

docs/compiling.rst

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,32 @@ regular LTO if ``-flto=thin`` is not available.
100100
Configuration variables
101101
-----------------------
102102

103-
By default, pybind11 will compile modules with the C++14 standard, if available
104-
on the target compiler, falling back to C++11 if C++14 support is not
105-
available. Note, however, that this default is subject to change: future
106-
pybind11 releases are expected to migrate to newer C++ standards as they become
107-
available. To override this, the standard flag can be given explicitly in
108-
``PYBIND11_CPP_STANDARD``:
103+
By default, pybind11 will compile modules with the highest C++ standard available
104+
on the target compiler, from the set C++17, C++14, and C++11. With CMake 3.8+, this
105+
uses CMake's compile features mechinism and meta-features to detect your compiler's
106+
abilities. Older CMake versions fall back to manually trying to compile a mini-program
107+
with each flag.
108+
109+
If you want to override this behavior, you have three options:
110+
111+
CMake 3.1+: If you set ``CMAKE_CXX_STANDARD`` before including pybind11, it will be respected and no
112+
futher action will be taken by pybind11.
113+
114+
CMake 3.1+: If you explicitly set a list of compile features in ``PYBIND11_CXX_FEATURES``, that will be used.
115+
See `CMAKE_CXX_KNOWN_FEATURES <https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html>`_
116+
for your CMake version.
117+
118+
.. code-block:: cmake
119+
120+
# These meta-features were added in CMake 3.8:
121+
set(PYBIND11_CXX_FEATURES cxx_std_11)
122+
set(PYBIND11_CXX_FEATURES cxx_std_14)
123+
set(PYBIND11_CXX_FEATURES cxx_std_17) # Experimental C++17 support
124+
125+
add_subdirectory(pybind11) # or find_package(pybind11)
126+
127+
CMake 2.8+: If neither of the above is set and you want to explicitly control the flag,
128+
the standard flag can be given as ``PYBIND11_CPP_STANDARD``:
109129

110130
.. code-block:: cmake
111131
@@ -120,10 +140,14 @@ available. To override this, the standard flag can be given explicitly in
120140
121141
add_subdirectory(pybind11) # or find_package(pybind11)
122142
123-
Note that this and all other configuration variables must be set **before** the
143+
Note that these and all other configuration variables must be set **before** the
124144
call to ``add_subdirectory`` or ``find_package``. The variables can also be set
125145
when calling CMake from the command line using the ``-D<variable>=<value>`` flag.
126146

147+
Mixed C and C++ projects should use the ``PYBIND11_CXX_FEATURES`` mechanism to avoid
148+
adding flags to the C compiler. If you need the latest version of CMake, it is trivial
149+
to install; try ``pip install cmake`` or ``pip install --user cmake``.
150+
127151
The target Python version can be selected by setting ``PYBIND11_PYTHON_VERSION``
128152
or an exact Python installation can be specified with ``PYTHON_EXECUTABLE``.
129153
For example:

tools/pybind11Config.cmake.in

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
#
2929
# Python headers, libraries (as needed by platform), and the C++ standard
3030
# are attached to the target. Set PythonLibsNew variables to influence
31-
# python detection and PYBIND11_CPP_STANDARD (-std=c++11 or -std=c++14) to
32-
# influence standard setting. ::
31+
# python detection and PYBIND11_CPP_STANDARD or PYBIND11_CXX_FEATURES to
32+
# influence standard setting or CMake compiler features. ::
3333
#
3434
# find_package(pybind11 CONFIG REQUIRED)
3535
# message(STATUS "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIRS}")
@@ -90,7 +90,7 @@ if(NOT TARGET ${PN}::pybind11)
9090
set_property(TARGET ${PN}::module APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${PYTHON_LIBRARIES})
9191
endif()
9292

93-
set_property(TARGET ${PN}::pybind11 APPEND PROPERTY INTERFACE_COMPILE_OPTIONS "${PYBIND11_CPP_STANDARD}")
93+
_pybind11_target_cxx_std(${PN}::pybind11)
9494

9595
get_property(_iid TARGET ${PN}::pybind11 PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
9696
get_property(_ill TARGET ${PN}::module PROPERTY INTERFACE_LINK_LIBRARIES)

tools/pybind11Tools.cmake

Lines changed: 104 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,116 @@ find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} REQUIRED)
1818
include(CheckCXXCompilerFlag)
1919
include(CMakeParseArguments)
2020

21-
if(NOT PYBIND11_CPP_STANDARD AND NOT CMAKE_CXX_STANDARD)
22-
if(NOT MSVC)
23-
check_cxx_compiler_flag("-std=c++14" HAS_CPP14_FLAG)
21+
# The following options start out empty and cached; if empty they support "auto" behavior
22+
23+
## Don't do anything if CMAKE_CXX_STANDARD is set
24+
if(NOT CMAKE_CXX_STANDARD)
25+
# While complile features were introduced in 3.1, only 3.8+ have meta-features
26+
# (And C++17 seems to be mostly supported through the meta-feature)
27+
28+
if(CMAKE_VERSION VERSION_LESS 3.8 AND NOT PYBIND11_CXX_FEATURES)
29+
if(NOT PYBIND_CPP_STANDARD)
30+
# Only try to get the standard manually if CMake doesn't support compiler features
31+
if(MSVC)
32+
set(PYBIND11_CPP_STANDARD "/std:c++14")
33+
message(STATUS "pybind11 selected C++14 flag, MSVC")
34+
else()
35+
check_cxx_compiler_flag("-std=c++17" HAS_CPP17_FLAG)
36+
check_cxx_compiler_flag("-std=c++14" HAS_CPP14_FLAG)
37+
check_cxx_compiler_flag("-std=c++11" HAS_CPP11_FLAG)
38+
39+
if(HAS_CPP17_FLAG)
40+
set(PYBIND11_CPP_STANDARD "-std=c++17")
41+
message(STATUS "pybind11 selected C++17 flag")
42+
elseif(HAS_CPP14_FLAG)
43+
set(PYBIND11_CPP_STANDARD "-std=c++14")
44+
message(STATUS "pybind11 selected C++14 flag")
45+
elseif(HAS_CPP11_FLAG)
46+
set(PYBIND11_CPP_STANDARD "-std=c++11")
47+
message(STATUS "pybind11 selected C++11 flag")
48+
else()
49+
message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!")
50+
endif()
51+
endif()
52+
endif()
2453

25-
if (HAS_CPP14_FLAG)
26-
set(PYBIND11_CPP_STANDARD -std=c++14)
54+
# Auto add if CMake >= 3.8 and CXX_FEATURES is not set
55+
elseif(NOT PYBIND11_CXX_FEATURES)
56+
# IN_LIST introduced in CMAKE 3.3
57+
# Safe because this will only activate if CMake >= 3.8
58+
cmake_policy(SET CMP0057 NEW)
59+
60+
# The following only print if running the first time,
61+
# and no C++ mode selected
62+
if(cxx_std_17 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
63+
set(PYBIND11_CXX_FEATURES cxx_std_17)
64+
message(STATUS "pybind11 selected C++17 mode, compiler feature")
65+
elseif(cxx_std_14 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
66+
message(STATUS "pybind11 selected C++14 mode, compiler feature")
67+
set(PYBIND11_CXX_FEATURES cxx_std_14)
68+
elseif(cxx_std_11 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
69+
message(STATUS "pybind11 selected C++11 mode, compiler feature")
70+
set(PYBIND11_CXX_FEATURES cxx_std_11)
2771
else()
28-
check_cxx_compiler_flag("-std=c++11" HAS_CPP11_FLAG)
29-
if (HAS_CPP11_FLAG)
30-
set(PYBIND11_CPP_STANDARD -std=c++11)
72+
message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!")
73+
endif()
74+
endif()
75+
endif()
76+
77+
# Allow the user to override by setting the cache value after the auto-discovery
78+
# Empty values get filled on first run (PYBIND11_CPP_STANDARD for CMake < 3.8,
79+
# otherwise PYBIND11_CXX_FEATURES), and then at this point are promoted to the CACHE.
80+
81+
set(PYBIND11_CPP_STANDARD ${PYBIND11_CPP_STANDARD} CACHE STRING
82+
"C++ standard flag, e.g. -std=c++11, -std=c++14, /std:c++14. Defaults to highest supported for CMake 2.8-3.7")
83+
84+
if(NOT CMAKE_VERSION VERSION_LESS 3.1)
85+
#Only provide the option if CMake >= 3.1
86+
set(PYBIND11_CXX_FEATURES ${PYBIND11_CXX_FEATURES} CACHE STRING
87+
"List of compile features for PyBind, will use highest detected C++ version in CMake 3.8+")
88+
elseif(PYBIND11_CXX_FEATURES)
89+
message(FATAL_ERROR "PYBIND11_CXX_FEATURES is not supported for CMake < 3.1")
90+
endif()
91+
92+
function(_pybind11_target_cxx_std target_name)
93+
94+
# Do not do any overriding if global CMAKE_CXX_STANDARD is set
95+
if(NOT CMAKE_CXX_STANDARD)
96+
# See if this is an interface or regular target
97+
get_target_property(PYTYPE ${target_name} TYPE)
98+
get_target_property(PYIMPORTED ${target_name} IMPORTED)
99+
100+
# Allow manual settings (Needed for older CMakes)
101+
# Will always be set for old CMake
102+
if(PYBIND11_CPP_STANDARD)
103+
if(PYTYPE STREQUAL "INTERFACE_LIBRARY")
104+
if(PYIMPORTED)
105+
set_property(TARGET ${target_name} APPEND PROPERTY
106+
INTERFACE_COMPILE_OPTIONS ${PYBIND11_CPP_STANDARD})
107+
else()
108+
target_compile_options(${target_name} INTERFACE ${PYBIND11_CPP_STANDARD})
109+
endif()
110+
else()
111+
target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD})
112+
endif()
113+
114+
# A user of CMake 3.1 can override this, or 3.8 will default to using it
115+
elseif(PYBIND11_CXX_FEATURES)
116+
if(PYTYPE STREQUAL "INTERFACE_LIBRARY")
117+
if(PYIMPORTED)
118+
set_property(TARGET ${target_name} APPEND PROPERTY
119+
INTERFACE_COMPILE_FEATURES ${PYBIND11_CXX_FEATURES})
120+
else()
121+
target_compile_features(${target_name} INTERFACE ${PYBIND11_CXX_FEATURES})
122+
endif()
31123
else()
32-
message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!")
124+
target_compile_features(${target_name} PUBLIC ${PYBIND11_CXX_FEATURES})
125+
set_target_properties(${target_name} PROPERTIES CXX_EXTENSIONS OFF)
33126
endif()
34127
endif()
35-
elseif(MSVC)
36-
set(PYBIND11_CPP_STANDARD /std:c++14)
37128
endif()
129+
endfunction()
38130

39-
set(PYBIND11_CPP_STANDARD ${PYBIND11_CPP_STANDARD} CACHE STRING
40-
"C++ standard flag, e.g. -std=c++11, -std=c++14, /std:c++14. Defaults to C++14 mode." FORCE)
41-
endif()
42131

43132
# Checks whether the given CXX/linker flags can compile and link a cxx file. cxxflags and
44133
# linkerflags are lists of flags to use. The result variable is a unique variable name for each set
@@ -185,7 +274,7 @@ function(pybind11_add_module target_name)
185274
endif()
186275

187276
# Make sure C++11/14 are enabled
188-
target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD})
277+
_pybind11_target_cxx_std(${target_name})
189278

190279
if(ARG_NO_EXTRAS)
191280
return()

0 commit comments

Comments
 (0)