cmake_minimum_required(VERSION 3.20)
project(fetchml_native VERSION 0.1.0 LANGUAGES CXX C)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

# Build options
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)
option(ENABLE_TSAN "Enable ThreadSanitizer" OFF)

# Position independent code for shared libraries
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# Compiler flags
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
    set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -DNDEBUG -fomit-frame-pointer")
    set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -fno-omit-frame-pointer")
    set(CMAKE_C_FLAGS_RELEASE "-O3 -march=native -DNDEBUG -fomit-frame-pointer")
    set(CMAKE_C_FLAGS_DEBUG "-O0 -g -fno-omit-frame-pointer")
    
    # Security hardening flags (always enabled)
    set(SECURITY_FLAGS
        -D_FORTIFY_SOURCE=2       # Buffer overflow protection
        -fstack-protector-strong  # Stack canaries
        -Wformat-security         # Format string warnings
        -Werror=format-security   # Format string errors
        -fPIE                     # Position-independent code
    )
    
    # Add security flags to all build types
    add_compile_options(${SECURITY_FLAGS})
    
    # Linker security flags (Linux only)
    if(CMAKE_SYSTEM_NAME MATCHES "Linux")
        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now -pie")
        set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now")
    endif()
    
    # Warnings
    add_compile_options(-Wall -Wextra -Wpedantic)
    
    if(ENABLE_ASAN)
        add_compile_options(-fsanitize=address,undefined -fno-omit-frame-pointer)
        add_link_options(-fsanitize=address,undefined)
    endif()
    
    if(ENABLE_TSAN)
        add_compile_options(-fsanitize=thread)
        add_link_options(-fsanitize=thread)
    endif()
endif()

if(APPLE)
    # macOS universal binary support (optional - comment out if targeting single arch)
    # set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
endif()

# Find threading library
find_package(Threads REQUIRED)

# Include directories
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

# Enable testing
enable_testing()

# Libraries will be added as subdirectories
add_subdirectory(common)
add_subdirectory(queue_index)
add_subdirectory(dataset_hash)
add_subdirectory(nvml_gpu)

# Tests from root tests/ directory
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests)
    add_executable(test_storage tests/test_storage.cpp)
    target_link_libraries(test_storage queue_index)
    add_test(NAME storage_smoke COMMAND test_storage)
    
    add_executable(test_dataset_hash tests/test_dataset_hash.cpp)
    target_link_libraries(test_dataset_hash dataset_hash)
    add_test(NAME dataset_hash_smoke COMMAND test_dataset_hash)
    
    # Test storage_init on new directories
    add_executable(test_storage_init_new_dir tests/test_storage_init_new_dir.cpp)
    target_link_libraries(test_storage_init_new_dir queue_index)
    add_test(NAME storage_init_new_dir COMMAND test_storage_init_new_dir)
    
    # Test parallel_hash with >256 files
    add_executable(test_parallel_hash_large_dir tests/test_parallel_hash_large_dir.cpp)
    target_link_libraries(test_parallel_hash_large_dir dataset_hash)
    add_test(NAME parallel_hash_large_dir COMMAND test_parallel_hash_large_dir)
    
    # Test queue_index compact
    add_executable(test_queue_index_compact tests/test_queue_index_compact.cpp)
    target_link_libraries(test_queue_index_compact queue_index)
    add_test(NAME queue_index_compact COMMAND test_queue_index_compact)
    
    # Test ARMv8 SHA256 (only on ARM64)
    if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
        add_executable(test_sha256_arm_kat tests/test_sha256_arm_kat.cpp)
        target_link_libraries(test_sha256_arm_kat dataset_hash)
        add_test(NAME sha256_arm_kat COMMAND test_sha256_arm_kat)
    endif()
    
    # CVE-2024-45339: Test storage symlink resistance
    add_executable(test_storage_symlink_resistance tests/test_storage_symlink_resistance.cpp)
    target_link_libraries(test_storage_symlink_resistance queue_index)
    add_test(NAME storage_symlink_resistance COMMAND test_storage_symlink_resistance)
    
    # CVE-2025-0838: Test queue index batch limit
    add_executable(test_queue_index_batch_limit tests/test_queue_index_batch_limit.cpp)
    target_link_libraries(test_queue_index_batch_limit queue_index)
    add_test(NAME queue_index_batch_limit COMMAND test_queue_index_batch_limit)
endif()

# Combined target for building all libraries
add_custom_target(all_native_libs DEPENDS 
    queue_index 
    dataset_hash
    nvml_gpu
)
