tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CMakeLists.txt (21022B)


      1 # Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 #
      3 # Use of this source code is governed by a BSD-style
      4 # license that can be found in the LICENSE file.
      5 
      6 # Ubuntu focal ships with cmake 3.16.
      7 cmake_minimum_required(VERSION 3.16...3.27)
      8 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
      9 
     10 project(LIBJXL LANGUAGES C CXX)
     11 
     12 # TODO(sboukortt): remove once oss-fuzz passes -DBUILD_SHARED_LIBS=OFF
     13 if(JPEGXL_ENABLE_FUZZERS)
     14  message(STATUS "Fuzzer build detected, building static libs")
     15  set(BUILD_SHARED_LIBS OFF)
     16 endif()
     17 
     18 message(STATUS "CMAKE_SYSTEM_PROCESSOR is ${CMAKE_SYSTEM_PROCESSOR}")
     19 include(CheckCXXCompilerFlag)
     20 check_cxx_compiler_flag("-fsanitize=fuzzer-no-link" CXX_FUZZERS_SUPPORTED)
     21 check_cxx_compiler_flag("-fmacro-prefix-map=OLD=NEW" CXX_MACRO_PREFIX_MAP)
     22 check_cxx_compiler_flag("-fno-rtti" CXX_NO_RTTI_SUPPORTED)
     23 
     24 # Add "DebugOpt" CMake build type. Unlike builtin DEBUG it is optimized.
     25 string(REGEX REPLACE "-DNDEBUG " "" CMAKE_CXX_FLAGS_DEBUGOPT "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG" )
     26 string(REGEX REPLACE "-DNDEBUG " "" CMAKE_C_FLAGS_DEBUGOPT "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDEBUG" )
     27 
     28 # Enabled PIE binaries by default if supported.
     29 include(CheckPIESupported OPTIONAL RESULT_VARIABLE CHECK_PIE_SUPPORTED)
     30 if(CHECK_PIE_SUPPORTED)
     31  check_pie_supported(LANGUAGES CXX)
     32  if(CMAKE_CXX_LINK_PIE_SUPPORTED)
     33    set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
     34  endif()
     35 endif()
     36 
     37 if(PROVISION_DEPENDENCIES)
     38  # Run script to provision dependencies.
     39  find_program (BASH_PROGRAM bash)
     40  if(BASH_PROGRAM)
     41    execute_process(
     42      COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/deps.sh
     43      RESULT_VARIABLE PROVISION_DEPENDENCIES_RESULT)
     44  endif()
     45  if(NOT PROVISION_DEPENDENCIES_RESULT EQUAL "0")
     46    message(FATAL_ERROR "${CMAKE_CURRENT_SOURCE_DIR}/deps.sh failed with ${PROVISION_DEPENDENCIES_RESULT}")
     47  endif()
     48 endif()
     49 
     50 ### Project build options:
     51 if(CXX_FUZZERS_SUPPORTED)
     52  # Enabled by default except on arm64, Windows and Apple builds.
     53  set(ENABLE_FUZZERS_DEFAULT true)
     54 endif()
     55 find_package(PkgConfig)
     56 if(NOT APPLE AND NOT WIN32 AND NOT HAIKU AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
     57  pkg_check_modules(TCMallocMinimalVersionCheck QUIET IMPORTED_TARGET
     58      libtcmalloc_minimal)
     59  if(TCMallocMinimalVersionCheck_FOUND AND
     60     NOT TCMallocMinimalVersionCheck_VERSION VERSION_EQUAL 2.8.0)
     61    # Enabled by default except on Windows and Apple builds for
     62    # tcmalloc != 2.8.0. tcmalloc 2.8.1 already has a fix for this issue.
     63    set(ENABLE_TCMALLOC_DEFAULT true)
     64  else()
     65    message(STATUS
     66        "tcmalloc version ${TCMallocMinimalVersionCheck_VERSION} -- "
     67        "tcmalloc 2.8.0 disabled due to "
     68        "https://github.com/gperftools/gperftools/issues/1204")
     69  endif()
     70 endif()
     71 
     72 check_cxx_source_compiles(
     73   "int main() {
     74      #if !defined(HWY_DISABLED_TARGETS)
     75      static_assert(false, \"HWY_DISABLED_TARGETS is not defined\");
     76      #endif
     77      return 0;
     78    }"
     79  JXL_HWY_DISABLED_TARGETS_FORCED
     80 )
     81 
     82 if((SANITIZER STREQUAL "msan") OR EMSCRIPTEN)
     83  set(BUNDLE_LIBPNG_DEFAULT YES)
     84 else()
     85  set(BUNDLE_LIBPNG_DEFAULT NO)
     86 endif()
     87 
     88 
     89 if(EXISTS "${PROJECT_SOURCE_DIR}/third_party/libjpeg-turbo/jconfig.h.in")
     90  set(ENABLE_JPEGLI_DEFAULT YES)
     91 else()
     92  set(ENABLE_JPEGLI_DEFAULT NO)
     93  message(STATUS "libjpeg-turbo submodule is absent; not enabling jpegli")
     94 endif()
     95 
     96 include(TestBigEndian)
     97 test_big_endian(ARCH_IS_BIG_ENDIAN)
     98 if(ARCH_IS_BIG_ENDIAN)
     99  set(ENABLE_SKCMS_DEFAULT NO)
    100  message(STATUS "Big-endian architecture detected; defaulting to lcms2 instead of skcms")
    101 else()
    102  set(ENABLE_SKCMS_DEFAULT YES)
    103 endif()
    104 
    105 # Standard cmake naming for building shared libraries.
    106 get_property(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
    107 option(BUILD_SHARED_LIBS "Build shared libraries instead of static ones" ${SHARED_LIBS_SUPPORTED})
    108 
    109 set(JPEGXL_ENABLE_FUZZERS ${ENABLE_FUZZERS_DEFAULT} CACHE BOOL
    110    "Build JPEGXL fuzzer targets.")
    111 set(JPEGXL_ENABLE_DEVTOOLS false CACHE BOOL
    112    "Build JPEGXL developer tools.")
    113 set(JPEGXL_ENABLE_TOOLS true CACHE BOOL
    114    "Build JPEGXL user tools: cjxl and djxl.")
    115 set(JPEGXL_ENABLE_JPEGLI ${ENABLE_JPEGLI_DEFAULT} CACHE BOOL
    116    "Build jpegli library.")
    117 set(JPEGXL_ENABLE_JPEGLI_LIBJPEG true CACHE BOOL
    118    "Build libjpeg.so shared library based on jpegli.")
    119 set(JPEGXL_INSTALL_JPEGLI_LIBJPEG false CACHE BOOL
    120    "Install jpegli version of libjpeg.so system-wide.")
    121 set(JPEGLI_LIBJPEG_LIBRARY_VERSION "62.3.0" CACHE STRING
    122    "Library version of the libjpeg.so shared library that we build.")
    123 set(JPEGLI_LIBJPEG_LIBRARY_SOVERSION "62" CACHE STRING
    124    "Library so-version of the libjpeg.so shared library that we build.")
    125 set(JPEGXL_ENABLE_DOXYGEN true CACHE BOOL
    126    "Generate C API documentation using Doxygen.")
    127 set(JPEGXL_ENABLE_MANPAGES true CACHE BOOL
    128    "Build and install man pages for the command-line tools.")
    129 set(JPEGXL_ENABLE_BENCHMARK true CACHE BOOL
    130    "Build JPEGXL benchmark tools.")
    131 set(JPEGXL_ENABLE_EXAMPLES true CACHE BOOL
    132    "Build JPEGXL library usage examples.")
    133 set(JPEGXL_BUNDLE_LIBPNG ${BUNDLE_LIBPNG_DEFAULT} CACHE BOOL
    134    "Build libpng from source and link it statically.")
    135 set(JPEGXL_ENABLE_JNI true CACHE BOOL
    136    "Build JPEGXL JNI Java wrapper, if Java dependencies are installed.")
    137 set(JPEGXL_ENABLE_SJPEG true CACHE BOOL
    138    "Build JPEGXL with support for encoding with sjpeg.")
    139 set(JPEGXL_ENABLE_OPENEXR true CACHE BOOL
    140    "Build JPEGXL with support for OpenEXR if available.")
    141 set(JPEGXL_ENABLE_SKCMS ${ENABLE_SKCMS_DEFAULT} CACHE BOOL
    142    "Build with skcms instead of lcms2.")
    143 set(JPEGXL_ENABLE_VIEWERS false CACHE BOOL
    144    "Build JPEGXL viewer tools for evaluation.")
    145 set(JPEGXL_ENABLE_TCMALLOC ${ENABLE_TCMALLOC_DEFAULT} CACHE BOOL
    146    "Build JPEGXL using gperftools (tcmalloc) allocator.")
    147 set(JPEGXL_ENABLE_PLUGINS false CACHE BOOL
    148    "Build third-party plugins to support JPEG XL in other applications.")
    149 set(JPEGXL_ENABLE_COVERAGE false CACHE BOOL
    150    "Enable code coverage tracking for libjxl. This also enables debug and disables optimizations.")
    151 set(JPEGXL_ENABLE_SIZELESS_VECTORS false CACHE BOOL
    152    "Builds in support for SVE/RVV vectorization")
    153 set(JPEGXL_ENABLE_TRANSCODE_JPEG true CACHE BOOL
    154    "Builds in support for decoding transcoded JXL files back to JPEG,\
    155 disabling it makes the decoder reject JXL_DEC_JPEG_RECONSTRUCTION events,\
    156 (default enabled)")
    157 set(JPEGXL_ENABLE_BOXES true CACHE BOOL
    158    "Builds in support for decoding boxes in JXL files,\
    159 disabling it makes the decoder reject JXL_DEC_BOX events,\
    160 (default enabled)")
    161 set(JPEGXL_STATIC false CACHE BOOL
    162    "Build tools as static binaries.")
    163 set(JPEGXL_WARNINGS_AS_ERRORS false CACHE BOOL
    164    "Treat warnings as errors during compilation.")
    165 set(JPEGXL_DEP_LICENSE_DIR "" CACHE STRING
    166    "Directory where to search for system dependencies \"copyright\" files.")
    167 set(JPEGXL_FORCE_NEON false CACHE BOOL
    168    "Set flags to enable NEON in arm if not enabled by your toolchain.")
    169 set(JPEGXL_TEST_TOOLS false CACHE BOOL
    170    "Run scripts that test the encoding / decoding tools.")
    171 set(JPEGXL_ENABLE_AVX512 false CACHE BOOL
    172    "Build with AVX512 support (faster on CPUs that support it, but larger binary size).")
    173 set(JPEGXL_ENABLE_AVX512_SPR false CACHE BOOL
    174    "Build with AVX-512FP16 support (faster on CPUs that support it, but larger binary size).")
    175 set(JPEGXL_ENABLE_AVX512_ZEN4 false CACHE BOOL
    176 "Build with Zen4-optimized AVX512 support (faster on CPUs that support it, but larger binary size).")
    177 set(JPEGXL_ENABLE_WASM_THREADS true CACHE BOOL
    178    "Builds WASM modules with threads support")
    179 
    180 # Force system dependencies.
    181 set(JPEGXL_FORCE_SYSTEM_BROTLI false CACHE BOOL
    182    "Force using system installed brotli instead of third_party/brotli source.")
    183 set(JPEGXL_FORCE_SYSTEM_GTEST false CACHE BOOL
    184    "Force using system installed googletest (gtest) instead of third_party/googletest source.")
    185 set(JPEGXL_FORCE_SYSTEM_LCMS2 false CACHE BOOL
    186    "Force using system installed lcms2 instead of third_party/lcms source.")
    187 set(JPEGXL_FORCE_SYSTEM_HWY false CACHE BOOL
    188    "Force using system installed highway (libhwy-dev) instead of third_party/highway source.")
    189 
    190 # Check minimum compiler versions. Older compilers are not supported and fail
    191 # with hard to understand errors.
    192 if (NOT CMAKE_C_COMPILER_ID STREQUAL CMAKE_CXX_COMPILER_ID)
    193  message(FATAL_ERROR "Different C/C++ compilers set: "
    194          "${CMAKE_C_COMPILER_ID} vs ${CMAKE_CXX_COMPILER_ID}")
    195 endif()
    196 
    197 message(STATUS
    198    "Compiled IDs C:${CMAKE_C_COMPILER_ID}, C++:${CMAKE_CXX_COMPILER_ID}")
    199 
    200 set(JXL_HWY_INCLUDE_DIRS "$<BUILD_INTERFACE:$<TARGET_PROPERTY:$<IF:$<TARGET_EXISTS:hwy::hwy>,hwy::hwy,hwy>,INTERFACE_INCLUDE_DIRECTORIES>>")
    201 # Always disable SSSE3 since it is rare to have SSSE3 but not SSE4
    202 set(HWY_DISABLED_TARGETS "HWY_SSSE3")
    203 if (NOT JPEGXL_ENABLE_AVX512)
    204  message(STATUS "Disabled AVX512 (set JPEGXL_ENABLE_AVX512 to enable it)")
    205  set(HWY_DISABLED_TARGETS "${HWY_DISABLED_TARGETS}|HWY_AVX3")
    206  add_definitions(-DFJXL_ENABLE_AVX512=0)
    207 endif()
    208 if (NOT JPEGXL_ENABLE_AVX512_SPR)
    209  message(STATUS "Disabled AVX512_SPR (set JPEGXL_ENABLE_AVX512_SPR to enable it)")
    210  set(HWY_DISABLED_TARGETS "${HWY_DISABLED_TARGETS}|HWY_AVX3_SPR")
    211 endif()
    212 if (NOT JPEGXL_ENABLE_AVX512_ZEN4)
    213  message(STATUS "Disabled AVX512_ZEN4 (set JPEGXL_ENABLE_AVX512_ZEN4 to enable it)")
    214  set(HWY_DISABLED_TARGETS "${HWY_DISABLED_TARGETS}|HWY_AVX3_ZEN4")
    215 endif()
    216 
    217 
    218 
    219 # CMAKE_EXPORT_COMPILE_COMMANDS is used to generate the compilation database
    220 # used by clang-tidy.
    221 set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
    222 
    223 if(JPEGXL_STATIC)
    224  set(BUILD_SHARED_LIBS 0)
    225 
    226  # https://learn.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library?view=msvc-170
    227  # https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html
    228  set(CMAKE_MSVC_RUNTIME_LIBRARY "$<$<NOT:$<CONFIG:Debug>>:MultiThreaded>" CACHE STRING "")
    229 
    230  # Clang developers say that in case to use "static" we have to build stdlib
    231  # ourselves; for real use case we don't care about stdlib, as it is "granted",
    232  # so just linking all other libraries is fine.
    233  if (NOT MSVC)
    234    string(APPEND CMAKE_EXE_LINKER_FLAGS " -static")
    235  endif()
    236  if ((NOT WIN32 AND NOT APPLE) OR CYGWIN OR MINGW)
    237    set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
    238    string(APPEND CMAKE_EXE_LINKER_FLAGS " -static-libgcc -static-libstdc++")
    239  endif()
    240 endif()  # JPEGXL_STATIC
    241 
    242 # Threads
    243 set(THREADS_PREFER_PTHREAD_FLAG YES)
    244 find_package(Threads REQUIRED)
    245 
    246 # These settings are important to drive check_cxx_source_compiles
    247 # See CMP0067 (min cmake version is 3.10 anyway)
    248 
    249 if ("cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
    250  set(CMAKE_CXX_STANDARD 17)
    251 else()
    252  if ("cxx_std_14" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
    253    set(CMAKE_CXX_STANDARD 14)
    254  else()
    255    set(CMAKE_CXX_STANDARD 11)
    256  endif()
    257 endif()
    258 set(CMAKE_CXX_EXTENSIONS OFF)
    259 set(CMAKE_CXX_STANDARD_REQUIRED YES)
    260 
    261 # Atomics
    262 find_package(Atomics REQUIRED)
    263 
    264 if(JPEGXL_STATIC)
    265  if (MINGW)
    266    # In MINGW libstdc++ uses pthreads directly. When building statically a
    267    # program (regardless of whether the source code uses pthread or not) the
    268    # toolchain will add stdc++ and pthread to the linking step but stdc++ will
    269    # be linked statically while pthread will be linked dynamically.
    270    # To avoid this and have pthread statically linked with need to pass it in
    271    # the command line with "-Wl,-Bstatic -lpthread -Wl,-Bdynamic" but the
    272    # linker will discard it if not used by anything else up to that point in
    273    # the linker command line. If the program or any dependency don't use
    274    # pthread directly -lpthread is discarded and libstdc++ (added by the
    275    # toolchain later) will then use the dynamic version. For this we also need
    276    # to pass -lstdc++ explicitly before -lpthread. For pure C programs -lstdc++
    277    # will be discarded anyway.
    278    # This adds these flags as dependencies for *all* targets. Adding this to
    279    # CMAKE_EXE_LINKER_FLAGS instead would cause them to be included before any
    280    # object files and therefore discarded. This should be set in the
    281    # INTERFACE_LINK_LIBRARIES of Threads::Threads but some third_part targets
    282    # don't depend on it.
    283    link_libraries(-Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic)
    284  elseif(CMAKE_USE_PTHREADS_INIT)
    285    # "whole-archive" is not supported on OSX.
    286    if (NOT APPLE)
    287      # Set pthreads as a whole-archive, otherwise weak symbols in the static
    288      # libraries will discard pthreads symbols leading to segmentation fault at
    289      # runtime.
    290      message(STATUS "Using -lpthread as --whole-archive")
    291      set_target_properties(Threads::Threads PROPERTIES
    292        INTERFACE_LINK_LIBRARIES
    293            "-Wl,--whole-archive;-lpthread;-Wl,--no-whole-archive")
    294    endif()
    295  endif()
    296 endif()  # JPEGXL_STATIC
    297 
    298 if (EMSCRIPTEN AND JPEGXL_ENABLE_WASM_THREADS)
    299  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
    300  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
    301  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
    302 endif()
    303 
    304 if (CXX_MACRO_PREFIX_MAP)
    305  add_compile_options(-fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.)
    306 endif()
    307 
    308 if (CXX_NO_RTTI_SUPPORTED)
    309  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
    310 endif()
    311 
    312 # Internal flags for coverage builds:
    313 set(JPEGXL_COVERAGE_FLAGS)
    314 set(JPEGXL_COVERAGE_LINK_FLAGS)
    315 
    316 if (MSVC)
    317  # TODO(janwas): add flags
    318  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
    319 else ()
    320  # Global compiler flags for all targets here and in subdirectories.
    321  add_definitions(
    322    # Avoid changing the binary based on the current time and date.
    323    -D__DATE__="redacted"
    324    -D__TIMESTAMP__="redacted"
    325    -D__TIME__="redacted"
    326  )
    327 
    328  # TODO(eustas): JXL currently compiles, but does not pass tests...
    329  if (NOT JXL_HWY_DISABLED_TARGETS_FORCED)
    330    if (NOT JPEGXL_ENABLE_SIZELESS_VECTORS)
    331      set(HWY_DISABLED_TARGETS "${HWY_DISABLED_TARGETS}|HWY_SVE|HWY_SVE2|HWY_SVE_256|HWY_SVE2_128|HWY_RVV")
    332    endif()
    333    add_compile_options($<$<NOT:$<COMPILE_LANGUAGE:RC>>:-DHWY_DISABLED_TARGETS=\(${HWY_DISABLED_TARGETS}\)>)
    334  endif()
    335 
    336  # Machine flags.
    337  add_compile_options(-funwind-tables)
    338  if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    339    add_compile_options("SHELL:-Xclang -mrelax-all")
    340  endif()
    341  if (CXX_CONSTRUCTOR_ALIASES_SUPPORTED)
    342    add_compile_options("SHELL:-Xclang -mconstructor-aliases")
    343  endif()
    344 
    345  if(WIN32)
    346    # Not supported by clang-cl, but frame pointers are default on Windows
    347  else()
    348    add_compile_options(-fno-omit-frame-pointer)
    349  endif()
    350 
    351  # CPU flags - remove once we have NEON dynamic dispatch
    352 
    353  # TODO(janwas): this also matches M1, but only ARMv7 is intended/needed.
    354  if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
    355    if(JPEGXL_FORCE_NEON)
    356      # GCC requires these flags, otherwise __ARM_NEON is undefined.
    357      add_compile_options(-mfpu=neon-vfpv4 -mfloat-abi=hard)
    358    endif()
    359  endif()
    360 
    361  add_compile_options(
    362    # Ignore this to allow redefining __DATE__ and others.
    363    -Wno-builtin-macro-redefined
    364 
    365    # Global warning settings.
    366    -Wall
    367  )
    368 
    369  if (JPEGXL_WARNINGS_AS_ERRORS)
    370    add_compile_options(-Werror)
    371  endif ()
    372 
    373  if(JPEGXL_ENABLE_COVERAGE)
    374    set(JPEGXL_COVERAGE_FLAGS
    375        -g -O0 -fprofile-arcs -ftest-coverage
    376    )
    377    set(JPEGXL_COVERAGE_LINK_FLAGS
    378        --coverage
    379    )
    380  endif()  # JPEGXL_ENABLE_COVERAGE
    381 endif ()  # !MSVC
    382 
    383 include(GNUInstallDirs)
    384 
    385 # Separately build/configure testing frameworks and other third_party libraries
    386 # to allow disabling tests in those libraries.
    387 include(third_party/testing.cmake)
    388 add_subdirectory(third_party)
    389 # Copy the JXL license file to the output build directory.
    390 configure_file("${CMAKE_CURRENT_SOURCE_DIR}/LICENSE"
    391               ${PROJECT_BINARY_DIR}/LICENSE.jpeg-xl COPYONLY)
    392 
    393 # Enable tests regardless of where they are defined.
    394 enable_testing()
    395 include(CTest)
    396 # Specify default location of `testdata`:
    397 if(NOT DEFINED JPEGXL_TEST_DATA_PATH)
    398  set(JPEGXL_TEST_DATA_PATH "${PROJECT_SOURCE_DIR}/testdata")
    399 endif()
    400 
    401 # Libraries.
    402 add_subdirectory(lib)
    403 
    404 if(BUILD_TESTING)
    405  # Script to run tests over the source code in bash.
    406  find_program (BASH_PROGRAM bash)
    407  if(BASH_PROGRAM)
    408    add_test(
    409      NAME bash_test
    410      COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/bash_test.sh)
    411  endif()
    412 endif() # BUILD_TESTING
    413 
    414 # Documentation generated by Doxygen
    415 if(JPEGXL_ENABLE_DOXYGEN)
    416  find_package(Doxygen)
    417  if(DOXYGEN_FOUND)
    418    set(DOXYGEN_GENERATE_HTML "YES")
    419    set(DOXYGEN_GENERATE_XML "YES")
    420    set(DOXYGEN_STRIP_FROM_PATH "${CMAKE_CURRENT_SOURCE_DIR}/lib/include")
    421    if(JPEGXL_WARNINGS_AS_ERRORS)
    422      set(DOXYGEN_WARN_AS_ERROR "YES")
    423    endif()
    424    set(DOXYGEN_QUIET "YES")
    425    doxygen_add_docs(doc
    426      "${CMAKE_CURRENT_SOURCE_DIR}/lib/include"
    427      "${CMAKE_CURRENT_SOURCE_DIR}/doc/api.txt"
    428      WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
    429      COMMENT "Generating C API documentation")
    430 
    431    # Add sphinx doc build step for readthedocs.io (requires doxygen too).
    432    find_program(SPHINX_BUILD_PROGRAM sphinx-build)
    433    if(SPHINX_BUILD_PROGRAM)
    434      add_custom_command(
    435        OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/rtd/nonexistent"
    436        COMMENT "Generating readthedocs.io output on ${CMAKE_CURRENT_BINARY_DIR}/rtd"
    437        COMMAND ${SPHINX_BUILD_PROGRAM} -q -W -b html -j auto
    438          ${CMAKE_SOURCE_DIR}/doc/sphinx
    439          ${CMAKE_CURRENT_BINARY_DIR}/rtd
    440        DEPENDS doc
    441      )
    442      # This command runs the documentation generation every time since the output
    443      # target file doesn't exist.
    444      add_custom_target(rtd-html
    445        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/rtd/nonexistent
    446      )
    447    else() # SPHINX_BUILD_PROGRAM\
    448      message(WARNING "sphinx-build not found, skipping rtd documentation")
    449    endif() # SPHINX_BUILD_PROGRAM
    450 
    451  else()
    452    # Create a "doc" target for compatibility since "doc" is not otherwise added to
    453    # the build when doxygen is not installed.
    454    add_custom_target(doc false
    455      COMMENT "Error: Can't generate doc since Doxygen not installed.")
    456  endif() # DOXYGEN_FOUND
    457 endif() # JPEGXL_ENABLE_DOXYGEN
    458 
    459 if(JPEGXL_ENABLE_MANPAGES)
    460  find_program(ASCIIDOC a2x)
    461  if(ASCIIDOC)
    462    file(STRINGS "${ASCIIDOC}" ASCIIDOC_SHEBANG LIMIT_COUNT 1)
    463    if(ASCIIDOC_SHEBANG MATCHES "sh$" OR ASCIIDOC_SHEBANG MATCHES "libexec/bin/python$" OR MINGW)
    464      set(ASCIIDOC_PY_FOUND ON)
    465      # Run the program directly and set ASCIIDOC as empty.
    466      set(ASCIIDOC_PY "${ASCIIDOC}")
    467      set(ASCIIDOC "")
    468    elseif(ASCIIDOC_SHEBANG MATCHES "python2")
    469      find_package(Python2 COMPONENTS Interpreter)
    470      set(ASCIIDOC_PY_FOUND "${Python2_Interpreter_FOUND}")
    471      set(ASCIIDOC_PY Python2::Interpreter)
    472    elseif(ASCIIDOC_SHEBANG MATCHES "python3")
    473      find_package(Python3 COMPONENTS Interpreter)
    474      set(ASCIIDOC_PY_FOUND "${Python3_Interpreter_FOUND}")
    475      set(ASCIIDOC_PY Python3::Interpreter)
    476    else()
    477      find_package(Python COMPONENTS Interpreter QUIET)
    478      if(NOT Python_Interpreter_FOUND)
    479        find_program(ASCIIDOC_PY python)
    480        if(ASCIIDOC_PY)
    481          set(ASCIIDOC_PY_FOUND ON)
    482        endif()
    483      else()
    484        set(ASCIIDOC_PY_FOUND "${Python_Interpreter_FOUND}")
    485        set(ASCIIDOC_PY Python::Interpreter)
    486      endif()
    487    endif()
    488 
    489    if (ASCIIDOC_PY_FOUND)
    490      set(MANPAGE_FILES "")
    491      set(MANPAGES "")
    492      foreach(PAGE IN ITEMS cjxl djxl)
    493        # Invoking the Python interpreter ourselves instead of running the a2x binary
    494        # directly is necessary on MSYS2, otherwise it is run through cmd.exe which
    495        # does not recognize it.
    496        add_custom_command(
    497          OUTPUT "${PAGE}.1"
    498          COMMAND "${ASCIIDOC_PY}"
    499          ARGS ${ASCIIDOC}
    500            --format manpage --destination-dir="${CMAKE_CURRENT_BINARY_DIR}"
    501            "${CMAKE_CURRENT_SOURCE_DIR}/doc/man/${PAGE}.txt"
    502          MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/doc/man/${PAGE}.txt")
    503        list(APPEND MANPAGE_FILES "${CMAKE_CURRENT_BINARY_DIR}/${PAGE}.1")
    504        list(APPEND MANPAGES "${PAGE}.1")
    505      endforeach()
    506      add_custom_target(manpages ALL DEPENDS ${MANPAGES})
    507      install(FILES ${MANPAGE_FILES} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
    508    endif()  # ASCIIDOC_PY_FOUND
    509  else()
    510    message(WARNING "asciidoc was not found, the man pages will not be installed.")
    511  endif()  # ASCIIDOC
    512 endif()  # JPEGXL_ENABLE_MANPAGES
    513 
    514 # Example usage code.
    515 if (JPEGXL_ENABLE_EXAMPLES)
    516  include(examples/examples.cmake)
    517 endif ()
    518 
    519 # Plugins for third-party software
    520 if (JPEGXL_ENABLE_PLUGINS)
    521  add_subdirectory(plugins)
    522 endif ()
    523 
    524 # Binary tools
    525 add_subdirectory(tools)
    526 
    527 
    528 macro(list_test_targets out dir)
    529  get_property(dir_targets DIRECTORY ${dir} PROPERTY BUILDSYSTEM_TARGETS)
    530  foreach(target ${dir_targets})
    531    if (target MATCHES ".*_test")
    532      list(APPEND ${out} ${target})
    533    endif()
    534  endforeach()
    535  get_property(subdirectories DIRECTORY ${dir} PROPERTY SUBDIRECTORIES)
    536  foreach(subdir ${subdirectories})
    537    list_test_targets(${out} ${subdir})
    538  endforeach()
    539 endmacro()
    540 
    541 set(all_tests_list)
    542 list_test_targets(all_tests_list ${CMAKE_CURRENT_SOURCE_DIR})
    543 
    544 if(all_tests_list)
    545  add_custom_target(all_tests)
    546  add_dependencies(all_tests ${all_tests_list})
    547 endif()