BareGit
# cmake -B build . && cmake --build build -j
cmake_minimum_required(VERSION 3.24)

set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
set(CMAKE_POLICY_VERSION_MINIMUM 3.5)

project(Overseer)

option(OVERSEER_BUILD_TEST "Build unit tests." OFF)

include(FetchContent)

FetchContent_Declare(
    libmw
    GIT_REPOSITORY https://github.com/MetroWind/libmw.git
)
FetchContent_Declare(
    json
    GIT_REPOSITORY https://github.com/nlohmann/json.git
    GIT_TAG v3.11.3
)
FetchContent_Declare(
    inja
    GIT_REPOSITORY https://github.com/pantor/inja.git
    GIT_TAG main
)
FetchContent_Declare(
    spdlog
    GIT_REPOSITORY https://github.com/gabime/spdlog.git
    GIT_TAG v1.12.0
)
FetchContent_Declare(
    yaml-cpp
    GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
    GIT_TAG master           # 0.8.0 misses <cstdint> include; broken on GCC 15
)
FetchContent_Declare(
    cxxopts
    GIT_REPOSITORY https://github.com/jarro2783/cxxopts.git
    GIT_TAG v3.1.1
)
if(OVERSEER_BUILD_TEST)
    FetchContent_Declare(
        googletest
        URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz
    )
endif()

set(LIBMW_BUILD_URL ON)
set(LIBMW_BUILD_SQLITE ON)
set(LIBMW_BUILD_HTTP_SERVER ON)
set(LIBMW_BUILD_CRYPTO ON)
set(SPDLOG_USE_STD_FORMAT ON)
set(INJA_USE_EMBEDDED_JSON FALSE)
set(INJA_BUILD_TESTS FALSE)
set(BUILD_BENCHMARK FALSE)
set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "")
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "")
set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "")

# json must be visible to inja
include_directories(BEFORE SYSTEM)
FetchContent_MakeAvailable(libmw json inja spdlog yaml-cpp cxxopts)
if(OVERSEER_BUILD_TEST)
    FetchContent_MakeAvailable(googletest)
endif()

find_package(CURL REQUIRED)
find_package(SQLite3 REQUIRED)

find_package(PkgConfig REQUIRED)
pkg_check_modules(Magick REQUIRED IMPORTED_TARGET Magick++)
pkg_check_modules(Systemd REQUIRED IMPORTED_TARGET libsystemd)

# ---- Common include dirs / libs ----------------------------------------

set(OVERSEER_COMMON_INCLUDES
    ${libmw_SOURCE_DIR}/includes
    ${CURL_INCLUDE_DIR}
    ${json_SOURCE_DIR}/single_include
    ${inja_SOURCE_DIR}/single_include/inja
    ${SQLite3_INCLUDE_DIRS}
)

set(OVERSEER_COMMON_LIBS
    mw::mw
    mw::url
    mw::sqlite
    mw::http-server
    mw::crypto
    spdlog::spdlog
    yaml-cpp::yaml-cpp
    ${CURL_LIBRARIES}
    ${SQLite3_LIBRARIES}
)

# ---- liboverseer_inventory --------------------------------------------

set(INVENTORY_SOURCES
    src/inventory/src/storage.cpp
    src/inventory/src/stuff.cpp
    src/inventory/src/search.cpp
    src/inventory/src/attachment.cpp
    src/inventory/src/repo.cpp
)

add_library(overseer_inventory STATIC ${INVENTORY_SOURCES})
set_property(TARGET overseer_inventory PROPERTY CXX_STANDARD 23)
set_property(TARGET overseer_inventory PROPERTY CXX_EXTENSIONS OFF)
target_compile_options(overseer_inventory PRIVATE
    -Wall -Wextra -Wpedantic)
target_include_directories(overseer_inventory
    PUBLIC src/inventory/include
    PRIVATE ${OVERSEER_COMMON_INCLUDES})
target_link_libraries(overseer_inventory PUBLIC
    ${OVERSEER_COMMON_LIBS}
    PkgConfig::Magick)

# ---- overseer_db ------------------------------------------------------

set(DB_SOURCES
    src/db/migrations.cpp
    src/db/migration_001_init.cpp
    src/db/backup.cpp
)

