mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 05:38:22 +01:00
96099a79a8
Sincea376e7b9
Fix compilation on windows and clang-cl+ninja. the highest level assembly flag (/arch:AVX / -msse4.1) would be applied to all assembly files. This could result in higher level instructions being used which would defeat the runtime cpu detection check and could result in a crash. With this change -m style flags are used with clang-cl as it supports them and allows the correct level to be set. With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2 or SSE4 code unless a lesser /arch is forced so these flags are avoided. This matches the nmake build. For emscripten only sse2 and sse4.1 are tested (NEON will succeed in being enabled, but fail to build). This is consistent with the current behavior added in: commit36c81ff6a9
WASM-SIMD: port 2 patches from rreverser@'s tree * Stop on first found SIMD version * Imply lower SSE version when higher is found Bug: webp:488 Change-Id: I34d01274e5204a477b6b9f35ed566048a62b4c57 Tested: msvc 2013-2019 debug win32/x64 builds; clang-cl under 2019
148 lines
5.5 KiB
CMake
148 lines
5.5 KiB
CMake
# Check for SIMD extensions.
|
|
include(CMakePushCheckState)
|
|
|
|
function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
|
|
if(NOT ENABLE_SIMD)
|
|
message(STATUS "Disabling ${WEBP_SIMD_FLAG} optimization.")
|
|
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE)
|
|
cmake_push_check_state()
|
|
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
|
|
check_c_source_compiles("
|
|
#include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\"
|
|
int main(void) {
|
|
#if !defined(WEBP_USE_${WEBP_SIMD_FLAG})
|
|
this is not valid code
|
|
#endif
|
|
return 0;
|
|
}
|
|
" WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
|
|
cmake_pop_check_state()
|
|
if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
|
|
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE)
|
|
else()
|
|
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE)
|
|
endif()
|
|
endfunction()
|
|
|
|
# those are included in the names of WEBP_USE_* in c++ code.
|
|
set(WEBP_SIMD_FLAGS "SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA")
|
|
set(WEBP_SIMD_FILE_EXTENSIONS
|
|
"_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c")
|
|
if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
|
# With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2
|
|
# or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4
|
|
# flag, but an AVX one. Using that with SSE4 code risks generating illegal
|
|
# instructions when used on machines with SSE4 only. The flags are left for
|
|
# older (untested) versions to avoid any potential compatibility issues.
|
|
if(MSVC_VERSION GREATER_EQUAL 1800 AND NOT CMAKE_C_FLAGS MATCHES "/arch:")
|
|
set(SIMD_ENABLE_FLAGS)
|
|
else()
|
|
set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;")
|
|
endif()
|
|
set(SIMD_DISABLE_FLAGS)
|
|
else()
|
|
set(SIMD_ENABLE_FLAGS
|
|
"-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
|
|
set(SIMD_DISABLE_FLAGS
|
|
"-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa")
|
|
endif()
|
|
|
|
set(WEBP_SIMD_FILES_TO_NOT_INCLUDE)
|
|
set(WEBP_SIMD_FILES_TO_INCLUDE)
|
|
set(WEBP_SIMD_FLAGS_TO_INCLUDE)
|
|
|
|
if(${ANDROID})
|
|
if(${ANDROID_ABI} STREQUAL "armeabi-v7a")
|
|
# This is because Android studio uses the configuration "-march=armv7-a
|
|
# -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon
|
|
# optimizations but should (as this configuration does not exist anymore).
|
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon ")
|
|
endif()
|
|
endif()
|
|
|
|
list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH)
|
|
math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1")
|
|
|
|
foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
|
|
# With Emscripten 2.0.9 -msimd128 -mfpu=neon will enable NEON, but the
|
|
# source will fail to compile.
|
|
if(EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 2)
|
|
break()
|
|
endif()
|
|
|
|
list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG)
|
|
|
|
# First try with no extra flag added as the compiler might have default flags
|
|
# (especially on Android).
|
|
unset(WEBP_HAVE_${WEBP_SIMD_FLAG} CACHE)
|
|
cmake_push_check_state()
|
|
set(CMAKE_REQUIRED_FLAGS)
|
|
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
|
|
if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG})
|
|
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
|
|
if(EMSCRIPTEN)
|
|
set(SIMD_COMPILE_FLAG "-msimd128 ${SIMD_COMPILE_FLAG}")
|
|
endif()
|
|
set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG})
|
|
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
|
|
else()
|
|
if(MSVC AND SIMD_ENABLE_FLAGS)
|
|
# The detection for SSE2/SSE4 support under MSVC is based on the compiler
|
|
# version so e.g., clang-cl will require flags to enable the assembly.
|
|
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
|
|
else()
|
|
set(SIMD_COMPILE_FLAG " ")
|
|
endif()
|
|
endif()
|
|
# Check which files we should include or not.
|
|
list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION)
|
|
file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../"
|
|
"src/dsp/*${WEBP_SIMD_FILE_EXTENSION}")
|
|
if(WEBP_HAVE_${WEBP_SIMD_FLAG})
|
|
# Memorize the file and flags.
|
|
foreach(FILE ${SIMD_FILES})
|
|
list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE})
|
|
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG})
|
|
endforeach()
|
|
else()
|
|
# Remove the file from the list.
|
|
foreach(FILE ${SIMD_FILES})
|
|
list(APPEND WEBP_SIMD_FILES_NOT_TO_INCLUDE ${FILE})
|
|
endforeach()
|
|
# Explicitly disable SIMD.
|
|
if(SIMD_DISABLE_FLAGS)
|
|
list(GET SIMD_DISABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
|
|
include(CheckCCompilerFlag)
|
|
if(SIMD_COMPILE_FLAG)
|
|
unset(HAS_COMPILE_FLAG CACHE)
|
|
check_c_compiler_flag(${SIMD_COMPILE_FLAG} HAS_COMPILE_FLAG)
|
|
if(HAS_COMPILE_FLAG)
|
|
# Do one more check for Clang to circumvent CMake issue 13194.
|
|
if(COMMAND check_compiler_flag_common_patterns)
|
|
# Only in CMake 3.0 and above.
|
|
check_compiler_flag_common_patterns(COMMON_PATTERNS)
|
|
else()
|
|
set(COMMON_PATTERNS)
|
|
endif()
|
|
set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG})
|
|
check_c_source_compiles("int main(void) {return 0;}"
|
|
FLAG_${SIMD_COMPILE_FLAG}
|
|
FAIL_REGEX
|
|
"warning: argument unused during compilation:"
|
|
${COMMON_PATTERNS})
|
|
if(NOT FLAG_${SIMD_COMPILE_FLAG})
|
|
unset(HAS_COMPILE_FLAG CACHE)
|
|
endif()
|
|
endif()
|
|
if(HAS_COMPILE_FLAG)
|
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SIMD_COMPILE_FLAG}")
|
|
endif()
|
|
endif()
|
|
endif()
|
|
endif()
|
|
cmake_pop_check_state()
|
|
endforeach()
|