# Copyright (C) 2016-2023 Dan Cazarin (https://www.kfrlib.com) # This file is part of KFR # # KFR is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # KFR is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with KFR. cmake_minimum_required(VERSION 3.12) if (KFR_WITH_CLANG) set(CLANG_VERSION 17.0.6) if (WIN32) set(CLANG_URL https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/LLVM-${CLANG_VERSION}-win64.exe ) set(CLANG_ARCH_FILE "${CMAKE_CURRENT_BINARY_DIR}/clang-prebuilt.exe") set(CLANG_DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/clang") set(SEVENZIP_URL https://www.7-zip.org/a/7z2301-x64.msi) set(SEVENZIP_ARCH_FILE "${CMAKE_CURRENT_BINARY_DIR}/7z2301-x64.msi") set(SEVENZIP_DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/7z") message(STATUS "Downloading 7zip from ${SEVENZIP_URL}") file( DOWNLOAD ${SEVENZIP_URL} ${SEVENZIP_ARCH_FILE} EXPECTED_HASH SHA256=0BA639B6DACDF573D847C911BD147C6384381A54DAC082B1E8C77BC73D58958B SHOW_PROGRESS) cmake_path(NATIVE_PATH SEVENZIP_ARCH_FILE NORMALIZE SEVENZIP_ARCH_FILE_W) cmake_path(NATIVE_PATH SEVENZIP_DEST_DIR NORMALIZE SEVENZIP_DEST_DIR_W) execute_process(COMMAND msiexec /a "${SEVENZIP_ARCH_FILE_W}" "TARGETDIR=${SEVENZIP_DEST_DIR_W}" /qn) message(STATUS "Downloading Clang ${CLANG_VERSION} from ${CLANG_URL}") file( DOWNLOAD ${CLANG_URL} ${CLANG_ARCH_FILE} EXPECTED_HASH SHA256=89dc351af8e8fa1cafc6b48411e608aa9457c930a10f984aad5d21ab020165b2 SHOW_PROGRESS) message(STATUS "Unpacking Clang ${CLANG_VERSION}") execute_process( COMMAND ${SEVENZIP_DEST_DIR}/Files/7-Zip/7z.exe x -bb0 -bd -aos -o${CLANG_DEST_DIR} ${CLANG_ARCH_FILE} OUTPUT_QUIET) set(CMAKE_CXX_COMPILER ${CLANG_DEST_DIR}/bin/clang-cl.exe CACHE STRING "Clang" FORCE) set(CMAKE_C_COMPILER ${CLANG_DEST_DIR}/bin/clang-cl.exe CACHE STRING "Clang" FORCE) endif () if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") set(CLANG_URL https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/clang+llvm-${CLANG_VERSION}-x86_64-linux-gnu-ubuntu-22.04.tar.xz ) set(CLANG_ARCH_FILE "${CMAKE_CURRENT_BINARY_DIR}/clang-prebuilt.tar.xz") set(CLANG_DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/clang") message(STATUS "Downloading Clang ${CLANG_VERSION} from ${CLANG_URL}") file( DOWNLOAD ${CLANG_URL} ${CLANG_ARCH_FILE} EXPECTED_HASH SHA256=884ee67d647d77e58740c1e645649e29ae9e8a6fe87c1376be0f3a30f3cc9ab3 SHOW_PROGRESS) message(STATUS "Unpacking Clang ${CLANG_VERSION}") file(ARCHIVE_EXTRACT INPUT ${CLANG_ARCH_FILE} DESTINATION ${CLANG_DEST_DIR}) set(CMAKE_CXX_COMPILER ${CLANG_DEST_DIR}/clang+llvm-${CLANG_VERSION}-x86_64-linux-gnu-ubuntu-22.04/bin/clang++ CACHE STRING "Clang" FORCE) set(CMAKE_C_COMPILER ${CLANG_DEST_DIR}/clang+llvm-${CLANG_VERSION}-x86_64-linux-gnu-ubuntu-22.04/bin/clang CACHE STRING "Clang" FORCE) endif () message(STATUS "Clang ${CLANG_VERSION} is set up successfully") endif () file(STRINGS ${CMAKE_CURRENT_LIST_DIR}/include/kfr/kfr.h KFR_VERSION REGEX "#define KFR_VERSION_(MINOR|MAJOR|PATCH)") string(REGEX MATCHALL "[0-9]+" KFR_VERSION_MATCH ${KFR_VERSION}) string(REPLACE ";" "." KFR_VERSION "${KFR_VERSION_MATCH}") project( kfr VERSION ${KFR_VERSION} LANGUAGES CXX) if (DEBUG_CMAKE) get_cmake_property(VARS VARIABLES) list (SORT VARS) foreach (VAR ${VARS}) message(STATUS "${VAR}=${${VAR}}") endforeach() endif () set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS ON) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${PROJECT_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/bin) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${PROJECT_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${PROJECT_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/lib) if (CPU_ARCH) if (NOT KFR_ARCH) message( WARNING "CPU_ARCH is deprecated. Use KFR_ARCH instead. KFR will use machine native architecture by default" ) else () message( WARNING "Both KFR_ARCH and CPU_ARCH are defined. KFR will use architecture set by KFR_ARCH (${KFR_ARCH})" ) endif () endif () if (EMSCRIPTEN) set(KFR_ARCH "sse41" CACHE STRING "") set(KFR_ENABLE_MULTIARCH OFF CACHE BOOL "") endif () set(X86 FALSE) if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") set(X86 TRUE) endif () if (CMAKE_OSX_ARCHITECTURES MATCHES "x86_64") set(X86 TRUE) endif () if (CMAKE_OSX_ARCHITECTURES MATCHES "^[Aa][Rr][Mm]64$") set(X86 FALSE) endif () if (CMAKE_CXX_COMPILER_TARGET MATCHES "^arm") set(X86 FALSE) endif () if (CMAKE_ANDROID_ARCH_ABI MATCHES "x86") set(X86 TRUE) endif () if (CMAKE_SIZEOF_VOID_P EQUAL 8) set(BITNESS64 TRUE) else () set(BITNESS64 FALSE) endif () if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") set(CLANG 1) else () set(CLANG 0) endif () include(cmake/target_set_arch.cmake) include(cmake/link_as_whole.cmake) include(cmake/add_kfr_library.cmake) # Include autogenerated list of source files include(sources.cmake) include(CMakeDependentOption) option(KFR_ENABLE_MULTIARCH "Multiple architectures will be built with runtime dispatch" ON) option(ENABLE_TESTS "Enable KFR tests" OFF) cmake_dependent_option(ENABLE_EXAMPLES "Enable KFR examples" ON "ENABLE_TESTS" OFF) if (CLANG) option(KFR_ENABLE_DFT "Enable DFT and related algorithms." ON) else () option(KFR_ENABLE_DFT "Enable DFT and related algorithms." OFF) endif () option(KFR_ENABLE_ASMTEST "Enable writing disassembly" OFF) option(KFR_REGENERATE_TESTS "Regenerate auto tests" OFF) option(KFR_DISABLE_CLANG_EXTENSIONS "Disable Clang vector extensions" OFF) option(KFR_EXTENDED_TESTS "Extended tests (up to hour)" OFF) option(KFR_SKIP_TESTS "Build tests but don't run tests" OFF) option(KFR_ENABLE_CAPI_BUILD "Enable KFR C API building" OFF) option(KFR_INSTALL_HEADERS "Include headers in installation" ON) option(KFR_INSTALL_LIBRARIES "Include libraries in installation" ON) mark_as_advanced(KFR_ENABLE_ASMTEST) mark_as_advanced(KFR_REGENERATE_TESTS) mark_as_advanced(KFR_DISABLE_CLANG_EXTENSIONS) if (CMAKE_ANDROID_ARCH_ABI) set(KFR_ENABLE_MULTIARCH OFF CACHE INTERNAL "" FORCE) endif () if (KFR_ENABLE_CAPI_BUILD AND NOT KFR_ENABLE_DFT) message( FATAL_ERROR "KFR_ENABLE_CAPI_BUILD requires KFR_ENABLE_DFT to be enabled") endif () if (NOT KFR_ARCH) set(KFR_ARCH target) endif () if (KFR_ARCH STREQUAL "detect") set(KFR_ARCH host) endif () set(DETECT_NAMES host target) if (X86) set(ALLOWED_ARCHS generic sse sse2 sse3 ssse3 sse41 sse42 avx avx2 avx512) else () set(ALLOWED_ARCHS generic neon neon64) endif () if (NOT X86) if (KFR_ARCH IN_LIST DETECT_NAMES) if (BITNESS64) set(KFR_ARCH neon64) else () set(KFR_ARCH neon) endif () endif () endif () if (KFR_ARCH IN_LIST DETECT_NAMES AND NOT CMAKE_CROSSCOMPILING) message(STATUS "Detecting ${KFR_ARCH} architecture") try_run( RUN_RESULT COMPILE_RESULT "${CMAKE_CURRENT_BINARY_DIR}/tmpdir" ${CMAKE_CURRENT_SOURCE_DIR}/cmake/detect_cpu.cpp CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CMAKE_CURRENT_SOURCE_DIR}/include" -DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_STANDARD_REQUIRED=ON "-DCOMPILE_DEFINITIONS=-DCPU_${KFR_ARCH}=1" -DCMAKE_CXX_EXTENSIONS=ON COMPILE_OUTPUT_VARIABLE COMPILE_OUT RUN_OUTPUT_VARIABLE RUN_OUT) if (COMPILE_RESULT AND RUN_RESULT EQUAL 0) message( STATUS "Default CPU architecture for KFR is ${RUN_OUT} (set KFR_ARCH to override)" ) set(KFR_ARCH ${RUN_OUT} CACHE INTERNAL "Detected CPU" FORCE) else () message(STATUS COMPILE_RESULT = ${COMPILE_RESULT}) message(STATUS RUN_RESULT = ${RUN_RESULT}) message(STATUS COMPILE_OUT = ${COMPILE_OUT}) message(FATAL_ERROR RUN_OUT = ${RUN_OUT}) endif () else () message( STATUS "Default CPU architecture for KFR is ${KFR_ARCH} (set by KFR_ARCH)") endif () if (X86 AND KFR_ARCH STREQUAL "target") set(KFR_ARCH sse2 CACHE INTERNAL "Default CPU" FORCE) endif () if (NOT KFR_ARCH IN_LIST ALLOWED_ARCHS) message(FATAL_ERROR "Incorrect architecture set by KFR_ARCH: ${KFR_ARCH}") endif () if (NOT KFR_ARCHS) if (X86) if (APPLE) set(KFR_ARCHS sse41 avx avx2 avx512) else () set(KFR_ARCHS sse2 sse41 avx avx2 avx512) endif () else () set(KFR_ARCHS ${KFR_ARCH}) endif () endif () if (KFR_ENABLE_MULTIARCH) message( STATUS "Runtime dispatch is enabled for architectures: ${KFR_ARCHS} (set KFR_ARCHS to change, set KFR_ENABLE_MULTIARCH=OFF to disable)" ) else () message( STATUS "Runtime dispatch is disabled. Set KFR_ENABLE_MULTIARCH=ON to enable" ) endif () string(REPLACE ";" ", " KFR_ARCHS_COMMA "${KFR_ARCHS}") if (KFR_ENABLE_MULTIARCH) add_compile_definitions(KFR_ENABLED_ARCHS="${KFR_ARCHS_COMMA}") endif () add_library(use_arch INTERFACE) target_set_arch(use_arch INTERFACE ${KFR_ARCH}) if (WIN32) add_definitions(-D_CRT_SECURE_NO_WARNINGS) add_definitions(-D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) add_definitions(-D_ENABLE_EXTENDED_ALIGNED_STORAGE) endif () set(STD_LIB) if (NOT IOS AND NOT ANDROID) set(STD_LIB stdc++) endif () if (ANDROID) set(PTHREAD_LIB) else () set(PTHREAD_LIB pthread) endif () # KFR library add_library(kfr INTERFACE) # target_sources(kfr INTERFACE ${KFR_SRC}) target_include_directories( kfr INTERFACE $ $) target_compile_options(kfr INTERFACE "$<$:-DKFR_DEBUG>") if (APPLE) target_compile_options(kfr INTERFACE -faligned-allocation) endif () if (EMSCRIPTEN) target_compile_options(kfr INTERFACE -msimd128) endif () if (MSVC) target_compile_options(kfr INTERFACE -bigobj) else () target_link_libraries(kfr INTERFACE ${STD_LIB} ${PTHREAD_LIB} m) endif () if (KFR_DISABLE_CLANG_EXTENSIONS) target_compile_definitions(kfr INTERFACE -DCMT_DISABLE_CLANG_EXT) endif () if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") add_compile_options(-Wno-ignored-qualifiers -Wno-psabi) endif () if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") add_compile_options(-Wno-c++1z-extensions -Wno-psabi -Wno-unknown-warning-option) endif () if (MSVC) add_compile_options(/wd4141) target_compile_options(kfr INTERFACE $<$:/Zc:lambda>) endif () if (NOT KFR_ENABLE_DFT) target_compile_definitions(kfr INTERFACE -DKFR_NO_DFT) endif () if (KFR_EXTENDED_TESTS) target_compile_definitions(kfr INTERFACE -DKFR_EXTENDED_TESTS) endif () set(KFR_DEBUG_INSTALL_SUFFIX "/debug" CACHE STRING "") add_subdirectory(src/dsp) add_subdirectory(src/io) if (KFR_ENABLE_DFT) add_subdirectory(src/dft) endif () if (KFR_ENABLE_CAPI_BUILD) add_subdirectory(src/capi) endif () if (ENABLE_EXAMPLES) add_subdirectory(examples) add_subdirectory(tools) endif () if (ENABLE_TESTS) add_subdirectory(tests) endif () set(kfr_defines) function (append_defines_from target) get_target_property(compile_defs ${target} INTERFACE_COMPILE_DEFINITIONS) if (compile_defs) list(APPEND kfr_defines "${compile_defs}") endif () set(kfr_defines ${kfr_defines} PARENT_SCOPE) endfunction () append_defines_from(kfr) if (KFR_ENABLE_DFT) append_defines_from(kfr_dft) endif () append_defines_from(kfr_io) string(REPLACE "=" " " kfr_defines "${kfr_defines}") string(REPLACE ";" "\n#define " kfr_defines "${kfr_defines}") if (kfr_defines) set(kfr_defines "#define ${kfr_defines}\n") endif () file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/kfr_config.h "${kfr_defines}") if (KFR_INSTALL_HEADERS) install(DIRECTORY include/kfr DESTINATION include) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/kfr_config.h DESTINATION include/kfr RENAME config.h) endif () # uninstall target if (NOT TARGET uninstall) configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target( uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake) endif () include(GNUInstallDirs) include(CMakePackageConfigHelpers) set(KFR_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/kfr" CACHE STRING "Path to KFR CMake files") configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/KFRConfig.cmake" INSTALL_DESTINATION "lib/cmake/kfr" NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO) install(TARGETS kfr EXPORT kfr_export) install( EXPORT kfr_export DESTINATION "${KFR_INSTALL_CMAKEDIR}" CONFIGURATIONS Debug Release FILE KFRConfig.cmake) write_basic_package_version_file(KFRConfigVersion.cmake VERSION ${KFR_VERSION} COMPATIBILITY SameMinorVersion) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KFRConfigVersion.cmake" DESTINATION "${KFR_INSTALL_CMAKEDIR}" )