cmake_minimum_required(VERSION 3.20)

project(mini_vector
  VERSION 1.0.0
  DESCRIPTION "A from-scratch C++20 vector with custom allocator support"
  LANGUAGES CXX
)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

option(MINI_VECTOR_BUILD_TESTS "Build GoogleTest suite" ON)
option(MINI_VECTOR_BUILD_DEMO "Build the demo executable" ON)
option(MINI_VECTOR_SANITIZE "Enable AddressSanitizer and UndefinedSanitizer" ON)
option(MINI_VECTOR_USE_STUDENT
  "Compile tests/demo against student/vector.hpp instead of the reference implementation"
  OFF
)

function(mini_vector_apply_warnings target)
  if(MSVC)
    target_compile_options(${target} PRIVATE /W4 /WX)
  else()
    target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic -Werror)
  endif()
endfunction()

function(mini_vector_apply_sanitizers target)
  if(MINI_VECTOR_SANITIZE AND NOT MSVC)
    target_compile_options(${target} PRIVATE -fsanitize=address,undefined)
    target_link_options(${target} PRIVATE -fsanitize=address,undefined)
  endif()
endfunction()

add_library(mini_vector INTERFACE)
add_library(mini::vector ALIAS mini_vector)

if(MINI_VECTOR_USE_STUDENT)
  target_include_directories(mini_vector INTERFACE
    ${CMAKE_CURRENT_SOURCE_DIR}/student
  )
else()
  target_include_directories(mini_vector INTERFACE
    ${CMAKE_CURRENT_SOURCE_DIR}/include
  )
endif()

if(MINI_VECTOR_BUILD_DEMO)
  add_executable(mini_vector_demo examples/demo.cpp)
  target_link_libraries(mini_vector_demo PRIVATE mini::vector)
  mini_vector_apply_warnings(mini_vector_demo)
  mini_vector_apply_sanitizers(mini_vector_demo)
endif()

if(MINI_VECTOR_BUILD_TESTS)
  include(FetchContent)
  FetchContent_Declare(
    googletest
    URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.tar.gz
    URL_HASH SHA256=7b42b4d6ed48810c5362c265a17faebe90dc2373c885e5216439d37927f02926
    DOWNLOAD_EXTRACT_TIMESTAMP TRUE
  )
  set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
  FetchContent_MakeAvailable(googletest)

  enable_testing()

  add_executable(vector_tests
    tests/test_basic.cpp
    tests/test_no_default_ctor.cpp
    tests/test_custom_allocator.cpp
    tests/test_exception_safety.cpp
    tests/test_move_only.cpp
  )
  target_include_directories(vector_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests)
  target_link_libraries(vector_tests PRIVATE mini::vector GTest::gtest_main)
  mini_vector_apply_warnings(vector_tests)
  mini_vector_apply_sanitizers(vector_tests)

  include(GoogleTest)
  gtest_discover_tests(vector_tests)
endif()
