xref: /aosp_15_r20/external/libgav1/cmake/libgav1_targets.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_GAV1_TARGETS_CMAKE_)
16  return()
17endif() # LIBGAV1_CMAKE_GAV1_TARGETS_CMAKE_
18set(LIBGAV1_CMAKE_GAV1_TARGETS_CMAKE_ 1)
19
20if(LIBGAV1_IDE_FOLDER)
21  set(LIBGAV1_EXAMPLES_IDE_FOLDER "${LIBGAV1_IDE_FOLDER}/examples")
22  set(LIBGAV1_TESTS_IDE_FOLDER "${LIBGAV1_IDE_FOLDER}/tests")
23else()
24  set(LIBGAV1_EXAMPLES_IDE_FOLDER "libgav1_examples")
25  set(LIBGAV1_TESTS_IDE_FOLDER "libgav1_tests")
26endif()
27
28# Resets list variables used to track libgav1 targets.
29macro(libgav1_reset_target_lists)
30  unset(libgav1_targets)
31  unset(libgav1_exe_targets)
32  unset(libgav1_lib_targets)
33  unset(libgav1_objlib_targets)
34  unset(libgav1_sources)
35  unset(libgav1_test_targets)
36endmacro()
37
38# Creates an executable target. The target name is passed as a parameter to the
39# NAME argument, and the sources passed as a parameter to the SOURCES argument:
40# libgav1_add_executable(NAME <name> SOURCES <sources> [optional args])
41#
42# Optional args:
43# cmake-format: off
44#   - OUTPUT_NAME: Override output file basename. Target basename defaults to
45#     NAME.
46#   - TEST: Flag. Presence means treat executable as a test.
47#   - DEFINES: List of preprocessor macro definitions.
48#   - INCLUDES: list of include directories for the target.
49#   - COMPILE_FLAGS: list of compiler flags for the target.
50#   - LINK_FLAGS: List of linker flags for the target.
51#   - OBJLIB_DEPS: List of CMake object library target dependencies.
52#   - LIB_DEPS: List of CMake library dependencies.
53# cmake-format: on
54#
55# Sources passed to this macro are added to $libgav1_test_sources when TEST is
56# specified. Otherwise sources are added to $libgav1_sources.
57#
58# Targets passed to this macro are always added $libgav1_targets. When TEST is
59# specified targets are also added to list $libgav1_test_targets. Otherwise
60# targets are added to $libgav1_exe_targets.
61macro(libgav1_add_executable)
62  unset(exe_TEST)
63  unset(exe_TEST_DEFINES_MAIN)
64  unset(exe_NAME)
65  unset(exe_OUTPUT_NAME)
66  unset(exe_SOURCES)
67  unset(exe_DEFINES)
68  unset(exe_INCLUDES)
69  unset(exe_COMPILE_FLAGS)
70  unset(exe_LINK_FLAGS)
71  unset(exe_OBJLIB_DEPS)
72  unset(exe_LIB_DEPS)
73  set(optional_args TEST)
74  set(single_value_args NAME OUTPUT_NAME)
75  set(multi_value_args SOURCES DEFINES INCLUDES COMPILE_FLAGS LINK_FLAGS
76                       OBJLIB_DEPS LIB_DEPS)
77
78  cmake_parse_arguments(exe "${optional_args}" "${single_value_args}"
79                        "${multi_value_args}" ${ARGN})
80
81  if(LIBGAV1_VERBOSE GREATER 1)
82    message("--------- libgav1_add_executable ---------\n"
83            "exe_TEST=${exe_TEST}\n"
84            "exe_TEST_DEFINES_MAIN=${exe_TEST_DEFINES_MAIN}\n"
85            "exe_NAME=${exe_NAME}\n"
86            "exe_OUTPUT_NAME=${exe_OUTPUT_NAME}\n"
87            "exe_SOURCES=${exe_SOURCES}\n"
88            "exe_DEFINES=${exe_DEFINES}\n"
89            "exe_INCLUDES=${exe_INCLUDES}\n"
90            "exe_COMPILE_FLAGS=${exe_COMPILE_FLAGS}\n"
91            "exe_LINK_FLAGS=${exe_LINK_FLAGS}\n"
92            "exe_OBJLIB_DEPS=${exe_OBJLIB_DEPS}\n"
93            "exe_LIB_DEPS=${exe_LIB_DEPS}\n"
94            "------------------------------------------\n")
95  endif()
96
97  if(NOT (exe_NAME AND exe_SOURCES))
98    message(FATAL_ERROR "libgav1_add_executable: NAME and SOURCES required.")
99  endif()
100
101  list(APPEND libgav1_targets ${exe_NAME})
102  if(exe_TEST)
103    list(APPEND libgav1_test_targets ${exe_NAME})
104    list(APPEND libgav1_test_sources ${exe_SOURCES})
105  else()
106    list(APPEND libgav1_exe_targets ${exe_NAME})
107    list(APPEND libgav1_sources ${exe_SOURCES})
108  endif()
109
110  add_executable(${exe_NAME} ${exe_SOURCES})
111  if(exe_TEST)
112    add_test(NAME ${exe_NAME} COMMAND ${exe_NAME})
113    set_property(TARGET ${exe_NAME} PROPERTY FOLDER ${LIBGAV1_TESTS_IDE_FOLDER})
114  else()
115    set_property(TARGET ${exe_NAME}
116                 PROPERTY FOLDER ${LIBGAV1_EXAMPLES_IDE_FOLDER})
117  endif()
118
119  if(exe_OUTPUT_NAME)
120    set_target_properties(${exe_NAME} PROPERTIES OUTPUT_NAME ${exe_OUTPUT_NAME})
121  endif()
122
123  libgav1_process_intrinsics_sources(TARGET ${exe_NAME} SOURCES ${exe_SOURCES})
124
125  if(exe_DEFINES)
126    target_compile_definitions(${exe_NAME} PRIVATE ${exe_DEFINES})
127  endif()
128
129  if(exe_INCLUDES)
130    target_include_directories(${exe_NAME} PRIVATE ${exe_INCLUDES})
131  endif()
132
133  unset(exe_LIBGAV1_COMPILE_FLAGS)
134  if(exe_TEST)
135    list(FILTER exe_SOURCES INCLUDE REGEX "\\.c$")
136    list(LENGTH exe_SOURCES exe_SOURCES_length)
137    if(exe_SOURCES_length EQUAL 0)
138      set(exe_LIBGAV1_COMPILE_FLAGS ${LIBGAV1_TEST_CXX_FLAGS})
139    else()
140      set(exe_LIBGAV1_COMPILE_FLAGS ${LIBGAV1_TEST_C_FLAGS})
141    endif()
142  else()
143    set(exe_LIBGAV1_COMPILE_FLAGS ${LIBGAV1_CXX_FLAGS})
144  endif()
145
146  if(exe_COMPILE_FLAGS OR exe_LIBGAV1_COMPILE_FLAGS)
147    target_compile_options(${exe_NAME}
148                           PRIVATE ${exe_COMPILE_FLAGS}
149                                   ${exe_LIBGAV1_COMPILE_FLAGS})
150  endif()
151
152  if(exe_LINK_FLAGS OR LIBGAV1_EXE_LINKER_FLAGS)
153    list(APPEND exe_LINK_FLAGS "${LIBGAV1_EXE_LINKER_FLAGS}")
154    if(${CMAKE_VERSION} VERSION_LESS "3.13")
155      # LINK_FLAGS is managed as a string.
156      libgav1_set_and_stringify(SOURCE "${exe_LINK_FLAGS}" DEST exe_LINK_FLAGS)
157      set_target_properties(${exe_NAME}
158                            PROPERTIES LINK_FLAGS "${exe_LINK_FLAGS}")
159    else()
160      target_link_options(${exe_NAME} PRIVATE ${exe_LINK_FLAGS})
161    endif()
162  endif()
163
164  if(exe_OBJLIB_DEPS)
165    foreach(objlib_dep ${exe_OBJLIB_DEPS})
166      target_sources(${exe_NAME} PRIVATE $<TARGET_OBJECTS:${objlib_dep}>)
167    endforeach()
168  endif()
169
170  if(CMAKE_THREAD_LIBS_INIT)
171    list(APPEND exe_LIB_DEPS ${CMAKE_THREAD_LIBS_INIT})
172  endif()
173
174  if(BUILD_SHARED_LIBS AND (MSVC OR WIN32))
175    target_compile_definitions(${exe_NAME} PRIVATE "LIBGAV1_BUILDING_DLL=0")
176  endif()
177
178  if(exe_LIB_DEPS)
179    unset(exe_static)
180    if("${CMAKE_EXE_LINKER_FLAGS} ${LIBGAV1_EXE_LINKER_FLAGS}" MATCHES "static")
181      set(exe_static ON)
182    endif()
183
184    if(exe_static AND CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
185      # Third party dependencies can introduce dependencies on system and test
186      # libraries. Since the target created here is an executable, and CMake
187      # does not provide a method of controlling order of link dependencies,
188      # wrap all of the dependencies of this target in start/end group flags to
189      # ensure that dependencies of third party targets can be resolved when
190      # those dependencies happen to be resolved by dependencies of the current
191      # target.
192      list(INSERT exe_LIB_DEPS 0 -Wl,--start-group)
193      list(APPEND exe_LIB_DEPS -Wl,--end-group)
194    endif()
195    target_link_libraries(${exe_NAME} PRIVATE ${exe_LIB_DEPS})
196  endif()
197endmacro()
198
199# Creates a library target of the specified type. The target name is passed as a
200# parameter to the NAME argument, the type as a parameter to the TYPE argument,
201# and the sources passed as a parameter to the SOURCES argument:
202# libgav1_add_library(NAME <name> TYPE <type> SOURCES <sources> [optional args])
203#
204# Optional args:
205# cmake-format: off
206#   - OUTPUT_NAME: Override output file basename. Target basename defaults to
207#     NAME. OUTPUT_NAME is ignored when BUILD_SHARED_LIBS is enabled and CMake
208#     is generating a build for which MSVC or WIN32 are true. This is to avoid
209#     output basename collisions with DLL import libraries.
210#   - TEST: Flag. Presence means treat library as a test.
211#   - DEFINES: List of preprocessor macro definitions.
212#   - INCLUDES: list of include directories for the target.
213#   - COMPILE_FLAGS: list of compiler flags for the target.
214#   - LINK_FLAGS: List of linker flags for the target.
215#   - OBJLIB_DEPS: List of CMake object library target dependencies.
216#   - LIB_DEPS: List of CMake library dependencies.
217#   - PUBLIC_INCLUDES: List of include paths to export to dependents.
218# cmake-format: on
219#
220# Sources passed to the macro are added to the lists tracking libgav1 sources:
221# cmake-format: off
222#   - When TEST is specified sources are added to $libgav1_test_sources.
223#   - Otherwise sources are added to $libgav1_sources.
224# cmake-format: on
225#
226# Targets passed to this macro are added to the lists tracking libgav1 targets:
227# cmake-format: off
228#   - Targets are always added to $libgav1_targets.
229#   - When the TEST flag is specified, targets are added to
230#     $libgav1_test_targets.
231#   - When TEST is not specified:
232#     - Libraries of type SHARED are added to $libgav1_dylib_targets.
233#     - Libraries of type OBJECT are added to $libgav1_objlib_targets.
234#     - Libraries of type STATIC are added to $libgav1_lib_targets.
235# cmake-format: on
236macro(libgav1_add_library)
237  unset(lib_TEST)
238  unset(lib_NAME)
239  unset(lib_OUTPUT_NAME)
240  unset(lib_TYPE)
241  unset(lib_SOURCES)
242  unset(lib_DEFINES)
243  unset(lib_INCLUDES)
244  unset(lib_COMPILE_FLAGS)
245  unset(lib_LINK_FLAGS)
246  unset(lib_OBJLIB_DEPS)
247  unset(lib_LIB_DEPS)
248  unset(lib_PUBLIC_INCLUDES)
249  set(optional_args TEST)
250  set(single_value_args NAME OUTPUT_NAME TYPE)
251  set(multi_value_args SOURCES DEFINES INCLUDES COMPILE_FLAGS LINK_FLAGS
252                       OBJLIB_DEPS LIB_DEPS PUBLIC_INCLUDES)
253
254  cmake_parse_arguments(lib "${optional_args}" "${single_value_args}"
255                        "${multi_value_args}" ${ARGN})
256
257  if(LIBGAV1_VERBOSE GREATER 1)
258    message("--------- libgav1_add_library ---------\n"
259            "lib_TEST=${lib_TEST}\n"
260            "lib_NAME=${lib_NAME}\n"
261            "lib_OUTPUT_NAME=${lib_OUTPUT_NAME}\n"
262            "lib_TYPE=${lib_TYPE}\n"
263            "lib_SOURCES=${lib_SOURCES}\n"
264            "lib_DEFINES=${lib_DEFINES}\n"
265            "lib_INCLUDES=${lib_INCLUDES}\n"
266            "lib_COMPILE_FLAGS=${lib_COMPILE_FLAGS}\n"
267            "lib_LINK_FLAGS=${lib_LINK_FLAGS}\n"
268            "lib_OBJLIB_DEPS=${lib_OBJLIB_DEPS}\n"
269            "lib_LIB_DEPS=${lib_LIB_DEPS}\n"
270            "lib_PUBLIC_INCLUDES=${lib_PUBLIC_INCLUDES}\n"
271            "---------------------------------------\n")
272  endif()
273
274  if(NOT (lib_NAME AND lib_TYPE AND lib_SOURCES))
275    message(FATAL_ERROR "libgav1_add_library: NAME, TYPE and SOURCES required.")
276  endif()
277
278  list(APPEND libgav1_targets ${lib_NAME})
279  if(lib_TEST)
280    list(APPEND libgav1_test_targets ${lib_NAME})
281    list(APPEND libgav1_test_sources ${lib_SOURCES})
282  else()
283    list(APPEND libgav1_sources ${lib_SOURCES})
284    if(lib_TYPE STREQUAL OBJECT)
285      list(APPEND libgav1_objlib_targets ${lib_NAME})
286    elseif(lib_TYPE STREQUAL SHARED)
287      list(APPEND libgav1_dylib_targets ${lib_NAME})
288    elseif(lib_TYPE STREQUAL STATIC)
289      list(APPEND libgav1_lib_targets ${lib_NAME})
290    else()
291      message(WARNING "libgav1_add_library: Unhandled type: ${lib_TYPE}")
292    endif()
293  endif()
294
295  add_library(${lib_NAME} ${lib_TYPE} ${lib_SOURCES})
296  libgav1_process_intrinsics_sources(TARGET ${lib_NAME} SOURCES ${lib_SOURCES})
297
298  if(lib_OUTPUT_NAME)
299    if(NOT (BUILD_SHARED_LIBS AND (MSVC OR WIN32)))
300      set_target_properties(${lib_NAME}
301                            PROPERTIES OUTPUT_NAME ${lib_OUTPUT_NAME})
302    endif()
303  endif()
304
305  if(lib_DEFINES)
306    target_compile_definitions(${lib_NAME} PRIVATE ${lib_DEFINES})
307  endif()
308
309  if(lib_INCLUDES)
310    target_include_directories(${lib_NAME} PRIVATE ${lib_INCLUDES})
311  endif()
312
313  if(lib_PUBLIC_INCLUDES)
314    target_include_directories(${lib_NAME} PUBLIC ${lib_PUBLIC_INCLUDES})
315  endif()
316
317  if(lib_COMPILE_FLAGS OR LIBGAV1_CXX_FLAGS)
318    target_compile_options(${lib_NAME}
319                           PRIVATE ${lib_COMPILE_FLAGS} ${LIBGAV1_CXX_FLAGS})
320  endif()
321
322  if(lib_LINK_FLAGS)
323    set_target_properties(${lib_NAME} PROPERTIES LINK_FLAGS ${lib_LINK_FLAGS})
324  endif()
325
326  if(lib_OBJLIB_DEPS)
327    foreach(objlib_dep ${lib_OBJLIB_DEPS})
328      target_sources(${lib_NAME} PRIVATE $<TARGET_OBJECTS:${objlib_dep}>)
329    endforeach()
330  endif()
331
332  if(lib_LIB_DEPS)
333    if(lib_TYPE STREQUAL STATIC)
334      set(link_type PUBLIC)
335    else()
336      set(link_type PRIVATE)
337      if(lib_TYPE STREQUAL SHARED AND CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
338        # The libgav1 shared object uses the static libgav1 as input to turn it
339        # into a shared object. Include everything from the static library in
340        # the shared object.
341        if(APPLE)
342          list(INSERT lib_LIB_DEPS 0 -Wl,-force_load)
343        else()
344          list(INSERT lib_LIB_DEPS 0 -Wl,--whole-archive)
345          list(APPEND lib_LIB_DEPS -Wl,--no-whole-archive)
346        endif()
347      endif()
348    endif()
349    target_link_libraries(${lib_NAME} ${link_type} ${lib_LIB_DEPS})
350  endif()
351
352  if(NOT MSVC AND lib_NAME MATCHES "^lib")
353    # Non-MSVC generators prepend lib to static lib target file names. Libgav1
354    # already includes lib in its name. Avoid naming output files liblib*.
355    set_target_properties(${lib_NAME} PROPERTIES PREFIX "")
356  endif()
357
358  if(lib_TYPE STREQUAL SHARED AND NOT MSVC)
359    set_target_properties(${lib_NAME}
360                          PROPERTIES VERSION ${LIBGAV1_SOVERSION} SOVERSION
361                                     ${LIBGAV1_SOVERSION_MAJOR})
362  endif()
363
364  if(BUILD_SHARED_LIBS AND (MSVC OR WIN32))
365    if(lib_TYPE STREQUAL SHARED)
366      target_compile_definitions(${lib_NAME} PRIVATE "LIBGAV1_BUILDING_DLL=1")
367    else()
368      target_compile_definitions(${lib_NAME} PRIVATE "LIBGAV1_BUILDING_DLL=0")
369    endif()
370  endif()
371
372  # Determine if $lib_NAME is a header only target.
373  set(sources_list ${lib_SOURCES})
374  list(FILTER sources_list INCLUDE REGEX cc$)
375  if(NOT sources_list)
376    if(NOT XCODE)
377      # This is a header only target. Tell CMake the link language.
378      set_target_properties(${lib_NAME} PROPERTIES LINKER_LANGUAGE CXX)
379    else()
380      # The Xcode generator ignores LINKER_LANGUAGE. Add a dummy cc file.
381      libgav1_create_dummy_source_file(TARGET ${lib_NAME} BASENAME ${lib_NAME})
382    endif()
383  endif()
384
385  if(lib_TEST)
386    set_property(TARGET ${lib_NAME} PROPERTY FOLDER ${LIBGAV1_TESTS_IDE_FOLDER})
387  else()
388    set(sources_list ${lib_SOURCES})
389    list(FILTER sources_list INCLUDE REGEX examples)
390    if(sources_list)
391      set_property(TARGET ${lib_NAME}
392                   PROPERTY FOLDER ${LIBGAV1_EXAMPLES_IDE_FOLDER})
393    else()
394      set_property(TARGET ${lib_NAME} PROPERTY FOLDER ${LIBGAV1_IDE_FOLDER})
395    endif()
396  endif()
397endmacro()
398