diff options
Diffstat (limited to 'cmake/libgav1_flags.cmake')
-rw-r--r-- | cmake/libgav1_flags.cmake | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/cmake/libgav1_flags.cmake b/cmake/libgav1_flags.cmake new file mode 100644 index 0000000..2d8d9a6 --- /dev/null +++ b/cmake/libgav1_flags.cmake @@ -0,0 +1,251 @@ +# Copyright 2019 The libgav1 Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if(LIBGAV1_CMAKE_LIBGAV1_FLAGS_CMAKE_) + return() +endif() # LIBGAV1_CMAKE_LIBGAV1_FLAGS_CMAKE_ +set(LIBGAV1_CMAKE_LIBGAV1_FLAGS_CMAKE_ 1) + +include(CheckCXXCompilerFlag) +include(CheckCXXSourceCompiles) + +# Adds compiler flags specified by FLAGS to the sources specified by SOURCES: +# +# libgav1_set_compiler_flags_for_sources(SOURCES <sources> FLAGS <flags>) +macro(libgav1_set_compiler_flags_for_sources) + unset(compiler_SOURCES) + unset(compiler_FLAGS) + unset(optional_args) + unset(single_value_args) + set(multi_value_args SOURCES FLAGS) + cmake_parse_arguments(compiler "${optional_args}" "${single_value_args}" + "${multi_value_args}" ${ARGN}) + + if(NOT (compiler_SOURCES AND compiler_FLAGS)) + libgav1_die("libgav1_set_compiler_flags_for_sources: SOURCES and " + "FLAGS required.") + endif() + + set_source_files_properties(${compiler_SOURCES} PROPERTIES COMPILE_FLAGS + ${compiler_FLAGS}) + + if(LIBGAV1_VERBOSE GREATER 1) + foreach(source ${compiler_SOURCES}) + foreach(flag ${compiler_FLAGS}) + message("libgav1_set_compiler_flags_for_sources: source:${source} " + "flag:${flag}") + endforeach() + endforeach() + endif() +endmacro() + +# Tests compiler flags stored in list(s) specified by FLAG_LIST_VAR_NAMES, adds +# flags to $LIBGAV1_CXX_FLAGS when tests pass. Terminates configuration if +# FLAG_REQUIRED is specified and any flag check fails. +# +# ~~~ +# libgav1_test_cxx_flag(<FLAG_LIST_VAR_NAMES <flag list variable(s)>> +# [FLAG_REQUIRED]) +# ~~~ +macro(libgav1_test_cxx_flag) + unset(cxx_test_FLAG_LIST_VAR_NAMES) + unset(cxx_test_FLAG_REQUIRED) + unset(single_value_args) + set(optional_args FLAG_REQUIRED) + set(multi_value_args FLAG_LIST_VAR_NAMES) + cmake_parse_arguments(cxx_test "${optional_args}" "${single_value_args}" + "${multi_value_args}" ${ARGN}) + + if(NOT cxx_test_FLAG_LIST_VAR_NAMES) + libgav1_die("libgav1_test_cxx_flag: FLAG_LIST_VAR_NAMES required") + endif() + + unset(cxx_flags) + foreach(list_var ${cxx_test_FLAG_LIST_VAR_NAMES}) + if(LIBGAV1_VERBOSE) + message("libgav1_test_cxx_flag: adding ${list_var} to cxx_flags") + endif() + list(APPEND cxx_flags ${${list_var}}) + endforeach() + + if(LIBGAV1_VERBOSE) + message("CXX test: all flags: ${cxx_flags}") + endif() + + unset(all_cxx_flags) + list(APPEND all_cxx_flags ${LIBGAV1_CXX_FLAGS} ${cxx_flags}) + + # Turn off output from check_cxx_source_compiles. Print status directly + # instead since the logging messages from check_cxx_source_compiles can be + # quite confusing. + set(CMAKE_REQUIRED_QUIET TRUE) + + # Run the actual compile test. + unset(libgav1_all_cxx_flags_pass CACHE) + message("--- Running combined CXX flags test, flags: ${all_cxx_flags}") + check_cxx_compiler_flag("${all_cxx_flags}" libgav1_all_cxx_flags_pass) + + if(cxx_test_FLAG_REQUIRED AND NOT libgav1_all_cxx_flags_pass) + libgav1_die("Flag test failed for required flag(s): " + "${all_cxx_flags} and FLAG_REQUIRED specified.") + endif() + + if(libgav1_all_cxx_flags_pass) + # Test passed: update the global flag list used by the libgav1 target + # creation wrappers. + set(LIBGAV1_CXX_FLAGS ${cxx_flags}) + list(REMOVE_DUPLICATES LIBGAV1_CXX_FLAGS) + + if(LIBGAV1_VERBOSE) + message("LIBGAV1_CXX_FLAGS=${LIBGAV1_CXX_FLAGS}") + endif() + + message("--- Passed combined CXX flags test") + else() + message("--- Failed combined CXX flags test, testing flags individually.") + + if(cxx_flags) + message("--- Testing flags from $cxx_flags: " "${cxx_flags}") + foreach(cxx_flag ${cxx_flags}) + # Between 3.17.0 and 3.18.2 check_cxx_compiler_flag() sets a normal + # variable at parent scope while check_cxx_source_compiles() continues + # to set an internal cache variable, so we unset both to avoid the + # failure / success state persisting between checks. See + # https://gitlab.kitware.com/cmake/cmake/-/issues/21207. + unset(cxx_flag_test_passed) + unset(cxx_flag_test_passed CACHE) + message("--- Testing flag: ${cxx_flag}") + check_cxx_compiler_flag("${cxx_flag}" cxx_flag_test_passed) + + if(cxx_flag_test_passed) + message("--- Passed test for ${cxx_flag}") + else() + list(REMOVE_ITEM cxx_flags ${cxx_flag}) + message("--- Failed test for ${cxx_flag}, flag removed.") + endif() + endforeach() + + set(LIBGAV1_CXX_FLAGS ${cxx_flags}) + endif() + endif() + + if(LIBGAV1_CXX_FLAGS) + list(REMOVE_DUPLICATES LIBGAV1_CXX_FLAGS) + endif() +endmacro() + +# Tests executable linker flags stored in list specified by FLAG_LIST_VAR_NAME, +# adds flags to $LIBGAV1_EXE_LINKER_FLAGS when test passes. Terminates +# configuration when flag check fails. libgav1_set_cxx_flags() must be called +# before calling this macro because it assumes $LIBGAV1_CXX_FLAGS contains only +# valid CXX flags. +# +# libgav1_test_exe_linker_flag(<FLAG_LIST_VAR_NAME <flag list variable)>) +macro(libgav1_test_exe_linker_flag) + unset(link_FLAG_LIST_VAR_NAME) + unset(optional_args) + unset(multi_value_args) + set(single_value_args FLAG_LIST_VAR_NAME) + cmake_parse_arguments(link "${optional_args}" "${single_value_args}" + "${multi_value_args}" ${ARGN}) + + if(NOT link_FLAG_LIST_VAR_NAME) + libgav1_die("libgav1_test_link_flag: FLAG_LIST_VAR_NAME required") + endif() + + libgav1_set_and_stringify(DEST linker_flags SOURCE_VARS + ${link_FLAG_LIST_VAR_NAME}) + + if(LIBGAV1_VERBOSE) + message("EXE LINKER test: all flags: ${linker_flags}") + endif() + + # Tests of $LIBGAV1_CXX_FLAGS have already passed. Include them with the + # linker test. + libgav1_set_and_stringify(DEST CMAKE_REQUIRED_FLAGS SOURCE_VARS + LIBGAV1_CXX_FLAGS) + + # Cache the global exe linker flags. + if(CMAKE_EXE_LINKER_FLAGS) + set(cached_CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + libgav1_set_and_stringify(DEST CMAKE_EXE_LINKER_FLAGS SOURCE + ${linker_flags}) + endif() + + libgav1_set_and_stringify(DEST CMAKE_EXE_LINKER_FLAGS SOURCE ${linker_flags} + ${CMAKE_EXE_LINKER_FLAGS}) + + # Turn off output from check_cxx_source_compiles. Print status directly + # instead since the logging messages from check_cxx_source_compiles can be + # quite confusing. + set(CMAKE_REQUIRED_QUIET TRUE) + + message("--- Running EXE LINKER test for flags: ${linker_flags}") + + unset(linker_flag_test_passed CACHE) + set(libgav1_cxx_main "\nint main() { return 0; }") + check_cxx_source_compiles("${libgav1_cxx_main}" linker_flag_test_passed) + + if(NOT linker_flag_test_passed) + libgav1_die("EXE LINKER test failed.") + endif() + + message("--- Passed EXE LINKER flag test.") + + # Restore cached global exe linker flags. + if(cached_CMAKE_EXE_LINKER_FLAGS) + set(CMAKE_EXE_LINKER_FLAGS cached_CMAKE_EXE_LINKER_FLAGS) + else() + unset(CMAKE_EXE_LINKER_FLAGS) + endif() +endmacro() + +# Runs the libgav1 compiler tests. This macro builds up the list of list var(s) +# that is passed to libgav1_test_cxx_flag(). +# +# Note: libgav1_set_build_definitions() must be called before this macro. +macro(libgav1_set_cxx_flags) + unset(cxx_flag_lists) + + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") + list(APPEND cxx_flag_lists libgav1_base_cxx_flags) + endif() + + # Append clang flags after the base set to allow -Wno* overrides to take + # effect. Some of the base flags may enable a large set of warnings, e.g., + # -Wall. + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + list(APPEND cxx_flag_lists libgav1_clang_cxx_flags) + endif() + + if(MSVC) + list(APPEND cxx_flag_lists libgav1_msvc_cxx_flags) + endif() + + if(LIBGAV1_VERBOSE) + if(cxx_flag_lists) + libgav1_set_and_stringify(DEST cxx_flags SOURCE_VARS ${cxx_flag_lists}) + message("libgav1_set_cxx_flags: internal CXX flags: ${cxx_flags}") + endif() + endif() + + if(LIBGAV1_CXX_FLAGS) + list(APPEND cxx_flag_lists LIBGAV1_CXX_FLAGS) + if(LIBGAV1_VERBOSE) + message("libgav1_set_cxx_flags: user CXX flags: ${LIBGAV1_CXX_FLAGS}") + endif() + endif() + + libgav1_test_cxx_flag(FLAG_LIST_VAR_NAMES ${cxx_flag_lists}) +endmacro() |