1 # Copyright (c) 2016 Evan Nemerson <evan@nemerson.com>
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:
11 # The above copyright notice and this permission notice shall be
12 # included in all copies or substantial portions of the Software.
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
23 # This module provides a convenient way to add C/C++ compiler flags if
24 # the compiler supports them.
26 include (CheckCCompilerFlag)
27 include (CheckCXXCompilerFlag)
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 "")
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")
41 # Set a variable to different flags, depending on which compiler is in
45 # set_compiler_flags(VARIABLE varname MSVC /wd666 INTEL /wd1729)
47 # This will set varname to /wd666 if the compiler is MSVC, and /wd1729
51 # - GCC: GNU C Compiler
52 # - GCCISH: A compiler that (tries to) be GCC-compatible on the CLI
53 # (i.e., anything but MSVC).
55 # - MSVC: Microsoft Visual C++ compiler
56 # - INTEL: Intel C Compiler
58 # Note: the compiler is determined based on the value of the
59 # CMAKE_C_COMPILER_ID variable, not CMAKE_CXX_COMPILER_ID.
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})
67 unset (multiValueArgs)
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})
81 if (NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
82 list (APPEND compiler_flags ${COMPILER_SPECIFIC_FLAGS_GCCISH})
85 set (${COMPILER_SPECIFIC_FLAGS_VARIABLE} "${compiler_flags}" PARENT_SCOPE)
88 function (source_file_add_compiler_flags_unchecked file)
90 list (REMOVE_AT flags 0)
91 get_source_file_property (sources ${file} SOURCES)
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}")
99 set_source_files_properties (${file}
100 PROPERTIES COMPILE_FLAGS "${existing} ${flag}")
105 function (source_file_add_compiler_flags file)
107 list (REMOVE_AT flags 0)
108 get_source_file_property (sources ${file} SOURCES)
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}")
115 set (flag_to_test ${flag})
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})
127 source_file_add_compiler_flags_unchecked (${file} ${flag})
137 function (target_add_compiler_flags target)
139 list (REMOVE_AT flags 0)
140 get_target_property (sources ${target} SOURCES)
142 foreach (source ${sources})
143 source_file_add_compiler_flags (${source} ${flags})
148 endfunction (target_add_compiler_flags)
150 # global_add_compiler_flags (flag1 [flag2 [flag3 ...]]):
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)
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}")
162 set (flag_to_test "${flag}")
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})
168 set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
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}")
177 unset (cxx_test_name)
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)