1#[[Cmake helper function to parse source files from make files 2this is to avoid breaking existing make and auto make support 3but still have the option to use CMake with only lists at one place]] 4 5cmake_minimum_required(VERSION 3.1) 6 7function(get_library_version OPUS_LIBRARY_VERSION OPUS_LIBRARY_VERSION_MAJOR) 8 file(STRINGS configure.ac opus_lt_current_string 9 LIMIT_COUNT 1 10 REGEX "OPUS_LT_CURRENT=") 11 string(REGEX MATCH 12 "OPUS_LT_CURRENT=([0-9]*)" 13 _ 14 ${opus_lt_current_string}) 15 set(OPUS_LT_CURRENT ${CMAKE_MATCH_1}) 16 17 file(STRINGS configure.ac opus_lt_revision_string 18 LIMIT_COUNT 1 19 REGEX "OPUS_LT_REVISION=") 20 string(REGEX MATCH 21 "OPUS_LT_REVISION=([0-9]*)" 22 _ 23 ${opus_lt_revision_string}) 24 set(OPUS_LT_REVISION ${CMAKE_MATCH_1}) 25 26 file(STRINGS configure.ac opus_lt_age_string 27 LIMIT_COUNT 1 28 REGEX "OPUS_LT_AGE=") 29 string(REGEX MATCH 30 "OPUS_LT_AGE=([0-9]*)" 31 _ 32 ${opus_lt_age_string}) 33 set(OPUS_LT_AGE ${CMAKE_MATCH_1}) 34 35 math(EXPR OPUS_LIBRARY_VERSION_MAJOR "${OPUS_LT_CURRENT} - ${OPUS_LT_AGE}") 36 set(OPUS_LIBRARY_VERSION_MINOR ${OPUS_LT_AGE}) 37 set(OPUS_LIBRARY_VERSION_PATCH ${OPUS_LT_REVISION}) 38 set( 39 OPUS_LIBRARY_VERSION 40 "${OPUS_LIBRARY_VERSION_MAJOR}.${OPUS_LIBRARY_VERSION_MINOR}.${OPUS_LIBRARY_VERSION_PATCH}" 41 PARENT_SCOPE) 42 set(OPUS_LIBRARY_VERSION_MAJOR ${OPUS_LIBRARY_VERSION_MAJOR} PARENT_SCOPE) 43endfunction() 44 45function(get_package_version PACKAGE_VERSION) 46 find_package(Git) 47 if(GIT_FOUND) 48 execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --match "v*" 49 OUTPUT_VARIABLE OPUS_PACKAGE_VERSION) 50 if(OPUS_PACKAGE_VERSION) 51 string(STRIP ${OPUS_PACKAGE_VERSION}, OPUS_PACKAGE_VERSION) 52 string(REPLACE \n 53 "" 54 OPUS_PACKAGE_VERSION 55 ${OPUS_PACKAGE_VERSION}) 56 string(REPLACE , 57 "" 58 OPUS_PACKAGE_VERSION 59 ${OPUS_PACKAGE_VERSION}) 60 61 string(SUBSTRING ${OPUS_PACKAGE_VERSION} 62 1 63 -1 64 OPUS_PACKAGE_VERSION) 65 set(PACKAGE_VERSION ${OPUS_PACKAGE_VERSION} PARENT_SCOPE) 66 return() 67 endif() 68 endif() 69 70 if(EXISTS "${CMAKE_SOURCE_DIR}/package_version") 71 # Not a git repo, lets' try to parse it from package_version file if exists 72 file(STRINGS package_version opus_package_version_string 73 LIMIT_COUNT 1 74 REGEX "PACKAGE_VERSION=") 75 string(REPLACE "PACKAGE_VERSION=" 76 "" 77 opus_package_version_string 78 ${opus_package_version_string}) 79 string(REPLACE "\"" 80 "" 81 opus_package_version_string 82 ${opus_package_version_string}) 83 set(PACKAGE_VERSION ${opus_package_version_string} PARENT_SCOPE) 84 return() 85 endif() 86 87 # if all else fails set to 0 88 set(PACKAGE_VERSION 0 PARENT_SCOPE) 89endfunction() 90 91function(check_and_set_flag NAME FLAG) 92 include(CheckCCompilerFlag) 93 check_c_compiler_flag(${FLAG} ${NAME}_SUPPORTED) 94 if(${NAME}_SUPPORTED) 95 add_definitions(${FLAG}) 96 endif() 97endfunction() 98 99function(check_flag NAME FLAG) 100 include(CheckCCompilerFlag) 101 check_c_compiler_flag(${FLAG} ${NAME}_SUPPORTED) 102endfunction() 103 104include(CheckIncludeFile) 105# function to check if compiler supports SSE, SSE2, SSE4.1 and AVX if target 106# systems may not have SSE support then use OPUS_MAY_HAVE_SSE option if target 107# system is guaranteed to have SSE support then OPUS_PRESUME_SSE can be used to 108# skip SSE runtime check 109function(opus_detect_sse COMPILER_SUPPORT_SIMD) 110 message(STATUS "Check SIMD support by compiler") 111 check_include_file(xmmintrin.h HAVE_XMMINTRIN_H) # SSE1 112 if(HAVE_XMMINTRIN_H) 113 if(MSVC) 114 # different arch options for 32 and 64 bit target for MSVC 115 if(CMAKE_SIZEOF_VOID_P EQUAL 4) 116 check_flag(SSE1 /arch:SSE) 117 else() 118 set(SSE1_SUPPORTED 1 PARENT_SCOPE) 119 endif() 120 else() 121 check_and_set_flag(SSE1 -msse) 122 endif() 123 else() 124 set(SSE1_SUPPORTED 0 PARENT_SCOPE) 125 endif() 126 127 check_include_file(emmintrin.h HAVE_EMMINTRIN_H) # SSE2 128 if(HAVE_EMMINTRIN_H) 129 if(MSVC) 130 if(CMAKE_SIZEOF_VOID_P EQUAL 4) 131 check_flag(SSE2 /arch:SSE2) 132 else() 133 set(SSE2_SUPPORTED 1 PARENT_SCOPE) 134 endif() 135 else() 136 check_and_set_flag(SSE2 -msse2) 137 endif() 138 else() 139 set(SSE2_SUPPORTED 0 PARENT_SCOPE) 140 endif() 141 142 check_include_file(smmintrin.h HAVE_SMMINTRIN_H) # SSE4.1 143 if(HAVE_SMMINTRIN_H) 144 if(MSVC) 145 if(CMAKE_SIZEOF_VOID_P EQUAL 4) 146 check_flag(SSE4_1 /arch:SSE2) # SSE2 and above 147 else() 148 set(SSE4_1_SUPPORTED 1 PARENT_SCOPE) 149 endif() 150 else() 151 check_and_set_flag(SSE4_1 -msse4.1) 152 endif() 153 else() 154 set(SSE4_1_SUPPORTED 0 PARENT_SCOPE) 155 endif() 156 157 check_include_file(immintrin.h HAVE_IMMINTRIN_H) # AVX 158 if(HAVE_IMMINTRIN_H) 159 if(MSVC) 160 check_flag(AVX /arch:AVX) 161 else() 162 check_and_set_flag(AVX -mavx) 163 endif() 164 else() 165 set(AVX_SUPPORTED 0 PARENT_SCOPE) 166 endif() 167 168 if(MSVC) # To avoid warning D9025 of overriding compiler options 169 if(AVX_SUPPORTED) # on 64 bit and 32 bits 170 add_definitions(/arch:AVX) 171 elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) # if AVX not supported then set SSE flag 172 if(SSE4_1_SUPPORTED OR SSE2_SUPPORTED) 173 add_definitions(/arch:SSE2) 174 elseif(SSE1_SUPPORTED) 175 add_definitions(/arch:SSE) 176 endif() 177 endif() 178 endif() 179 180 if(SSE1_SUPPORTED OR SSE2_SUPPORTED OR SSE4_1_SUPPORTED OR AVX_SUPPORTED) 181 set(COMPILER_SUPPORT_SIMD 1 PARENT_SCOPE) 182 else() 183 message(STATUS "No SIMD support in compiler") 184 endif() 185endfunction() 186 187function(opus_detect_neon COMPILER_SUPPORT_NEON) 188 if(CMAKE_SYSTEM_PROCESSOR MATCHES "(armv7-a|aarch64)") 189 message(STATUS "Check NEON support by compiler") 190 check_include_file(arm_neon.h HAVE_ARM_NEON_H) 191 if(HAVE_ARM_NEON_H) 192 set(COMPILER_SUPPORT_NEON ${HAVE_ARM_NEON_H} PARENT_SCOPE) 193 endif() 194 endif() 195endfunction() 196 197function(opus_supports_cpu_detection RUNTIME_CPU_CAPABILITY_DETECTION) 198 if(MSVC) 199 check_include_file(intrin.h HAVE_INTRIN_H) 200 else() 201 check_include_file(cpuid.h HAVE_CPUID_H) 202 endif() 203 if(HAVE_INTRIN_H OR HAVE_CPUID_H) 204 set(RUNTIME_CPU_CAPABILITY_DETECTION 1 PARENT_SCOPE) 205 else() 206 set(RUNTIME_CPU_CAPABILITY_DETECTION 0 PARENT_SCOPE) 207 endif() 208endfunction() 209 210function(add_sources_group target group) 211 target_sources(${target} PRIVATE ${ARGN}) 212 source_group(${group} FILES ${ARGN}) 213endfunction() 214 215function(get_opus_sources SOURCE_GROUP MAKE_FILE SOURCES) 216 # read file, each item in list is one group 217 file(STRINGS ${MAKE_FILE} opus_sources) 218 219 # add wildcard for regex match 220 string(CONCAT SOURCE_GROUP ${SOURCE_GROUP} ".*$") 221 222 # find group 223 foreach(val IN LISTS opus_sources) 224 if(val MATCHES ${SOURCE_GROUP}) 225 list(LENGTH val list_length) 226 if(${list_length} EQUAL 1) 227 # for tests split by '=' and clean up the rest into a list 228 string(FIND ${val} "=" index) 229 math(EXPR index "${index} + 1") 230 string(SUBSTRING ${val} 231 ${index} 232 -1 233 sources) 234 string(REPLACE " " 235 ";" 236 sources 237 ${sources}) 238 else() 239 # discard the group 240 list(REMOVE_AT val 0) 241 set(sources ${val}) 242 endif() 243 break() 244 endif() 245 endforeach() 246 247 list(LENGTH sources list_length) 248 if(${list_length} LESS 1) 249 message( 250 FATAL_ERROR 251 "No files parsed succesfully from ${SOURCE_GROUP} in ${MAKE_FILE}") 252 endif() 253 254 # remove trailing whitespaces 255 set(list_var "") 256 foreach(source ${sources}) 257 string(STRIP "${source}" source) 258 list(APPEND list_var "${source}") 259 endforeach() 260 261 set(${SOURCES} ${list_var} PARENT_SCOPE) 262endfunction() 263