-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from psteinb/cmake-detect-feature
Cmake detect feature
- Loading branch information
Showing
12 changed files
with
1,131 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,7 @@ | ||
*~ | ||
build | ||
build/* | ||
debug/* | ||
*sln | ||
*.vcxproj* | ||
x64 | ||
x32 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,337 @@ | ||
##extract a single line that contains the given pattern (starting from that patter) | ||
function(extract_line LINESTART_PATTERN MULTILINE_STRING OUTPUT_VARIABLE) | ||
|
||
STRING(FIND ${MULTILINE_STRING} "${PATTERN}" MATCH_OFFSET) | ||
STRING(SUBSTRING ${MATCH_OFFSET} 0 ${MATCH_OFFSET} MULTILINE_NO_START) | ||
STRING(FIND ${MULTILINE_NO_START} "\n" MULTILINE_RETURN_OFFSET) | ||
STRING(SUBSTRING ${MULTILINE_NO_START} 0 ${MULTILINE_RETURN_OFFSET} MATCHING_LINE) | ||
set(OUTPUT_VARIABLE ${MATCHING_LINE} PARENT_SCOPE) | ||
|
||
endfunction(extract_line) | ||
|
||
##extract system information from wmic.exe on Windows | ||
function(wmic_get ATTRIBUTENAME RESULTVALUE) | ||
EXEC_PROGRAM("wmic.exe" ARGS "cpu get ${ATTRIBUTENAME}" OUTPUT_VARIABLE WMIC_OUTPUT) | ||
string(REGEX REPLACE " [ ]+" ";" WMIC_OUTPUT_CLEANED ${WMIC_OUTPUT}) | ||
set(WMIC_OUTPUT_LIST "${WMIC_OUTPUT_CLEANED};") | ||
list(GET WMIC_OUTPUT_LIST 1 VALUEOFINTEREST) | ||
|
||
string(STRIP "${VALUEOFINTEREST}" VALUEOFINTEREST) | ||
set(${RESULTVALUE} ${VALUEOFINTEREST} PARENT_SCOPE) | ||
#message(STATUS "[wmic_get] RESULT = ${VALUEOFINTEREST}") | ||
|
||
endfunction(wmic_get) | ||
|
||
IF(CMAKE_SYSTEM_NAME MATCHES "Linux") | ||
EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO) | ||
|
||
##FIND VENDOR | ||
STRING(FIND ${CPUINFO} "vendor" VENDOR_TITLE_OFFSET) | ||
STRING(SUBSTRING ${CPUINFO} ${VENDOR_TITLE_OFFSET} 50 GUESSED_VENDOR_LINE) | ||
STRING(REGEX REPLACE "^vendor.*: ([a-zA-Z]+)\n.*" "\\1" VENDOR_TITLE ${GUESSED_VENDOR_LINE}) | ||
message(STATUS "vendor found: ${VENDOR_TITLE}") | ||
set(CPU_VENDOR "${VENDOR_TITLE}" CACHE STRING "cpu vendor") | ||
|
||
##FIND MODEL NAME | ||
STRING(FIND ${CPUINFO} "model name" MODEL_NAME_OFFSET) | ||
STRING(SUBSTRING ${CPUINFO} ${MODEL_NAME_OFFSET} 100 GUESSED_MODEL_NAME_LINE) | ||
STRING(FIND ${GUESSED_MODEL_NAME_LINE} "\n" MODEL_NAME_RETURN_OFFSET) | ||
STRING(SUBSTRING ${GUESSED_MODEL_NAME_LINE} 0 ${MODEL_NAME_RETURN_OFFSET} GUESSED_MODEL_NAME_LINE) | ||
|
||
STRING(REGEX REPLACE "^model name.*: ([a-zA-Z]+.*)$" "\\1" MODEL_NAME ${GUESSED_MODEL_NAME_LINE}) | ||
message(STATUS "model name found: ${MODEL_NAME}") | ||
set(CPU_MODEL_NAME "${MODEL_NAME}" CACHE STRING "cpu model name") | ||
|
||
##FIND INSTRUCTIONS | ||
STRING(REGEX REPLACE "^.*(sse) .*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "sse" "${SSE_THERE}" SSE_TRUE) | ||
IF (SSE_TRUE) | ||
set(SSE_FOUND true CACHE BOOL "SSE available on host") | ||
ELSE (SSE_TRUE) | ||
set(SSE_FOUND false CACHE BOOL "SSE available on host") | ||
ENDIF (SSE_TRUE) | ||
|
||
STRING(REGEX REPLACE "^.*(sse2) .*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "sse2" "${SSE_THERE}" SSE2_TRUE) | ||
IF (SSE2_TRUE) | ||
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host") | ||
ELSE (SSE2_TRUE) | ||
set(SSE2_FOUND false CACHE BOOL "SSE2 available on host") | ||
ENDIF (SSE2_TRUE) | ||
|
||
# /proc/cpuinfo apparently omits sse3 :( | ||
STRING(REGEX REPLACE "^.*[^s](sse3) .*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "sse3" "${SSE_THERE}" SSE3_TRUE) | ||
IF (NOT SSE3_TRUE) | ||
STRING(REGEX REPLACE "^.*(T2300).*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "T2300" "${SSE_THERE}" SSE3_TRUE) | ||
ENDIF (NOT SSE3_TRUE) | ||
|
||
STRING(REGEX REPLACE "^.* (ssse3) .*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "ssse3" "${SSE_THERE}" SSSE3_TRUE) | ||
IF (SSE3_TRUE OR SSSE3_TRUE) | ||
set(SSE3_FOUND true CACHE BOOL "SSE3 available on host") | ||
ELSE (SSE3_TRUE OR SSSE3_TRUE) | ||
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host") | ||
ENDIF (SSE3_TRUE OR SSSE3_TRUE) | ||
IF (SSSE3_TRUE) | ||
set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host") | ||
ELSE (SSSE3_TRUE) | ||
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host") | ||
ENDIF (SSSE3_TRUE) | ||
|
||
STRING(REGEX REPLACE "^.* (sse4_1) .*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "sse4_1" "${SSE_THERE}" SSE41_TRUE) | ||
IF (SSE41_TRUE) | ||
set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host") | ||
ELSE (SSE41_TRUE) | ||
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") | ||
ENDIF (SSE41_TRUE) | ||
|
||
STRING(REGEX REPLACE "^.* (sse4_2) .*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "sse4_2" "${SSE_THERE}" SSE42_TRUE) | ||
IF (SSE42_TRUE) | ||
set(SSE4_2_FOUND true CACHE BOOL "SSE4.2 available on host") | ||
ELSE (SSE42_TRUE) | ||
set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host") | ||
ENDIF (SSE42_TRUE) | ||
|
||
if("${CPUINFO}" MATCHES ".*avx .*") | ||
set(AVX_FOUND true CACHE BOOL "AVX available on host") | ||
else() | ||
set(AVX_FOUND false CACHE BOOL "AVX available on host") | ||
endif() | ||
|
||
if("${CPUINFO}" MATCHES ".*avx2 .*") | ||
set(AVX2_FOUND true CACHE BOOL "AVX2 available on host") | ||
else() | ||
set(AVX2_FOUND false CACHE BOOL "AVX2 available on host") | ||
endif() | ||
|
||
# | ||
if(EXISTS "/sys/devices/system/cpu/cpu0/cache/index2/size") | ||
EXEC_PROGRAM(cat ARGS "/sys/devices/system/cpu/cpu0/cache/index2/size" OUTPUT_VARIABLE L2_SIZE_KB_STRING) | ||
|
||
if(${L2_SIZE_KB_STRING} MATCHES ".*[K|k]") | ||
string(REGEX REPLACE "[K|k]" "" L2_SIZE_KB ${L2_SIZE_KB_STRING}) | ||
set(CPU_L2_SIZE_KB "${L2_SIZE_KB}" CACHE STRING "cpu L2 cache size in kB") | ||
else() | ||
if(${L2_SIZE_KB_STRING} MATCHES ".*[M|m]") | ||
string(REGEX REPLACE "[M|m]" "000" L2_SIZE_KB ${L2_SIZE_KB_STRING}) | ||
set(CPU_L2_SIZE_KB "${L2_SIZE_KB}" CACHE STRING "cpu L2 cache size in kB") | ||
else() | ||
message(WARNING "unable to find unit prefix (K|M) in /sys/devices/system/cpu/cpu0/cache/index2/size:${L2_SIZE_KB_STRING} (assuming it's contents as expressed in kB, crossing fingers)") | ||
set(CPU_L2_SIZE_KB "${L2_SIZE_KB_STRING}" CACHE STRING "cpu L2 cache size in kB") | ||
endif() | ||
|
||
endif() | ||
|
||
else() | ||
message("unable to find /sys/devices/system/cpu/cpu0/cache/index2/size") | ||
set(CPU_L2_SIZE_KB "0" CACHE STRING "cpu L2 cache size in kB") | ||
endif() | ||
|
||
|
||
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin") | ||
EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.features" OUTPUT_VARIABLE | ||
CPUINFO) | ||
|
||
EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.leaf7_features" OUTPUT_VARIABLE | ||
LEAF7_CPUINFO) | ||
|
||
EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.vendor" OUTPUT_VARIABLE | ||
VENDOR_TITLE) | ||
|
||
EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.brand_string" OUTPUT_VARIABLE | ||
MODEL_NAME) | ||
|
||
EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.cache.size" OUTPUT_VARIABLE | ||
CPU_L2_SIZE_KB) | ||
|
||
set(CPU_VENDOR "${VENDOR_TITLE}" CACHE STRING "cpu vendor") | ||
set(CPU_MODEL_NAME "${MODEL_NAME}" CACHE STRING "cpu model name") | ||
|
||
STRING(REGEX REPLACE "^.*[^S](SSE) .*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "SSE" "${SSE_THERE}" SSE_TRUE) | ||
IF (SSE_TRUE) | ||
set(SSE_FOUND true CACHE BOOL "SSE2 available on host") | ||
ELSE (SSE_TRUE) | ||
set(SSE_FOUND false CACHE BOOL "SSE2 available on host") | ||
ENDIF (SSE_TRUE) | ||
|
||
STRING(REGEX REPLACE "^.*[^S](SSE2) .*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "SSE2" "${SSE_THERE}" SSE2_TRUE) | ||
IF (SSE2_TRUE) | ||
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host") | ||
ELSE (SSE2_TRUE) | ||
set(SSE2_FOUND false CACHE BOOL "SSE2 available on host") | ||
ENDIF (SSE2_TRUE) | ||
|
||
STRING(REGEX REPLACE "^.*[^S](SSE2).*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "SSE2" "${SSE_THERE}" SSE2_TRUE) | ||
IF (SSE2_TRUE) | ||
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host") | ||
ELSE (SSE2_TRUE) | ||
set(SSE2_FOUND false CACHE BOOL "SSE2 available on host") | ||
ENDIF (SSE2_TRUE) | ||
|
||
STRING(REGEX REPLACE "^.*[^S](SSE3).*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "SSE3" "${SSE_THERE}" SSE3_TRUE) | ||
IF (SSE3_TRUE) | ||
set(SSE3_FOUND true CACHE BOOL "SSE3 available on host") | ||
ELSE (SSE3_TRUE) | ||
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host") | ||
ENDIF (SSE3_TRUE) | ||
|
||
STRING(REGEX REPLACE "^.*(SSSE3).*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "SSSE3" "${SSE_THERE}" SSSE3_TRUE) | ||
IF (SSSE3_TRUE) | ||
set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host") | ||
ELSE (SSSE3_TRUE) | ||
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host") | ||
ENDIF (SSSE3_TRUE) | ||
|
||
STRING(REGEX REPLACE "^.*(SSE4.1).*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "SSE4.1" "${SSE_THERE}" SSE41_TRUE) | ||
IF (SSE41_TRUE) | ||
set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host") | ||
ELSE (SSE41_TRUE) | ||
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") | ||
ENDIF (SSE41_TRUE) | ||
|
||
STRING(REGEX REPLACE "^.*(SSE4.2).*$" "\\1" SSE_THERE ${CPUINFO}) | ||
STRING(COMPARE EQUAL "SSE4.2" "${SSE_THERE}" SSE42_TRUE) | ||
IF (SSE42_TRUE) | ||
set(SSE4_2_FOUND true CACHE BOOL "SSE4.2 available on host") | ||
ELSE (SSE42_TRUE) | ||
set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host") | ||
ENDIF (SSE42_TRUE) | ||
|
||
if("${CPUINFO}" MATCHES ".*AVX.*") | ||
set(AVX_FOUND true CACHE BOOL "AVX available on host") | ||
else() | ||
set(AVX_FOUND false CACHE BOOL "AVX available on host") | ||
endif() | ||
|
||
if("${CPUINFO}" MATCHES ".*AVX2 .*") | ||
set(AVX2_FOUND true CACHE BOOL "AVX2 available on host") | ||
else() | ||
if("${LEAF7_CPUINFO}" MATCHES ".*AVX2 .*") | ||
set(AVX2_FOUND true CACHE BOOL "AVX2 available on host") | ||
else() | ||
set(AVX2_FOUND false CACHE BOOL "AVX2 available on host") | ||
endif() | ||
endif() | ||
|
||
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Windows") | ||
|
||
#as an alternative to wmic, use | ||
#get_filename_component(_vendor_id "[HKEY_LOCAL_MACHINE\\Hardware\\Description\\System\\CentralProcessor\\0;VendorIdentifier]" NAME CACHE) | ||
#get_filename_component(_cpu_id "[HKEY_LOCAL_MACHINE\\Hardware\\Description\\System\\CentralProcessor\\0;Identifier]" NAME CACHE) | ||
|
||
wmic_get("Name" MODEL_NAME) | ||
string(STRIP ${MODEL_NAME} MODEL_NAME) | ||
set(CPU_MODEL_NAME "${MODEL_NAME}" CACHE STRING "cpu model name") | ||
|
||
wmic_get("Manufacturer" MODEL_VENDOR) | ||
set(CPU_VENDOR "${MODEL_VENDOR}" CACHE STRING "cpu model vendor") | ||
|
||
wmic_get("L2CacheSize" L2_CACHE_SIZE) | ||
wmic_get("NumberOfCores" CPU_NPHYS_CORES) | ||
|
||
#dirty hack that I need to validate with other machines in Win7 | ||
if(NOT "${L2_CACHE_SIZE}" STREQUAL "") | ||
if(${CPU_NPHYS_CORES} GREATER 1) | ||
math(EXPR L2_CACHE_SIZE "${L2_CACHE_SIZE}/${CPU_NPHYS_CORES}") | ||
endif() | ||
set(CPU_L2_SIZE_KB "${L2_CACHE_SIZE}" CACHE STRING "cpu L2 cache size in kB") | ||
else() | ||
message("unable to decipher L2 cache size") | ||
endif() | ||
set(CPU_L2_SIZE_KB "0" CACHE STRING "cpu L2 cache size in kB") | ||
set(CPU_VENDOR "" CACHE STRING "cpu model vendor") | ||
set(CPU_MODEL_NAME "" CACHE STRING "cpu model name") | ||
|
||
#thanks to the wonderful VC project (https://github.com/VcDevel/Vc) | ||
include (OptimizeForArchitecture) | ||
|
||
OFA_AutodetectHostArchitecture() | ||
OFA_HandleX86Options() | ||
|
||
|
||
list(FIND _available_vector_units_list "sse" SSE_INDEX) | ||
list(FIND _available_vector_units_list "sse2" SSE2_INDEX) | ||
list(FIND _available_vector_units_list "sse3" SSE3_INDEX) | ||
list(FIND _available_vector_units_list "ssse3" SSSE3_INDEX) | ||
list(FIND _available_vector_units_list "sse4.1" SSE4_1_INDEX) | ||
list(FIND _available_vector_units_list "sse4.2" SSE4_2_INDEX) | ||
list(FIND _available_vector_units_list "avx" AVX_INDEX) | ||
list(FIND _available_vector_units_list "avx2" AVX2_INDEX) | ||
|
||
if(${SSE_INDEX} GREATER -1) | ||
set(SSE_FOUND true CACHE BOOL "SSE available on host") | ||
endif() | ||
if(${SSE2_INDEX} GREATER -1) | ||
set(SSE2_FOUND true CACHE BOOL "SSE2 available on host") | ||
endif() | ||
if(${SSE3_INDEX} GREATER -1) | ||
set(SSE3_FOUND true CACHE BOOL "SSE3 available on host") | ||
endif() | ||
if(${SSSE3_INDEX} GREATER -1) | ||
set(SSSE3_FOUND true CACHE BOOL "SSSE3 available on host") | ||
endif() | ||
if(${SSE4_1_INDEX} GREATER -1) | ||
set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host") | ||
endif() | ||
if(${SSE4_2_INDEX} GREATER -1) | ||
set(SSE4_2_FOUND true CACHE BOOL "SSE4.2 available on host") | ||
endif() | ||
if(${AVX_INDEX} GREATER -1) | ||
set(AVX_FOUND true CACHE BOOL "AVX available on host") | ||
endif() | ||
if(${AVX2_INDEX} GREATER -1) | ||
set(AVX2_FOUND true CACHE BOOL "AVX2 available on host") | ||
endif() | ||
|
||
set(SSE_FOUND true CACHE BOOL "SSE available on host") | ||
set(SSE2_FOUND false CACHE BOOL "SSE2 available on host") | ||
set(SSE3_FOUND false CACHE BOOL "SSE3 available on host") | ||
set(SSSE3_FOUND false CACHE BOOL "SSSE3 available on host") | ||
set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") | ||
set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host") | ||
set(AVX_FOUND false CACHE BOOL "AVX available on host") | ||
set(AVX2_FOUND false CACHE BOOL "AVX2 available on host") | ||
|
||
ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux") | ||
|
||
message(STATUS "found hardware: ${CPU_VENDOR} ${CPU_MODEL_NAME}") | ||
set(FOUND_FEATURES) | ||
|
||
if(SSE_FOUND) | ||
list(APPEND FOUND_FEATURES "sse") | ||
endif(SSE_FOUND) | ||
if(SSE2_FOUND) | ||
list(APPEND FOUND_FEATURES "sse2") | ||
endif(SSE2_FOUND) | ||
if( SSE3_FOUND) | ||
list(APPEND FOUND_FEATURES "sse3") | ||
endif( SSE3_FOUND) | ||
if( SSSE3_FOUND) | ||
list(APPEND FOUND_FEATURES "ssse3") | ||
endif( SSSE3_FOUND) | ||
if( SSE4_1_FOUND) | ||
list(APPEND FOUND_FEATURES "sse4.1") | ||
endif( SSE4_1_FOUND) | ||
if( SSE4_2_FOUND) | ||
list(APPEND FOUND_FEATURES "sse4.2") | ||
endif( SSE4_2_FOUND) | ||
if( AVX_FOUND) | ||
list(APPEND FOUND_FEATURES "avx") | ||
endif( AVX_FOUND) | ||
if( AVX2_FOUND) | ||
list(APPEND FOUND_FEATURES "avx2") | ||
endif( AVX2_FOUND) | ||
|
||
message(STATUS "found hardware features: ${FOUND_FEATURES}") | ||
|
||
mark_as_advanced(SSE_FOUND SSE2_FOUND SSE3_FOUND SSSE3_FOUND SSE4_1_FOUND SSE4_2_FOUND AVX_FOUND AVX2_FOUND CPU_VENDOR CPU_MODEL_NAME CPU_L2_SIZE_KB) |
Oops, something went wrong.