xref: /aosp_15_r20/external/libopus/cmake/OpusFunctions.cmake (revision a58d3d2adb790c104798cd88c8a3aff4fa8b82cc)
1if(__opus_functions)
2  return()
3endif()
4set(__opus_functions INCLUDED)
5
6function(get_library_version OPUS_LIBRARY_VERSION OPUS_LIBRARY_VERSION_MAJOR)
7  file(STRINGS configure.ac opus_lt_current_string
8       LIMIT_COUNT 1
9       REGEX "OPUS_LT_CURRENT=")
10  string(REGEX MATCH
11               "OPUS_LT_CURRENT=([0-9]*)"
12               _
13               ${opus_lt_current_string})
14  set(OPUS_LT_CURRENT ${CMAKE_MATCH_1})
15
16  file(STRINGS configure.ac opus_lt_revision_string
17       LIMIT_COUNT 1
18       REGEX "OPUS_LT_REVISION=")
19  string(REGEX MATCH
20               "OPUS_LT_REVISION=([0-9]*)"
21               _
22               ${opus_lt_revision_string})
23  set(OPUS_LT_REVISION ${CMAKE_MATCH_1})
24
25  file(STRINGS configure.ac opus_lt_age_string
26       LIMIT_COUNT 1
27       REGEX "OPUS_LT_AGE=")
28  string(REGEX MATCH
29               "OPUS_LT_AGE=([0-9]*)"
30               _
31               ${opus_lt_age_string})
32  set(OPUS_LT_AGE ${CMAKE_MATCH_1})
33
34  math(EXPR OPUS_LIBRARY_VERSION_MAJOR "${OPUS_LT_CURRENT} - ${OPUS_LT_AGE}")
35  set(OPUS_LIBRARY_VERSION_MINOR ${OPUS_LT_AGE})
36  set(OPUS_LIBRARY_VERSION_PATCH ${OPUS_LT_REVISION})
37  set(
38    OPUS_LIBRARY_VERSION
39    "${OPUS_LIBRARY_VERSION_MAJOR}.${OPUS_LIBRARY_VERSION_MINOR}.${OPUS_LIBRARY_VERSION_PATCH}"
40    PARENT_SCOPE)
41  set(OPUS_LIBRARY_VERSION_MAJOR ${OPUS_LIBRARY_VERSION_MAJOR} PARENT_SCOPE)
42endfunction()
43
44function(check_flag NAME FLAG)
45  include(CheckCCompilerFlag)
46  check_c_compiler_flag(${FLAG} ${NAME}_SUPPORTED)
47endfunction()
48
49include(CheckIncludeFile)
50
51# This function determines if the compiler has support for SSE, SSE2, SSE4.1, AVX,
52# AVX2 and FMA. Should the target systems potentially lack SSE support, the
53# OPUS_MAY_HAVE_SSE option is recommended for use. If, however, the target system is
54# assured to support SSE, the OPUS_PRESUME_SSE option can be employed, thus
55# eliminating the necessity for an SSE runtime check.
56function(opus_detect_sse COMPILER_SUPPORT_SIMD)
57  message(STATUS "Check SIMD support by compiler")
58  check_include_file(xmmintrin.h HAVE_XMMINTRIN_H) # SSE1
59  if(HAVE_XMMINTRIN_H)
60    if(MSVC)
61      # different arch options for 32 and 64 bit target for MSVC
62      if(CMAKE_SIZEOF_VOID_P EQUAL 4)
63        check_flag(SSE1 /arch:SSE)
64      else()
65        set(SSE1_SUPPORTED
66            1
67            PARENT_SCOPE)
68      endif()
69    else()
70      check_flag(SSE1 -msse)
71    endif()
72  else()
73    set(SSE1_SUPPORTED
74        0
75        PARENT_SCOPE)
76  endif()
77
78  check_include_file(emmintrin.h HAVE_EMMINTRIN_H) # SSE2
79  if(HAVE_EMMINTRIN_H)
80    if(MSVC)
81      if(CMAKE_SIZEOF_VOID_P EQUAL 4)
82        check_flag(SSE2 /arch:SSE2)
83      else()
84        set(SSE2_SUPPORTED
85            1
86            PARENT_SCOPE)
87      endif()
88    else()
89      check_flag(SSE2 -msse2)
90    endif()
91  else()
92    set(SSE2_SUPPORTED
93        0
94        PARENT_SCOPE)
95  endif()
96
97  check_include_file(smmintrin.h HAVE_SMMINTRIN_H) # SSE4.1
98  if(HAVE_SMMINTRIN_H)
99    if(MSVC)
100      if(CMAKE_SIZEOF_VOID_P EQUAL 4)
101        check_flag(SSE4_1 /arch:SSE2) # SSE2 and above
102      else()
103        set(SSE4_1_SUPPORTED
104            1
105            PARENT_SCOPE)
106      endif()
107    else()
108      check_flag(SSE4_1 -msse4.1)
109    endif()
110  else()
111    set(SSE4_1_SUPPORTED
112        0
113        PARENT_SCOPE)
114  endif()
115
116  check_include_file(immintrin.h HAVE_IMMINTRIN_H) # AVX2
117  if(HAVE_IMMINTRIN_H)
118    if(MSVC)
119      check_flag(AVX2 /arch:AVX2)
120    else()
121      check_flag(AVX2 -mavx2 -mfma -mavx)
122    endif()
123  else()
124    set(AVX2_SUPPORTED
125        0
126        PARENT_SCOPE)
127  endif()
128
129  if(SSE1_SUPPORTED OR SSE2_SUPPORTED OR SSE4_1_SUPPORTED OR AVX2_SUPPORTED)
130    set(COMPILER_SUPPORT_SIMD 1 PARENT_SCOPE)
131  else()
132    message(STATUS "No SIMD support in compiler")
133  endif()
134endfunction()
135
136function(opus_detect_neon COMPILER_SUPPORT_NEON)
137  if(CMAKE_SYSTEM_PROCESSOR MATCHES "(arm|aarch64)")
138    message(STATUS "Check NEON support by compiler")
139    check_include_file(arm_neon.h HAVE_ARM_NEON_H)
140    if(HAVE_ARM_NEON_H)
141      set(COMPILER_SUPPORT_NEON ${HAVE_ARM_NEON_H} PARENT_SCOPE)
142    endif()
143  endif()
144endfunction()
145
146function(opus_supports_cpu_detection RUNTIME_CPU_CAPABILITY_DETECTION)
147  set(RUNTIME_CPU_CAPABILITY_DETECTION 0 PARENT_SCOPE)
148  if(OPUS_CPU_X86 OR OPUS_CPU_X64)
149    if(MSVC)
150      check_include_file(intrin.h HAVE_INTRIN_H)
151      if(HAVE_INTRIN_H)
152        # if intrin.h is available we assume __cpuid is there
153        set(RUNTIME_CPU_CAPABILITY_DETECTION 1 PARENT_SCOPE)
154      endif()
155    else()
156      include(CFeatureCheck)
157      c_feature_check(CPU_INFO_BY_ASM)
158      set(CPU_INFO_BY_ASM_SUPPORTED ${CPU_INFO_BY_ASM_SUPPORTED} PARENT_SCOPE)
159      check_include_file(cpuid.h HAVE_CPUID_H)
160      if(HAVE_CPUID_H)
161        c_feature_check(CPU_INFO_BY_C)
162        set(CPU_INFO_BY_C_SUPPORTED ${CPU_INFO_BY_C_SUPPORTED} PARENT_SCOPE)
163      endif()
164      if(CPU_INFO_BY_ASM_SUPPORTED OR CPU_INFO_BY_C_SUPPORTED)
165        set(RUNTIME_CPU_CAPABILITY_DETECTION 1 PARENT_SCOPE)
166      endif()
167    endif()
168  elseif(OPUS_CPU_ARM)
169    # ARM cpu detection is implemented for Windows and anything
170    # using a Linux kernel (such as Android).
171    if (CMAKE_SYSTEM_NAME MATCHES "(Windows|Linux|Android)")
172      set(RUNTIME_CPU_CAPABILITY_DETECTION 1 PARENT_SCOPE)
173    endif ()
174  else()
175    set(RUNTIME_CPU_CAPABILITY_DETECTION 0 PARENT_SCOPE)
176  endif()
177endfunction()
178
179function(add_sources_group target group)
180  target_sources(${target} PRIVATE ${ARGN})
181  source_group(${group} FILES ${ARGN})
182endfunction()
183
184function(get_opus_sources SOURCE_GROUP MAKE_FILE SOURCES)
185  # read file, each item in list is one group
186  file(STRINGS ${MAKE_FILE} opus_sources)
187
188  # add wildcard for regex match
189  string(CONCAT SOURCE_GROUP ${SOURCE_GROUP} ".*$")
190
191  # find group
192  foreach(val IN LISTS opus_sources)
193    if(val MATCHES ${SOURCE_GROUP})
194      list(LENGTH val list_length)
195      if(${list_length} EQUAL 1)
196        # for tests split by '=' and clean up the rest into a list
197        string(FIND ${val} "=" index)
198        math(EXPR index "${index} + 1")
199        string(SUBSTRING ${val}
200                         ${index}
201                         -1
202                         sources)
203        string(REPLACE " "
204                       ";"
205                       sources
206                       ${sources})
207      else()
208        # discard the group
209        list(REMOVE_AT val 0)
210        set(sources ${val})
211      endif()
212      break()
213    endif()
214  endforeach()
215
216  list(LENGTH sources list_length)
217  if(${list_length} LESS 1)
218    message(
219      FATAL_ERROR
220        "No files parsed successfully from ${SOURCE_GROUP} in ${MAKE_FILE}")
221  endif()
222
223  # remove trailing whitespaces
224  set(list_var "")
225  foreach(source ${sources})
226    string(STRIP "${source}" source)
227    list(APPEND list_var "${source}")
228  endforeach()
229
230  set(${SOURCES} ${list_var} PARENT_SCOPE)
231endfunction()
232