cmake_minimum_required(VERSION 3.24) #------------------------------------------------------------------------------- # Prefer Clang over GCC if available #------------------------------------------------------------------------------- if(UNIX AND NOT CMAKE_GENERATOR MATCHES "Visual Studio") find_program(CLANG_CC clang) find_program(CLANG_CXX clang++) if(CLANG_CC AND CLANG_CXX) if(NOT DEFINED CMAKE_C_COMPILER) set(CMAKE_C_COMPILER ${CLANG_CC} CACHE PATH "C compiler") endif() if(NOT DEFINED CMAKE_CXX_COMPILER) set(CMAKE_CXX_COMPILER ${CLANG_CXX} CACHE PATH "C++ compiler") endif() endif() endif() project(bsc VERSION 3.3.12 LANGUAGES C CXX) #------------------------------------------------------------------------------- # Options #------------------------------------------------------------------------------- option(BSC_ENABLE_NATIVE_COMPILATION "Enable platform-native optimizations" ON) option(BSC_ENABLE_OPENMP "Enable OpenMP support" ON) option(BSC_ENABLE_CUDA "Enable CUDA support (requires OpenMP)" ON) option(BSC_BUILD_SHARED_LIB "Build libbsc as a shared library" OFF) #------------------------------------------------------------------------------- # Language standards #------------------------------------------------------------------------------- set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) #------------------------------------------------------------------------------- # Default build type #------------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Release' as none was specified.") set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) endif() #------------------------------------------------------------------------------- # Detect architecture specific optimizations support #------------------------------------------------------------------------------- if(BSC_ENABLE_NATIVE_COMPILATION) include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) include(CheckCSourceRuns) check_c_compiler_flag(-march=native COMPILER_SUPPORTS_MARCH_NATIVE_C) check_cxx_compiler_flag(-march=native COMPILER_SUPPORTS_MARCH_NATIVE_CXX) if(MSVC AND NOT (COMPILER_SUPPORTS_MARCH_NATIVE_C AND COMPILER_SUPPORTS_MARCH_NATIVE_CXX)) check_c_source_runs( "#include\\nint main() { int r[4]; __cpuid(r, 7); return (r[1] & (1 << 30)) && ((_xgetbv(0) & 0xe0) == 0xe0) ? 0 : 1; }" COMPILER_SUPPORTS_MSVC_ARCH_AVX512 ) check_c_source_runs( "#include\\nint main() { int r[4]; __cpuid(r, 7); return (r[1] & (1 << 5)) && ((_xgetbv(0) & 0x06) == 0x06) ? 0 : 1; }" COMPILER_SUPPORTS_MSVC_ARCH_AVX2 ) check_c_source_runs( "#include\\nint main() { int r[4]; __cpuid(r, 1); return (r[2] & (1 << 20)) ? 0 : 1; }" COMPILER_SUPPORTS_MSVC_ARCH_SSE42 ) else() set(COMPILER_SUPPORTS_MSVC_ARCH_AVX512 OFF) set(COMPILER_SUPPORTS_MSVC_ARCH_AVX2 OFF) set(COMPILER_SUPPORTS_MSVC_ARCH_SSE42 OFF) endif() set(COMPILER_CUDA_ARCHITECTURES "native") else() set(COMPILER_SUPPORTS_MARCH_NATIVE_C OFF) set(COMPILER_SUPPORTS_MARCH_NATIVE_CXX OFF) set(COMPILER_SUPPORTS_MSVC_ARCH_AVX512 OFF) set(COMPILER_SUPPORTS_MSVC_ARCH_AVX2 OFF) set(COMPILER_SUPPORTS_MSVC_ARCH_SSE42 OFF) set(COMPILER_CUDA_ARCHITECTURES "all") endif() #------------------------------------------------------------------------------- # Detect OpenMP support #------------------------------------------------------------------------------- if(BSC_ENABLE_OPENMP) find_package(OpenMP) if(OpenMP_FOUND) message(STATUS "OpenMP found; enabling OpenMP support.") else() message(WARNING "OpenMP not found; disabling OpenMP support.") set(BSC_ENABLE_OPENMP OFF) endif() endif() #------------------------------------------------------------------------------- # Detect CUDA support #------------------------------------------------------------------------------- if(BSC_ENABLE_CUDA) if(NOT BSC_ENABLE_OPENMP) message(WARNING "OpenMP is required for CUDA; disabling CUDA support.") set(BSC_ENABLE_CUDA OFF) elseif(MSVC AND NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")) message(WARNING "${CMAKE_CXX_COMPILER_ID} is not supported by nvcc on Windows; disabling CUDA support.") set(BSC_ENABLE_CUDA OFF) else() find_package(CUDAToolkit) if(CUDAToolkit_FOUND) include(CheckLanguage) check_language(CUDA) if (CMAKE_CUDA_COMPILER) message(STATUS "CUDA Toolkit and CUDA Compiler found; enabling CUDA support.") set(CMAKE_CUDA_HOST_COMPILER ${CMAKE_CXX_COMPILER}) enable_language(CUDA) else() message(WARNING "CUDA Compiler not found; disabling CUDA support.") set(BSC_ENABLE_CUDA OFF) endif() else() message(WARNING "CUDA Toolkit not found; disabling CUDA support.") set(BSC_ENABLE_CUDA OFF) endif() endif() endif() #------------------------------------------------------------------------------- # libbsc library target #------------------------------------------------------------------------------- if(BSC_BUILD_SHARED_LIB) set(BSC_LIBRARY_TYPE SHARED) else() set(BSC_LIBRARY_TYPE STATIC) endif() add_library(libbsc ${BSC_LIBRARY_TYPE}) set_target_properties(libbsc PROPERTIES PREFIX "" IMPORT_PREFIX "") add_library(bsc::libbsc ALIAS libbsc) target_sources(libbsc PRIVATE libbsc/adler32/adler32.cpp libbsc/bwt/bwt.cpp libbsc/bwt/libsais/libsais.c libbsc/coder/coder.cpp libbsc/coder/qlfc/qlfc.cpp libbsc/coder/qlfc/qlfc_model.cpp libbsc/filters/detectors.cpp libbsc/filters/preprocessing.cpp libbsc/libbsc/libbsc.cpp libbsc/lzp/lzp.cpp libbsc/platform/platform.cpp libbsc/st/st.cpp ) if(BSC_BUILD_SHARED_LIB) target_compile_definitions(libbsc PUBLIC LIBBSC_SHARED) target_compile_definitions(libbsc PRIVATE LIBBSC_EXPORTS) endif() #------------------------------------------------------------------------------- # Enable architecture specific optimizations #------------------------------------------------------------------------------- if(COMPILER_SUPPORTS_MARCH_NATIVE_C) target_compile_options(libbsc PRIVATE $<$:-march=native>) elseif(COMPILER_SUPPORTS_MSVC_ARCH_AVX512) target_compile_options(libbsc PRIVATE $<$:/arch:AVX512>) elseif(COMPILER_SUPPORTS_MSVC_ARCH_AVX2) target_compile_options(libbsc PRIVATE $<$:/arch:AVX2>) elseif(COMPILER_SUPPORTS_MSVC_ARCH_SSE42) target_compile_options(libbsc PRIVATE $<$:/arch:SSE4.2>) endif() if(COMPILER_SUPPORTS_MARCH_NATIVE_CXX) target_compile_options(libbsc PRIVATE $<$:-march=native>) elseif(COMPILER_SUPPORTS_MSVC_ARCH_AVX512) target_compile_options(libbsc PRIVATE $<$:/arch:AVX512>) elseif(COMPILER_SUPPORTS_MSVC_ARCH_AVX2) target_compile_options(libbsc PRIVATE $<$:/arch:AVX2>) elseif(COMPILER_SUPPORTS_MSVC_ARCH_SSE42) target_compile_options(libbsc PRIVATE $<$:/arch:SSE4.2>) endif() #------------------------------------------------------------------------------- # Enable OpenMP support #------------------------------------------------------------------------------- if(BSC_ENABLE_OPENMP) target_compile_definitions(libbsc PRIVATE LIBSAIS_OPENMP) target_compile_definitions(libbsc PUBLIC LIBBSC_OPENMP_SUPPORT) target_link_libraries(libbsc PUBLIC OpenMP::OpenMP_C OpenMP::OpenMP_CXX) endif() #------------------------------------------------------------------------------- # Enable CUDA support #------------------------------------------------------------------------------- if(BSC_ENABLE_CUDA) set_target_properties(libbsc PROPERTIES CUDA_ARCHITECTURES ${COMPILER_CUDA_ARCHITECTURES}) target_sources(libbsc PRIVATE libbsc/st/st.cu libbsc/bwt/libcubwt/libcubwt.cu ) target_compile_options(libbsc PRIVATE $<$:-Xcompiler=${OpenMP_CXX_FLAGS};-Wno-deprecated-gpu-targets> ) target_compile_definitions(libbsc PUBLIC LIBBSC_CUDA_SUPPORT) target_link_libraries(libbsc PUBLIC CUDA::cudart) endif() #------------------------------------------------------------------------------- # bsc executable target #------------------------------------------------------------------------------- add_executable(bsc bsc.cpp) target_link_libraries(bsc PUBLIC bsc::libbsc) #------------------------------------------------------------------------------- # Installation directives #------------------------------------------------------------------------------- include(GNUInstallDirs) install(FILES libbsc/filters.h libbsc/libbsc.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libbsc ) install(TARGETS libbsc ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libbsc ) install(TARGETS bsc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )