include( CheckCCompilerFlag )
include( CheckCSourceCompiles )
function( set_if_compiler_supports_flag output_var flag )
string( REGEX REPLACE "[-.]" "_" SUPPORTED_flag_var "SUPPORTED${flag}" )
check_c_compiler_flag( -Werror=unused-command-line-argument SUPPORTED_Werror_unused_command_line_argument )
if( SUPPORTED_Werror_unused_command_line_argument )
set( FLAGS_CHECK_STR "${flag} -Werror=unused-command-line-argument" )
else()
set( FLAGS_CHECK_STR "${flag}" )
endif()
# if building WASM -msimd128 needs to be added to all checks for supported simd-compiler flags
_emscripten_enable_wasm_simd128()
check_c_compiler_flag( ${FLAGS_CHECK_STR} ${SUPPORTED_flag_var} )
if( ${SUPPORTED_flag_var} )
set( ${output_var} "${flag}" PARENT_SCOPE )
endif()
endfunction()
function( check_missing_intrinsics )
# if building WASM -msimd128 needs to be added to all checks for supported simd-compiler flags
_emscripten_enable_wasm_simd128()
set_if_compiler_supports_flag( FLAG_msse2 -msse2 )
set_if_compiler_supports_flag( FLAG_mavx -mavx )
_check_intrinsic( _mm_storeu_si16 "${FLAG_msse2}" "int16_t a = 0; _mm_storeu_si16( &a, _mm_setzero_si128() );" )
_check_intrinsic( _mm_storeu_si32 "${FLAG_msse2}" "int32_t a = 0; _mm_storeu_si32( &a, _mm_setzero_si128() );" )
_check_intrinsic( _mm_storeu_si64 "${FLAG_msse2}" "int64_t a = 0; _mm_storeu_si64( &a, _mm_setzero_si128() );" )
_check_intrinsic( _mm_loadu_si32 "${FLAG_msse2}" "int32_t a = 0; __m128i x = _mm_loadu_si32( &a );" )
_check_intrinsic( _mm_loadu_si64 "${FLAG_msse2}" "int64_t a = 0; __m128i x = _mm_loadu_si64( &a );" )
_check_intrinsic( _mm256_zeroupper "${FLAG_mavx}" "_mm256_zeroupper();" )
_check_intrinsic( _mm256_loadu2_m128i "${FLAG_mavx}" "int a[4] = { 0, }; \
__m256i x = _mm256_loadu2_m128i( ( const __m128i* ) a, \
( const __m128i* ) a );" )
endfunction()
function( _check_intrinsic symbol_name compiler_flags code )
set( CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${compiler_flags}")
set( CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/" )
check_c_source_compiles("
#include <simde/simde-arch.h>
#if defined(SIMDE_ARCH_AMD64) || defined(SIMDE_ARCH_X86) || defined(SIMDE_ARCH_WASM)
# include <immintrin.h> // need this first, otherwise we get linker-errors on windows
#else
# define SIMDE_ENABLE_NATIVE_ALIASES
#endif
#include <simde/x86/avx.h>
#include <stdint.h>
int main()
{
${code}
return 0;
}"
HAVE_INTRIN${symbol_name} )
if( NOT HAVE_INTRIN${symbol_name} )
add_compile_definitions( MISSING_INTRIN${symbol_name} )
endif()
endfunction()
function( _emscripten_enable_wasm_simd128 )
if( ${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten" )
# this is only used by try_compile(), check_c_compiler_flag(), and related functions,
# but not by the actual build.
set( CMAKE_REQUIRED_FLAGS -msimd128 PARENT_SCOPE )
endif()
endfunction()
function( detect_target_architecture output_var )
# try to detect the actual target architecture
if( ${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten" )
message( DEBUG "Emscripten" )
# Emscripten doesn't set the CMAKE_SYSTEM_PROCESSOR
list( PREPEND target_arch_list "WASM" )
elseif( NOT CMAKE_SYSTEM_PROCESSOR STREQUAL CMAKE_HOST_SYSTEM_PROCESSOR )
message( DEBUG "sys != host ${CMAKE_SYSTEM_PROCESSOR} STREQUAL ${CMAKE_HOST_SYSTEM_PROCESSOR} " )
# cross compiling: CMAKE_SYSTEM_PROCESSOR was set explicitly, so we use that as first guess
_append_cpu_type_guess( target_arch_list "${CMAKE_SYSTEM_PROCESSOR}" )
endif()
# build list of architectures in order of probability
_append_cpu_type_guess( target_arch_list "${CMAKE_VS_PLATFORM_NAME}" )
_append_cpu_type_guess( target_arch_list "${CMAKE_OSX_ARCHITECTURES}" )
_append_cpu_type_guess( target_arch_list "${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" ) # set by msvc, wen not using msbuild
_append_cpu_type_guess( target_arch_list "${CMAKE_ANDROID_ARCH_ABI}" )
_append_cpu_type_guess( target_arch_list "${CMAKE_C_LIBRARY_ARCHITECTURE}" )
_append_cpu_type_guess( target_arch_list "${CMAKE_SYSTEM_PROCESSOR}" )
_append_cpu_type_guess( target_arch_list "${CMAKE_HOST_SYSTEM_PROCESSOR}" )
list( APPEND target_arch_list "UNKNOWN" ) # no architecture for which we have specific optimizations
message( DEBUG "target_arch_list: ${target_arch_list}" )
# get most probable architecture
list( POP_FRONT target_arch_list detected_arch )
message( STATUS "normalized target architecture: ${detected_arch}" )
set( ${output_var} "${detected_arch}" PARENT_SCOPE )
endfunction()
function( _append_cpu_type_guess output_list input_str )
set( ret ${${output_list}} )
string( TOLOWER "${input_str}" input_lower )
if( ${input_lower} MATCHES "x86\|i386\|x64\|win32\|amd64" )
list( APPEND ret "X86" )
elseif( ${input_lower} MATCHES "aarch64\|arm")
list( APPEND ret "ARM" )
endif()
set( ${output_list} ${ret} PARENT_SCOPE )
endfunction()