File: CXXVersionCheck.cmake

package info (click to toggle)
innoextract 1.9-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,252 kB
  • sloc: cpp: 12,229; python: 1,703; sh: 76; makefile: 9
file content (146 lines) | stat: -rw-r--r-- 4,937 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

# Copyright (C) 2013-2020 Daniel Scharrer
#
# This software is provided 'as-is', without any express or implied
# warranty.  In no event will the author(s) be held liable for any damages
# arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not
#    claim that you wrote the original software. If you use this software
#    in a product, an acknowledgment in the product documentation would be
#    appreciated but is not required.
# 2. Altered source versions must be plainly marked as such, and must not be
#    misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.

include(CheckCXXSourceCompiles)
include(CompileCheck)

set(CXX_VERSION 2003)
get_filename_component(CXX_CHECK_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(CXX_CHECK_DIR "${CXX_CHECK_DIR}/check")

function(enable_cxx_version version)
	
	set(versions 17 14 11)
	
	if(MSVC)
		if(NOT version LESS 2011 AND NOT MSVC_VERSION LESS 1600)
			set(CXX_VERSION 2011)
			if(NOT version LESS 2017 AND NOT MSVC_VERSION LESS 1911)
				set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17")
				set(CXX_VERSION 2017)
			elseif(NOT version LESS 2014 AND NOT MSVC_VERSION LESS 1910)
				set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++14")
				set(CXX_VERSION 2014)
			elseif(NOT version LESS 2014 AND NOT MSVC_VERSION LESS 1900)
				# Only introduced with update 3 of MSVC 2015
				add_cxxflag("/std:c++14")
				if(FLAG_FOUND)
					set(CXX_VERSION 2014)
				endif()
			endif()
		endif()
	else()
		set(FLAG_FOUND 0)
		foreach(ver IN LISTS versions)
			if(NOT version LESS 20${ver} AND NOT FLAG_FOUND)
				add_cxxflag("-std=c++${ver}")
				if(FLAG_FOUND)
					set(CXX_VERSION 20${ver})
					break()
				endif()
			endif()
		endforeach()
		if(NOT FLAG_FOUND)
			# Check if the compiler supports the -std flag at all
			# Don't actually use the flag to allow for compiler extensions a la -sdt=gnu++03
			check_compiler_flag(FLAG_FOUND "-std=c++03")
			if(NOT FLAG_FOUND)
				check_compiler_flag(FLAG_FOUND "-std=c++98")
			endif()
		endif()
		if(NOT FLAG_FOUND)
			# Compiler does not support he -std flag, assume the highest supported C++ version is available
			# by default or can be enabled by CMake and rely on tests for individual features.
			foreach(ver IN LISTS versions)
				if(NOT version LESS 20${ver})
					set(CXX_VERSION 20${ver})
					break()
				endif()
			endforeach()
		endif()
		if(SET_WARNING_FLAGS AND NOT CXX_VERSION LESS 2011)
			add_cxxflag("-pedantic")
		endif()
	endif()
	
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
	set(CXX_VERSION ${CXX_VERSION} PARENT_SCOPE)
	
	# Tell CMake about our desired C++ version so that it doesn't override our value with a lower version.
	# We check -std ourselves first because
	# - This feature is new in CMake 3.1
	# - Not all CMake versions know how to check for all C++ versions
	# - CMake doesn't tell us what versions are available
	if(NOT CMAKE_VERSION VERSION_LESS 3.12)
		set(max_cxx_standard 20)
	elseif(NOT CMAKE_VERSION VERSION_LESS 3.8)
		set(max_cxx_standard 17)
	else()
		set(max_cxx_standard 14)
	endif()
	foreach(ver IN LISTS versions)
		if(NOT CXX_VERSION LESS 20${ver} AND NOT max_cxx_standard LESS ver)
			set(CMAKE_CXX_STANDARD ${ver} PARENT_SCOPE)
			set(CMAKE_CXX_STANDARD_REQUIRED OFF PARENT_SCOPE)
			set(CMAKE_CXX_EXTENSIONS OFF PARENT_SCOPE)
			break()
		endif()
	endforeach()
	
endfunction(enable_cxx_version)

function(check_cxx version feature resultvar)
	set(result)
	if(NOT CXX_VERSION LESS 20${version} OR (ARGC GREATER 3 AND ARGV3 STREQUAL "ALWAYS"))
		if(MSVC AND ARGC GREATER 3)
			if(NOT MSVC_VERSION LESS ARGV3)
				set(result 1)
			endif()
		else()
			string(REGEX REPLACE "[^a-zA-Z0-9_][^a-zA-Z0-9_]*" "-" check "${feature}")
			string(REGEX REPLACE "^--*" "" check "${check}")
			string(REGEX REPLACE "--*$" "" check "${check}")
			set(file "${CXX_CHECK_DIR}/cxx${version}-${check}.cpp")
			set(old_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
			set(old_CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
			strip_warning_flags(CMAKE_CXX_FLAGS)
			strip_warning_flags(CMAKE_EXE_LINKER_FLAGS)
			check_compile(result "${file}" "${feature}" "C++${version} feature")
			set(CMAKE_CXX_FLAGS "${old_CMAKE_CXX_FLAGS}")
			set(CMAKE_EXE_LINKER_FLAGS "${old_CMAKE_EXE_LINKER_FLAGS}")
		endif()
	endif()
	if(NOT DEFINED result OR result STREQUAL "")
		set(${resultvar} OFF PARENT_SCOPE)
	else()
		set(${resultvar} ON PARENT_SCOPE)
	endif()
endfunction()

macro(check_cxx11 feature resultvar)
	check_cxx(11 ${ARGV})
endmacro()

macro(check_cxx14 feature resultvar)
	check_cxx(14 ${ARGV})
endmacro()

macro(check_cxx17 feature resultvar)
	check_cxx(17 ${ARGV})
endmacro()