add flag back in
[roojspacker] / cmake / AddCompilerFlags.cmake
1 # Copyright (c) 2016 Evan Nemerson <evan@nemerson.com>
2 #
3 # Permission is hereby granted, free of charge, to any person
4 # obtaining a copy of this software and associated documentation files
5 # (the "Software"), to deal in the Software without restriction,
6 # including without limitation the rights to use, copy, modify, merge,
7 # publish, distribute, sublicense, and/or sell copies of the Software,
8 # and to permit persons to whom the Software is furnished to do so,
9 # subject to the following conditions:
10 #
11 # The above copyright notice and this permission notice shall be
12 # included in all copies or substantial portions of the Software.
13 #
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 # SOFTWARE.
22
23 # This module provides a convenient way to add C/C++ compiler flags if
24 # the compiler supports them.
25
26 include (CheckCCompilerFlag)
27 include (CheckCXXCompilerFlag)
28
29 # Depending on the settings, some compilers will accept unknown flags.
30 # We try to disable this behavior by also passing these flags when we
31 # check if a flag is supported.
32 set (ADD_COMPILER_FLAGS_PREPEND "")
33
34 if ("GNU" STREQUAL "${CMAKE_C_COMPILER_ID}")
35   set (ADD_COMPILER_FLAGS_PREPEND "-Wall -Wextra -Werror")
36 elseif ("Clang" STREQUAL "${CMAKE_C_COMPILER_ID}")
37   set (ADD_COMPILER_FLAGS_PREPEND "-Werror=unknown-warning-option")
38 endif ()
39
40 ##
41 # Set a variable to different flags, depending on which compiler is in
42 # use.
43 #
44 # Example:
45 #   set_compiler_flags(VARIABLE varname MSVC /wd666 INTEL /wd1729)
46 #
47 #   This will set varname to /wd666 if the compiler is MSVC, and /wd1729
48 #   if it is Intel.
49 #
50 # Possible compilers:
51 #  - GCC: GNU C Compiler
52 #  - GCCISH: A compiler that (tries to) be GCC-compatible on the CLI
53 #    (i.e., anything but MSVC).
54 #  - CLANG: clang
55 #  - MSVC: Microsoft Visual C++ compiler
56 #  - INTEL: Intel C Compiler
57 #
58 # Note: the compiler is determined based on the value of the
59 # CMAKE_C_COMPILER_ID variable, not CMAKE_CXX_COMPILER_ID.
60 ##
61 function (set_compiler_specific_flags)
62   set (oneValueArgs VARIABLE)
63   set (multiValueArgs GCC GCCISH INTEL CLANG MSVC)
64   cmake_parse_arguments(COMPILER_SPECIFIC_FLAGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
65   unset (options)
66   unset (oneValueArgs)
67   unset (multiValueArgs)
68
69   set (compiler_flags)
70
71   if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
72     list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_GCC})
73   elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
74     list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_CLANG})
75   elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "Intel")
76     list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_INTEL})
77   elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
78     list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_MSVC})
79   endif()
80
81   if (NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
82     list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_GCCISH})
83   endif ()
84
85   set (${COMPILER_SPECIFIC_FLAGS_VARIABLE} "${compiler_flags}" PARENT_SCOPE)
86 endfunction ()
87
88 function (source_file_add_compiler_flags_unchecked file)
89   set (flags ${ARGV})
90   list (REMOVE_AT flags 0)
91   get_source_file_property (sources ${file} SOURCES)
92
93   foreach (flag ${flags})
94     get_source_file_property (existing ${file} COMPILE_FLAGS)
95     if ("${existing}" STREQUAL "NOTFOUND")
96       set_source_files_properties (${file}
97         PROPERTIES COMPILE_FLAGS "${flag}")
98     else ()
99       set_source_files_properties (${file}
100         PROPERTIES COMPILE_FLAGS "${existing} ${flag}")
101     endif ()
102   endforeach (flag)
103 endfunction ()
104
105 function (source_file_add_compiler_flags file)
106   set (flags ${ARGV})
107   list (REMOVE_AT flags 0)
108   get_source_file_property (sources ${file} SOURCES)
109
110   foreach (flag ${flags})
111     if ("GNU" STREQUAL "${CMAKE_C_COMPILER_ID}")
112       # Because https://gcc.gnu.org/wiki/FAQ#wnowarning
113       string (REGEX REPLACE "\\-Wno\\-(.+)" "-W\\1" flag_to_test "${flag}")
114     else ()
115       set (flag_to_test ${flag})
116     endif ()
117
118     if ("${file}" MATCHES "\\.c$")
119       string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" test_name "CFLAG_${flag_to_test}")
120       CHECK_C_COMPILER_FLAG ("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${test_name})
121     elseif ("${file}" MATCHES "\\.(cpp|cc|cxx)$")
122       string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" test_name "CXXFLAG_${flag_to_test}")
123       CHECK_CXX_COMPILER_FLAG ("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${test_name})
124     endif ()
125
126     if (${test_name})
127       source_file_add_compiler_flags_unchecked (${file} ${flag})
128     endif ()
129
130     unset (test_name)
131     unset (flag_to_test)
132   endforeach (flag)
133
134   unset (flags)
135 endfunction ()
136
137 function (target_add_compiler_flags target)
138   set (flags ${ARGV})
139   list (REMOVE_AT flags 0)
140   get_target_property (sources ${target} SOURCES)
141
142   foreach (source ${sources})
143     source_file_add_compiler_flags (${source} ${flags})
144   endforeach (source)
145
146   unset (flags)
147   unset (sources)
148 endfunction (target_add_compiler_flags)
149
150 # global_add_compiler_flags (flag1 [flag2 [flag3 ...]]):
151 #
152 # This just adds the requested compiler flags to
153 # CMAKE_C/CXX_FLAGS variable if they work with the compiler.
154 function (global_add_compiler_flags)
155   set (flags ${ARGV})
156
157   foreach (flag ${flags})
158     if ("GNU" STREQUAL "${CMAKE_C_COMPILER_ID}")
159       # Because https://gcc.gnu.org/wiki/FAQ#wnowarning
160       string (REGEX REPLACE "\\-Wno\\-(.+)" "-W\\1" flag_to_test "${flag}")
161     else ()
162       set (flag_to_test "${flag}")
163     endif ()
164
165     string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" c_test_name "CFLAG_${flag_to_test}")
166     CHECK_C_COMPILER_FLAG ("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${c_test_name})
167     if (${c_test_name})
168       set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
169     endif ()
170     unset (c_test_name)
171
172     string (REGEX REPLACE "[^a-zA-Z0-9]+" "_" cxx_test_name "CFLAG_${flag_to_test}")
173     CHECK_CXX_COMPILER_FLAG ("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${cxx_test_name})
174     if (${cxx_test_name})
175       set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
176     endif ()
177     unset (cxx_test_name)
178
179     unset (flag_to_test)
180   endforeach (flag)
181
182   unset (flags)
183
184   set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE)
185   set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
186 endfunction (global_add_compiler_flags)