summaryrefslogtreecommitdiffstats
path: root/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
blob: cfaa78c5562bdb108e563ab961d6089292569dc6 (plain)
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
cmake_minimum_required(VERSION 3.1.0)
project(WriteCompilerDetectionHeader)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

include(WriteCompilerDetectionHeader)

get_property(cxx_known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
get_property(c_known_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES)

write_compiler_detection_header(
  FILE "${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h"
  PREFIX TEST
  COMPILERS GNU Clang AppleClang MSVC
  VERSION 3.1
  PROLOG "// something"
  EPILOG "// more"
  FEATURES
    ${cxx_known_features} ${c_known_features}
)

if (NOT CMAKE_CXX_COMPILE_FEATURES AND NOT CMAKE_C_COMPILE_FEATURES)
  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp"
    "int main(int,char**) { return 0; }\n"
  )
  add_executable(WriteCompilerDetectionHeader "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp")

  include(CheckCXXSourceCompiles)
  check_cxx_source_compiles("#include \"${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h\"\nint main() { return 0; }\n"
    file_include_works
  )
  if (file_include_works)
    message(SEND_ERROR "Inclusion of ${CMAKE_CURRENT_BINARY_DIR}/test_compiler_detection.h was expected to cause an error, but did not.")
  endif()
  return()
endif()

string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" COMPILER_VERSION_MAJOR "${CMAKE_CXX_COMPILER_VERSION}")
string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" COMPILER_VERSION_MINOR "${CMAKE_CXX_COMPILER_VERSION}")
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" COMPILER_VERSION_PATCH "${CMAKE_CXX_COMPILER_VERSION}")

macro(set_defines target true_defs false_defs)
  set(defines)
  foreach(def ${true_defs})
    list(APPEND defines ${def}=1)
  endforeach()
  foreach(def ${false_defs})
    list(APPEND defines ${def}=0)
  endforeach()
  target_compile_definitions(${target}
    PRIVATE
      ${defines}
      EXPECTED_COMPILER_VERSION_MAJOR=${COMPILER_VERSION_MAJOR}
      EXPECTED_COMPILER_VERSION_MINOR=${COMPILER_VERSION_MINOR}
      EXPECTED_COMPILER_VERSION_PATCH=${COMPILER_VERSION_PATCH}
  )
endmacro()

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
    OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
    OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
  # False for C++98 mode.
  list(APPEND false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
  list(APPEND false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
endif()

# for msvc the compiler version determines which c++11 features are available.
# Both variadic templates and delegating constructors support exist in
# all versions that we write compile headers for.
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND
    ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_delegating_constructors;")
  list(APPEND true_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
  list(APPEND true_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
  list(APPEND false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
  list(APPEND false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
endif()

if (CMAKE_C_COMPILER_ID STREQUAL "GNU"
    OR CMAKE_C_COMPILER_ID STREQUAL "Clang"
    OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
  add_executable(C_undefined c_undefined.c)
  set_property(TARGET C_undefined PROPERTY CXX_STANDARD 90)
  target_compile_options(C_undefined PRIVATE -Werror=undef)
endif()

add_executable(WriteCompilerDetectionHeader main.cpp)
set_property(TARGET WriteCompilerDetectionHeader PROPERTY CXX_STANDARD 98)
set_defines(WriteCompilerDetectionHeader "${true_defs}" "${false_defs}")

write_compiler_detection_header(
  FILE "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/multi_file_compiler_detection.h"
  PREFIX MULTI
  OUTPUT_FILES_VAR multi_files
  OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/compiler_support"
  COMPILERS GNU Clang AppleClang MSVC
  VERSION 3.1
  FEATURES
    ${cxx_known_features} ${c_known_features}
)

add_executable(multi_files multi_files.cpp)
set_property(TARGET multi_files PROPERTY CXX_STANDARD 98)
target_include_directories(multi_files PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files)
set_defines(multi_files "${true_defs}" "${false_defs}")

if(MSVC)
  return() # MSVC has only one mode.
endif()

# Since GNU 4.7
if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_delegating_constructors;")
  list(APPEND true_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
  list(REMOVE_ITEM false_defs EXPECTED_COMPILER_CXX_DELEGATING_CONSTRUCTORS)
endif()

# Since GNU 4.4
if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_variadic_templates;")
  list(APPEND true_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
  list(REMOVE_ITEM false_defs EXPECTED_COMPILER_CXX_VARIADIC_TEMPLATES)
endif()

add_executable(WriteCompilerDetectionHeader_11 main.cpp)
set_property(TARGET WriteCompilerDetectionHeader_11 PROPERTY CXX_STANDARD 11)
set_defines(WriteCompilerDetectionHeader_11 "${true_defs}" "${false_defs}")

add_executable(multi_files_11 multi_files.cpp)
set_property(TARGET multi_files_11 PROPERTY CXX_STANDARD 11)
target_include_directories(multi_files_11 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files)
set_defines(multi_files_11 "${true_defs}" "${false_defs}")