cmake_minimum_required(VERSION 3.21)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

include(LcVersion)

lc_detect_version(LOCKDC_RESOLVED_VERSION)

project(lockdc VERSION ${LOCKDC_RESOLVED_VERSION} LANGUAGES C)

include(GNUInstallDirs)
include(CMakeDependentOption)
include(CMakePackageConfigHelpers)
include(ProcessorCount)

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_library(LOCKDC_ATOMIC_LIBRARY NAMES atomic)
set(LOCKDC_EXPORTED_ATOMIC_LIBRARY "")
set(LOCKDC_PC_PRIVATE_EXTRA_LIBS "")
set(LOCKDC_PC_SYSTEM_LIBS "")
set(LOCKDC_EXPORTED_DARWIN_FRAMEWORKS "")
if(LOCKDC_ATOMIC_LIBRARY AND NOT LOCKDC_ATOMIC_LIBRARY MATCHES "-NOTFOUND$")
    set(LOCKDC_EXPORTED_ATOMIC_LIBRARY "atomic")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
    set(LOCKDC_EXPORTED_DARWIN_FRAMEWORKS "-framework CoreFoundation;-framework SystemConfiguration")
    list(APPEND LOCKDC_PC_SYSTEM_LIBS "-framework CoreFoundation" "-framework SystemConfiguration")
endif()

