Skip to content

Commit 5b925e9

Browse files
committed
CMake compiler features now used on CMake 3.8+
1 parent 6c62d27 commit 5b925e9

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
@@ -98,7 +98,8 @@ if(NOT (CMAKE_VERSION VERSION_LESS 3.0)) # CMake >= 3.0
9898
target_include_directories(pybind11 INTERFACE $<BUILD_INTERFACE:${PYBIND11_INCLUDE_DIR}>
9999
$<BUILD_INTERFACE:${PYTHON_INCLUDE_DIRS}>
100100
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
101-
target_compile_options(pybind11 INTERFACE $<BUILD_INTERFACE:${PYBIND11_CPP_STANDARD}>)
101+
102+
_pybind11_target_cxx_std(pybind11)
102103

103104
add_library(module INTERFACE)
104105
add_library(pybind11::module ALIAS module)

docs/changelog.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ v2.3.0 (Not yet released)
2121
* The ``value()`` method of ``py::enum_`` now accepts an optional docstring
2222
that will be shown in the documentation of the associated enumeration.
2323

24+
* Improved CMake C++ standard discovery for CMake 3.8+, and allow compiler features
25+
to be used on CMake 3.1+. Added C++17 standard check.
26+
`#1098 <https://github.com/pybind/pybind11/pull/1098>`_.
27+
2428
v2.2.2 (February 7, 2018)
2529
-----------------------------------------------------
2630

docs/compiling.rst

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

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

106126
.. code-block:: cmake
107127
@@ -116,10 +136,14 @@ available. To override this, the standard flag can be given explicitly in
116136
117137
add_subdirectory(pybind11) # or find_package(pybind11)
118138
119-
Note that this and all other configuration variables must be set **before** the
139+
Note that these and all other configuration variables must be set **before** the
120140
call to ``add_subdirectory`` or ``find_package``. The variables can also be set
121141
when calling CMake from the command line using the ``-D<variable>=<value>`` flag.
122142

143+
Mixed C and C++ projects should use the ``PYBIND11_CXX_FEATURES`` mechanism to avoid
144+
adding flags to the C compiler. If you need the latest version of CMake, it is trivial
145+
to install; try ``pip install cmake`` or ``pip install --user cmake``.
146+
123147
The target Python version can be selected by setting ``PYBIND11_PYTHON_VERSION``
124148
or an exact Python installation can be specified with ``PYTHON_EXECUTABLE``.
125149
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,28 +18,117 @@ 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
2422

25-
if (HAS_CPP14_FLAG)
26-
set(PYBIND11_CPP_STANDARD -std=c++14)
27-
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)
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")
3134
else()
32-
message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!")
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()
3351
endif()
3452
endif()
35-
elseif(MSVC)
36-
set(PYBIND11_CPP_STANDARD /std:c++14)
53+
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)
71+
else()
72+
message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!")
73+
endif()
3774
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.
3880

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)
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")
4190
endif()
4291

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()
123+
else()
124+
target_compile_features(${target_name} PUBLIC ${PYBIND11_CXX_FEATURES})
125+
set_target_properties(${target_name} PROPERTIES CXX_EXTENSIONS OFF)
126+
endif()
127+
endif()
128+
endif()
129+
endfunction()
130+
131+
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
45134
# of flags: the compilation result will be cached base on the result variable. If the flags work,
@@ -173,7 +262,7 @@ function(pybind11_add_module target_name)
173262
endif()
174263

175264
# Make sure C++11/14 are enabled
176-
target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD})
265+
_pybind11_target_cxx_std(${target_name})
177266

178267
if(ARG_NO_EXTRAS)
179268
return()

0 commit comments

Comments
 (0)