xref: /aosp_15_r20/external/libgav1/cmake/libgav1_flags.cmake (revision 095378508e87ed692bf8dfeb34008b65b3735891)
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