cmake_minimum_required(VERSION 3.15)
project(gbdc VERSION 1.0 LANGUAGES CXX)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(PYBIND11_FINDPYTHON ON)
find_package(pybind11 CONFIG REQUIRED)

include(CTest)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
    # Prefer Homebrew's keg-only libarchive for local/source builds; CI wheel builds
    # supply libarchive via CMAKE_PREFIX_PATH, so a missing brew formula is not fatal.
    execute_process(
        COMMAND brew --prefix libarchive
        OUTPUT_VARIABLE LIBARCHIVE_PREFIX
        OUTPUT_STRIP_TRAILING_WHITESPACE
        RESULT_VARIABLE LIBARCHIVE_BREW_RESULT
        ERROR_QUIET
    )
    if(LIBARCHIVE_BREW_RESULT EQUAL 0 AND EXISTS "${LIBARCHIVE_PREFIX}/include/archive.h")
        set(LibArchive_INCLUDE_DIR "${LIBARCHIVE_PREFIX}/include")
    endif()
endif()

find_package(LibArchive REQUIRED)

# A static libarchive (self-contained macOS wheels) carries none of its compression
# backends; expand it to the full static link line (lzma/zstd/lz4/zlib/bz2/...) via
# pkg-config. Shared/system libarchive (local & Linux builds) is left untouched.
if(LibArchive_LIBRARIES MATCHES "\\.a$")
    find_package(PkgConfig REQUIRED)
    pkg_check_modules(LIBARCHIVE_PC REQUIRED libarchive)
    set(LibArchive_LIBRARIES ${LIBARCHIVE_PC_STATIC_LDFLAGS})
    set(LibArchive_INCLUDE_DIRS ${LIBARCHIVE_PC_STATIC_INCLUDE_DIRS})
endif()

include_directories(${LibArchive_INCLUDE_DIRS})
set(LIBS ${LIBS} md5 ${LibArchive_LIBRARIES})

include_directories(gbdc PUBLIC "${PROJECT_SOURCE_DIR}")

add_subdirectory("src")
add_subdirectory("test")

add_executable(gbdctool src/Main.cc)
target_link_libraries(gbdctool PUBLIC ${LIBS} util extract transform)
# target_include_directories(gbdctool PUBLIC "${PROJECT_SOURCE_DIR}")
set_property(TARGET gbdctool PROPERTY OUTPUT_NAME gbdc)

# Per-tool commands: thin `gbd-<tool>` executables realised as symlinks to the single `gbdc`
# binary, which dispatches on its invocation name (argv[0]). See src/Main.cc.
set(GBD_TOOL_NAMES
    gbd-extract-base gbd-extract-gate gbd-extract-wcnf gbd-extract-opb
    gbd-checksani gbd-isohash gbd-isohash2 gbd-identify
    gbd-cnf2kis gbd-cnf2bip gbd-sanitize gbd-normalize)

foreach(toolname IN LISTS GBD_TOOL_NAMES)
    add_custom_command(TARGET gbdctool POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E create_symlink
                "$<TARGET_FILE_NAME:gbdctool>" "$<TARGET_FILE_DIR:gbdctool>/${toolname}"
        COMMENT "Creating symlink ${toolname} -> gbdc")
endforeach()

# Install the CLI. Wheel builds (scikit-build-core, SKBUILD_SCRIPTS_DIR defined) ship the compiled
# `gbdc` binary as package data inside platlib and expose the `gbdc` command through a Python
# console-script entry point (see gbdc_cli.py and [project.scripts] in pyproject.toml). The ELF
# binary is deliberately kept out of the wheel's scripts directory: auditwheel would otherwise
# relocate it and leave a shim that resolves the binary via sysconfig.get_path("platlib"), which
# points at the global site-packages and so breaks `pip install --user` installs
# (pypa/auditwheel#340). gbd invokes tools as `gbdc <tool>`, so a single binary suffices.
if(DEFINED SKBUILD_SCRIPTS_DIR)
    install(TARGETS gbdctool RUNTIME DESTINATION "gbdc.scripts")
    install(FILES "${PROJECT_SOURCE_DIR}/gbdc_cli.py" DESTINATION .)
else()
    # Plain CMake install (`make install`): put the tools on PATH and expose the per-tool
    # `gbd-<tool>` commands as symlinks to the single dispatching `gbdc` binary.
    install(TARGETS gbdctool RUNTIME DESTINATION "bin")
    install(CODE "
        set(_bindir \"bin\")
        if(NOT IS_ABSOLUTE \"\${_bindir}\")
            set(_bindir \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${_bindir}\")
        endif()
        foreach(toolname ${GBD_TOOL_NAMES})
            execute_process(COMMAND \${CMAKE_COMMAND} -E create_symlink gbdc \"\${_bindir}/\${toolname}\")
        endforeach()
    ")
endif()

pybind11_add_module(gbdc src/gbdlib.cc)
target_link_libraries(gbdc PUBLIC ${LIBS} util extract transform)
install(TARGETS gbdc DESTINATION .)

add_test(NAME Test_StreamBuffer COMMAND "test/tests_streambuffer")
# add_test(NAME Test_Feature_Extraction COMMAND "test/tests_feature_extraction")
add_test(NAME Test_StreamCompressor COMMAND "test/tests_streamcompressor")
add_test(NAME Test_GBDLib COMMAND "test/tests_gbdlib")
add_test(NAME Test_IsoHash2 COMMAND "test/tests_isohash2")