kfr

Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON)
Log | Files | Refs | README

CMakeLists.txt (14894B)


      1 # Copyright (C) 2016-2023 Dan Cazarin (https://www.kfrlib.com)
      2 # This file is part of KFR
      3 #
      4 # KFR is free software: you can redistribute it and/or modify
      5 # it under the terms of the GNU General Public License as published by
      6 # the Free Software Foundation, either version 2 of the License, or
      7 # (at your option) any later version.
      8 #
      9 # KFR is distributed in the hope that it will be useful,
     10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 # GNU General Public License for more details.
     13 #
     14 # You should have received a copy of the GNU General Public License
     15 # along with KFR.
     16 
     17 cmake_minimum_required(VERSION 3.12)
     18 
     19 if (KFR_WITH_CLANG)
     20     set(CLANG_VERSION 17.0.6)
     21     if (WIN32)
     22         set(CLANG_URL
     23             https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/LLVM-${CLANG_VERSION}-win64.exe
     24         )
     25         set(CLANG_ARCH_FILE "${CMAKE_CURRENT_BINARY_DIR}/clang-prebuilt.exe")
     26         set(CLANG_DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/clang")
     27 
     28         set(SEVENZIP_URL https://www.7-zip.org/a/7z2301-x64.msi)
     29         set(SEVENZIP_ARCH_FILE "${CMAKE_CURRENT_BINARY_DIR}/7z2301-x64.msi")
     30         set(SEVENZIP_DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/7z")
     31         message(STATUS "Downloading 7zip from ${SEVENZIP_URL}")
     32         file(
     33             DOWNLOAD ${SEVENZIP_URL} ${SEVENZIP_ARCH_FILE}
     34             EXPECTED_HASH
     35                 SHA256=0BA639B6DACDF573D847C911BD147C6384381A54DAC082B1E8C77BC73D58958B
     36             SHOW_PROGRESS)
     37 
     38         cmake_path(NATIVE_PATH SEVENZIP_ARCH_FILE NORMALIZE
     39                    SEVENZIP_ARCH_FILE_W)
     40         cmake_path(NATIVE_PATH SEVENZIP_DEST_DIR NORMALIZE SEVENZIP_DEST_DIR_W)
     41         execute_process(COMMAND msiexec /a "${SEVENZIP_ARCH_FILE_W}"
     42                                 "TARGETDIR=${SEVENZIP_DEST_DIR_W}" /qn)
     43 
     44         message(STATUS "Downloading Clang ${CLANG_VERSION} from ${CLANG_URL}")
     45         file(
     46             DOWNLOAD ${CLANG_URL} ${CLANG_ARCH_FILE}
     47             EXPECTED_HASH
     48                 SHA256=89dc351af8e8fa1cafc6b48411e608aa9457c930a10f984aad5d21ab020165b2
     49             SHOW_PROGRESS)
     50 
     51         message(STATUS "Unpacking Clang ${CLANG_VERSION}")
     52         execute_process(
     53             COMMAND ${SEVENZIP_DEST_DIR}/Files/7-Zip/7z.exe x -bb0 -bd -aos
     54                     -o${CLANG_DEST_DIR} ${CLANG_ARCH_FILE} OUTPUT_QUIET)
     55 
     56         set(CMAKE_CXX_COMPILER
     57             ${CLANG_DEST_DIR}/bin/clang-cl.exe
     58             CACHE STRING "Clang" FORCE)
     59         set(CMAKE_C_COMPILER
     60             ${CLANG_DEST_DIR}/bin/clang-cl.exe
     61             CACHE STRING "Clang" FORCE)
     62     endif ()
     63     if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
     64         set(CLANG_URL
     65             https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/clang+llvm-${CLANG_VERSION}-x86_64-linux-gnu-ubuntu-22.04.tar.xz
     66         )
     67         set(CLANG_ARCH_FILE "${CMAKE_CURRENT_BINARY_DIR}/clang-prebuilt.tar.xz")
     68         set(CLANG_DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/clang")
     69         message(STATUS "Downloading Clang ${CLANG_VERSION} from ${CLANG_URL}")
     70         file(
     71             DOWNLOAD ${CLANG_URL} ${CLANG_ARCH_FILE}
     72             EXPECTED_HASH
     73                 SHA256=884ee67d647d77e58740c1e645649e29ae9e8a6fe87c1376be0f3a30f3cc9ab3
     74             SHOW_PROGRESS)
     75         message(STATUS "Unpacking Clang ${CLANG_VERSION}")
     76         file(ARCHIVE_EXTRACT INPUT ${CLANG_ARCH_FILE} DESTINATION
     77              ${CLANG_DEST_DIR})
     78         set(CMAKE_CXX_COMPILER
     79             ${CLANG_DEST_DIR}/clang+llvm-${CLANG_VERSION}-x86_64-linux-gnu-ubuntu-22.04/bin/clang++
     80             CACHE STRING "Clang" FORCE)
     81         set(CMAKE_C_COMPILER
     82             ${CLANG_DEST_DIR}/clang+llvm-${CLANG_VERSION}-x86_64-linux-gnu-ubuntu-22.04/bin/clang
     83             CACHE STRING "Clang" FORCE)
     84     endif ()
     85     message(STATUS "Clang ${CLANG_VERSION} is set up successfully")
     86 endif ()
     87 
     88 file(STRINGS ${CMAKE_CURRENT_LIST_DIR}/include/kfr/kfr.h KFR_VERSION
     89      REGEX "#define KFR_VERSION_(MINOR|MAJOR|PATCH)")
     90 string(REGEX MATCHALL "[0-9]+" KFR_VERSION_MATCH ${KFR_VERSION})
     91 string(REPLACE ";" "." KFR_VERSION "${KFR_VERSION_MATCH}")
     92 
     93 project(
     94     kfr
     95     VERSION ${KFR_VERSION}
     96     LANGUAGES CXX)
     97     
     98 if (DEBUG_CMAKE)
     99     get_cmake_property(VARS VARIABLES)
    100     list (SORT VARS)
    101     foreach (VAR ${VARS})
    102         message(STATUS "${VAR}=${${VAR}}")
    103     endforeach()
    104 endif ()
    105 
    106 set(CMAKE_CXX_STANDARD 17)
    107 set(CMAKE_CXX_STANDARD_REQUIRED ON)
    108 set(CMAKE_CXX_EXTENSIONS ON)
    109 
    110 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/bin)
    111 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${PROJECT_BINARY_DIR}/bin)
    112 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/bin)
    113 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/lib)
    114 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${PROJECT_BINARY_DIR}/lib)
    115 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/lib)
    116 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/lib)
    117 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${PROJECT_BINARY_DIR}/lib)
    118 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/lib)
    119 
    120 if (CPU_ARCH)
    121     if (NOT KFR_ARCH)
    122         message(
    123             WARNING
    124                 "CPU_ARCH is deprecated. Use KFR_ARCH instead. KFR will use machine native architecture by default"
    125         )
    126     else ()
    127         message(
    128             WARNING
    129                 "Both KFR_ARCH and CPU_ARCH are defined. KFR will use architecture set by KFR_ARCH (${KFR_ARCH})"
    130         )
    131     endif ()
    132 endif ()
    133 
    134 if (EMSCRIPTEN)
    135     set(KFR_ARCH "sse41" CACHE STRING "")
    136     set(KFR_ENABLE_MULTIARCH OFF CACHE BOOL "")
    137 endif ()
    138 
    139 set(X86 FALSE)
    140 if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
    141     set(X86 TRUE)
    142 endif ()
    143 if (CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
    144     set(X86 TRUE)
    145 endif ()
    146 if (CMAKE_OSX_ARCHITECTURES MATCHES "^[Aa][Rr][Mm]64$")
    147     set(X86 FALSE)
    148 endif ()
    149 
    150 if (CMAKE_CXX_COMPILER_TARGET MATCHES "^arm")
    151     set(X86 FALSE)
    152 endif ()
    153 
    154 if (CMAKE_ANDROID_ARCH_ABI MATCHES "x86")
    155     set(X86 TRUE)
    156 endif ()
    157 
    158 if (CMAKE_SIZEOF_VOID_P EQUAL 8)
    159     set(BITNESS64 TRUE)
    160 else ()
    161     set(BITNESS64 FALSE)
    162 endif ()
    163 
    164 if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL
    165                                               "AppleClang")
    166     set(CLANG 1)
    167 else ()
    168     set(CLANG 0)
    169 endif ()
    170 
    171 include(cmake/target_set_arch.cmake)
    172 include(cmake/link_as_whole.cmake)
    173 include(cmake/add_kfr_library.cmake)
    174 
    175 # Include autogenerated list of source files
    176 include(sources.cmake)
    177 include(CMakeDependentOption)
    178 
    179 option(KFR_ENABLE_MULTIARCH
    180        "Multiple architectures will be built with runtime dispatch" ON)
    181 
    182 option(ENABLE_TESTS "Enable KFR tests" OFF)
    183 cmake_dependent_option(ENABLE_EXAMPLES "Enable KFR examples" ON "ENABLE_TESTS"
    184                        OFF)
    185 if (CLANG)
    186     option(KFR_ENABLE_DFT "Enable DFT and related algorithms." ON)
    187 else ()
    188     option(KFR_ENABLE_DFT "Enable DFT and related algorithms." OFF)
    189 endif ()
    190 option(KFR_ENABLE_ASMTEST "Enable writing disassembly" OFF)
    191 option(KFR_REGENERATE_TESTS "Regenerate auto tests" OFF)
    192 option(KFR_DISABLE_CLANG_EXTENSIONS "Disable Clang vector extensions" OFF)
    193 option(KFR_EXTENDED_TESTS "Extended tests (up to hour)" OFF)
    194 option(KFR_SKIP_TESTS "Build tests but don't run tests" OFF)
    195 option(KFR_ENABLE_CAPI_BUILD "Enable KFR C API building" OFF)
    196 option(KFR_INSTALL_HEADERS "Include headers in installation" ON)
    197 option(KFR_INSTALL_LIBRARIES "Include libraries in installation" ON)
    198 mark_as_advanced(KFR_ENABLE_ASMTEST)
    199 mark_as_advanced(KFR_REGENERATE_TESTS)
    200 mark_as_advanced(KFR_DISABLE_CLANG_EXTENSIONS)
    201 
    202 if (CMAKE_ANDROID_ARCH_ABI)
    203     set(KFR_ENABLE_MULTIARCH OFF CACHE INTERNAL "" FORCE)
    204 endif ()
    205 
    206 if (KFR_ENABLE_CAPI_BUILD AND NOT KFR_ENABLE_DFT)
    207     message(
    208         FATAL_ERROR
    209             "KFR_ENABLE_CAPI_BUILD requires KFR_ENABLE_DFT to be enabled")
    210 endif ()
    211 
    212 if (NOT KFR_ARCH)
    213     set(KFR_ARCH target)
    214 endif ()
    215 
    216 if (KFR_ARCH STREQUAL "detect")
    217     set(KFR_ARCH host)
    218 endif ()
    219 
    220 set(DETECT_NAMES host target)
    221 if (X86)
    222     set(ALLOWED_ARCHS
    223         generic
    224         sse
    225         sse2
    226         sse3
    227         ssse3
    228         sse41
    229         sse42
    230         avx
    231         avx2
    232         avx512)
    233 else ()
    234     set(ALLOWED_ARCHS generic neon neon64)
    235 endif ()
    236 
    237 if (NOT X86)
    238     if (KFR_ARCH IN_LIST DETECT_NAMES)
    239         if (BITNESS64)
    240             set(KFR_ARCH neon64)
    241         else ()
    242             set(KFR_ARCH neon)
    243         endif ()
    244     endif ()
    245 endif ()
    246 
    247 if (KFR_ARCH IN_LIST DETECT_NAMES AND NOT CMAKE_CROSSCOMPILING)
    248     message(STATUS "Detecting ${KFR_ARCH} architecture")
    249     try_run(
    250         RUN_RESULT COMPILE_RESULT "${CMAKE_CURRENT_BINARY_DIR}/tmpdir"
    251         ${CMAKE_CURRENT_SOURCE_DIR}/cmake/detect_cpu.cpp
    252         CMAKE_FLAGS
    253             "-DINCLUDE_DIRECTORIES=${CMAKE_CURRENT_SOURCE_DIR}/include"
    254             -DCMAKE_CXX_STANDARD=17
    255             -DCMAKE_CXX_STANDARD_REQUIRED=ON
    256             "-DCOMPILE_DEFINITIONS=-DCPU_${KFR_ARCH}=1"
    257             -DCMAKE_CXX_EXTENSIONS=ON
    258         COMPILE_OUTPUT_VARIABLE COMPILE_OUT
    259         RUN_OUTPUT_VARIABLE RUN_OUT)
    260     if (COMPILE_RESULT AND RUN_RESULT EQUAL 0)
    261         message(
    262             STATUS
    263                 "Default CPU architecture for KFR is ${RUN_OUT} (set KFR_ARCH to override)"
    264         )
    265         set(KFR_ARCH
    266             ${RUN_OUT}
    267             CACHE INTERNAL "Detected CPU" FORCE)
    268     else ()
    269         message(STATUS COMPILE_RESULT = ${COMPILE_RESULT})
    270         message(STATUS RUN_RESULT = ${RUN_RESULT})
    271         message(STATUS COMPILE_OUT = ${COMPILE_OUT})
    272         message(FATAL_ERROR RUN_OUT = ${RUN_OUT})
    273     endif ()
    274 else ()
    275     message(
    276         STATUS
    277             "Default CPU architecture for KFR is ${KFR_ARCH} (set by KFR_ARCH)")
    278 endif ()
    279 
    280 
    281 if (X86 AND KFR_ARCH STREQUAL "target")
    282     set(KFR_ARCH sse2 CACHE INTERNAL "Default CPU" FORCE)
    283 endif ()
    284 
    285 if (NOT KFR_ARCH IN_LIST ALLOWED_ARCHS)
    286     message(FATAL_ERROR "Incorrect architecture set by KFR_ARCH: ${KFR_ARCH}")
    287 endif ()
    288 
    289 if (NOT KFR_ARCHS)
    290     if (X86)
    291         if (APPLE)
    292             set(KFR_ARCHS sse41 avx avx2 avx512)
    293         else ()
    294             set(KFR_ARCHS sse2 sse41 avx avx2 avx512)
    295         endif ()
    296     else ()
    297         set(KFR_ARCHS ${KFR_ARCH})
    298     endif ()
    299 endif ()
    300 
    301 if (KFR_ENABLE_MULTIARCH)
    302     message(
    303         STATUS
    304             "Runtime dispatch is enabled for architectures: ${KFR_ARCHS} (set KFR_ARCHS to change, set KFR_ENABLE_MULTIARCH=OFF to disable)"
    305     )
    306 else ()
    307     message(
    308         STATUS
    309             "Runtime dispatch is disabled. Set KFR_ENABLE_MULTIARCH=ON to enable"
    310     )
    311 endif ()
    312 
    313 string(REPLACE ";" ", " KFR_ARCHS_COMMA "${KFR_ARCHS}")
    314 
    315 if (KFR_ENABLE_MULTIARCH)
    316     add_compile_definitions(KFR_ENABLED_ARCHS="${KFR_ARCHS_COMMA}")
    317 endif ()
    318 
    319 add_library(use_arch INTERFACE)
    320 target_set_arch(use_arch INTERFACE ${KFR_ARCH})
    321 
    322 if (WIN32)
    323     add_definitions(-D_CRT_SECURE_NO_WARNINGS)
    324     add_definitions(-D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS)
    325     add_definitions(-D_ENABLE_EXTENDED_ALIGNED_STORAGE)
    326 endif ()
    327 
    328 set(STD_LIB)
    329 if (NOT IOS AND NOT ANDROID)
    330     set(STD_LIB stdc++)
    331 endif ()
    332 
    333 if (ANDROID)
    334     set(PTHREAD_LIB)
    335 else ()
    336     set(PTHREAD_LIB pthread)
    337 endif ()
    338 
    339 # KFR library
    340 add_library(kfr INTERFACE)
    341 # target_sources(kfr INTERFACE ${KFR_SRC})
    342 target_include_directories(
    343     kfr INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    344                   $<INSTALL_INTERFACE:include>)
    345 target_compile_options(kfr INTERFACE "$<$<CONFIG:DEBUG>:-DKFR_DEBUG>")
    346 if (APPLE)
    347     target_compile_options(kfr INTERFACE -faligned-allocation)
    348 endif ()
    349 
    350 if (EMSCRIPTEN)
    351     target_compile_options(kfr INTERFACE -msimd128)
    352 endif ()
    353 
    354 if (MSVC)
    355     target_compile_options(kfr INTERFACE -bigobj)
    356 else ()
    357     target_link_libraries(kfr INTERFACE ${STD_LIB} ${PTHREAD_LIB} m)
    358 endif ()
    359 if (KFR_DISABLE_CLANG_EXTENSIONS)
    360     target_compile_definitions(kfr INTERFACE -DCMT_DISABLE_CLANG_EXT)
    361 endif ()
    362 if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    363     add_compile_options(-Wno-ignored-qualifiers -Wno-psabi)
    364 endif ()
    365 if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    366     add_compile_options(-Wno-c++1z-extensions -Wno-psabi
    367                         -Wno-unknown-warning-option)
    368 endif ()
    369 if (MSVC)
    370     add_compile_options(/wd4141)
    371     target_compile_options(kfr INTERFACE $<$<CXX_COMPILER_ID:MSVC>:/Zc:lambda>)
    372 endif ()
    373 
    374 if (NOT KFR_ENABLE_DFT)
    375     target_compile_definitions(kfr INTERFACE -DKFR_NO_DFT)
    376 endif ()
    377 if (KFR_EXTENDED_TESTS)
    378     target_compile_definitions(kfr INTERFACE -DKFR_EXTENDED_TESTS)
    379 endif ()
    380 
    381 set(KFR_DEBUG_INSTALL_SUFFIX "/debug" CACHE STRING "")
    382 
    383 add_subdirectory(src/dsp)
    384 add_subdirectory(src/io)
    385 if (KFR_ENABLE_DFT)
    386     add_subdirectory(src/dft)
    387 endif ()
    388 if (KFR_ENABLE_CAPI_BUILD)
    389     add_subdirectory(src/capi)
    390 endif ()
    391 
    392 if (ENABLE_EXAMPLES)
    393     add_subdirectory(examples)
    394     add_subdirectory(tools)
    395 endif ()
    396 if (ENABLE_TESTS)
    397     add_subdirectory(tests)
    398 endif ()
    399 
    400 set(kfr_defines)
    401 
    402 function (append_defines_from target)
    403     get_target_property(compile_defs ${target} INTERFACE_COMPILE_DEFINITIONS)
    404     if (compile_defs)
    405         list(APPEND kfr_defines "${compile_defs}")
    406     endif ()
    407     set(kfr_defines
    408         ${kfr_defines}
    409         PARENT_SCOPE)
    410 endfunction ()
    411 
    412 append_defines_from(kfr)
    413 if (KFR_ENABLE_DFT)
    414     append_defines_from(kfr_dft)
    415 endif ()
    416 append_defines_from(kfr_io)
    417 
    418 string(REPLACE "=" " " kfr_defines "${kfr_defines}")
    419 string(REPLACE ";" "\n#define " kfr_defines "${kfr_defines}")
    420 if (kfr_defines)
    421     set(kfr_defines "#define ${kfr_defines}\n")
    422 endif ()
    423 
    424 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/kfr_config.h "${kfr_defines}")
    425 
    426 if (KFR_INSTALL_HEADERS)
    427     install(DIRECTORY include/kfr DESTINATION include)
    428 
    429     install(
    430         FILES ${CMAKE_CURRENT_BINARY_DIR}/kfr_config.h
    431         DESTINATION include/kfr
    432         RENAME config.h)
    433 endif ()
    434 
    435 # uninstall target
    436 if (NOT TARGET uninstall)
    437     configure_file(
    438         "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
    439         "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake" IMMEDIATE
    440         @ONLY)
    441 
    442     add_custom_target(
    443         uninstall
    444         COMMAND ${CMAKE_COMMAND} -P
    445                 ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake)
    446 endif ()
    447 
    448 include(GNUInstallDirs)
    449 include(CMakePackageConfigHelpers)
    450 
    451 set(KFR_INSTALL_CMAKEDIR
    452     "${CMAKE_INSTALL_LIBDIR}/cmake/kfr"
    453     CACHE STRING "Path to KFR CMake files")
    454 
    455 configure_package_config_file(
    456     ${CMAKE_CURRENT_SOURCE_DIR}/cmake/config.cmake.in
    457     "${CMAKE_CURRENT_BINARY_DIR}/KFRConfig.cmake"
    458     INSTALL_DESTINATION "lib/cmake/kfr"
    459     NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO)
    460 
    461 install(TARGETS kfr EXPORT kfr_export)
    462 
    463 install(
    464     EXPORT kfr_export
    465     DESTINATION "${KFR_INSTALL_CMAKEDIR}"
    466     CONFIGURATIONS Debug Release
    467     FILE KFRConfig.cmake)
    468 
    469 write_basic_package_version_file(KFRConfigVersion.cmake
    470     VERSION ${KFR_VERSION} 
    471     COMPATIBILITY SameMinorVersion)
    472 
    473 install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KFRConfigVersion.cmake"
    474     DESTINATION
    475     "${KFR_INSTALL_CMAKEDIR}" )