diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ca27aa96..9169ff403 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -281,8 +281,8 @@ else() message(STATUS "Compiling for 16 bit Rx DSP chain") endif() -# find cpu flags (and set compiler) -include(FindCPUflags) +# Set compiler options based on target architecture and selected extensions +include(CompilerOptions) # Instruct CMake to run moc automatically when needed set(CMAKE_AUTOMOC ON) diff --git a/cmake/Modules/CompilerOptions.cmake b/cmake/Modules/CompilerOptions.cmake new file mode 100644 index 000000000..9dadf3ae7 --- /dev/null +++ b/cmake/Modules/CompilerOptions.cmake @@ -0,0 +1,29 @@ +include_guard(GLOBAL) + +include(DetectArchitecture) + +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) +if(MSVC) + add_compile_options(/MP) +else() + add_compile_options(-Wall -Wextra -Wvla -Woverloaded-virtual -ffast-math -ftree-vectorize) +endif() + +if (SANITIZE_ADDRESS) + message(STATUS "Activate address sanitization") + if(MSVC) + set(ASAN_LIB_ARCH ${MSVC_CXX_ARCHITECTURE_ID}) + string(TOLOWER ${ASAN_LIB_ARCH} ASAN_LIB_ARCH) + if(ASAN_LIB_ARCH STREQUAL "x86") + set(ASAN_LIB_ARCH "i386") + elseif(ASAN_LIB_ARCH STREQUAL "x64") + set(ASAN_LIB_ARCH "x86_64") + endif() + add_compile_options(/fsanitize=address) + link_libraries(clang_rt.asan_dynamic-${ASAN_LIB_ARCH} clang_rt.asan_dynamic_runtime_thunk-${ASAN_LIB_ARCH}) + add_link_options(/wholearchive:clang_rt.asan_dynamic_runtime_thunk-${ASAN_LIB_ARCH}.lib) + else() + add_compile_options(-fsanitize=address -fno-omit-frame-pointer -g) + add_link_options(-fsanitize=address) + endif() +endif() diff --git a/cmake/Modules/FindCPUflags.cmake b/cmake/Modules/DetectArchitecture.cmake similarity index 81% rename from cmake/Modules/FindCPUflags.cmake rename to cmake/Modules/DetectArchitecture.cmake index 82ca3c2ef..29daa06e4 100644 --- a/cmake/Modules/FindCPUflags.cmake +++ b/cmake/Modules/DetectArchitecture.cmake @@ -1,242 +1,206 @@ -include_guard(GLOBAL) - -include(CheckCXXCompilerFlag) -include(CheckSymbolExists) -include(CMakePushCheckState) - -set(TEST_DIR ${PROJECT_SOURCE_DIR}/cmake/test) - -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(C_CLANG 1) -elseif(MAKE_CXX_COMPILER_ID MATCHES "GNU") - set(C_GCC 1) -elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - set(C_MSVC 1) -endif() - -# Detect current compilation architecture and create standard definitions -macro(detect_architecture symbol arch) - if (NOT DEFINED ARCHITECTURE) - check_symbol_exists("${symbol}" "" ARCHITECTURE_${arch}) - - if (ARCHITECTURE_${arch}) - set(ARCHITECTURE ${arch}) - set(ARCHITECTURE_${arch} TRUE) - add_compile_definitions(ARCHITECTURE_${arch}) - endif() - endif() -endmacro() - -macro(force_ext_available extension) - message(STATUS "Looking for __${extension}__ - forced found") - set(HAS_${extension} 1 CACHE INTERNAL "") -endmacro() - -function(detect_extensions extension) - unset(HAS_${extension}) - if (ARGC EQUAL 2 AND (${ARGV1})) # force available - force_ext_available(${extension}) - endif() - check_symbol_exists("__${extension}__" "" HAS_${extension}) - if (HAS_${extension}) - add_compile_definitions(USE_${extension}) - endif() -endfunction() - -function(detect_msvc_native_opt) - try_run(RUN_AVX512 COMPILE_AVX512 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx512.cxx" COMPILE_DEFINITIONS /arch:AVX512) - if (COMPILE_AVX512 AND RUN_AVX512 EQUAL 0) - set(ARCH_OPT "AVX512" PARENT_SCOPE) - return() - endif() - try_run(RUN_AVX2 COMPILE_AVX2 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx2.cxx" COMPILE_DEFINITIONS /arch:AVX2) - if (COMPILE_AVX2 AND RUN_AVX2 EQUAL 0) - set(ARCH_OPT "AVX2" PARENT_SCOPE) - return() - endif() - try_run(RUN_AVX COMPILE_AVX "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx.cxx" COMPILE_DEFINITIONS /arch:AVX) - if (COMPILE_AVX AND RUN_AVX EQUAL 0) - set(ARCH_OPT "AVX" PARENT_SCOPE) - return() - endif() - - # Supporting 32-bit x86, what year is it? - set(COMPILE_DEF "") - set(ARCH_OPT "" PARENT_SCOPE) - if (ARCHITECTURE_x86) - set(COMPILE_DEF "/arch:SSE2") - set(ARCH_OPT "SSE2" PARENT_SCOPE) - endif() - - try_run(RUN_SSE42 COMPILE_SSE42 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse42.cxx" COMPILE_DEFINITIONS ${COMPILE_DEF}) - if (COMPILE_SSE42 AND RUN_SSE42 EQUAL 0) - force_ext_available(SSE4_2) - return() - endif() - try_run(RUN_SSE41 COMPILE_SSE41 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse41.cxx" COMPILE_DEFINITIONS ${COMPILE_DEF}) - if (COMPILE_SSE41 AND RUN_SSE41 EQUAL 0) - force_ext_available(SSE4_1) - return() - endif() - try_run(RUN_SSSE3 COMPILE_SSSE3 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_ssse3.cxx" COMPILE_DEFINITIONS ${COMPILE_DEF}) - if (COMPILE_SSSE3 AND RUN_SSSE3 EQUAL 0) - force_ext_available(SSSE3) - return() - endif() - try_run(RUN_SSE3 COMPILE_SSE3 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse3.cxx" COMPILE_DEFINITIONS ${COMPILE_DEF}) - if (COMPILE_SSE3 AND RUN_SSE3 EQUAL 0) - force_ext_available(SSE3) - return() - endif() - try_run(RUN_SSE2 COMPILE_SSE2 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse2.cxx" COMPILE_DEFINITIONS ${COMPILE_DEF}) - if (COMPILE_SSE2 AND RUN_SSE2 EQUAL 0) - force_ext_available(SSE2) - return() - endif() - - if (ARCHITECTURE_x86) - # At this point we might as well... - set(ARCH_OPT "IA32" PARENT_SCOPE) - return() - endif() -endfunction() - -if (C_MSVC) - detect_architecture("_M_AMD64" x86_64) - detect_architecture("_M_IX86" x86) - detect_architecture("_M_ARM" ARM) - detect_architecture("_M_ARM64" ARM64) -else() - detect_architecture("__x86_64__" x86_64) - detect_architecture("__i386__" x86) - detect_architecture("__arm__" ARM) - detect_architecture("__aarch64__" ARM64) -endif() -if (NOT DEFINED ARCHITECTURE) - message(FATAL_ERROR "Not supported. Please add needed architecture detection.") -endif() - -# Note: On x86 MSVC's /arch:SSE2 enables all SSE intrinsics support and is default option. -# On x86_64 MSVC's SSE is supported and enabled, so only AVX selection is needed. - -if (FORCE_SSSE3) - message(WARNING "FORCE_SSSE3 flag is deprecated, please use ARCH_OPT option.") - set(ARCH_OPT "") - if (C_MSVC) - if (ARCHITECTURE_x86) - set(ARCH_OPT "SSE2") - endif() - force_ext_available(SSSE3) - else() - set(FORCE_OPT "-mssse3") - endif() -endif() - -if (FORCE_SSE41) - message(WARNING "FORCE_SSE41 flag is deprecated, please use ARCH_OPT option.") - set(ARCH_OPT "") - if (C_MSVC) - if (ARCHITECTURE_x86) - set(ARCH_OPT "SSE2") - else() - force_ext_available(SSE4_1) - endif() - else() - set(FORCE_OPT "-msse4.1") - endif() -endif() - -if (C_MSVC) - # Glue to make ARCH_OPT more flexible for MSVC - if (ARCH_OPT STREQUAL "native") - detect_msvc_native_opt() - elseif(ARCH_OPT STREQUAL "SSE4_2") - force_ext_available(SSE4_2) - set(ARCH_OPT "") - elseif(ARCH_OPT STREQUAL "SSE4_1") - force_ext_available(SSE4_1) - set(ARCH_OPT "") - elseif(ARCH_OPT STREQUAL "SSSE3") - force_ext_available(SSSE3) - set(ARCH_OPT "") - elseif(ARCH_OPT STREQUAL "SSE3") - force_ext_available(SSE3) - set(ARCH_OPT "") - elseif(ARCH_OPT STREQUAL "SSE2") - force_ext_available(SSE2) - set(ARCH_OPT "") - endif() -endif() - -message(STATUS "Target architecture: ${ARCHITECTURE}-${ARCH_OPT}") - -cmake_push_check_state(RESET) -if (ARCH_OPT) - if(C_MSVC) - set(CMAKE_REQUIRED_FLAGS "/arch:${ARCH_OPT}") - add_compile_options(${CMAKE_REQUIRED_FLAGS}) - else() - set(CMAKE_REQUIRED_FLAGS "-march=${ARCH_OPT}") - add_compile_options(-march=${ARCH_OPT}) - endif() -elseif(FORCE_SSSE3 OR FORCE_SSE41) - if (NOT C_MSVC) - set(CMAKE_REQUIRED_FLAGS ${FORCE_OPT}) - add_compile_options(${FORCE_OPT}) - endif() -endif() - -check_cxx_compiler_flag("${CMAKE_REQUIRED_FLAGS}" FLAG_SUPPORTED) -if (NOT FLAG_SUPPORTED) - message(FATAL_ERROR "Flag '${CMAKE_REQUIRED_FLAGS}' rejected by compiler. Please adjust ARCH_OPT option.") -endif() - -if (ARCHITECTURE_ARM) - if (C_MSVC) - force_ext_available(ARM_NEON) - else() - list(APPEND CMAKE_REQUIRED_FLAGS -mfpu=neon) - endif() -endif() - -# This is quite basic detection, can be extended if needed -detect_extensions(ARM_NEON) -detect_extensions(AVX512F) -detect_extensions(AVX2 HAS_AVX512F) -detect_extensions(AVX HAS_AVX2) -detect_extensions(SSE4_2 HAS_AVX) -detect_extensions(SSE4_1 HAS_SSE4_2) -detect_extensions(SSSE3 HAS_SSE4_1) -detect_extensions(SSE3 HAS_SSSE3) -detect_extensions(SSE2 HAS_SSE3) - -cmake_pop_check_state() - -set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) -if (C_CLANG OR C_GCC) - add_compile_options(-Wall -Wextra -Wvla -Woverloaded-virtual -ffast-math -ftree-vectorize) -elseif (C_MSVC) - add_compile_options(/MP) -endif() - -if (SANITIZE_ADDRESS) - message(STATUS "Activate address sanitization") - if(MSVC) - set(ASAN_LIB_ARCH ${MSVC_CXX_ARCHITECTURE_ID}) - string(TOLOWER ${ASAN_LIB_ARCH} ASAN_LIB_ARCH) - if(ASAN_LIB_ARCH STREQUAL "x86") - set(ASAN_LIB_ARCH "i386") - elseif(ASAN_LIB_ARCH STREQUAL "x64") - set(ASAN_LIB_ARCH "x86_64") - endif() - add_compile_options(/fsanitize=address) - link_libraries(clang_rt.asan_dynamic-${ASAN_LIB_ARCH} clang_rt.asan_dynamic_runtime_thunk-${ASAN_LIB_ARCH}) - add_link_options(/wholearchive:clang_rt.asan_dynamic_runtime_thunk-${ASAN_LIB_ARCH}.lib) - else() - add_compile_options(-fsanitize=address -fno-omit-frame-pointer -g) - add_link_options(-fsanitize=address) - endif() -endif() - -# clear binary test folder -FILE(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/tmp) +include_guard(GLOBAL) + +include(CheckCXXCompilerFlag) +include(CheckSymbolExists) +include(CMakePushCheckState) + +# Detect current compilation architecture and create standard definitions +macro(detect_architecture symbol arch) + if (NOT DEFINED ARCHITECTURE) + check_symbol_exists("${symbol}" "" ARCHITECTURE_${arch}) + + if (ARCHITECTURE_${arch}) + set(ARCHITECTURE ${arch}) + set(ARCHITECTURE_${arch} TRUE) + add_compile_definitions(ARCHITECTURE_${arch}) + endif() + endif() +endmacro() + +macro(force_ext_available extension) + message(STATUS "Looking for __${extension}__ - forced found") + set(HAS_${extension} 1 CACHE INTERNAL "") +endmacro() + +function(detect_extensions extension) + unset(HAS_${extension}) + if (ARGC EQUAL 2 AND (${ARGV1})) # force available + force_ext_available(${extension}) + endif() + check_symbol_exists("__${extension}__" "" HAS_${extension}) + if (HAS_${extension}) + add_compile_definitions(USE_${extension}) + endif() +endfunction() + +function(detect_msvc_native_opt) + set(TEST_DIR ${PROJECT_SOURCE_DIR}/cmake/test) + + try_run(RUN_AVX512 COMPILE_AVX512 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx512.cxx" COMPILE_DEFINITIONS /arch:AVX512) + if (COMPILE_AVX512 AND RUN_AVX512 EQUAL 0) + set(ARCH_OPT "AVX512" PARENT_SCOPE) + return() + endif() + try_run(RUN_AVX2 COMPILE_AVX2 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx2.cxx" COMPILE_DEFINITIONS /arch:AVX2) + if (COMPILE_AVX2 AND RUN_AVX2 EQUAL 0) + set(ARCH_OPT "AVX2" PARENT_SCOPE) + return() + endif() + try_run(RUN_AVX COMPILE_AVX "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_avx.cxx" COMPILE_DEFINITIONS /arch:AVX) + if (COMPILE_AVX AND RUN_AVX EQUAL 0) + set(ARCH_OPT "AVX" PARENT_SCOPE) + return() + endif() + + # Supporting 32-bit x86, what year is it? + set(COMPILE_DEF "") + set(ARCH_OPT "" PARENT_SCOPE) + if (ARCHITECTURE_x86) + set(COMPILE_DEF "/arch:SSE2") + set(ARCH_OPT "SSE2" PARENT_SCOPE) + endif() + + try_run(RUN_SSE42 COMPILE_SSE42 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse42.cxx" COMPILE_DEFINITIONS ${COMPILE_DEF}) + if (COMPILE_SSE42 AND RUN_SSE42 EQUAL 0) + force_ext_available(SSE4_2) + return() + endif() + try_run(RUN_SSE41 COMPILE_SSE41 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse41.cxx" COMPILE_DEFINITIONS ${COMPILE_DEF}) + if (COMPILE_SSE41 AND RUN_SSE41 EQUAL 0) + force_ext_available(SSE4_1) + return() + endif() + try_run(RUN_SSSE3 COMPILE_SSSE3 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_ssse3.cxx" COMPILE_DEFINITIONS ${COMPILE_DEF}) + if (COMPILE_SSSE3 AND RUN_SSSE3 EQUAL 0) + force_ext_available(SSSE3) + return() + endif() + try_run(RUN_SSE3 COMPILE_SSE3 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse3.cxx" COMPILE_DEFINITIONS ${COMPILE_DEF}) + if (COMPILE_SSE3 AND RUN_SSE3 EQUAL 0) + force_ext_available(SSE3) + return() + endif() + try_run(RUN_SSE2 COMPILE_SSE2 "${CMAKE_BINARY_DIR}/tmp" "${TEST_DIR}/test_x86_sse2.cxx" COMPILE_DEFINITIONS ${COMPILE_DEF}) + if (COMPILE_SSE2 AND RUN_SSE2 EQUAL 0) + force_ext_available(SSE2) + return() + endif() + + if (ARCHITECTURE_x86) + # At this point we might as well... + set(ARCH_OPT "IA32" PARENT_SCOPE) + return() + endif() +endfunction() + +if (MSVC) + detect_architecture("_M_AMD64" x86_64) + detect_architecture("_M_IX86" x86) + detect_architecture("_M_ARM" ARM) + detect_architecture("_M_ARM64" ARM64) +else() + detect_architecture("__x86_64__" x86_64) + detect_architecture("__i386__" x86) + detect_architecture("__arm__" ARM) + detect_architecture("__aarch64__" ARM64) +endif() +if (NOT DEFINED ARCHITECTURE) + message(FATAL_ERROR "Not supported. Please add needed architecture detection.") +endif() + +# Note: On x86 MSVC's /arch:SSE2 enables all SSE intrinsics support and is default option. +# On x86_64 MSVC's SSE is supported and enabled, so only AVX selection is needed. + +if (FORCE_SSSE3) + message(WARNING "FORCE_SSSE3 flag is deprecated, please use ARCH_OPT option.") + set(ARCH_OPT "") + if (MSVC) + if (ARCHITECTURE_x86) + set(ARCH_OPT "SSE2") + endif() + force_ext_available(SSSE3) + else() + set(FORCE_OPT "-mssse3") + endif() +endif() + +if (FORCE_SSE41) + message(WARNING "FORCE_SSE41 flag is deprecated, please use ARCH_OPT option.") + set(ARCH_OPT "") + if (MSVC) + if (ARCHITECTURE_x86) + set(ARCH_OPT "SSE2") + else() + force_ext_available(SSE4_1) + endif() + else() + set(FORCE_OPT "-msse4.1") + endif() +endif() + +if (MSVC) + # Glue to make ARCH_OPT more flexible for MSVC + if (ARCH_OPT STREQUAL "native") + detect_msvc_native_opt() + FILE(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/tmp) + elseif(ARCH_OPT STREQUAL "SSE4_2") + force_ext_available(SSE4_2) + set(ARCH_OPT "") + elseif(ARCH_OPT STREQUAL "SSE4_1") + force_ext_available(SSE4_1) + set(ARCH_OPT "") + elseif(ARCH_OPT STREQUAL "SSSE3") + force_ext_available(SSSE3) + set(ARCH_OPT "") + elseif(ARCH_OPT STREQUAL "SSE3") + force_ext_available(SSE3) + set(ARCH_OPT "") + elseif(ARCH_OPT STREQUAL "SSE2") + force_ext_available(SSE2) + set(ARCH_OPT "") + endif() +endif() + +message(STATUS "Target architecture: ${ARCHITECTURE}-${ARCH_OPT}") + +cmake_push_check_state(RESET) +if (ARCH_OPT) + if(MSVC) + set(CMAKE_REQUIRED_FLAGS "/arch:${ARCH_OPT}") + add_compile_options(${CMAKE_REQUIRED_FLAGS}) + else() + set(CMAKE_REQUIRED_FLAGS "-march=${ARCH_OPT}") + add_compile_options(-march=${ARCH_OPT}) + endif() +elseif(FORCE_SSSE3 OR FORCE_SSE41) + if (NOT MSVC) + set(CMAKE_REQUIRED_FLAGS ${FORCE_OPT}) + add_compile_options(${FORCE_OPT}) + endif() +endif() + +check_cxx_compiler_flag("${CMAKE_REQUIRED_FLAGS}" FLAG_SUPPORTED) +if (NOT FLAG_SUPPORTED) + message(FATAL_ERROR "Flag '${CMAKE_REQUIRED_FLAGS}' rejected by compiler. Please adjust ARCH_OPT option.") +endif() + +if (ARCHITECTURE_ARM) + if (MSVC) + force_ext_available(ARM_NEON) + else() + list(APPEND CMAKE_REQUIRED_FLAGS -mfpu=neon) + endif() +endif() + +# This is quite basic detection, can be extended if needed +detect_extensions(ARM_NEON) +detect_extensions(AVX512F) +detect_extensions(AVX2 HAS_AVX512F) +detect_extensions(AVX HAS_AVX2) +detect_extensions(SSE4_2 HAS_AVX) +detect_extensions(SSE4_1 HAS_SSE4_2) +detect_extensions(SSSE3 HAS_SSE4_1) +detect_extensions(SSE3 HAS_SSSE3) +detect_extensions(SSE2 HAS_SSE3) + +cmake_pop_check_state() diff --git a/swagger/CMakeLists.txt b/swagger/CMakeLists.txt index c44a42a30..c40c0993a 100644 --- a/swagger/CMakeLists.txt +++ b/swagger/CMakeLists.txt @@ -17,7 +17,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client ) -if (C_GCC OR C_CLANG) +if (NOT MSVC) set_target_properties(swagger PROPERTIES COMPILE_FLAGS "-Wno-conversion-null -Wno-unused-variable -Wno-unused-parameter") endif()