1# Check for SIMD extensions. 2include(CMakePushCheckState) 3 4function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD) 5 if(NOT ENABLE_SIMD) 6 message(STATUS "Disabling ${WEBP_SIMD_FLAG} optimization.") 7 set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE) 8 return() 9 endif() 10 unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE) 11 cmake_push_check_state() 12 set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}) 13 check_c_source_compiles(" 14 #include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\" 15 int main(void) { 16 #if !defined(WEBP_USE_${WEBP_SIMD_FLAG}) 17 this is not valid code 18 #endif 19 return 0; 20 } 21 " WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}) 22 cmake_pop_check_state() 23 if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}) 24 set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE) 25 else() 26 set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE) 27 endif() 28endfunction() 29 30# those are included in the names of WEBP_USE_* in c++ code. 31set(WEBP_SIMD_FLAGS "SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA") 32set(WEBP_SIMD_FILE_EXTENSIONS 33 "_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c") 34if(MSVC) 35 # MSVC does not have a SSE4 flag but AVX support implies SSE4 support. 36 set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;") 37 set(SIMD_DISABLE_FLAGS) 38else() 39 set(SIMD_ENABLE_FLAGS 40 "-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa") 41 set(SIMD_DISABLE_FLAGS 42 "-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa") 43endif() 44 45set(WEBP_SIMD_FILES_TO_NOT_INCLUDE) 46set(WEBP_SIMD_FILES_TO_INCLUDE) 47set(WEBP_SIMD_FLAGS_TO_INCLUDE) 48 49if(${ANDROID}) 50 if(${ANDROID_ABI} STREQUAL "armeabi-v7a") 51 # This is because Android studio uses the configuration "-march=armv7-a 52 # -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon 53 # optimizations but should (as this configuration does not exist anymore). 54 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon ") 55 endif() 56endif() 57 58list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH) 59math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1") 60unset(HIGHEST_SSE_FLAG) 61 62foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE}) 63 list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG) 64 65 # First try with no extra flag added as the compiler might have default flags 66 # (especially on Android). 67 unset(WEBP_HAVE_${WEBP_SIMD_FLAG} CACHE) 68 cmake_push_check_state() 69 set(CMAKE_REQUIRED_FLAGS) 70 webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) 71 if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG}) 72 list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) 73 set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG}) 74 webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) 75 else() 76 if(MSVC) 77 list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) 78 else() 79 set(SIMD_COMPILE_FLAG " ") 80 endif() 81 endif() 82 # Check which files we should include or not. 83 list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION) 84 file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../" 85 "src/dsp/*${WEBP_SIMD_FILE_EXTENSION}") 86 if(WEBP_HAVE_${WEBP_SIMD_FLAG}) 87 if(${I_SIMD} LESS 2 AND NOT HIGHEST_SSE_FLAG) 88 set(HIGHEST_SSE_FLAG ${SIMD_COMPILE_FLAG}) 89 endif() 90 # Memorize the file and flags. 91 foreach(FILE ${SIMD_FILES}) 92 list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE}) 93 if(${I_SIMD} LESS 2) 94 list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${HIGHEST_SSE_FLAG}) 95 else() 96 list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG}) 97 endif() 98 endforeach() 99 else() 100 # Remove the file from the list. 101 foreach(FILE ${SIMD_FILES}) 102 list(APPEND WEBP_SIMD_FILES_NOT_TO_INCLUDE ${FILE}) 103 endforeach() 104 # Explicitly disable SIMD. 105 if(SIMD_DISABLE_FLAGS) 106 list(GET SIMD_DISABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) 107 include(CheckCCompilerFlag) 108 if(SIMD_COMPILE_FLAG) 109 unset(HAS_COMPILE_FLAG CACHE) 110 check_c_compiler_flag(${SIMD_COMPILE_FLAG} HAS_COMPILE_FLAG) 111 if(HAS_COMPILE_FLAG) 112 # Do one more check for Clang to circumvent CMake issue 13194. 113 if(COMMAND check_compiler_flag_common_patterns) 114 # Only in CMake 3.0 and above. 115 check_compiler_flag_common_patterns(COMMON_PATTERNS) 116 else() 117 set(COMMON_PATTERNS) 118 endif() 119 set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG}) 120 check_c_source_compiles("int main(void) {return 0;}" 121 FLAG_${SIMD_COMPILE_FLAG} 122 FAIL_REGEX 123 "warning: argument unused during compilation:" 124 ${COMMON_PATTERNS}) 125 if(NOT FLAG_${SIMD_COMPILE_FLAG}) 126 unset(HAS_COMPILE_FLAG CACHE) 127 endif() 128 endif() 129 if(HAS_COMPILE_FLAG) 130 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SIMD_COMPILE_FLAG}") 131 endif() 132 endif() 133 endif() 134 endif() 135 cmake_pop_check_state() 136endforeach() 137