set(LOCKDC_COVERAGE_RUNTIME_LIBRARY "")
if(LOCKDC_ENABLE_COVERAGE AND CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
    set(LOCKDC_COVERAGE_RUNTIME_LIBRARY "gcov")
endif()
foreach(_lockdc_pc_system_lib IN LISTS CMAKE_DL_LIBS LOCKDC_EXPORTED_ATOMIC_LIBRARY LOCKDC_COVERAGE_RUNTIME_LIBRARY)
    if(_lockdc_pc_system_lib STREQUAL "")
        continue()
    endif()
    if(IS_ABSOLUTE "${_lockdc_pc_system_lib}" OR _lockdc_pc_system_lib MATCHES "^-")
        list(APPEND LOCKDC_PC_SYSTEM_LIBS "${_lockdc_pc_system_lib}")
    else()
        list(APPEND LOCKDC_PC_SYSTEM_LIBS "-l${_lockdc_pc_system_lib}")
    endif()
endforeach()
if(LOCKDC_PC_SYSTEM_LIBS)
    string(JOIN " " LOCKDC_PC_PRIVATE_EXTRA_LIBS ${LOCKDC_PC_SYSTEM_LIBS})
endif()

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

option(LOCKDC_BUILD_STATIC "Build the static lockdc library." ON)
option(LOCKDC_BUILD_SHARED "Build the shared lockdc library." ON)
option(LOCKDC_BUILD_DEPENDENCIES "Provision vendored dependency artifacts needed by this preset." OFF)
option(LOCKDC_BUILD_EXAMPLES "Build example programs." ON)
option(LOCKDC_BUILD_TESTS "Build unit tests." ON)
option(LOCKDC_BUILD_LUA_BINDINGS "Build the optional Lua extension when Lua headers are available." ON)
cmake_dependent_option(LOCKDC_BUILD_E2E_TESTS
    "Build end-to-end tests that target a real lockd environment."
    OFF
    "LOCKDC_BUILD_TESTS"
    OFF
)
option(LOCKDC_BUILD_BENCHMARKS "Build local benchmark targets." ON)
option(LOCKDC_BUILD_FUZZERS "Build clang/libFuzzer targets for parser and stream hardening." OFF)
option(LOCKDC_ENABLE_COVERAGE "Build test targets with gcov coverage instrumentation." OFF)
option(LOCKDC_INSTALL "Enable install rules." ON)

set(LOCKDC_OPENSSL_VERSION "3.6.2" CACHE STRING "Pinned OpenSSL release supplied by c.pkt.systems.")
set(LOCKDC_ZLIB_VERSION "1.3.2" CACHE STRING "Pinned zlib release supplied by c.pkt.systems.")
set(LOCKDC_CURL_VERSION "8.20.0" CACHE STRING "Pinned curl release supplied by c.pkt.systems.")
set(LOCKDC_NGHTTP2_VERSION "1.69.0" CACHE STRING "Pinned nghttp2 release supplied by c.pkt.systems.")
set(LOCKDC_LIBSSH2_VERSION "1.11.1" CACHE STRING "Pinned libssh2 release supplied by c.pkt.systems.")
set(LOCKDC_LONEJSON_VERSION "0.31.0" CACHE STRING "Pinned lonejson release used for mapped JSON load/save and internal JSON parsing helpers." FORCE)
set(LOCKDC_LONEJSON_ABI_VERSION "16" CACHE STRING "Pinned lonejson shared-library ABI/SOVERSION." FORCE)
set(LOCKDC_CMOCKA_VERSION "2.0.2" CACHE STRING "Pinned cmocka release used for unit tests.")
set(LOCKDC_PSLOG_VERSION "0.4.1" CACHE STRING "Pinned libpslog release used for SDK logging." FORCE)
set(LOCKDC_CPKT_VERSION "0.2.0" CACHE STRING "Pinned c.pkt.systems dependency bundle version.")
set(LOCKDC_ABI_VERSION "1" CACHE STRING "Shared-library ABI/SOVERSION for liblockdc.")
set(LOCKDC_DOWNLOAD_ROOT "${CMAKE_SOURCE_DIR}/.cache/downloads" CACHE PATH "Shared download root for vendored dependency archives.")
set(LOCKDC_DIST_DIR "${CMAKE_BINARY_DIR}/dist" CACHE PATH "Output directory for generated package archives and checksum manifests.")
set(LOCKDC_VERSION_OVERRIDE "" CACHE STRING "Override the detected liblockdc package version with an explicit semantic version.")
set(LOCKDC_TARGET_ARCH "${CMAKE_SYSTEM_PROCESSOR}" CACHE STRING "Artifact architecture name")
set(LOCKDC_TARGET_OS "${CMAKE_SYSTEM_NAME}" CACHE STRING "Artifact operating system name")
set(LOCKDC_TARGET_LIBC "" CACHE STRING "Artifact libc suffix for Linux targets (gnu, musl, or empty)")
set(LOCKDC_DEPENDENCY_BUILD_TYPE "Release")
ProcessorCount(LOCKDC_DEPENDENCY_BUILD_JOBS_DEFAULT)
if(NOT LOCKDC_DEPENDENCY_BUILD_JOBS_DEFAULT OR LOCKDC_DEPENDENCY_BUILD_JOBS_DEFAULT LESS 1)
    set(LOCKDC_DEPENDENCY_BUILD_JOBS_DEFAULT 1)
endif()
set(LOCKDC_DEPENDENCY_BUILD_JOBS "${LOCKDC_DEPENDENCY_BUILD_JOBS_DEFAULT}" CACHE STRING "Parallel job count for vendored dependency builds.")
set(LOCKDC_DEPENDENCY_DOWNLOAD_TIMEOUT "300" CACHE STRING "Maximum time in seconds for a vendored dependency download attempt.")
set(LOCKDC_DEPENDENCY_DOWNLOAD_INACTIVITY_TIMEOUT "60" CACHE STRING "Maximum idle time in seconds for a vendored dependency download attempt.")

if(NOT LOCKDC_BUILD_STATIC AND NOT LOCKDC_BUILD_SHARED)
    message(FATAL_ERROR "Enable at least one of LOCKDC_BUILD_STATIC or LOCKDC_BUILD_SHARED.")
endif()
if(NOT LOCKDC_ABI_VERSION MATCHES "^[0-9]+$")
    message(FATAL_ERROR "LOCKDC_ABI_VERSION must be a non-negative integer.")
endif()

if(LOCKDC_BUILD_FUZZERS)
    if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
        message(FATAL_ERROR "LOCKDC_BUILD_FUZZERS=ON requires Clang as the C compiler")
    endif()
    if(NOT LOCKDC_BUILD_STATIC)
        message(FATAL_ERROR "LOCKDC_BUILD_FUZZERS=ON requires LOCKDC_BUILD_STATIC=ON")
    endif()
endif()

string(TOLOWER "${LOCKDC_TARGET_OS}" LOCKDC_TARGET_OS_LOWER)
string(TOLOWER "${LOCKDC_TARGET_ARCH}" LOCKDC_TARGET_ARCH_LOWER)

if(LOCKDC_TARGET_ARCH_LOWER STREQUAL "amd64")
    set(LOCKDC_TARGET_ARCH_LOWER "x86_64")
endif()
if(LOCKDC_TARGET_ARCH_LOWER STREQUAL "arm64" AND NOT LOCKDC_TARGET_OS_LOWER STREQUAL "darwin")
    set(LOCKDC_TARGET_ARCH_LOWER "aarch64")
endif()
if(LOCKDC_TARGET_ARCH_LOWER STREQUAL "arm")
    set(LOCKDC_TARGET_ARCH_LOWER "armhf")
endif()
set(LOCKDC_TARGET_ARCH "${LOCKDC_TARGET_ARCH_LOWER}" CACHE STRING "Artifact architecture name" FORCE)

if(LOCKDC_TARGET_OS_LOWER STREQUAL "linux" AND NOT LOCKDC_TARGET_LIBC)
    execute_process(
        COMMAND "${CMAKE_C_COMPILER}" -dumpmachine
        OUTPUT_VARIABLE lockdc_compiler_machine
        RESULT_VARIABLE lockdc_compiler_machine_result
        OUTPUT_STRIP_TRAILING_WHITESPACE
        ERROR_QUIET
    )
    if(lockdc_compiler_machine_result EQUAL 0 AND lockdc_compiler_machine MATCHES "musl")
        set(LOCKDC_TARGET_LIBC "musl")
    else()
        set(LOCKDC_TARGET_LIBC "gnu")
    endif()
endif()

if(LOCKDC_TARGET_OS_LOWER STREQUAL "darwin")
    set(LOCKDC_TARGET_ID "${LOCKDC_TARGET_ARCH_LOWER}-apple-darwin")
elseif(LOCKDC_TARGET_OS_LOWER STREQUAL "freebsd")
    set(LOCKDC_TARGET_ID "${LOCKDC_TARGET_ARCH_LOWER}-freebsd")
elseif(LOCKDC_TARGET_OS_LOWER STREQUAL "linux")
    if(LOCKDC_TARGET_LIBC)
        set(LOCKDC_TARGET_ID "${LOCKDC_TARGET_ARCH_LOWER}-linux-${LOCKDC_TARGET_LIBC}")
    else()
        set(LOCKDC_TARGET_ID "${LOCKDC_TARGET_ARCH_LOWER}-linux")
    endif()
else()
    set(LOCKDC_TARGET_ID "${LOCKDC_TARGET_ARCH_LOWER}-${LOCKDC_TARGET_OS_LOWER}")
endif()

if(NOT DEFINED LOCKDC_EXTERNAL_ROOT)
    set(LOCKDC_EXTERNAL_ROOT "${CMAKE_SOURCE_DIR}/.cache/deps/${LOCKDC_TARGET_ID}" CACHE PATH "Stable install root for downloaded third-party dependencies.")
endif()
if(NOT DEFINED LOCKDC_DEPENDENCY_BUILD_ROOT)
    set(LOCKDC_DEPENDENCY_BUILD_ROOT "${CMAKE_SOURCE_DIR}/.cache/deps-build/${LOCKDC_TARGET_ID}" CACHE PATH "Stable build root for downloaded third-party dependencies.")
endif()

function(lc_configure_c_target target)
    if(UNIX OR APPLE OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
        target_compile_definitions(${target} PRIVATE _POSIX_C_SOURCE=200809L)
    endif()
    if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
        target_compile_definitions(${target} PRIVATE _DARWIN_C_SOURCE=1)
    endif()
    set_target_properties(${target} PROPERTIES
        C_STANDARD 90
        C_STANDARD_REQUIRED ON
        C_EXTENSIONS OFF
        POSITION_INDEPENDENT_CODE ON
        VISIBILITY_INLINES_HIDDEN NO
    )
    if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
        target_compile_options(${target} PRIVATE
            -std=c89
            -Wall
            -Wextra
            -Wpedantic
        )
    endif()
endfunction()

function(lc_enable_coverage_if_requested target)
    get_target_property(target_type ${target} TYPE)
    if(LOCKDC_ENABLE_COVERAGE AND CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
        target_compile_definitions(${target} PRIVATE LOCKDC_COVERAGE_BUILD=1)
        target_compile_options(${target} PRIVATE --coverage -O0)
        if(NOT target_type STREQUAL "STATIC_LIBRARY")
            target_link_options(${target} PRIVATE --coverage)
        endif()
    endif()
endfunction()

function(lc_enable_fuzz_instrumentation_if_requested target)
    get_target_property(target_type ${target} TYPE)
    if(LOCKDC_BUILD_FUZZERS AND CMAKE_C_COMPILER_ID MATCHES "Clang")
        target_compile_definitions(${target} PRIVATE FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1)
        target_compile_options(${target} PRIVATE
            -fsanitize=fuzzer-no-link,address,undefined
            -fno-omit-frame-pointer
            -g
        )
        if(NOT target_type STREQUAL "STATIC_LIBRARY")
            target_link_options(${target} PRIVATE -fsanitize=fuzzer-no-link,address,undefined)
        endif()
    endif()
endfunction()

function(lc_assert_fuzz_toolchain_supported)
    set(fuzz_probe_dir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/fuzz-toolchain-probe")
    set(fuzz_probe_source "${fuzz_probe_dir}/probe.c")
    set(fuzz_probe_binary "${fuzz_probe_dir}/probe")

    file(MAKE_DIRECTORY "${fuzz_probe_dir}")
    file(WRITE "${fuzz_probe_source}" [=[
int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size) {
    (void)data;
    (void)size;
    return 0;
}
]=])

    execute_process(
        COMMAND "${CMAKE_C_COMPILER}"
            -v
            -fsanitize=fuzzer,address
            -fno-omit-frame-pointer
            "${fuzz_probe_source}"
            -o "${fuzz_probe_binary}"
        RESULT_VARIABLE fuzz_probe_result
        OUTPUT_VARIABLE fuzz_probe_stdout
        ERROR_VARIABLE fuzz_probe_stderr
    )

    if(NOT fuzz_probe_result EQUAL 0)
        message(FATAL_ERROR
            "LOCKDC_BUILD_FUZZERS=ON requires a C toolchain that can link -fsanitize=fuzzer,address. "
            "The selected compiler is '${CMAKE_C_COMPILER}'. Install the matching compiler-rt/libFuzzer runtime "
            "for this Clang toolchain or use a Clang toolchain that provides those libraries.\n"
            "clang output:\n${fuzz_probe_stdout}\n${fuzz_probe_stderr}")
    endif()
endfunction()

find_program(CLANG_FORMAT_BIN NAMES clang-format)

file(GLOB_RECURSE LOCKDC_FORMAT_SOURCES CONFIGURE_DEPENDS
    ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h
    ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h
    ${CMAKE_CURRENT_SOURCE_DIR}/bench/*.c
    ${CMAKE_CURRENT_SOURCE_DIR}/bench/*.h
    ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.c
    ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.h
    ${CMAKE_CURRENT_SOURCE_DIR}/examples/*.c
    ${CMAKE_CURRENT_SOURCE_DIR}/examples/*.h
)

if(CLANG_FORMAT_BIN)
    add_custom_target(clang-format
        COMMAND ${CLANG_FORMAT_BIN} -i -style=file ${LOCKDC_FORMAT_SOURCES}
        VERBATIM
    )
else()
    add_custom_target(clang-format
        COMMAND ${CMAKE_COMMAND} -E echo "clang-format not found"
        COMMAND ${CMAKE_COMMAND} -E false
        VERBATIM
    )
endif()

add_custom_target(format DEPENDS clang-format)

set(lc_generated_include_dir "${CMAKE_CURRENT_BINARY_DIR}/generated/include")
file(MAKE_DIRECTORY "${lc_generated_include_dir}/lc")
configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/cmake/lc_version.h.in"
    "${lc_generated_include_dir}/lc/version.h"
    @ONLY
)
configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/cmake/lockdc.pc.in"
    "${CMAKE_CURRENT_BINARY_DIR}/lockdc.pc"
    @ONLY
)
set(LOCKDC_SYSTEM_LIBRARIES Threads::Threads ${CMAKE_DL_LIBS})
if(LOCKDC_ATOMIC_LIBRARY AND NOT LOCKDC_ATOMIC_LIBRARY MATCHES "-NOTFOUND$")
    list(APPEND LOCKDC_SYSTEM_LIBRARIES "${LOCKDC_ATOMIC_LIBRARY}")
endif()
if(NOT LOCKDC_COVERAGE_RUNTIME_LIBRARY STREQUAL "")
    list(APPEND LOCKDC_SYSTEM_LIBRARIES "${LOCKDC_COVERAGE_RUNTIME_LIBRARY}")
endif()
set(LOCKDC_PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/include/lc/lc.h")
set(LOCKDC_PUBLIC_VERSION_HEADER "${lc_generated_include_dir}/lc/version.h")

include(LcDependencies)
lc_configure_dependencies()

set(lc_sources
    src/lc_api.c
    src/lc_allocator.c
    src/lc_attachment_api.c
    src/lc_client_api.c
    src/lc_client_management_api.c
    src/lc_consumer_service.c
    src/lc_core.c
    src/lc_intcompat.c
    src/lc_lease_api.c
    src/lc_lonejson.c
    src/lc_local_mutate_api.c
    src/lc_management_api.c
    src/lc_message_api.c
    src/lc_mutate_stream.c
    src/lc_queue_api.c
    src/lc_queue_stream_api.c
    src/lc_log.c
    src/lc_state_api.c
    src/lc_streaming.c
    src/lc_transport.c
)

set(LOCKDC_PSLOG_STATIC_INCLUDE_DIR "${LOCKDC_EXTERNAL_ROOT}/pslog/install/include")
set(LOCKDC_PSLOG_SHARED_INCLUDE_DIR "${LOCKDC_EXTERNAL_ROOT}/pslog/install/include")
set(LOCKDC_LONEJSON_STATIC_INCLUDE_DIR "${LOCKDC_EXTERNAL_ROOT}/lonejson/install/include")
set(LOCKDC_LONEJSON_SHARED_INCLUDE_DIR "${LOCKDC_EXTERNAL_ROOT}/lonejson/install/include")
set(LOCKDC_PSLOG_INCLUDE_DIR "")
set(LOCKDC_LONEJSON_INCLUDE_DIR "")
foreach(lockdc_pslog_include_candidate
    "${LOCKDC_PSLOG_STATIC_INCLUDE_DIR}"
    "${LOCKDC_PSLOG_SHARED_INCLUDE_DIR}"
)
    if(EXISTS "${lockdc_pslog_include_candidate}/pslog.h")
        set(LOCKDC_PSLOG_INCLUDE_DIR "${lockdc_pslog_include_candidate}")
        break()
    endif()
endforeach()
foreach(lockdc_lonejson_include_candidate
    "${LOCKDC_LONEJSON_STATIC_INCLUDE_DIR}"
    "${LOCKDC_LONEJSON_SHARED_INCLUDE_DIR}"
)
    if(EXISTS "${lockdc_lonejson_include_candidate}/lonejson.h")
        set(LOCKDC_LONEJSON_INCLUDE_DIR "${lockdc_lonejson_include_candidate}")
        break()
    endif()
endforeach()
if(LOCKDC_PSLOG_INCLUDE_DIR STREQUAL "")
    if(LOCKDC_BUILD_SHARED AND NOT LOCKDC_BUILD_STATIC)
        set(LOCKDC_PSLOG_INCLUDE_DIR "${LOCKDC_PSLOG_SHARED_INCLUDE_DIR}")
    else()
        set(LOCKDC_PSLOG_INCLUDE_DIR "${LOCKDC_PSLOG_STATIC_INCLUDE_DIR}")
    endif()
endif()
if(LOCKDC_LONEJSON_INCLUDE_DIR STREQUAL "")
    if(LOCKDC_BUILD_SHARED AND NOT LOCKDC_BUILD_STATIC)
        set(LOCKDC_LONEJSON_INCLUDE_DIR "${LOCKDC_LONEJSON_SHARED_INCLUDE_DIR}")
    else()
        set(LOCKDC_LONEJSON_INCLUDE_DIR "${LOCKDC_LONEJSON_STATIC_INCLUDE_DIR}")
    endif()
endif()

function(lc_configure_library_target target)
    target_sources(${target} PRIVATE ${lc_sources})
    target_include_directories(${target}
        PUBLIC
            $<BUILD_INTERFACE:${lc_generated_include_dir}>
            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
            $<BUILD_INTERFACE:${LOCKDC_PSLOG_INCLUDE_DIR}>
            $<BUILD_INTERFACE:${LOCKDC_LONEJSON_INCLUDE_DIR}>
            $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
        PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}/src
    )
    target_compile_definitions(${target} PRIVATE LC_VERSION_STRING="${LOCKDC_RESOLVED_VERSION}")
    target_link_libraries(${target} PUBLIC ${LOCKDC_SYSTEM_LIBRARIES})
    lc_configure_c_target(${target})
    lc_enable_coverage_if_requested(${target})
    lc_enable_fuzz_instrumentation_if_requested(${target})
endfunction()

function(lc_add_release_privacy_scan target)
    if(NOT CMAKE_BUILD_TYPE STREQUAL "Release")
        return()
    endif()
    if(LOCKDC_SANITIZER_INSTRUMENTED)
        return()
    endif()
    add_custom_command(TARGET ${target} POST_BUILD
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_STRIP_BIN=${CMAKE_STRIP}
            -DLOCKDC_STRIP_TARGET=$<TARGET_FILE:${target}>
            -DLOCKDC_TARGET_ID=${LOCKDC_TARGET_ID}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/strip_release_target.cmake
        VERBATIM
    )
    add_custom_command(TARGET ${target} POST_BUILD
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -DLOCKDC_SCAN_LABEL=$<TARGET_FILE_NAME:${target}>
            -DLOCKDC_SCAN_PATHS=$<TARGET_FILE:${target}>
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/release_privacy_scan.cmake
        VERBATIM
    )
endfunction()

function(lc_add_build_tree_shared_dependency_lookup target)
    if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
        return()
    endif()
    foreach(lockdc_external_library_dir
        "${LOCKDC_EXTERNAL_ROOT}/curl/install/lib"
        "${LOCKDC_EXTERNAL_ROOT}/openssl/install/lib"
        "${LOCKDC_EXTERNAL_ROOT}/nghttp2/install/lib"
        "${LOCKDC_EXTERNAL_ROOT}/pslog/install/lib"
        "${LOCKDC_EXTERNAL_ROOT}/lonejson/install/lib"
        "${LOCKDC_EXTERNAL_ROOT}/libssh2/install/lib"
        "${LOCKDC_EXTERNAL_ROOT}/zlib/install/lib"
    )
        if(EXISTS "${lockdc_external_library_dir}")
            target_link_options(${target} INTERFACE
                "$<BUILD_INTERFACE:LINKER:-rpath-link,${lockdc_external_library_dir}>"
            )
        endif()
    endforeach()
endfunction()

if(LOCKDC_BUILD_STATIC)
    add_library(lc_static STATIC)
    add_library(lockdc::static ALIAS lc_static)
    lc_configure_library_target(lc_static)
    target_link_libraries(lc_static PUBLIC
        lc::curl_static
        lc::openssl_ssl_static
        lc::openssl_crypto_static
        lc::nghttp2_static
        lc::pslog_static
        lc::lonejson_static
    )
    set_target_properties(lc_static PROPERTIES
        OUTPUT_NAME lockdc
    )
    lc_add_release_privacy_scan(lc_static)
endif()

if(LOCKDC_BUILD_SHARED)
    add_library(lc_shared SHARED)
    add_library(lockdc::shared ALIAS lc_shared)
    lc_configure_library_target(lc_shared)
    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
        target_link_options(lc_shared PRIVATE "LINKER:--enable-new-dtags")
        set(lockdc_shared_install_rpath "$ORIGIN")
    elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
        set(lockdc_shared_install_rpath "@loader_path")
    else()
        set(lockdc_shared_install_rpath "")
    endif()
    target_link_libraries(lc_shared PRIVATE
        lc::curl_shared
        lc::openssl_ssl_shared
        lc::openssl_crypto_shared
        lc::nghttp2_shared
        lc::pslog_shared
        lc::lonejson_shared
    )
    lc_add_build_tree_shared_dependency_lookup(lc_shared)
    set_target_properties(lc_shared PROPERTIES
        OUTPUT_NAME lockdc
        VERSION ${PROJECT_VERSION}
        SOVERSION ${LOCKDC_ABI_VERSION}
        BUILD_RPATH "${lockdc_shared_install_rpath}"
        BUILD_RPATH_USE_ORIGIN ON
        BUILD_WITH_INSTALL_RPATH ON
        INSTALL_RPATH "${lockdc_shared_install_rpath}"
        INSTALL_RPATH_USE_LINK_PATH OFF
    )
    lc_add_release_privacy_scan(lc_shared)
endif()

if(LOCKDC_BUILD_TESTS)
    add_library(lc_test_static STATIC)
    lc_configure_library_target(lc_test_static)
    target_link_libraries(lc_test_static PRIVATE
        lc::curl_static
        lc::openssl_ssl_static
        lc::openssl_crypto_static
        lc::nghttp2_static
        lc::pslog_static
        lc::lonejson_static
    )
    set_target_properties(lc_test_static PROPERTIES
        OUTPUT_NAME lockdc_test
    )
endif()

set(LOCKDC_SHARED_LIB_NAME "")
set(LOCKDC_SHARED_SONAME "")
set(LOCKDC_SHARED_LINK_NAME "")
set(LOCKDC_PACKAGE_METADATA_SHARED_LIB_NAME "")
set(LOCKDC_PACKAGE_METADATA_SHARED_SONAME "")
set(LOCKDC_PACKAGE_METADATA_SHARED_LINK_NAME "")
set(LOCKDC_ACTIVE_C_FLAGS "${CMAKE_C_FLAGS}")
set(LOCKDC_SANITIZER_INSTRUMENTED 0)

if(DEFINED CMAKE_BUILD_TYPE AND NOT "${CMAKE_BUILD_TYPE}" STREQUAL "")
    string(TOUPPER "${CMAKE_BUILD_TYPE}" LOCKDC_CMAKE_BUILD_TYPE_UPPER)
    string(APPEND LOCKDC_ACTIVE_C_FLAGS " ${CMAKE_C_FLAGS_${LOCKDC_CMAKE_BUILD_TYPE_UPPER}}")
endif()
if(LOCKDC_ACTIVE_C_FLAGS MATCHES "(^|[ \t])-fsanitize=([^ \t,]+,)*(address|undefined)(,[^ \t,]+)*($|[ \t])")
    set(LOCKDC_SANITIZER_INSTRUMENTED 1)
endif()

if(TARGET lc_shared)
    set(LOCKDC_SHARED_LINK_NAME "${CMAKE_SHARED_LIBRARY_PREFIX}lockdc${CMAKE_SHARED_LIBRARY_SUFFIX}")
    set(LOCKDC_PACKAGE_METADATA_SHARED_LIB_NAME "$<TARGET_FILE_NAME:lc_shared>")
    set(LOCKDC_PACKAGE_METADATA_SHARED_SONAME "$<TARGET_SONAME_FILE_NAME:lc_shared>")
    set(LOCKDC_PACKAGE_METADATA_SHARED_LINK_NAME "$<TARGET_LINKER_FILE_NAME:lc_shared>")
endif()

configure_package_config_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/cmake/lockdcConfig.cmake.in"
    "${CMAKE_CURRENT_BINARY_DIR}/lockdcConfig.cmake"
    INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/lockdc"
)
write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/lockdcConfigVersion.cmake"
    VERSION "${PROJECT_VERSION}"
    COMPATIBILITY SameMajorVersion
)

file(READ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_metadata.cmake.in" LOCKDC_PACKAGE_METADATA_TEMPLATE)
string(CONFIGURE "${LOCKDC_PACKAGE_METADATA_TEMPLATE}" LOCKDC_PACKAGE_METADATA_CONTENT @ONLY)
file(GENERATE
    OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/package-metadata.cmake"
    CONTENT "${LOCKDC_PACKAGE_METADATA_CONTENT}"
)

set(SOURCE_URL "git+https://github.com/sa6mwa/liblockdc.git")
set(SOURCE_TAG_LINE "  tag = \"v${LOCKDC_RESOLVED_VERSION}\",")
set(LOCKDC_LUA_ROCKSPEC_PATH "${CMAKE_CURRENT_BINARY_DIR}/lockdc-${PROJECT_VERSION}-1.rockspec")
file(GLOB LOCKDC_STALE_LUA_ROCKSPEC_PATHS "${CMAKE_CURRENT_BINARY_DIR}/lockdc-*-1.rockspec")
foreach(_lockdc_stale_lua_rockspec_path IN LISTS LOCKDC_STALE_LUA_ROCKSPEC_PATHS)
    if(NOT "${_lockdc_stale_lua_rockspec_path}" STREQUAL "${LOCKDC_LUA_ROCKSPEC_PATH}")
        file(REMOVE "${_lockdc_stale_lua_rockspec_path}")
    endif()
endforeach()
configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/lockdc.rockspec.in"
    "${LOCKDC_LUA_ROCKSPEC_PATH}"
    @ONLY
)

set(LOCKDC_LUA_INCLUDE_DIR "")
set(LOCKDC_LUA_LIBRARY "")
if(LOCKDC_BUILD_LUA_BINDINGS)
    find_path(LOCKDC_LUA_INCLUDE_DIR
        NAMES lua.h
        PATH_SUFFIXES include include/lua5.5 include/lua-5.5 include/lua lua5.5 lua-5.5 lua
        PATHS /usr/local /usr /usr/local/include /usr/include
    )
    if("${LOCKDC_LUA_INCLUDE_DIR}" STREQUAL "" AND EXISTS "/usr/local/include/lua.h")
        set(LOCKDC_LUA_INCLUDE_DIR "/usr/local/include")
    endif()
    if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
        find_library(LOCKDC_LUA_LIBRARY
            NAMES lua5.5 lua-5.5 lua55 lua
            PATH_SUFFIXES lib lib64
            PATHS /usr/local /usr /opt/local
        )
    endif()
    if(LOCKDC_BUILD_SHARED AND NOT "${LOCKDC_LUA_INCLUDE_DIR}" STREQUAL "")
        if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
           CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
           NOT "${LOCKDC_LUA_LIBRARY}" STREQUAL "")
            add_library(lockdc_lua_core MODULE src/lua/lockdc_lua.c)
            target_include_directories(lockdc_lua_core PRIVATE "${LOCKDC_LUA_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/src")
            target_link_libraries(lockdc_lua_core PRIVATE lc_shared)
            if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
                target_link_options(lockdc_lua_core PRIVATE "LINKER:--allow-shlib-undefined")
            elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
                target_link_options(lockdc_lua_core PRIVATE "LINKER:-undefined,dynamic_lookup")
            else()
                target_link_libraries(lockdc_lua_core PRIVATE "${LOCKDC_LUA_LIBRARY}")
            endif()
            lc_configure_c_target(lockdc_lua_core)
            set_target_properties(lockdc_lua_core PROPERTIES
                PREFIX ""
                OUTPUT_NAME core
                LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lua/lockdc"
            )
        else()
            message(STATUS
                "Lua bindings requested but no Lua runtime library was found for ${CMAKE_SYSTEM_NAME}; "
                "skipping lockdc_lua_core")
        endif()
    endif()
endif()

if(LOCKDC_INSTALL)

    install(FILES ${LOCKDC_PUBLIC_HEADER} ${LOCKDC_PUBLIC_VERSION_HEADER}
        DESTINATION include/lc
        COMPONENT dev
    )
    if(TARGET lc_shared)
        install(TARGETS lc_shared

            LIBRARY DESTINATION lib
            COMPONENT runtime
            NAMELINK_COMPONENT dev
            RUNTIME DESTINATION bin
            COMPONENT runtime
        )
    endif()
    if(TARGET lc_static)
        install(TARGETS lc_static
            ARCHIVE DESTINATION lib
            COMPONENT dev
        )
    endif()
    install(FILES
        "${CMAKE_CURRENT_BINARY_DIR}/lockdc.pc"
        DESTINATION lib/pkgconfig
        COMPONENT dev
    )
    install(FILES
        "${CMAKE_CURRENT_BINARY_DIR}/lockdcConfig.cmake"
        "${CMAKE_CURRENT_BINARY_DIR}/lockdcConfigVersion.cmake"
        DESTINATION lib/cmake/lockdc
        COMPONENT dev
    )

    foreach(_lc_component runtime dev)
        install(FILES
            "${CMAKE_CURRENT_SOURCE_DIR}/README.md"
            "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE"
            DESTINATION share/doc/liblockdc
            COMPONENT "${_lc_component}"
        )
    endforeach()
endif()

if(LOCKDC_BUILD_EXAMPLES)
    add_subdirectory(examples)
endif()

if(LOCKDC_BUILD_BENCHMARKS)
    add_subdirectory(bench)
endif()

if(LOCKDC_BUILD_TESTS OR LOCKDC_BUILD_FUZZERS)
    enable_testing()
endif()

if(LOCKDC_BUILD_TESTS)
    add_subdirectory(tests)

    if(TARGET lc_shared AND TARGET lc_static)
        add_test(NAME package_archives_test
            COMMAND ${CMAKE_COMMAND}
                -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
                -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
                -DLOCKDC_VERSION=${LOCKDC_RESOLVED_VERSION}
                -DLOCKDC_TARGET_ID=${LOCKDC_TARGET_ID}
                -DLOCKDC_DIST_DIR=${LOCKDC_DIST_DIR}
                -DLOCKDC_SHARED_LIB_NAME=$<TARGET_FILE_NAME:lc_shared>
                -DLOCKDC_SHARED_SONAME=$<TARGET_SONAME_FILE_NAME:lc_shared>
                -DLOCKDC_SHARED_LINK_NAME=$<TARGET_LINKER_FILE_NAME:lc_shared>
                -DLOCKDC_SANITIZER_INSTRUMENTED=${LOCKDC_SANITIZER_INSTRUMENTED}
                -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/package_archives_test.cmake
        )
        set_tests_properties(package_archives_test PROPERTIES RUN_SERIAL TRUE)
    endif()

    if(TARGET lc_shared AND TARGET lc_static
       AND NOT CMAKE_CROSSCOMPILING
       AND CMAKE_BUILD_TYPE STREQUAL "Release")
        add_test(NAME release_tarball_sdk_test
            COMMAND ${CMAKE_COMMAND}
                -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
                -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
                -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/release_tarball_sdk_test.cmake
        )
        set_tests_properties(release_tarball_sdk_test PROPERTIES RUN_SERIAL TRUE)

        add_test(NAME lua_release_package_test
            COMMAND ${CMAKE_COMMAND}
                -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
                -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
                -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/lua_release_package_test.cmake
        )
        set_tests_properties(lua_release_package_test PROPERTIES RUN_SERIAL TRUE)

        add_test(NAME release_checksums_stability_test
            COMMAND ${CMAKE_COMMAND}
                -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
                -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
                -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/release_checksums_stability_test.cmake
        )
        set_tests_properties(release_checksums_stability_test PROPERTIES RUN_SERIAL TRUE)
    endif()

    add_test(NAME version_resolution_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/version_resolution_test.cmake
    )
    set_tests_properties(version_resolution_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME dist_dir_configure_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/dist_dir_configure_test.cmake
    )
    set_tests_properties(dist_dir_configure_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME c_only_configure_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -DLOCKDC_C_COMPILER=${CMAKE_C_COMPILER}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/c_only_configure_test.cmake
    )
    set_tests_properties(c_only_configure_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME deferred_vendored_install_manifest_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -DLOCKDC_C_COMPILER=${CMAKE_C_COMPILER}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/deferred_vendored_install_manifest_test.cmake
    )
    set_tests_properties(deferred_vendored_install_manifest_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME arch_alias_configure_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -DLOCKDC_C_COMPILER=${CMAKE_C_COMPILER}
            -DLOCKDC_EXTERNAL_ROOT=${LOCKDC_EXTERNAL_ROOT}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/arch_alias_configure_test.cmake
    )
    set_tests_properties(arch_alias_configure_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME package_script_targeting_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/package_script_targeting_test.cmake
    )
    set_tests_properties(package_script_targeting_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME cross_test_targeting_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/cross_test_targeting_test.cmake
    )
    set_tests_properties(cross_test_targeting_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME runtime_license_install_tree_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -DLOCKDC_VERSION=${LOCKDC_RESOLVED_VERSION}
            -DLOCKDC_TARGET_ID=${LOCKDC_TARGET_ID}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/runtime_license_install_tree_test.cmake
    )
    set_tests_properties(runtime_license_install_tree_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME install_tree_sdk_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -DLOCKDC_C_COMPILER=${CMAKE_C_COMPILER}
            -DLOCKDC_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG}
            -DLOCKDC_EXTERNAL_ROOT=${LOCKDC_EXTERNAL_ROOT}
            $<$<BOOL:${CMAKE_BUILD_TYPE}>:-DLOCKDC_BUILD_TYPE=${CMAKE_BUILD_TYPE}>
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/install_tree_sdk_test.cmake
    )
    set_tests_properties(install_tree_sdk_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME devenv_compose_config_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/devenv_compose_config_test.cmake
    )
    set_tests_properties(devenv_compose_config_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME pslog_build_modes_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -DLOCKDC_C_COMPILER=${CMAKE_C_COMPILER}
            $<$<BOOL:${CMAKE_TOOLCHAIN_FILE}>:-DLOCKDC_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}>
            -DLOCKDC_EXTERNAL_ROOT=${LOCKDC_EXTERNAL_ROOT}
            -DLOCKDC_DEPENDENCY_BUILD_ROOT=${LOCKDC_DEPENDENCY_BUILD_ROOT}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/pslog_build_modes_test.cmake
    )
    set_tests_properties(pslog_build_modes_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME curl_dependency_interface_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -DLOCKDC_EXTERNAL_ROOT=${LOCKDC_EXTERNAL_ROOT}
            -DLOCKDC_DEPENDENCY_BUILD_ROOT=${LOCKDC_DEPENDENCY_BUILD_ROOT}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/curl_dependency_interface_test.cmake
    )
    set_tests_properties(curl_dependency_interface_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME libssh2_dependency_interface_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_EXTERNAL_ROOT=${LOCKDC_EXTERNAL_ROOT}
            -DLOCKDC_DEPENDENCY_BUILD_ROOT=${LOCKDC_DEPENDENCY_BUILD_ROOT}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/libssh2_dependency_interface_test.cmake
    )
    set_tests_properties(libssh2_dependency_interface_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME pslog_dependency_download_name_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/pslog_dependency_download_name_test.cmake
    )
    set_tests_properties(pslog_dependency_download_name_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME host_dependency_root_layout_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/host_dependency_root_layout_test.cmake
    )
    set_tests_properties(host_dependency_root_layout_test PROPERTIES RUN_SERIAL TRUE)

    add_test(NAME dependency_download_timeout_test
        COMMAND ${CMAKE_COMMAND}
            -DLOCKDC_ROOT=${CMAKE_CURRENT_SOURCE_DIR}
            -DLOCKDC_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
            -DLOCKDC_C_COMPILER=${CMAKE_C_COMPILER}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tests/dependency_download_timeout_test.cmake
    )
    set_tests_properties(dependency_download_timeout_test PROPERTIES RUN_SERIAL TRUE)

endif()

if(LOCKDC_BUILD_FUZZERS)
    lc_assert_fuzz_toolchain_supported()
    add_subdirectory(tests/fuzz)
endif()

find_program(GCOV_BIN NAMES gcov)

if(LOCKDC_BUILD_TESTS AND LOCKDC_ENABLE_COVERAGE AND GCOV_BIN)
    add_custom_target(coverage-report
        COMMAND ${CMAKE_CTEST_COMMAND} --test-dir ${CMAKE_CURRENT_BINARY_DIR} --output-on-failure
        COMMAND ${CMAKE_COMMAND} -E env GCOV=${GCOV_BIN}
                ${CMAKE_CURRENT_SOURCE_DIR}/scripts/coverage_report.sh
                ${CMAKE_CURRENT_BINARY_DIR}
                ${CMAKE_CURRENT_BINARY_DIR}/coverage-report
        DEPENDS lc_test_static
        USES_TERMINAL
        VERBATIM
    )
endif()
