• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2# Copyright (C) 2023 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may not
5# use this file except in compliance with the License. You may obtain a copy of
6# the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations under
14# the License.
15#
16
17cmake_minimum_required(VERSION 3.13)
18
19project(libuhdr VERSION 1.0 LANGUAGES C CXX
20        DESCRIPTION "Library for encoding and decoding ultrahdr images")
21
22###########################################################
23# Detect system
24###########################################################
25if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
26elseif(${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
27elseif(${CMAKE_SYSTEM_NAME} MATCHES "Android")
28elseif(WIN32)
29elseif(APPLE)
30else()
31  message(FATAL_ERROR "Platform ${CMAKE_SYSTEM_NAME} not recognized")
32endif()
33
34if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*")
35  if(CMAKE_SIZEOF_VOID_P EQUAL 8)
36    set(ARCH "x86_64")
37  else()
38    set(ARCH "x86")
39  endif()
40elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*")
41  set(ARCH "x86")
42elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*|arm64.*|ARM64.*)")
43  if(CMAKE_SIZEOF_VOID_P EQUAL 8)
44    set(ARCH "aarch64")
45  else()
46    set(ARCH "arm")
47  endif()
48elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)")
49  set(ARCH "arm")
50else()
51  message(FATAL_ERROR "Architecture: ${CMAKE_SYSTEM_PROCESSOR} not recognized")
52endif()
53
54###########################################################
55# Directories
56###########################################################
57set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib)
58set(THIRD_PARTY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party)
59set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests)
60set(BENCHMARK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/benchmark)
61set(FUZZERS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/fuzzer)
62set(EXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples)
63set(EXPORT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
64
65if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
66  message(WARNING "Selected in-source build. Preferably, create a build/ directory and build from there.")
67endif()
68
69###########################################################
70# Options
71###########################################################
72get_cmake_property(IS_MULTI GENERATOR_IS_MULTI_CONFIG)
73if(NOT IS_MULTI)
74  if(NOT CMAKE_BUILD_TYPE)
75    message(STATUS "No build type chosen, selecting Release")
76    set(CMAKE_BUILD_TYPE "Release" CACHE STRING "The type of build: Debug Release MinSizeRel RelWithDebInfo." FORCE)
77  endif()
78endif()
79
80if(NOT DEFINED BUILD_SHARED_LIBS)
81  message(STATUS "No target type chosen, selecting Shared")
82  option(BUILD_SHARED_LIBS "Build shared libraries" TRUE)
83endif()
84
85function(option_if_not_defined name description default)
86  if(NOT DEFINED ${name})
87    option(${name} ${description} ${default})
88  endif()
89endfunction()
90
91option_if_not_defined(UHDR_BUILD_EXAMPLES "Build examples " TRUE)
92option_if_not_defined(UHDR_BUILD_TESTS "Build unit tests " FALSE)
93option_if_not_defined(UHDR_BUILD_BENCHMARK "Build benchmark " FALSE)
94option_if_not_defined(UHDR_BUILD_FUZZERS "Build fuzzers " FALSE)
95option_if_not_defined(UHDR_BUILD_DEPS "Build deps and not use pre-installed packages " FALSE)
96option_if_not_defined(UHDR_ENABLE_LOGS "Build with verbose logging " FALSE)
97option_if_not_defined(UHDR_ENABLE_INSTALL "Add install and uninstall targets for libuhdr package" TRUE)
98option_if_not_defined(UHDR_ENABLE_INTRINSICS "Build with intrinsics " TRUE)
99
100# pre-requisites
101if(UHDR_BUILD_TESTS AND EMSCRIPTEN)
102  message(FATAL_ERROR "Building tests not supported in Web Assembly Path")
103endif()
104
105if(UHDR_BUILD_BENCHMARK AND WIN32)
106  message(FATAL_ERROR "Building benchmarks not supported in Windows")
107endif()
108
109if(UHDR_BUILD_BENCHMARK AND EMSCRIPTEN)
110  message(FATAL_ERROR "Building benchmarks not supported in Web Assembly Path")
111endif()
112
113# side effects
114if(NOT BUILD_SHARED_LIBS AND UHDR_ENABLE_INSTALL)
115  set(UHDR_ENABLE_INSTALL FALSE) # libjpeg dependency is correctly mentioned as Requires.private in libuhdr.pc
116                                 # `pkg-config --libs libuhdr` returns -L/usr/local/lib -luhdr
117                                 # `pkg-config --libs --static libuhdr` returns -L/usr/local/lib -luhdr -ljpeg
118                                 # Not many build systems pass `--static` argument to pkg-config
119                                 # So if pc file to work universally for static and shared libs its best to
120                                 # elevate libjpeg dependency from Requires.private to Requires.
121                                 # But, for now, disable install and uninstall targets if target type is static.
122  message(STATUS "Install and uninstall targets - Disabled")
123endif()
124
125if(CMAKE_CROSSCOMPILING AND UHDR_ENABLE_INSTALL)
126  set(UHDR_ENABLE_INSTALL FALSE) # disable install and uninstall targets during cross compilation.
127  message(STATUS "Install and uninstall targets - Disabled")
128endif()
129
130if(UHDR_BUILD_FUZZERS AND NOT UHDR_BUILD_DEPS)
131  set(UHDR_BUILD_DEPS TRUE) # For fuzz testing its best to build all dependencies from source.
132                            # This is to instrument dependency libs as well.
133  message(STATUS "Building dependencies from source - Enabled")
134endif()
135
136if(DEFINED UHDR_SANITIZE_OPTIONS AND NOT UHDR_BUILD_DEPS)
137  set(UHDR_BUILD_DEPS TRUE) # If sanitize options are enabled, its best to build all dependencies from source.
138                            # This is to instrument dependency libs as well.
139  message(STATUS "Building dependencies from source - Enabled")
140endif()
141
142if(UHDR_BUILD_DEPS AND UHDR_ENABLE_INSTALL)
143  set(UHDR_ENABLE_INSTALL FALSE) # If dependencies are not chosen from installed packages but are built
144                                 # from source, its best to disallow system wide installation of
145                                 # uhdr to avoid possible abi/api conflicts.
146  message(STATUS "Install and uninstall targets - Disabled")
147endif()
148
149###########################################################
150# Compile flags
151###########################################################
152set(CMAKE_CXX_STANDARD 17)
153set(CMAKE_CXX_STANDARD_REQUIRED ON)
154set(CMAKE_CXX_EXTENSIONS OFF)
155if(BUILD_SHARED_LIBS)
156  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
157  set(CMAKE_CXX_VISIBILITY_PRESET hidden)
158  set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)
159  add_compile_options(-DUHDR_BUILDING_SHARED_LIBRARY)
160endif()
161if(UHDR_ENABLE_LOGS)
162  add_compile_options(-DLOG_NDEBUG)
163endif()
164if(UHDR_ENABLE_INTRINSICS)
165  add_compile_options(-DUHDR_ENABLE_INTRINSICS)
166endif()
167
168include(CheckCXXCompilerFlag)
169function(CheckCompilerOption opt res)
170  set(CMAKE_REQUIRED_FLAGS ${opt})
171  check_cxx_compiler_flag(${opt} ${res})
172  unset(CMAKE_REQUIRED_FLAGS)
173  if(NOT ${res})
174    message(FATAL_ERROR "Unsupported compiler option(s) ${opt}")
175  endif()
176endfunction(CheckCompilerOption)
177
178if(DEFINED UHDR_SANITIZE_OPTIONS)
179  CheckCompilerOption("-fsanitize=${UHDR_SANITIZE_OPTIONS}" SUPPORTS_SAN_OPTIONS)
180  add_compile_options(-fsanitize=${UHDR_SANITIZE_OPTIONS})
181  add_link_options(-fsanitize=${UHDR_SANITIZE_OPTIONS})
182endif()
183
184if(UHDR_BUILD_FUZZERS)
185  CheckCompilerOption("-fsanitize=fuzzer-no-link" fuzz)
186  add_compile_options(-fsanitize=fuzzer-no-link)
187endif()
188
189if(MSVC)
190  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
191  # Disable specific warnings
192  # TODO: None of these should be disabled, but for now, for a warning-free msvc build these are
193  # added. fix the warnings and remove these filters
194  add_compile_options(/wd4244) # conversion from 'type1' to 'type2', possible loss of data
195  add_compile_options(/wd4267) # conversion from 'size_t' to 'type' possible loss of data
196  add_compile_options(/wd4305) # truncation from 'double' to 'float'
197  add_compile_options(/wd4838) # conversion from 'type1' to 'type2' requires a narrowing conversion
198  add_compile_options(/wd26812) # Prefer enum class over enum
199elseif(EMSCRIPTEN)
200else()
201  add_compile_options(-ffunction-sections)
202  add_compile_options(-fdata-sections)
203  add_compile_options(-fomit-frame-pointer)
204  add_compile_options(-ffp-contract=fast)
205  if(ARCH STREQUAL "x86")
206    add_compile_options(-m32)
207    add_compile_options(-march=i386)
208    add_compile_options(-mtune=generic)
209  elseif(ARCH STREQUAL "x86_64")
210    add_compile_options(-m64)
211    add_compile_options(-march=x86-64)
212    add_compile_options(-mtune=generic)
213  elseif(ARCH STREQUAL "arm")
214    add_compile_options(-march=armv7-a)
215    add_compile_options(-marm)
216    add_compile_options(-mfloat-abi=hard)
217    add_compile_options(-mfpu=vfpv3)
218  elseif(ARCH STREQUAL "aarch64")
219    add_compile_options(-march=armv8-a)
220  endif()
221endif()
222
223###########################################################
224# Utils
225###########################################################
226# copied from https://github.com/google/shaderc/blob/main/cmake/utils.cmake
227macro(get_transitive_static_libs target out_list)
228  if(TARGET ${target})
229    get_target_property(target_type ${target} TYPE)
230    if(target_type STREQUAL "STATIC_LIBRARY")
231      list(INSERT ${out_list} 0 ${target})
232      get_target_property(libs ${target} LINK_LIBRARIES)
233      if(libs)
234        foreach(lib ${libs})
235          get_transitive_static_libs(${lib} ${out_list})
236        endforeach()
237      endif()
238    endif()
239  endif()
240endmacro()
241
242# combine a list of static libraries in to a single library
243function(combine_static_libs target output_target)
244  set(all_libs_list "")
245  get_transitive_static_libs(${target} all_libs_list)
246  foreach(lib IN LISTS all_libs_list)
247    target_sources(${output_target} PRIVATE $<TARGET_OBJECTS:${lib}>)
248  endforeach()
249endfunction()
250
251###########################################################
252# Dependencies
253###########################################################
254if(${CMAKE_SYSTEM_NAME} MATCHES "Android")
255  find_library(log-lib log)
256endif()
257
258# Threads
259set(CMAKE_THREAD_PREFER_PTHREAD ON)
260set(THREADS_PREFER_PTHREAD_FLAG ON)
261find_package(Threads REQUIRED)
262
263include(ExternalProject)
264
265get_directory_property(UHDR_COMPILE_FLAGS COMPILE_OPTIONS)
266string (REPLACE ";" " " UHDR_COMPILE_FLAGS_STR "${UHDR_COMPILE_FLAGS}")
267set(UHDR_CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${UHDR_COMPILE_FLAGS_STR}")
268set(UHDR_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${UHDR_COMPILE_FLAGS_STR}")
269set(UHDR_CMAKE_ARGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER})
270list(APPEND UHDR_CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
271list(APPEND UHDR_CMAKE_ARGS -DCMAKE_C_FLAGS=${UHDR_CMAKE_C_FLAGS})
272list(APPEND UHDR_CMAKE_ARGS -DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG})
273list(APPEND UHDR_CMAKE_ARGS -DCMAKE_C_FLAGS_RELEASE=${CMAKE_C_FLAGS_RELEASE})
274list(APPEND UHDR_CMAKE_ARGS -DCMAKE_C_FLAGS_MINSIZEREL=${CMAKE_C_FLAGS_MINSIZEREL})
275list(APPEND UHDR_CMAKE_ARGS -DCMAKE_C_FLAGS_RELWITHDEBINFO=${CMAKE_C_FLAGS_RELWITHDEBINFO})
276list(APPEND UHDR_CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER})
277list(APPEND UHDR_CMAKE_ARGS -DCMAKE_CXX_FLAGS=${UHDR_CMAKE_CXX_FLAGS})
278list(APPEND UHDR_CMAKE_ARGS -DCMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG})
279list(APPEND UHDR_CMAKE_ARGS -DCMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE})
280list(APPEND UHDR_CMAKE_ARGS -DCMAKE_CXX_FLAGS_MINSIZEREL=${CMAKE_CXX_FLAGS_MINSIZEREL})
281list(APPEND UHDR_CMAKE_ARGS -DCMAKE_CXX_FLAGS_RELWITHDEBINFO=${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
282if(BUILD_SHARED_LIBS)
283  list(APPEND UHDR_CMAKE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE=ON)
284endif()
285if(MSVC AND UHDR_BUILD_TESTS)
286  list(APPEND UHDR_CMAKE_ARGS "-Dgtest_force_shared_crt=ON")
287endif()
288if(DEFINED CMAKE_TOOLCHAIN_FILE)
289  list(APPEND UHDR_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_TOOLCHAIN_FILE})
290endif()
291if(DEFINED UHDR_ANDROID_NDK_PATH)
292  list(APPEND UHDR_CMAKE_ARGS -DUHDR_ANDROID_NDK_PATH=${UHDR_ANDROID_NDK_PATH})
293endif()
294
295# libjpeg-turbo
296if(NOT UHDR_BUILD_DEPS)
297  find_package(JPEG QUIET)
298  if(NOT JPEG_FOUND)
299    message(FATAL_ERROR "Could NOT find JPEG (missing: JPEG_LIBRARIES JPEG_INCLUDE_DIRS),\
300                         retry after installing JPEG library at sysroot or try 'cmake -DUHDR_BUILD_DEPS=1'")
301  else()
302    message(STATUS "Found JPEG: ${JPEG_LIBRARIES} (found version \"${JPEG_VERSION}\")")
303  endif()
304endif()
305
306if(NOT JPEG_FOUND)
307  set(JPEGTURBO_TARGET_NAME turbojpeg)
308  set(JPEGTURBO_PREFIX_DIR ${CMAKE_CURRENT_BINARY_DIR}/${JPEGTURBO_TARGET_NAME})
309  set(JPEGTURBO_SOURCE_DIR ${THIRD_PARTY_DIR}/${JPEGTURBO_TARGET_NAME})
310  set(JPEGTURBO_BINARY_DIR ${JPEGTURBO_PREFIX_DIR}/src/${JPEGTURBO_TARGET_NAME}-build)
311  set(JPEG_INCLUDE_DIRS ${JPEGTURBO_SOURCE_DIR} ${JPEGTURBO_BINARY_DIR})
312  if(MSVC)
313    set(JPEG_LIB ${CMAKE_STATIC_LIBRARY_PREFIX}jpeg-static${CMAKE_STATIC_LIBRARY_SUFFIX})
314  else()
315    set(JPEG_LIB ${CMAKE_STATIC_LIBRARY_PREFIX}jpeg${CMAKE_STATIC_LIBRARY_SUFFIX})
316  endif()
317  if(IS_MULTI)
318    set(JPEG_LIB_PREFIX ${JPEGTURBO_BINARY_DIR}/$<CONFIG>/)
319  else()
320    set(JPEG_LIB_PREFIX ${JPEGTURBO_BINARY_DIR}/)
321  endif()
322  set(JPEG_LIBRARIES ${JPEG_LIB_PREFIX}${JPEG_LIB})
323  if(EMSCRIPTEN)
324    ExternalProject_Add(${JPEGTURBO_TARGET_NAME}
325        GIT_REPOSITORY https://github.com/libjpeg-turbo/libjpeg-turbo.git
326        GIT_TAG 3.0.1
327        PREFIX ${JPEGTURBO_PREFIX_DIR}
328        SOURCE_DIR ${JPEGTURBO_SOURCE_DIR}
329        BINARY_DIR ${JPEGTURBO_BINARY_DIR}
330        CONFIGURE_COMMAND emcmake cmake ${JPEGTURBO_SOURCE_DIR}
331                          -DENABLE_SHARED=0 -DWITH_SIMD=0
332        BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config $<CONFIG> --target jpeg-static
333        BUILD_BYPRODUCTS ${JPEG_LIBRARIES}
334        INSTALL_COMMAND ""
335    )
336  else()
337    ExternalProject_Add(${JPEGTURBO_TARGET_NAME}
338        GIT_REPOSITORY https://github.com/libjpeg-turbo/libjpeg-turbo.git
339        GIT_TAG 3.0.1
340        PREFIX ${JPEGTURBO_PREFIX_DIR}
341        SOURCE_DIR ${JPEGTURBO_SOURCE_DIR}
342        BINARY_DIR ${JPEGTURBO_BINARY_DIR}
343        BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config $<CONFIG> --target jpeg-static
344        CMAKE_ARGS ${UHDR_CMAKE_ARGS} -DENABLE_SHARED=0
345        BUILD_BYPRODUCTS ${JPEG_LIBRARIES}
346        INSTALL_COMMAND ""
347    )
348  endif()
349endif()
350
351if(UHDR_BUILD_TESTS)
352  # gtest and gmock
353  set(GTEST_TARGET_NAME googletest)
354  set(GTEST_PREFIX_DIR ${CMAKE_CURRENT_BINARY_DIR}/${GTEST_TARGET_NAME})
355  set(GTEST_SOURCE_DIR ${THIRD_PARTY_DIR}/${GTEST_TARGET_NAME})
356  set(GTEST_BINARY_DIR ${GTEST_PREFIX_DIR}/src/${GTEST_TARGET_NAME}-build)
357  set(GTEST_INCLUDE_DIRS
358      ${GTEST_SOURCE_DIR}/googletest/include
359      ${GTEST_SOURCE_DIR}/googlemock/include)
360  set(GTEST_LIB ${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX})
361  set(GTEST_LIB_MAIN ${CMAKE_STATIC_LIBRARY_PREFIX}gtest_main${CMAKE_STATIC_LIBRARY_SUFFIX})
362  if(IS_MULTI)
363    set(GTEST_LIB_PREFIX ${GTEST_BINARY_DIR}/lib/$<CONFIG>/)
364  else()
365    set(GTEST_LIB_PREFIX ${GTEST_BINARY_DIR}/lib/)
366  endif()
367  set(GTEST_BOTH_LIBRARIES ${GTEST_LIB_PREFIX}${GTEST_LIB} ${GTEST_LIB_PREFIX}${GTEST_LIB_MAIN})
368  ExternalProject_Add(${GTEST_TARGET_NAME}
369      GIT_REPOSITORY https://github.com/google/googletest
370      GIT_TAG v1.14.0
371      PREFIX ${GTEST_PREFIX_DIR}
372      SOURCE_DIR ${GTEST_SOURCE_DIR}
373      BINARY_DIR ${GTEST_BINARY_DIR}
374      CMAKE_ARGS ${UHDR_CMAKE_ARGS}
375      BUILD_BYPRODUCTS ${GTEST_BOTH_LIBRARIES}
376      INSTALL_COMMAND ""
377  )
378endif()
379
380if(UHDR_BUILD_BENCHMARK)
381  # benchmark
382  set(BM_TARGET_NAME benchmark)
383  set(BM_PREFIX_DIR ${CMAKE_CURRENT_BINARY_DIR}/${BM_TARGET_NAME})
384  set(BM_SOURCE_DIR ${THIRD_PARTY_DIR}/${BM_TARGET_NAME})
385  set(BM_BINARY_DIR ${BM_PREFIX_DIR}/src/${BM_TARGET_NAME}-build)
386  set(BENCHMARK_INCLUDE_DIR ${BM_SOURCE_DIR}/include)
387  set(BM_LIB ${CMAKE_STATIC_LIBRARY_PREFIX}benchmark${CMAKE_STATIC_LIBRARY_SUFFIX})
388  set(BM_LIB_MAIN ${CMAKE_STATIC_LIBRARY_PREFIX}benchmark_main${CMAKE_STATIC_LIBRARY_SUFFIX})
389  if(IS_MULTI)
390    set(BM_LIB_PREFIX ${BM_BINARY_DIR}/src/$<CONFIG>/)
391  else()
392    set(BM_LIB_PREFIX ${BM_BINARY_DIR}/src/)
393  endif()
394  set(BENCHMARK_LIBRARIES ${BM_LIB_PREFIX}${BM_LIB} ${BM_LIB_PREFIX}${BM_LIB_MAIN})
395  ExternalProject_Add(${BM_TARGET_NAME}
396      GIT_REPOSITORY https://github.com/google/benchmark.git
397      GIT_TAG v1.8.3
398      PREFIX ${BM_PREFIX_DIR}
399      SOURCE_DIR ${BM_SOURCE_DIR}
400      BINARY_DIR ${BM_BINARY_DIR}
401      CMAKE_ARGS ${UHDR_CMAKE_ARGS}
402                 -DBENCHMARK_ENABLE_TESTING=OFF
403                 -DBENCHMARK_DOWNLOAD_DEPENDENCIES=OFF
404      BUILD_BYPRODUCTS ${BENCHMARK_LIBRARIES}
405      INSTALL_COMMAND ""
406  )
407endif()
408
409set_property(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
410    ${JPEGTURBO_BINARY_DIR} ${GTEST_BINARY_DIR} ${BM_BINARY_DIR})
411
412###########################################################
413# File Lists
414###########################################################
415file(GLOB UHDR_CORE_SRCS_LIST "${SOURCE_DIR}/src/*.cpp")
416if(UHDR_ENABLE_INTRINSICS)
417  if(ARCH STREQUAL "arm" OR ARCH STREQUAL "aarch64")
418    file(GLOB UHDR_CORE_NEON_SRCS_LIST "${SOURCE_DIR}/src/dsp/arm/*.cpp")
419    list(APPEND UHDR_CORE_SRCS_LIST ${UHDR_CORE_NEON_SRCS_LIST})
420  endif()
421endif()
422file(GLOB UHDR_TEST_SRCS_LIST "${TESTS_DIR}/*.cpp")
423file(GLOB UHDR_BM_SRCS_LIST "${BENCHMARK_DIR}/*.cpp")
424file(GLOB IMAGE_IO_SRCS_LIST "${THIRD_PARTY_DIR}/image_io/src/**/*.cc")
425
426set(PRIVATE_INCLUDE_DIR ${SOURCE_DIR}/include/ ${JPEG_INCLUDE_DIRS})
427set(COMMON_LIBS_LIST ${JPEG_LIBRARIES} Threads::Threads)
428
429###########################################################
430# Targets
431###########################################################
432set(IMAGEIO_TARGET_NAME image_io)
433add_library(${IMAGEIO_TARGET_NAME} STATIC ${IMAGE_IO_SRCS_LIST})
434target_include_directories(${IMAGEIO_TARGET_NAME} PRIVATE
435  "${THIRD_PARTY_DIR}/image_io/includes"
436  "${THIRD_PARTY_DIR}/image_io/src/modp_b64"
437  "${THIRD_PARTY_DIR}/image_io/src/modp_b64/modp_b64")
438
439set(UHDR_CORE_LIB_NAME core)
440add_library(${UHDR_CORE_LIB_NAME} STATIC ${UHDR_CORE_SRCS_LIST})
441if(NOT JPEG_FOUND)
442  add_dependencies(${UHDR_CORE_LIB_NAME} ${JPEGTURBO_TARGET_NAME})
443endif()
444if(NOT MSVC)
445  target_compile_options(${UHDR_CORE_LIB_NAME} PRIVATE -Wall -Wextra -Wshadow)
446endif()
447target_include_directories(${UHDR_CORE_LIB_NAME} PRIVATE
448  ${PRIVATE_INCLUDE_DIR}
449  "${THIRD_PARTY_DIR}/image_io/includes/"
450)
451target_include_directories(${UHDR_CORE_LIB_NAME} PUBLIC ${EXPORT_INCLUDE_DIR})
452if(${CMAKE_SYSTEM_NAME} MATCHES "Android")
453  target_link_libraries(${UHDR_CORE_LIB_NAME} PUBLIC ${log-lib})
454endif()
455target_link_libraries(${UHDR_CORE_LIB_NAME} PRIVATE ${COMMON_LIBS_LIST} ${IMAGEIO_TARGET_NAME})
456
457if(UHDR_BUILD_EXAMPLES)
458  add_executable(ultrahdr_app "${EXAMPLES_DIR}/ultrahdr_app.cpp")
459  add_dependencies(ultrahdr_app ${UHDR_CORE_LIB_NAME})
460  if(UHDR_BUILD_FUZZERS)
461    target_link_options(ultrahdr_app PRIVATE -fsanitize=fuzzer-no-link)
462  endif()
463  target_link_libraries(ultrahdr_app PRIVATE ${UHDR_CORE_LIB_NAME})
464endif()
465
466if(UHDR_BUILD_TESTS OR UHDR_BUILD_BENCHMARK)
467  include(CTest)
468  if(WIN32)
469    file(COPY "${TESTS_DIR}/data/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/data")
470  else()
471    execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink
472      "${TESTS_DIR}/data/" "${CMAKE_CURRENT_BINARY_DIR}/data"
473      RESULT_VARIABLE result
474      ERROR_VARIABLE errorinfo)
475    string(FIND "${errorinfo}" "error" errorstatus)
476    if(result GREATER 0 OR errorstatus GREATER -1)
477      message(FATAL_ERROR "Creating sym link failed with info ${errorinfo}")
478    endif()
479  endif()
480endif()
481
482if(UHDR_BUILD_TESTS)
483  add_executable(ultrahdr_unit_test ${UHDR_TEST_SRCS_LIST})
484  add_dependencies(ultrahdr_unit_test ${GTEST_TARGET_NAME} ${UHDR_CORE_LIB_NAME})
485  target_include_directories(ultrahdr_unit_test PRIVATE
486    ${PRIVATE_INCLUDE_DIR}
487    ${GTEST_INCLUDE_DIRS}
488  )
489  if(UHDR_BUILD_FUZZERS)
490    target_link_options(ultrahdr_unit_test PRIVATE -fsanitize=fuzzer-no-link)
491  endif()
492  target_link_libraries(ultrahdr_unit_test ${UHDR_CORE_LIB_NAME} ${GTEST_BOTH_LIBRARIES})
493  add_test(NAME UHDRUnitTests, COMMAND ultrahdr_unit_test)
494endif()
495
496if(UHDR_BUILD_BENCHMARK)
497  add_executable(ultrahdr_bm ${UHDR_BM_SRCS_LIST})
498  add_dependencies(ultrahdr_bm ${BM_TARGET_NAME} ${UHDR_CORE_LIB_NAME})
499  target_include_directories(ultrahdr_bm PRIVATE
500    ${PRIVATE_INCLUDE_DIR}
501    ${BENCHMARK_INCLUDE_DIR}
502  )
503  if(UHDR_BUILD_FUZZERS)
504    target_link_options(ultrahdr_bm PRIVATE -fsanitize=fuzzer-no-link)
505  endif()
506  target_link_libraries(ultrahdr_bm ${UHDR_CORE_LIB_NAME} ${BENCHMARK_LIBRARIES})
507
508  set(RES_FILE "${TESTS_DIR}/data/UltrahdrBenchmarkTestRes-1.0.zip")
509  set(RES_FILE_MD5SUM "96651c5c07505c37aa017c57f480e6c1")
510  set(GET_RES_FILE TRUE)
511  if(EXISTS ${RES_FILE})
512    file(MD5 ${RES_FILE} CURR_MD5_SUM)
513    if(CURR_MD5_SUM STREQUAL RES_FILE_MD5SUM)
514      message("Zip File already exists: " ${RES_FILE})
515      set(GET_RES_FILE FALSE)
516    else()
517      file(REMOVE "${RES_FILE}")
518    endif()
519  endif()
520
521  if(GET_RES_FILE)
522    message("-- Downloading benchmark test resources")
523    set(RES_URL "https://storage.googleapis.com/android_media/external/libultrahdr/benchmark/UltrahdrBenchmarkTestRes-1.0.zip")
524    file(DOWNLOAD ${RES_URL} ${RES_FILE} STATUS result EXPECTED_MD5 ${RES_FILE_MD5SUM})
525    list(GET result 0 retval)
526    if(retval)
527      file(REMOVE "${RES_FILE}")
528      list(GET result 0 errcode)
529      list(GET result 1 info)
530      message(FATAL_ERROR "Error downloading ${RES_URL}: ${info} (${errcode})")
531    endif()
532  endif()
533  message("-- Extracting benchmark test resources")
534  execute_process(COMMAND "${CMAKE_COMMAND}" -E tar xf "${RES_FILE}"
535      WORKING_DIRECTORY "${TESTS_DIR}/data/"
536      RESULT_VARIABLE result
537      ERROR_VARIABLE errorinfo)
538  string(FIND "${errorinfo}" "error" errorstatus)
539  if(result GREATER 0 OR errorstatus GREATER -1)
540    message(FATAL_ERROR "Extracting benchmark test resources failed with info ${errorinfo}")
541  endif()
542endif()
543
544if(UHDR_BUILD_FUZZERS)
545  add_executable(ultrahdr_enc_fuzzer ${FUZZERS_DIR}/ultrahdr_enc_fuzzer.cpp)
546  add_dependencies(ultrahdr_enc_fuzzer ${UHDR_CORE_LIB_NAME})
547  target_include_directories(ultrahdr_enc_fuzzer PRIVATE ${PRIVATE_INCLUDE_DIR})
548  if(DEFINED ENV{LIB_FUZZING_ENGINE})
549    target_link_options(ultrahdr_enc_fuzzer PRIVATE $ENV{LIB_FUZZING_ENGINE})
550  else()
551    target_link_options(ultrahdr_enc_fuzzer PRIVATE -fsanitize=fuzzer)
552  endif()
553  target_link_libraries(ultrahdr_enc_fuzzer ${UHDR_CORE_LIB_NAME})
554
555  add_executable(ultrahdr_dec_fuzzer ${FUZZERS_DIR}/ultrahdr_dec_fuzzer.cpp)
556  add_dependencies(ultrahdr_dec_fuzzer ${UHDR_CORE_LIB_NAME})
557  target_include_directories(ultrahdr_dec_fuzzer PRIVATE ${PRIVATE_INCLUDE_DIR})
558  if(DEFINED ENV{LIB_FUZZING_ENGINE})
559    target_link_options(ultrahdr_dec_fuzzer PRIVATE $ENV{LIB_FUZZING_ENGINE})
560  else()
561    target_link_options(ultrahdr_dec_fuzzer PRIVATE -fsanitize=fuzzer)
562  endif()
563  target_link_libraries(ultrahdr_dec_fuzzer ${UHDR_CORE_LIB_NAME})
564endif()
565
566set(UHDR_TARGET_NAME uhdr)
567add_library(${UHDR_TARGET_NAME})
568add_dependencies(${UHDR_TARGET_NAME} ${UHDR_CORE_LIB_NAME})
569target_link_libraries(${UHDR_TARGET_NAME} PRIVATE ${JPEG_LIBRARIES})
570set_target_properties(${UHDR_TARGET_NAME} PROPERTIES PUBLIC_HEADER ultrahdr_api.h)
571combine_static_libs(${UHDR_CORE_LIB_NAME} ${UHDR_TARGET_NAME})
572
573if(UHDR_ENABLE_INSTALL)
574  if(NOT(MSVC OR XCODE))
575    include(GNUInstallDirs)
576
577    # pkg-config: libuhdr.pc
578    configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/libuhdr.pc.in"
579                   "${CMAKE_CURRENT_BINARY_DIR}/libuhdr.pc" @ONLY NEWLINE_STYLE UNIX)
580    install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libuhdr.pc"
581            DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
582    install(TARGETS ${UHDR_TARGET_NAME}
583            RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
584            LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
585            ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
586            PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
587    if(BUILD_SHARED_LIBS)
588      if(APPLE)
589        install(CODE "message(STATUS \"You may need to add path \"
590                                     \"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/ \"
591                                     \"to DYLD_FALLBACK_LIBRARY_PATH if binaries are unable to load uhdr library \n\"
592                                     \"e.g. export DYLD_FALLBACK_LIBRARY_PATH=$DYLD_FALLBACK_LIBRARY_PATH:${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/ \")")
593      elseif(UNIX)
594        install(CODE "message(STATUS \"You may need to add path \"
595                                     \"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/ \"
596                                     \"to LD_LIBRARY_PATH if binaries are unable to load uhdr library \n\"
597                                     \"e.g. export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/ \")")
598      endif()
599    endif()
600
601    configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
602                   "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
603    add_custom_target(uninstall
604      COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
605  endif()
606endif()
607