add_library(overseer_db STATIC ${DB_SOURCES})
set_property(TARGET overseer_db PROPERTY CXX_STANDARD 23)
set_property(TARGET overseer_db PROPERTY CXX_EXTENSIONS OFF)
target_compile_options(overseer_db PRIVATE
    -Wall -Wextra -Wpedantic)
target_include_directories(overseer_db
    PUBLIC src
    PRIVATE ${OVERSEER_COMMON_INCLUDES})
target_link_libraries(overseer_db PUBLIC ${OVERSEER_COMMON_LIBS})

# ---- overseer (binary) ------------------------------------------------

set(OVERSEER_SOURCES
    src/overseer/main.cpp
    src/overseer/config.cpp
    src/overseer/render.cpp
    src/overseer/session.cpp
    src/overseer/auth_handler.cpp
    src/overseer/attachment_handler.cpp
    src/overseer/server.cpp
    src/overseer/modules/inventory/routes.cpp
    src/overseer/modules/inventory/views.cpp
)

add_executable(overseer ${OVERSEER_SOURCES})
set_property(TARGET overseer PROPERTY CXX_STANDARD 23)
set_property(TARGET overseer PROPERTY CXX_EXTENSIONS OFF)
target_compile_options(overseer PRIVATE
    -Wall -Wextra -Wpedantic)
target_include_directories(overseer PRIVATE
    src
    ${OVERSEER_COMMON_INCLUDES})
target_link_libraries(overseer PRIVATE
    overseer_inventory
    overseer_db
    cxxopts
    PkgConfig::Magick
    PkgConfig::Systemd)

# Where the runtime data lives during dev:
target_compile_definitions(overseer PRIVATE
    OVERSEER_DEFAULT_TEMPLATE_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/overseer/modules"
    OVERSEER_DEFAULT_STATIC_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/static")

# ---- tests ------------------------------------------------------------

if(OVERSEER_BUILD_TEST)
    # Server / route code reused by the HTTP integration tests. We
    # rebuild just enough of the binary's source so the test binary
    # links cleanly without dragging in main().
    add_library(overseer_server STATIC
        src/overseer/config.cpp
        src/overseer/render.cpp
        src/overseer/session.cpp
        src/overseer/auth_handler.cpp
        src/overseer/attachment_handler.cpp
        src/overseer/server.cpp
        src/overseer/modules/inventory/routes.cpp
        src/overseer/modules/inventory/views.cpp)
    set_property(TARGET overseer_server PROPERTY CXX_STANDARD 23)
    set_property(TARGET overseer_server PROPERTY CXX_EXTENSIONS OFF)
    target_compile_options(overseer_server PRIVATE
        -Wall -Wextra -Wpedantic)
    target_include_directories(overseer_server PUBLIC
        src
        ${OVERSEER_COMMON_INCLUDES})
    target_link_libraries(overseer_server PUBLIC
        overseer_inventory overseer_db
        PkgConfig::Magick
        PkgConfig::Systemd)
    target_compile_definitions(overseer_server PRIVATE
        OVERSEER_DEFAULT_TEMPLATE_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/overseer/modules"
        OVERSEER_DEFAULT_STATIC_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/static")

    set(TEST_FILES
        tests/test_inventory.cpp
        tests/test_migrations.cpp
        tests/test_http.cpp
        tests/support/seed.cpp
    )
    add_executable(overseer_test ${TEST_FILES})
    set_property(TARGET overseer_test PROPERTY CXX_STANDARD 23)
    target_include_directories(overseer_test PRIVATE
        src
        tests
        ${OVERSEER_COMMON_INCLUDES}
        ${googletest_SOURCE_DIR}/googletest/include)
    target_link_libraries(overseer_test PRIVATE
        overseer_server overseer_inventory overseer_db
        GTest::gtest_main GTest::gmock_main)
    target_compile_definitions(overseer_test PRIVATE
        OVERSEER_TEST_TEMPLATE_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/overseer/modules"
        OVERSEER_TEST_STATIC_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/static")

    enable_testing()
    include(GoogleTest)
    gtest_discover_tests(overseer_test
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endif()