1# Copyright 2019 The libgav1 Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15if(LIBGAV1_CMAKE_LIBGAV1_FLAGS_CMAKE_) 16 return() 17endif() # LIBGAV1_CMAKE_LIBGAV1_FLAGS_CMAKE_ 18set(LIBGAV1_CMAKE_LIBGAV1_FLAGS_CMAKE_ 1) 19 20include(CheckCXXCompilerFlag) 21include(CheckCXXSourceCompiles) 22 23# Adds compiler flags specified by FLAGS to the sources specified by SOURCES: 24# 25# libgav1_set_compiler_flags_for_sources(SOURCES <sources> FLAGS <flags>) 26macro(libgav1_set_compiler_flags_for_sources) 27 unset(compiler_SOURCES) 28 unset(compiler_FLAGS) 29 unset(optional_args) 30 unset(single_value_args) 31 set(multi_value_args SOURCES FLAGS) 32 cmake_parse_arguments(compiler "${optional_args}" "${single_value_args}" 33 "${multi_value_args}" ${ARGN}) 34 35 if(NOT (compiler_SOURCES AND compiler_FLAGS)) 36 libgav1_die("libgav1_set_compiler_flags_for_sources: SOURCES and " 37 "FLAGS required.") 38 endif() 39 40 set_source_files_properties(${compiler_SOURCES} PROPERTIES COMPILE_FLAGS 41 ${compiler_FLAGS}) 42 43 if(LIBGAV1_VERBOSE GREATER 1) 44 foreach(source ${compiler_SOURCES}) 45 foreach(flag ${compiler_FLAGS}) 46 message("libgav1_set_compiler_flags_for_sources: source:${source} " 47 "flag:${flag}") 48 endforeach() 49 endforeach() 50 endif() 51endmacro() 52 53# Tests compiler flags stored in list(s) specified by FLAG_LIST_VAR_NAMES, adds 54# flags to $LIBGAV1_CXX_FLAGS when tests pass. Terminates configuration if 55# FLAG_REQUIRED is specified and any flag check fails. 56# 57# ~~~ 58# libgav1_test_cxx_flag(<FLAG_LIST_VAR_NAMES <flag list variable(s)>> 59# [FLAG_REQUIRED]) 60# ~~~ 61macro(libgav1_test_cxx_flag) 62 unset(cxx_test_FLAG_LIST_VAR_NAMES) 63 unset(cxx_test_FLAG_REQUIRED) 64 unset(single_value_args) 65 set(optional_args FLAG_REQUIRED) 66 set(multi_value_args FLAG_LIST_VAR_NAMES) 67 cmake_parse_arguments(cxx_test "${optional_args}" "${single_value_args}" 68 "${multi_value_args}" ${ARGN}) 69 70 if(NOT cxx_test_FLAG_LIST_VAR_NAMES) 71 libgav1_die("libgav1_test_cxx_flag: FLAG_LIST_VAR_NAMES required") 72 endif() 73 74 unset(cxx_flags) 75 foreach(list_var ${cxx_test_FLAG_LIST_VAR_NAMES}) 76 if(LIBGAV1_VERBOSE) 77 message("libgav1_test_cxx_flag: adding ${list_var} to cxx_flags") 78 endif() 79 list(APPEND cxx_flags ${${list_var}}) 80 endforeach() 81 82 if(LIBGAV1_VERBOSE) 83 message("CXX test: all flags: ${cxx_flags}") 84 endif() 85 86 unset(all_cxx_flags) 87 list(APPEND all_cxx_flags ${LIBGAV1_CXX_FLAGS} ${cxx_flags}) 88 89 # Turn off output from check_cxx_source_compiles. Print status directly 90 # instead since the logging messages from check_cxx_source_compiles can be 91 # quite confusing. 92 set(CMAKE_REQUIRED_QUIET TRUE) 93 94 # Run the actual compile test. 95 unset(libgav1_all_cxx_flags_pass CACHE) 96 message("--- Running combined CXX flags test, flags: ${all_cxx_flags}") 97 check_cxx_compiler_flag("${all_cxx_flags}" libgav1_all_cxx_flags_pass) 98 99 if(cxx_test_FLAG_REQUIRED AND NOT libgav1_all_cxx_flags_pass) 100 libgav1_die("Flag test failed for required flag(s): " 101 "${all_cxx_flags} and FLAG_REQUIRED specified.") 102 endif() 103 104 if(libgav1_all_cxx_flags_pass) 105 # Test passed: update the global flag list used by the libgav1 target 106 # creation wrappers. 107 set(LIBGAV1_CXX_FLAGS ${cxx_flags}) 108 list(REMOVE_DUPLICATES LIBGAV1_CXX_FLAGS) 109 110 if(LIBGAV1_VERBOSE) 111 message("LIBGAV1_CXX_FLAGS=${LIBGAV1_CXX_FLAGS}") 112 endif() 113 114 message("--- Passed combined CXX flags test") 115 else() 116 message("--- Failed combined CXX flags test, testing flags individually.") 117 118 if(cxx_flags) 119 message("--- Testing flags from $cxx_flags: " "${cxx_flags}") 120 foreach(cxx_flag ${cxx_flags}) 121 # Between 3.17.0 and 3.18.2 check_cxx_compiler_flag() sets a normal 122 # variable at parent scope while check_cxx_source_compiles() continues 123 # to set an internal cache variable, so we unset both to avoid the 124 # failure / success state persisting between checks. See 125 # https://gitlab.kitware.com/cmake/cmake/-/issues/21207. 126 unset(cxx_flag_test_passed) 127 unset(cxx_flag_test_passed CACHE) 128 message("--- Testing flag: ${cxx_flag}") 129 check_cxx_compiler_flag("${cxx_flag}" cxx_flag_test_passed) 130 131 if(cxx_flag_test_passed) 132 message("--- Passed test for ${cxx_flag}") 133 else() 134 list(REMOVE_ITEM cxx_flags ${cxx_flag}) 135 message("--- Failed test for ${cxx_flag}, flag removed.") 136 endif() 137 endforeach() 138 139 set(LIBGAV1_CXX_FLAGS ${cxx_flags}) 140 endif() 141 endif() 142 143 if(LIBGAV1_CXX_FLAGS) 144 list(REMOVE_DUPLICATES LIBGAV1_CXX_FLAGS) 145 endif() 146endmacro() 147 148# Tests executable linker flags stored in list specified by FLAG_LIST_VAR_NAME, 149# adds flags to $LIBGAV1_EXE_LINKER_FLAGS when test passes. Terminates 150# configuration when flag check fails. libgav1_set_cxx_flags() must be called 151# before calling this macro because it assumes $LIBGAV1_CXX_FLAGS contains only 152# valid CXX flags. 153# 154# libgav1_test_exe_linker_flag(<FLAG_LIST_VAR_NAME <flag list variable)>) 155macro(libgav1_test_exe_linker_flag) 156 unset(link_FLAG_LIST_VAR_NAME) 157 unset(optional_args) 158 unset(multi_value_args) 159 set(single_value_args FLAG_LIST_VAR_NAME) 160 cmake_parse_arguments(link "${optional_args}" "${single_value_args}" 161 "${multi_value_args}" ${ARGN}) 162 163 if(NOT link_FLAG_LIST_VAR_NAME) 164 libgav1_die("libgav1_test_link_flag: FLAG_LIST_VAR_NAME required") 165 endif() 166 167 libgav1_set_and_stringify(DEST linker_flags SOURCE_VARS 168 ${link_FLAG_LIST_VAR_NAME}) 169 170 if(LIBGAV1_VERBOSE) 171 message("EXE LINKER test: all flags: ${linker_flags}") 172 endif() 173 174 # Tests of $LIBGAV1_CXX_FLAGS have already passed. Include them with the 175 # linker test. 176 libgav1_set_and_stringify(DEST CMAKE_REQUIRED_FLAGS SOURCE_VARS 177 LIBGAV1_CXX_FLAGS) 178 179 # Cache the global exe linker flags. 180 if(CMAKE_EXE_LINKER_FLAGS) 181 set(cached_CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) 182 libgav1_set_and_stringify(DEST CMAKE_EXE_LINKER_FLAGS SOURCE 183 ${linker_flags}) 184 endif() 185 186 libgav1_set_and_stringify(DEST CMAKE_EXE_LINKER_FLAGS SOURCE ${linker_flags} 187 ${CMAKE_EXE_LINKER_FLAGS}) 188 189 # Turn off output from check_cxx_source_compiles. Print status directly 190 # instead since the logging messages from check_cxx_source_compiles can be 191 # quite confusing. 192 set(CMAKE_REQUIRED_QUIET TRUE) 193 194 message("--- Running EXE LINKER test for flags: ${linker_flags}") 195 196 unset(linker_flag_test_passed CACHE) 197 set(libgav1_cxx_main "\nint main() { return 0; }") 198 check_cxx_source_compiles("${libgav1_cxx_main}" linker_flag_test_passed) 199 200 if(NOT linker_flag_test_passed) 201 libgav1_die("EXE LINKER test failed.") 202 endif() 203 204 message("--- Passed EXE LINKER flag test.") 205 206 # Restore cached global exe linker flags. 207 if(cached_CMAKE_EXE_LINKER_FLAGS) 208 set(CMAKE_EXE_LINKER_FLAGS ${cached_CMAKE_EXE_LINKER_FLAGS}) 209 else() 210 unset(CMAKE_EXE_LINKER_FLAGS) 211 endif() 212endmacro() 213 214# Runs the libgav1 compiler tests. This macro builds up the list of list var(s) 215# that is passed to libgav1_test_cxx_flag(). 216# 217# Note: libgav1_set_build_definitions() must be called before this macro. 218macro(libgav1_set_cxx_flags) 219 unset(cxx_flag_lists) 220 221 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") 222 list(APPEND cxx_flag_lists libgav1_base_cxx_flags) 223 endif() 224 225 # Append clang flags after the base set to allow -Wno* overrides to take 226 # effect. Some of the base flags may enable a large set of warnings, e.g., 227 # -Wall. 228 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 229 list(APPEND cxx_flag_lists libgav1_clang_cxx_flags) 230 endif() 231 232 if(MSVC) 233 list(APPEND cxx_flag_lists libgav1_msvc_cxx_flags) 234 endif() 235 236 if(LIBGAV1_VERBOSE) 237 if(cxx_flag_lists) 238 libgav1_set_and_stringify(DEST cxx_flags SOURCE_VARS ${cxx_flag_lists}) 239 message("libgav1_set_cxx_flags: internal CXX flags: ${cxx_flags}") 240 endif() 241 endif() 242 243 if(LIBGAV1_CXX_FLAGS) 244 list(APPEND cxx_flag_lists LIBGAV1_CXX_FLAGS) 245 if(LIBGAV1_VERBOSE) 246 message("libgav1_set_cxx_flags: user CXX flags: ${LIBGAV1_CXX_FLAGS}") 247 endif() 248 endif() 249 250 libgav1_test_cxx_flag(FLAG_LIST_VAR_NAMES ${cxx_flag_lists}) 251endmacro() 252 253# Sets LIBGAV1_TEST_C_FLAGS and LIBGAV1_TEST_CXX_FLAGS. 254# 255# Note: libgav1_set_cxx_flags() must be called before this macro. Furthermore, 256# the call to this macro should be made after all additions to LIBGAV1_CXX_FLAGS 257# are complete. 258macro(libgav1_set_test_flags) 259 if(LIBGAV1_ENABLE_TESTS) 260 set(LIBGAV1_TEST_CXX_FLAGS ${LIBGAV1_CXX_FLAGS}) 261 list(FILTER LIBGAV1_TEST_CXX_FLAGS EXCLUDE REGEX "-Wframe-larger-than") 262 263 if(NOT CMAKE_CXX_COMPILER_ID STREQUAL CMAKE_C_COMPILER_ID) 264 message( 265 FATAL_ERROR 266 "C/CXX compiler mismatch (${CMAKE_C_COMPILER_ID} vs" 267 " ${CMAKE_CXX_COMPILER_ID})! Compiler flags are only tested using" 268 " CMAKE_CXX_COMPILER, rerun cmake with CMAKE_C_COMPILER set to the" 269 " C compiler from the same package as CMAKE_CXX_COMPILER to ensure" 270 " the build completes successfully.") 271 endif() 272 set(LIBGAV1_TEST_C_FLAGS ${LIBGAV1_TEST_CXX_FLAGS}) 273 list(FILTER LIBGAV1_TEST_C_FLAGS EXCLUDE REGEX 274 "-fvisibility-inlines-hidden") 275 endif() 276endmacro() 277