# Copyright 2019 Joe Drago. All rights reserved. # SPDX-License-Identifier: BSD-2-Clause cmake_minimum_required(VERSION 3.13) # New in CMake version 3.15. MSVC warning flags are not in CMAKE__FLAGS by default. if(POLICY CMP0092) cmake_policy(SET CMP0092 NEW) endif() # Specify search path for CMake modules to be loaded by include() and find_package() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") project(libavif LANGUAGES C VERSION 1.0.3) # Set C99 as the default set(CMAKE_C_STANDARD 99) # SOVERSION scheme: MAJOR.MINOR.PATCH # If there was an incompatible interface change: # Increment MAJOR. Set MINOR and PATCH to 0 # If there was a compatible interface change: # Increment MINOR. Set PATCH to 0 # If the source code was changed, but there were no interface changes: # Increment PATCH. set(LIBRARY_VERSION_MAJOR 16) set(LIBRARY_VERSION_MINOR 0) set(LIBRARY_VERSION_PATCH 3) set(LIBRARY_VERSION "${LIBRARY_VERSION_MAJOR}.${LIBRARY_VERSION_MINOR}.${LIBRARY_VERSION_PATCH}") set(LIBRARY_SOVERSION ${LIBRARY_VERSION_MAJOR}) option(BUILD_SHARED_LIBS "Build shared avif library" ON) option(AVIF_ENABLE_WERROR "Treat all compiler warnings as errors" ON) option(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R "Enable experimental YCgCo-R matrix code" OFF) option(AVIF_CODEC_AOM "Use the AOM codec for encoding/decoding (see AVIF_CODEC_AOM_DECODE/AVIF_CODEC_AOM_ENCODE)" OFF) option(AVIF_CODEC_DAV1D "Use the dav1d codec for decoding" OFF) option(AVIF_CODEC_LIBGAV1 "Use the libgav1 codec for decoding" OFF) option(AVIF_CODEC_RAV1E "Use the rav1e codec for encoding" OFF) option(AVIF_CODEC_SVT "Use the SVT-AV1 codec for encoding" OFF) option(AVIF_CODEC_AVM "Use the AVM (AV2) codec for encoding/decoding (EXPERIMENTAL)" OFF) # These options allow libavif to only link against / use libaom's encoder or decoder, instead of being forced to use both option(AVIF_CODEC_AOM_DECODE "if AVIF_CODEC_AOM is on, use/offer libaom's decoder" ON) option(AVIF_CODEC_AOM_ENCODE "if AVIF_CODEC_AOM is on, use/offer libaom's encoder" ON) option(AVIF_LOCAL_AOM "Build the AOM codec by providing your own copy of the repo in ext/aom (see Local Builds in README)" OFF) option(AVIF_LOCAL_DAV1D "Build the dav1d codec by providing your own copy of the repo in ext/dav1d (see Local Builds in README)" OFF ) option(AVIF_LOCAL_LIBGAV1 "Build the libgav1 codec by providing your own copy of the repo in ext/libgav1 (see Local Builds in README)" OFF ) option(AVIF_LOCAL_RAV1E "Build the rav1e codec by providing your own copy of the repo in ext/rav1e (see Local Builds in README)" OFF ) option(AVIF_LOCAL_SVT "Build the SVT-AV1 codec by providing your own copy of the repo in ext/SVT-AV1 (see Local Builds in README)" OFF ) option(AVIF_LOCAL_GTEST "Build the GoogleTest framework by providing your own copy of the repo in ext/googletest (see Local Builds in README)" OFF ) option(AVIF_LOCAL_AVM "Build the AVM (AV2) codec by providing your own copy of the repo in ext/avm (see Local Builds in README)" OFF ) if(AVIF_LOCAL_LIBGAV1) enable_language(CXX) endif() if(APPLE) set(XCRUN xcrun) else() set(XCRUN) endif() if(BUILD_SHARED_LIBS) set(AVIF_LIBRARY_PREFIX "${CMAKE_SHARED_LIBRARY_PREFIX}") set(AVIF_LIBRARY_SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}") else() set(AVIF_LIBRARY_PREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}") set(AVIF_LIBRARY_SUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}") endif() set(AVIF_PLATFORM_DEFINITIONS) set(AVIF_PLATFORM_INCLUDES) set(AVIF_PLATFORM_LIBRARIES) # --------------------------------------------------------------------------------------- # This insanity is for people embedding libavif or making fully static or Windows builds. # Any proper unix environment should ignore these entire following blocks. option(AVIF_LOCAL_ZLIBPNG "Build zlib and libpng by providing your own copy inside the ext subdir." OFF) if(AVIF_LOCAL_ZLIBPNG) # Put the value of ZLIB_INCLUDE_DIR in the cache. This works around cmake behavior that has been updated by # cmake policy CMP0102 in cmake 3.17. Remove the CACHE workaround when we require cmake 3.17 or later. See # https://gitlab.kitware.com/cmake/cmake/-/issues/21343. set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/zlib" CACHE PATH "zlib include dir") # This include_directories() call must be before add_subdirectory(ext/zlib) to work around the # zlib/CMakeLists.txt bug fixed by https://github.com/madler/zlib/pull/818. include_directories(${ZLIB_INCLUDE_DIR}) add_subdirectory(ext/zlib) # This include_directories() call and the previous include_directories() call provide the zlib # include directories for add_subdirectory(ext/libpng). Because we set PNG_BUILD_ZLIB, # libpng/CMakeLists.txt won't call find_package(ZLIB REQUIRED) and will see an empty # ${ZLIB_INCLUDE_DIRS}. include_directories("${CMAKE_CURRENT_BINARY_DIR}/ext/zlib") set(CMAKE_DEBUG_POSTFIX "") # This is the only way I could avoid libpng going crazy if it found awk.exe, seems benign otherwise set(PREV_ANDROID ${ANDROID}) set(ANDROID TRUE) set(PNG_BUILD_ZLIB "${CMAKE_CURRENT_SOURCE_DIR}/ext/zlib" CACHE STRING "" FORCE) set(PNG_SHARED ${BUILD_SHARED_LIBS} CACHE BOOL "") set(PNG_TESTS OFF CACHE BOOL "") add_subdirectory(ext/libpng) set(PNG_PNG_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libpng") set(PNG_LIBRARY png_static) include_directories("${CMAKE_CURRENT_BINARY_DIR}/ext/libpng") set(ANDROID ${PREV_ANDROID}) set(ZLIB_LIBRARY zlibstatic) endif() option(AVIF_LOCAL_JPEG "Build jpeg by providing your own copy inside the ext subdir." OFF) if(AVIF_LOCAL_JPEG) add_subdirectory(ext/libjpeg) if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") set(JPEG_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libjpeg") set(JPEG_LIBRARY jpeg) else() set(JPEG_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libjpeg" PARENT_SCOPE) set(JPEG_LIBRARY jpeg PARENT_SCOPE) endif() endif() option(AVIF_LOCAL_LIBYUV "Build libyuv by providing your own copy inside the ext subdir." OFF) if(AVIF_LOCAL_LIBYUV) set(LIB_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/ext/libyuv/build/${AVIF_LIBRARY_PREFIX}yuv${AVIF_LIBRARY_SUFFIX}") if(NOT EXISTS "${LIB_FILENAME}") message(FATAL_ERROR "libavif(AVIF_LOCAL_LIBYUV): ${LIB_FILENAME} is missing, bailing out") endif() if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") set(LIBYUV_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libyuv/include") set(LIBYUV_LIBRARY ${LIB_FILENAME}) else() set(LIBYUV_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libyuv/include" PARENT_SCOPE) set(LIBYUV_LIBRARY ${LIB_FILENAME} PARENT_SCOPE) endif() if(BUILD_SHARED_LIBS) # Fix "libyuv.so: undefined reference to `jpeg_read_raw_data'" errors. if(NOT AVIF_LOCAL_JPEG) find_package(JPEG REQUIRED) endif() set(LIBYUV_LIBRARY ${LIBYUV_LIBRARY} ${JPEG_LIBRARY}) endif() set(libyuv_FOUND TRUE) message(STATUS "libavif: local libyuv found; libyuv-based fast paths enabled.") else(AVIF_LOCAL_LIBYUV) find_package(libyuv QUIET) # not required if(libyuv_FOUND) # libyuv 1755 exposed all of the I*Matrix() functions, which libavif relies on. # libyuv 1774 exposed ScalePlane_12 function, which libavif can use for some additional optimizations. # libyuv 1813 added the I*ToARGBMatrixFilter() functions, which libavif can use with the bilinear filter. if(NOT LIBYUV_VERSION) message(STATUS "libavif: libyuv found, but version unknown; libyuv-based fast paths disabled.") unset(libyuv_FOUND) elseif(LIBYUV_VERSION LESS 1755) message(STATUS "libavif: libyuv (${LIBYUV_VERSION}) found, but is too old; libyuv-based fast paths disabled.") unset(libyuv_FOUND) else() message(STATUS "libavif: libyuv (${LIBYUV_VERSION}) found; libyuv-based fast paths enabled.") if(LIBYUV_VERSION LESS 1813) message(STATUS "libavif: some libyuv optimizations require at least version 1813 to work.") endif() endif() else() message(STATUS "libavif: libyuv not found; libyuv-based fast paths disabled.") endif() endif() if(libyuv_FOUND) set(AVIF_PLATFORM_DEFINITIONS ${AVIF_PLATFORM_DEFINITIONS} -DAVIF_LIBYUV_ENABLED=1) set(AVIF_PLATFORM_INCLUDES ${AVIF_PLATFORM_INCLUDES} ${LIBYUV_INCLUDE_DIR}) set(AVIF_PLATFORM_LIBRARIES ${AVIF_PLATFORM_LIBRARIES} ${LIBYUV_LIBRARY}) endif(libyuv_FOUND) option(AVIF_LOCAL_LIBSHARPYUV "Build libsharpyuv by providing your own copy inside the ext subdir." OFF) if(AVIF_LOCAL_LIBSHARPYUV) set(LIB_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/ext/libwebp/build/libsharpyuv${AVIF_LIBRARY_SUFFIX}") if(NOT EXISTS "${LIB_FILENAME}") message(FATAL_ERROR "libavif(AVIF_LOCAL_LIBSHARPYUV): ${LIB_FILENAME} is missing, bailing out") endif() if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") set(LIBSHARPYUV_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libwebp") set(LIBSHARPYUV_LIBRARY ${LIB_FILENAME}) else() set(LIBSHARPYUV_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libwebp" PARENT_SCOPE) set(LIBSHARPYUV_LIBRARY ${LIB_FILENAME} PARENT_SCOPE) endif() set(libsharpyuv_FOUND TRUE) else(AVIF_LOCAL_LIBSHARPYUV) # find_package(libsharpyuv QUIET) # SDL_image provides libsharpyuv through libwebp endif() if(LIBAVIF_WITH_SHARPYUV_SDLIMAGE) #Control sharpyuv through sdl_image message(STATUS "libavif: libsharpyuv found; sharp rgb to yuv conversion enabled.") set(AVIF_PLATFORM_DEFINITIONS ${AVIF_PLATFORM_DEFINITIONS} -DAVIF_LIBSHARPYUV_ENABLED=1) #set(AVIF_PLATFORM_INCLUDES ${AVIF_PLATFORM_INCLUDES} ${LIBSHARPYUV_INCLUDE_DIR}) set(AVIF_PLATFORM_LIBRARIES sharpyuv) else() message(STATUS "libavif: libsharpyuv not found") endif() # --------------------------------------------------------------------------------------- # Enable all warnings include(CheckCCompilerFlag) if(CMAKE_C_COMPILER_ID MATCHES "Clang") message(STATUS "libavif: Enabling warnings for Clang") add_compile_options(-Wall -Wextra -Wshorten-64-to-32) elseif(CMAKE_C_COMPILER_ID MATCHES "GNU") message(STATUS "libavif: Enabling warnings for GCC") add_compile_options(-Wall -Wextra) elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC") message(STATUS "libavif: Enabling warnings for MSVC") add_compile_options( /W4 /wd4324 # Disable: structure was padded due to alignment specifier /wd4996 # Disable: potentially unsafe stdlib methods # This tells MSVC to read source code as UTF-8 and assume console can only use ASCII (minimal safe). # libavif uses ANSI API to print to console, which is not portable between systems using different # languages and results in mojibake unless we only use codes shared by every code page: ASCII. # A C4556 warning will be generated on violation. # Commonly used /utf-8 flag assumes UTF-8 for both source and console, which is usually not the case. # Warnings can be suppressed but there will still be random characters printed to the console. /source-charset:utf-8 /execution-charset:us-ascii ) else() message(FATAL_ERROR "libavif: Unknown compiler, bailing out") endif() if(AVIF_ENABLE_WERROR) # Warnings as errors if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "GNU") add_compile_options(-Werror) elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC") add_compile_options(/WX) else() message(FATAL_ERROR "libavif: Unknown compiler, bailing out") endif() endif() if(AVIF_ENABLE_COVERAGE) if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID MATCHES "GNU") message(STATUS "libavif: Enabling coverage for Clang") add_compile_options(-fprofile-instr-generate -fcoverage-mapping -O0) set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-fprofile-instr-generate -fcoverage-mapping") else() # TODO: Add support for other compilers message(WARNING "libavif: Ignoring request for coverage (AVIF_ENABLE_COVERAGE); only clang is currently supported.") endif() endif() if(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R) add_compile_definitions(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R) endif() set(AVIF_SRCS src/alpha.c src/avif.c src/colr.c src/diag.c src/exif.c src/io.c src/mem.c src/obu.c src/rawdata.c src/read.c src/reformat.c src/reformat_libsharpyuv.c src/reformat_libyuv.c src/scale.c src/stream.c src/utils.c src/write.c ) # Only applicable to macOS. In GitHub CI's macos-latest os image, this prevents using the libpng # and libjpeg headers from /Library/Frameworks/Mono.framework/Headers instead of # /usr/local/include. set(CMAKE_FIND_FRAMEWORK LAST) if(UNIX) # Find out if we have threading available set(CMAKE_THREAD_PREFER_PTHREADS ON) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads) set(AVIF_PLATFORM_LIBRARIES ${AVIF_PLATFORM_LIBRARIES} m Threads::Threads) endif() set(AVIF_CODEC_DEFINITIONS) set(AVIF_CODEC_INCLUDES) set(AVIF_CODEC_LIBRARIES) if(AVIF_CODEC_DAV1D) set(AVIF_CODEC_DEFINITIONS ${AVIF_CODEC_DEFINITIONS} -DAVIF_CODEC_DAV1D=1) set(AVIF_SRCS ${AVIF_SRCS} src/codec_dav1d.c) if(AVIF_LOCAL_DAV1D) set(AVIF_DAV1D_BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/dav1d/build") # If ${ANDROID_ABI} is set, look for the library under that subdirectory. if(DEFINED ANDROID_ABI) set(AVIF_DAV1D_BUILD_DIR "${AVIF_DAV1D_BUILD_DIR}/${ANDROID_ABI}") endif() set(LIB_FILENAME "${AVIF_DAV1D_BUILD_DIR}/src/libdav1d${AVIF_LIBRARY_SUFFIX}") if(NOT EXISTS "${LIB_FILENAME}") if("${AVIF_LIBRARY_SUFFIX}" STREQUAL ".a") message(FATAL_ERROR "libavif: ${LIB_FILENAME} is missing, bailing out") else() # On windows, meson will produce a libdav1d.a instead of the expected libdav1d.dll/.lib. # See https://github.com/mesonbuild/meson/issues/8153. set(LIB_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/ext/dav1d/build/src/libdav1d.a") if(NOT EXISTS "${LIB_FILENAME}") message(FATAL_ERROR "libavif: ${LIB_FILENAME} (or libdav1d${AVIF_LIBRARY_SUFFIX}) is missing, bailing out") endif() endif() endif() set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} "${AVIF_DAV1D_BUILD_DIR}" "${AVIF_DAV1D_BUILD_DIR}/include" "${AVIF_DAV1D_BUILD_DIR}/include/dav1d" "${CMAKE_CURRENT_SOURCE_DIR}/ext/dav1d/include" ) set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${LIB_FILENAME}) else() # Check to see if dav1d is independently being built by the outer CMake project if(NOT TARGET dav1d) find_package(dav1d REQUIRED) set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} ${DAV1D_INCLUDE_DIR}) endif() set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${DAV1D_LIBRARY}) endif() if(UNIX AND NOT APPLE) set(AVIF_PLATFORM_LIBRARIES ${AVIF_PLATFORM_LIBRARIES} ${CMAKE_DL_LIBS}) # for dlsym endif() message(STATUS "libavif: Codec enabled: dav1d (decode)") endif() if(AVIF_CODEC_LIBGAV1) set(AVIF_CODEC_DEFINITIONS ${AVIF_CODEC_DEFINITIONS} -DAVIF_CODEC_LIBGAV1=1) set(AVIF_SRCS ${AVIF_SRCS} src/codec_libgav1.c) if(AVIF_LOCAL_LIBGAV1) set(AVIF_LIBGAV1_BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/libgav1/build") # If ${ANDROID_ABI} is set, look for the library under that subdirectory. if(DEFINED ANDROID_ABI) set(AVIF_LIBGAV1_BUILD_DIR "${AVIF_LIBGAV1_BUILD_DIR}/${ANDROID_ABI}") endif() set(LIB_FILENAME "${AVIF_LIBGAV1_BUILD_DIR}/libgav1${AVIF_LIBRARY_SUFFIX}") if(NOT EXISTS "${LIB_FILENAME}") message(FATAL_ERROR "libavif: ${LIB_FILENAME} is missing, bailing out") endif() set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/ext/libgav1/src") set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${LIB_FILENAME}) else() # Check to see if libgav1 is independently being built by the outer CMake project if(NOT TARGET libgav1) find_package(libgav1 REQUIRED) set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} ${LIBGAV1_INCLUDE_DIR}) endif() set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${LIBGAV1_LIBRARY}) endif() message(STATUS "libavif: Codec enabled: libgav1 (decode)") endif() if(AVIF_CODEC_RAV1E) set(AVIF_CODEC_DEFINITIONS ${AVIF_CODEC_DEFINITIONS} -DAVIF_CODEC_RAV1E=1) set(AVIF_SRCS ${AVIF_SRCS} src/codec_rav1e.c) if(AVIF_LOCAL_RAV1E) set(LIB_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/ext/rav1e/build.libavif/usr/lib/${AVIF_LIBRARY_PREFIX}rav1e${AVIF_LIBRARY_SUFFIX}" ) if(NOT EXISTS "${LIB_FILENAME}") message(FATAL_ERROR "libavif: compiled rav1e library is missing (in ext/rav1e/build.libavif/usr/lib), bailing out") endif() set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/ext/rav1e/build.libavif/usr/include/rav1e") set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${LIB_FILENAME}) else() # Check to see if rav1e is independently being built by the outer CMake project if(NOT TARGET rav1e) find_package(rav1e REQUIRED) set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} ${RAV1E_INCLUDE_DIR}) endif() set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${RAV1E_LIBRARIES}) endif() # Unfortunately, rav1e requires a few more libraries if(WIN32) set(AVIF_PLATFORM_LIBRARIES ${AVIF_PLATFORM_LIBRARIES} ws2_32.lib bcrypt.lib userenv.lib ntdll.lib) elseif(UNIX AND NOT APPLE) set(AVIF_PLATFORM_LIBRARIES ${AVIF_PLATFORM_LIBRARIES} ${CMAKE_DL_LIBS}) # for backtrace endif() message(STATUS "libavif: Codec enabled: rav1e (encode)") endif() if(AVIF_CODEC_SVT) set(AVIF_CODEC_DEFINITIONS ${AVIF_CODEC_DEFINITIONS} -DAVIF_CODEC_SVT=1) set(AVIF_SRCS ${AVIF_SRCS} src/codec_svt.c) if(AVIF_LOCAL_SVT) set(LIB_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/ext/SVT-AV1/Bin/Release/${AVIF_LIBRARY_PREFIX}SvtAv1Enc${AVIF_LIBRARY_SUFFIX}" ) if(NOT EXISTS "${LIB_FILENAME}") message(FATAL_ERROR "libavif: compiled svt library is missing (in ext/SVT-AV1/Bin/Release), bailing out") endif() set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/ext/SVT-AV1/include") set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${LIB_FILENAME}) else() # Check to see if svt is independently being built by the outer CMake project if(NOT TARGET svt) find_package(svt REQUIRED) set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} ${SVT_INCLUDE_DIR}) endif() set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${SVT_LIBRARY}) endif() message(STATUS "libavif: Codec enabled: svt (encode)") endif() if(AVIF_CODEC_AOM) set(AVIF_CODEC_DEFINITIONS ${AVIF_CODEC_DEFINITIONS} -DAVIF_CODEC_AOM=1) if(AVIF_CODEC_AOM_ENCODE AND AVIF_CODEC_AOM_DECODE) set(AVIF_CODEC_AOM_ENCODE_DECODE_CONFIG "encode/decode") set(AVIF_CODEC_DEFINITIONS ${AVIF_CODEC_DEFINITIONS} -DAVIF_CODEC_AOM_ENCODE=1 -DAVIF_CODEC_AOM_DECODE=1) elseif(AVIF_CODEC_AOM_ENCODE) set(AVIF_CODEC_AOM_ENCODE_DECODE_CONFIG "encode only") set(AVIF_CODEC_DEFINITIONS ${AVIF_CODEC_DEFINITIONS} -DAVIF_CODEC_AOM_ENCODE=1) elseif(AVIF_CODEC_AOM_DECODE) set(AVIF_CODEC_AOM_ENCODE_DECODE_CONFIG "decode only") set(AVIF_CODEC_DEFINITIONS ${AVIF_CODEC_DEFINITIONS} -DAVIF_CODEC_AOM_DECODE=1) else() message( FATAL_ERROR "libavif: AVIF_CODEC_AOM is on, but both AVIF_CODEC_AOM_ENCODE and AVIF_CODEC_AOM_DECODE are off. Disable AVIF_CODEC_AOM to disable both parts of the codec." ) endif() set(AVIF_SRCS ${AVIF_SRCS} src/codec_aom.c) if(AVIF_LOCAL_AOM) set(LIB_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/ext/aom/build.libavif/${AVIF_LIBRARY_PREFIX}aom${AVIF_LIBRARY_SUFFIX}") if(NOT EXISTS "${LIB_FILENAME}") message(FATAL_ERROR "libavif: ${LIB_FILENAME} is missing, bailing out") endif() set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/ext/aom") set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${LIB_FILENAME}) else() # Check to see if aom is independently being built by the outer CMake project if(NOT TARGET aom) find_package(aom REQUIRED) set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} ${AOM_INCLUDE_DIR}) endif() set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${AOM_LIBRARIES}) endif() message(STATUS "libavif: Codec enabled: aom (${AVIF_CODEC_AOM_ENCODE_DECODE_CONFIG})") endif() if(AVIF_CODEC_AVM) message(WARNING "libavif: AV2 support with avm is experimental. Only use for testing.") # The avm repository is a fork of aom and inherited a lot of folders, files and build artifacts named the same way. # Having both dependencies at the same time generates conflicts in includes, binary lookups etc. if(AVIF_CODEC_AOM) message(FATAL_ERROR "libavif: aom conflicts with avm, bailing out") endif() set(AVIF_CODEC_DEFINITIONS ${AVIF_CODEC_DEFINITIONS} -DAVIF_CODEC_AVM=1) set(AVIF_SRCS ${AVIF_SRCS} src/codec_avm.c) if(AVIF_LOCAL_AVM) # Building the avm repository generates files such as "libaom.a" because it is a fork of aom. set(LIB_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/ext/avm/build.libavif/${AVIF_LIBRARY_PREFIX}aom${AVIF_LIBRARY_SUFFIX}") if(NOT EXISTS "${LIB_FILENAME}") message(FATAL_ERROR "libavif: ${LIB_FILENAME} (from avm) is missing, bailing out") endif() set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/ext/avm") set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${LIB_FILENAME}) # ext/avm/aom/aom_encoder.h includes config/aom_config.h which is generated by the local build of avm. set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/ext/avm/build.libavif") else() # Check to see if avm is independently being built by the outer CMake project if(NOT TARGET avm) find_package(avm REQUIRED) set(AVIF_CODEC_INCLUDES ${AVIF_CODEC_INCLUDES} ${AVM_INCLUDE_DIR}) endif() set(AVIF_CODEC_LIBRARIES ${AVIF_CODEC_LIBRARIES} ${AVM_LIBRARIES}) endif() message(STATUS "libavif: Codec enabled: avm (encode/decode)") endif() if(NOT AVIF_CODEC_AOM AND NOT AVIF_CODEC_DAV1D AND NOT AVIF_CODEC_LIBGAV1 AND NOT AVIF_CODEC_AVM ) message(WARNING "libavif: No decoding library is enabled.") endif() add_library(avif ${AVIF_SRCS}) set_target_properties(avif PROPERTIES VERSION ${LIBRARY_VERSION} SOVERSION ${LIBRARY_SOVERSION} C_VISIBILITY_PRESET hidden) target_compile_definitions(avif PRIVATE ${AVIF_PLATFORM_DEFINITIONS} ${AVIF_CODEC_DEFINITIONS}) target_link_libraries(avif PRIVATE ${AVIF_CODEC_LIBRARIES} ${AVIF_PLATFORM_LIBRARIES}) target_include_directories( avif PUBLIC $ $ PRIVATE ${AVIF_PLATFORM_INCLUDES} ${AVIF_CODEC_INCLUDES} ) if(BUILD_SHARED_LIBS AND WIN32 AND NOT CMAKE_PLATFORM_NO_VERSIONED_SONAME) set_property(TARGET avif PROPERTY OUTPUT_NAME "avif-${LIBRARY_SOVERSION}") set_property(TARGET avif PROPERTY DLL_NAME_WITH_SOVERSION OFF) endif() set(AVIF_PKG_CONFIG_EXTRA_CFLAGS "") if(BUILD_SHARED_LIBS) target_compile_definitions(avif PUBLIC AVIF_DLL PRIVATE AVIF_BUILDING_SHARED_LIBS) set(AVIF_PKG_CONFIG_EXTRA_CFLAGS " -DAVIF_DLL") if(AVIF_LOCAL_LIBGAV1) set_target_properties(avif PROPERTIES LINKER_LANGUAGE "CXX") endif() endif() # Give access to functions defined in internal.h when BUILD_SHARED_LIBS is ON, to tests for example. # The avif_internal target should not be used by external code. if(BUILD_SHARED_LIBS) add_library(avif_internal STATIC ${AVIF_SRCS}) # Copy most properties from the public avif library target. target_compile_definitions(avif_internal PRIVATE "$") target_link_libraries(avif_internal PRIVATE "$") target_include_directories( avif_internal PUBLIC "$" PRIVATE "$" ) else() add_library(avif_internal ALIAS avif) endif() option(AVIF_BUILD_EXAMPLES "Build avif examples." OFF) if(AVIF_BUILD_EXAMPLES) set(AVIF_EXAMPLES avif_example_decode_memory avif_example_decode_file avif_example_decode_streaming avif_example_encode) foreach(EXAMPLE ${AVIF_EXAMPLES}) add_executable(${EXAMPLE} examples/${EXAMPLE}.c) if(AVIF_LOCAL_LIBGAV1) set_target_properties(${EXAMPLE} PROPERTIES LINKER_LANGUAGE "CXX") endif() target_link_libraries(${EXAMPLE} avif ${AVIF_PLATFORM_LIBRARIES}) endforeach() endif() if(CMAKE_SKIP_INSTALL_RULES) set(SKIP_INSTALL_ALL TRUE) endif() if(NOT SKIP_INSTALL_ALL) include(GNUInstallDirs) endif() if(AVIF_CODEC_LIBRARIES MATCHES vmaf) enable_language(CXX) endif() option(AVIF_BUILD_APPS "Build avif apps." OFF) option(AVIF_BUILD_TESTS "Build avif tests." OFF) option(AVIF_ENABLE_GTEST "Build avif C++ tests, which depend on GoogleTest. Requires GoogleTest. Has no effect unless AVIF_BUILD_TESTS is ON." ON ) if(AVIF_BUILD_APPS OR (AVIF_BUILD_TESTS AND AVIF_ENABLE_GTEST)) if(NOT AVIF_LOCAL_ZLIBPNG) find_package(ZLIB REQUIRED) find_package(PNG 1.6.32 REQUIRED) # 1.6.32 or above for png_get_eXIf_1()/png_set_eXIf_1() and iTXt (for XMP). endif() if(NOT AVIF_LOCAL_JPEG) find_package(JPEG REQUIRED) endif() add_library( avif_apps STATIC apps/shared/avifexif.c apps/shared/avifjpeg.c apps/shared/avifpng.c apps/shared/avifutil.c apps/shared/iccjpeg.c apps/shared/iccmaker.c apps/shared/y4m.c ) target_link_libraries(avif_apps avif ${AVIF_PLATFORM_LIBRARIES} ${PNG_LIBRARY} ${ZLIB_LIBRARY} ${JPEG_LIBRARY}) # In GitHub CI's macos-latest os image, /usr/local/include has not only the headers of libpng # and libjpeg but also the headers of an older version of libavif. Put the avif include # directory before ${PNG_PNG_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} to prevent picking up old libavif # headers from /usr/local/include. target_include_directories( avif_apps PRIVATE $ ${PNG_PNG_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} INTERFACE apps/shared ) endif() if(AVIF_BUILD_APPS) add_executable(avifenc apps/avifenc.c) if(AVIF_LOCAL_LIBGAV1 OR AVIF_CODEC_LIBRARIES MATCHES vmaf) set_target_properties(avifenc PROPERTIES LINKER_LANGUAGE "CXX") endif() target_link_libraries(avifenc avif_apps) add_executable(avifdec apps/avifdec.c) if(AVIF_LOCAL_LIBGAV1 OR AVIF_CODEC_LIBRARIES MATCHES vmaf) set_target_properties(avifdec PROPERTIES LINKER_LANGUAGE "CXX") endif() target_link_libraries(avifdec avif_apps) if(NOT SKIP_INSTALL_APPS AND NOT SKIP_INSTALL_ALL) install( TARGETS avifenc avifdec RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) endif() endif() if(AVIF_BUILD_TESTS) enable_testing() # Allow ctest to be called from top-level directory. add_subdirectory(tests) endif() option(AVIF_BUILD_MAN_PAGES "Build avif man pages." OFF) if(AVIF_BUILD_MAN_PAGES) if(AVIF_BUILD_APPS) find_program(PANDOC_EXE pandoc) if(PANDOC_EXE) message(STATUS "libavif: Using pandoc: ${PANDOC_EXE}") else() message(FATAL_ERROR "libavif: Pandoc is missing, bailing out") endif() set(MAN_PAGES avifenc.1 avifdec.1) foreach(MAN_PAGE ${MAN_PAGES}) add_custom_command( OUTPUT ${MAN_PAGE} COMMAND ${PANDOC_EXE} -s -V "footer=libavif ${PROJECT_VERSION}" -f markdown -t man -o "${CMAKE_CURRENT_BINARY_DIR}/${MAN_PAGE}" "${CMAKE_CURRENT_SOURCE_DIR}/doc/${MAN_PAGE}.md" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/doc/${MAN_PAGE}.md" VERBATIM ) endforeach() add_custom_target(man_pages ALL DEPENDS ${MAN_PAGES}) foreach(MAN_PAGE ${MAN_PAGES}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${MAN_PAGE}" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") endforeach() else() message(WARNING "libavif: No man pages are built (AVIF_BUILD_MAN_PAGES); AVIF_BUILD_APPS must be on.") endif() endif() if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) install( TARGETS avif EXPORT ${PROJECT_NAME}-config RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) # Enable CMake configs in VCPKG mode if(BUILD_SHARED_LIBS OR VCPKG_TARGET_TRIPLET) install(EXPORT ${PROJECT_NAME}-config DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) include(CMakePackageConfigHelpers) write_basic_package_version_file( ${PROJECT_NAME}-config-version.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) endif() # Handle both relative and absolute paths (e.g. NixOS) for a relocatable package if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") set(PC_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}") else() set(PC_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") endif() if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") set(PC_LIBDIR "${CMAKE_INSTALL_LIBDIR}") else() set(PC_LIBDIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") endif() configure_file(libavif.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libavif.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libavif.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) endif() if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL) install(FILES include/avif/avif.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/avif") endif() # --------------------------------------------------------------------------------------- # Win32 (Visual Studio) fixups macro(avif_set_folder_safe target folder) if(TARGET ${target}) set_target_properties(${target} PROPERTIES FOLDER ${folder}) endif() endmacro() macro(avif_exclude_safe target) if(TARGET ${target}) set_target_properties(${target} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD True) endif() endmacro() if(WIN32) set_property(GLOBAL PROPERTY USE_FOLDERS ON) avif_set_folder_safe(avif "ext/avif") if(AVIF_BUILD_EXAMPLES) foreach(EXAMPLE ${AVIF_EXAMPLES}) avif_set_folder_safe(${EXAMPLE} "ext/avif/examples") endforeach() endif() if(AVIF_LOCAL_ZLIBPNG) avif_set_folder_safe(example "ext/zlibpng") avif_set_folder_safe(genfiles "ext/zlibpng") avif_set_folder_safe(minigzip "ext/zlibpng") avif_set_folder_safe(png_static "ext/zlibpng") avif_set_folder_safe(zlib "ext/zlibpng") avif_set_folder_safe(zlibstatic "ext/zlibpng") # Don't bother building these targets avif_exclude_safe(example) avif_exclude_safe(genfiles) avif_exclude_safe(minigzip) endif() if(AVIF_LOCAL_JPEG) avif_set_folder_safe(jpeg "ext/libjpeg") endif() endif() add_subdirectory(contrib)