cmake_minimum_required(VERSION 3.25) project(UniversalContainer VERSION 0.1.0 LANGUAGES CXX) option(UC_BUILD_TESTS "Build the correctness test executable" ON) option(UC_BUILD_BENCHMARKS "Build the benchmark executable" ON) set(UC_VECTOR_PROFILE "baseline" CACHE STRING "Code generation profile: scalar, baseline, or avx2") set_property(CACHE UC_VECTOR_PROFILE PROPERTY STRINGS scalar baseline avx2) if(NOT UC_VECTOR_PROFILE MATCHES "^(scalar|baseline|avx2)$") message(FATAL_ERROR "UC_VECTOR_PROFILE must be scalar, baseline, or avx2") endif() set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE) if(MSVC) # Self-contained executables: /MT in Release and /MTd in Debug. set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() set(UC_OUTPUT_ROOT "${CMAKE_SOURCE_DIR}/out") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${UC_OUTPUT_ROOT}/bin/${UC_VECTOR_PROFILE}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${UC_OUTPUT_ROOT}/lib/${UC_VECTOR_PROFILE}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${UC_OUTPUT_ROOT}/lib/${UC_VECTOR_PROFILE}") set(CMAKE_PDB_OUTPUT_DIRECTORY "${UC_OUTPUT_ROOT}/symbols/${UC_VECTOR_PROFILE}") set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY "${UC_OUTPUT_ROOT}/symbols/${UC_VECTOR_PROFILE}") foreach(config Debug Release RelWithDebInfo MinSizeRel) string(TOUPPER "${config}" config_upper) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config_upper} "${UC_OUTPUT_ROOT}/bin/${UC_VECTOR_PROFILE}/${config}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${config_upper} "${UC_OUTPUT_ROOT}/lib/${UC_VECTOR_PROFILE}/${config}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${config_upper} "${UC_OUTPUT_ROOT}/lib/${UC_VECTOR_PROFILE}/${config}") set(CMAKE_PDB_OUTPUT_DIRECTORY_${config_upper} "${UC_OUTPUT_ROOT}/symbols/${UC_VECTOR_PROFILE}/${config}") set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_${config_upper} "${UC_OUTPUT_ROOT}/symbols/${UC_VECTOR_PROFILE}/${config}") endforeach() add_library(universal_container INTERFACE) target_include_directories(universal_container INTERFACE "${CMAKE_SOURCE_DIR}/include") target_compile_features(universal_container INTERFACE cxx_std_20) target_compile_definitions(universal_container INTERFACE UC_BUILD_PROFILE="${UC_VECTOR_PROFILE}") if(MSVC) target_compile_options(universal_container INTERFACE /W4 /permissive- /EHsc /Zc:__cplusplus) if(UC_VECTOR_PROFILE STREQUAL "scalar") # MSVC has no documented TU-wide switch. /d2Qvec- is accepted by the # installed compiler and its presence is command-line audited together # with /Qvec-report:1; the report text itself is not parsed; # _USE_STD_VECTOR_ALGORITHMS=0 also disables explicit SIMD in MSVC STL # algorithms. CRT memmove may still dispatch to SIMD internally. target_compile_options(universal_container INTERFACE $<$:/O2> /d2Qvec- /Qvec-report:1 /Oi-) target_compile_definitions(universal_container INTERFACE UC_SIMD_PROFILE_SCALAR=1 _USE_STD_VECTOR_ALGORITHMS=0) elseif(UC_VECTOR_PROFILE STREQUAL "avx2") target_compile_options(universal_container INTERFACE $<$:/O2> /arch:AVX2) target_compile_definitions(universal_container INTERFACE UC_SIMD_PROFILE_AVX2=1) else() # Baseline x64 code generation: auto-vectorization is enabled, but no AVX ISA is requested. target_compile_options(universal_container INTERFACE $<$:/O2>) target_compile_definitions(universal_container INTERFACE UC_SIMD_PROFILE_BASELINE=1) endif() else() target_compile_options(universal_container INTERFACE -Wall -Wextra -Wpedantic) if(UC_VECTOR_PROFILE STREQUAL "scalar") target_compile_options(universal_container INTERFACE $<$:-O2;-fno-tree-vectorize;-fno-tree-slp-vectorize;-mno-avx>) elseif(UC_VECTOR_PROFILE STREQUAL "avx2") target_compile_options(universal_container INTERFACE $<$:-O2;-mavx2>) else() target_compile_options(universal_container INTERFACE $<$:-O2;-mno-avx>) endif() endif() add_executable(uc_demo src/demo.cpp) target_link_libraries(uc_demo PRIVATE universal_container) set_property(TARGET uc_demo PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE) if(UC_BUILD_TESTS) enable_testing() add_executable(uc_tests tests/adaptive_sequence_tests.cpp) target_link_libraries(uc_tests PRIVATE universal_container) set_property(TARGET uc_tests PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE) add_test(NAME adaptive_sequence COMMAND uc_tests) endif() if(UC_BUILD_BENCHMARKS) add_executable(uc_bench src/benchmark.cpp) target_link_libraries(uc_bench PRIVATE universal_container) set_property(TARGET uc_bench PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE) add_executable(uc_focused_bench src/focused_benchmark.cpp) target_link_libraries(uc_focused_bench PRIVATE universal_container) set_property(TARGET uc_focused_bench PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE) endif()