Skip to content

Commit cdc49bc

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

File tree

2 files changed

+95
-24
lines changed

2 files changed

+95
-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: 93 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,108 @@ 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")
2833
else()
34+
check_cxx_compiler_flag("-std=c++17" HAS_CPP17_FLAG)
35+
check_cxx_compiler_flag("-std=c++14" HAS_CPP14_FLAG)
2936
check_cxx_compiler_flag("-std=c++11" HAS_CPP11_FLAG)
30-
if (HAS_CPP11_FLAG)
31-
set(PYBIND11_CPP_STANDARD -std=c++11)
37+
38+
if(HAS_CPP17_FLAG)
39+
set(PYBIND11_CPP_STANDARD "-std=c++17")
40+
elseif(HAS_CPP14_FLAG)
41+
set(PYBIND11_CPP_STANDARD "-std=c++14")
42+
elseif(HAS_CPP11_FLAG)
43+
set(PYBIND11_CPP_STANDARD "-std=c++11")
3244
else()
3345
message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!")
3446
endif()
3547
endif()
36-
elseif(MSVC)
37-
set(PYBIND11_CPP_STANDARD /std:c++14)
3848
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)
49+
50+
# Auto add if CMake >= 3.8 and CXX_FEATURES is not set
51+
elseif(NOT PYBIND11_CXX_FEATURES)
52+
# IN_LIST introduced in CMAKE 3.3
53+
# Safe because this will only activate if CMake >= 3.8
54+
cmake_policy(SET CMP0057 NEW)
55+
56+
if(cxx_std_17 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
57+
set(PYBIND11_CXX_FEATURES cxx_std_17)
58+
message(STATUS "pybind11 in C++17 mode, compiler feature")
59+
elseif(std_std_14 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
60+
message(STATUS "pybind11 in C++14 mode, compiler feature")
61+
set(PYBIND11_CXX_FEATURES cxx_std_14)
62+
elseif(std_std_11 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
63+
message(STATUS "pybind11 in C++11 mode, compiler feature")
64+
set(PYBIND11_CXX_FEATURES cxx_std_11)
65+
else()
66+
message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!")
67+
endif()
4268
endif()
4369
endif()
4470

71+
# Allow the user to override by setting the cache value after the auto-discovery
72+
# Empty values get filled on first run (PYBIND11_CPP_STANDARD for CMake < 3.8,
73+
# otherwise PYBIND11_CXX_FEATURES), and then at this point are promoted to the CACHE.
74+
75+
set(PYBIND11_CPP_STANDARD ${PYBIND11_CPP_STANDARD} CACHE STRING
76+
"C++ standard flag, e.g. -std=c++11, -std=c++14, /std:c++14. Defaults to highest supported for CMake 2.8-3.7")
77+
78+
if(NOT CMAKE_VERSION VERSION_LESS 3.1)
79+
#Only provide the option if CMake >= 3.1
80+
set(PYBIND11_CXX_FEATURES ${PYBIND11_CXX_FEATURES} CACHE STRING
81+
"List of compile features for PyBind, will use highest detected C++ version in CMake 3.8+")
82+
elseif(PYBIND11_CXX_FEATURES)
83+
message(FATAL_ERROR "PYBIND11_CXX_FEATURES is not supported for CMake < 3.1")
84+
endif()
85+
86+
function(_pybind11_target_cxx_std target_name)
87+
message(STATUS "Calling: ${target_name}")
88+
89+
# Do not do any overriding if global CMAKE_CXX_STANDARD is set
90+
if(NOT CMAKE_CXX_STANDARD)
91+
message(STATUS "Calling: ${target_name}")
92+
# See if this is an interface or regular target
93+
get_target_property(PYTYPE ${target_name} TYPE)
94+
message(STATUS "With: ${PYTYPE}")
95+
96+
# Allow manual settings (Needed for older CMakes)
97+
# Will always be set for old CMake
98+
if(PYBIND11_CPP_STANDARD)
99+
if(PYTYPE STREQUAL "INTERFACE_LIBRARY")
100+
target_compile_options(${target_name} INTERFACE ${PYBIND11_CPP_STANDARD})
101+
message(STATUS "X Interface: ${target_name}")
102+
else()
103+
target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD})
104+
message(STATUS "X Fixed: ${target_name}")
105+
endif()
106+
107+
# A user of CMake 3.1 can override this, or 3.8 will default to using it
108+
elseif(PYBIND11_CXX_FEATURES)
109+
message(STATUS "CXX_FEAT: ${PYBIND11_CXX_FEATURES}")
110+
if(PYTYPE STREQUAL "INTERFACE_LIBRARY")
111+
target_compile_features(${target_name} INTERFACE ${PYBIND11_CXX_FEATURES})
112+
message(STATUS "Interface: ${target_name}")
113+
else()
114+
target_compile_features(${target_name} PUBLIC ${PYBIND11_CXX_FEATURES})
115+
set_target_properties(${target_name} PROPERTIES CXX_EXTENSIONS OFF)
116+
message(STATUS "Fixed: ${target_name}")
117+
endif()
118+
endif()
119+
endif()
120+
endfunction()
121+
122+
45123
# Checks whether the given CXX/linker flags can compile and link a cxx file. cxxflags and
46124
# linkerflags are lists of flags to use. The result variable is a unique variable name for each set
47125
# of flags: the compilation result will be cached base on the result variable. If the flags work,
@@ -175,12 +253,8 @@ function(pybind11_add_module target_name)
175253
endif()
176254

177255
# 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()
256+
message(STATUS "Adding C++ness")
257+
_pybind11_target_cxx_std(${target_name})
184258

185259
if(ARG_NO_EXTRAS)
186260
return()

0 commit comments

Comments
 (0)