Skip to content

Commit 9d663ce

Browse files
committed
Cleaner implementation that supports modern CMake flag discovery
1 parent 449606a commit 9d663ce

File tree

2 files changed

+92
-24
lines changed

2 files changed

+92
-24
lines changed

CMakeLists.txt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +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-
if(CMAKE_VERSION VERSION_LESS 3.8 OR PYBIND_CPP_STANDARD)
102-
target_compile_options(pybind11 INTERFACE $<BUILD_INTERFACE:${PYBIND11_CPP_STANDARD}>)
103-
else()
104-
target_compile_features(pybind11 INTERFACE cxx_std_11)
105-
endif()
101+
102+
_pybind11_target_cxx_std(pybind11)
106103

107104
add_library(module INTERFACE)
108105
add_library(pybind11::module ALIAS module)

tools/pybind11Tools.cmake

Lines changed: 90 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,106 @@ find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} REQUIRED)
1818
include(CheckCXXCompilerFlag)
1919
include(CMakeParseArguments)
2020

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
2124
if(NOT CMAKE_CXX_STANDARD)
22-
if(NOT PYBIND11_CPP_STANDARD AND CMAKE_VERSION VERSION_LESS 3.8)
23-
if(NOT MSVC)
24-
check_cxx_compiler_flag("-std=c++14" HAS_CPP14_FLAG)
25-
26-
if (HAS_CPP14_FLAG)
27-
set(PYBIND11_CPP_STANDARD -std=c++14)
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")
2834
else()
35+
check_cxx_compiler_flag("-std=c++17" HAS_CPP17_FLAG)
36+
check_cxx_compiler_flag("-std=c++14" HAS_CPP14_FLAG)
2937
check_cxx_compiler_flag("-std=c++11" HAS_CPP11_FLAG)
30-
if (HAS_CPP11_FLAG)
31-
set(PYBIND11_CPP_STANDARD -std=c++11)
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")
3248
else()
3349
message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!")
3450
endif()
3551
endif()
36-
elseif(MSVC)
37-
set(PYBIND11_CPP_STANDARD /std:c++14)
3852
endif()
39-
40-
set(PYBIND11_CPP_STANDARD ${PYBIND11_CPP_STANDARD} CACHE STRING
41-
"C++ standard flag, e.g. -std=c++11, -std=c++14, /std:c++14. Defaults to C++14 mode." FORCE)
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(std_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(std_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()
4274
endif()
4375
endif()
4476

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+
99+
# Allow manual settings (Needed for older CMakes)
100+
# Will always be set for old CMake
101+
if(PYBIND11_CPP_STANDARD)
102+
if(PYTYPE STREQUAL "INTERFACE_LIBRARY")
103+
target_compile_options(${target_name} INTERFACE ${PYBIND11_CPP_STANDARD})
104+
else()
105+
target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD})
106+
endif()
107+
108+
# A user of CMake 3.1 can override this, or 3.8 will default to using it
109+
elseif(PYBIND11_CXX_FEATURES)
110+
if(PYTYPE STREQUAL "INTERFACE_LIBRARY")
111+
target_compile_features(${target_name} INTERFACE ${PYBIND11_CXX_FEATURES})
112+
else()
113+
target_compile_features(${target_name} PUBLIC ${PYBIND11_CXX_FEATURES})
114+
set_target_properties(${target_name} PROPERTIES CXX_EXTENSIONS OFF)
115+
endif()
116+
endif()
117+
endif()
118+
endfunction()
119+
120+
45121
# Checks whether the given CXX/linker flags can compile and link a cxx file. cxxflags and
46122
# linkerflags are lists of flags to use. The result variable is a unique variable name for each set
47123
# of flags: the compilation result will be cached base on the result variable. If the flags work,
@@ -175,12 +251,7 @@ function(pybind11_add_module target_name)
175251
endif()
176252

177253
# Make sure C++11/14 are enabled
178-
if(PYBIND11_CPP_STANDARD OR ${CMAKE_VERSION} VERSION_LESS 3.8)
179-
target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD})
180-
else()
181-
target_compile_features(${target_name} PUBLIC cxx_std_11) # Will be 14 if parent project requests 14
182-
set_target_properties(${target_name} PROPERTIES CXX_EXTENSIONS OFF)
183-
endif()
254+
_pybind11_target_cxx_std(${target_name})
184255

185256
if(ARG_NO_EXTRAS)
186257
return()

0 commit comments

Comments
 (0)