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