CMake changes
[opus.git] / CMakeLists.txt
1 cmake_minimum_required(VERSION 3.1)
2
3 include(opus_functions.cmake)
4
5 get_library_version(OPUS_LIBRARY_VERSION OPUS_LIBRARY_VERSION_MAJOR)
6 message(STATUS "Opus library version: ${OPUS_LIBRARY_VERSION}")
7
8 get_package_version(PACKAGE_VERSION)
9 message(STATUS "Opus package version: ${PACKAGE_VERSION}")
10
11 string(REGEX
12        REPLACE "^([0-9]+.[0-9]+\\.?([0-9]+)?).*"
13                "\\1"
14                PROJECT_VERSION
15                ${PACKAGE_VERSION})
16 message(STATUS "Opus project version: ${PROJECT_VERSION}")
17
18 project(Opus LANGUAGES C VERSION ${PROJECT_VERSION})
19 include(opus_buildtype.cmake)
20
21 option(OPUS_STACK_PROTECTOR "Use stack protection" ON)
22 option(OPUS_USE_ALLOCA "Use alloca for stack arrays (on non-C99 compilers)" OFF)
23 option(OPUS_CUSTOM_MODES "Enable non-Opus modes, e.g. 44.1 kHz & 2^n frames"
24        OFF)
25 option(OPUS_BUILD_PROGRAMS "Build programs" OFF)
26 option(OPUS_FIXED_POINT
27        "Compile as fixed-point (for machines without a fast enough FPU)" OFF)
28 option(OPUS_ENABLE_FLOAT_API
29        "Compile with the floating point API (for machines with float library"
30        ON)
31 option(OPUS_INSTALL_PKG_CONFIG_MODULE "Install PkgConfig module" ON)
32 option(OPUS_INSTALL_CMAKE_CONFIG_MODULE "Install CMake package config module"
33        ON)
34
35 include(opus_config.cmake)
36 include(opus_sources.cmake)
37 include(GNUInstallDirs)
38 include(CMakeDependentOption)
39 include(FeatureSummary)
40
41 if(OPUS_STACK_PROTECTOR)
42   if(NOT MSVC) # GC on by default on MSVC
43     check_and_set_flag(STACK_PROTECTION_STRONG -fstack-protector-strong)
44   endif()
45 else()
46   if(MSVC)
47     check_and_set_flag(BUFFER_SECURITY_CHECK /GS-)
48   endif()
49 endif()
50
51 if(OPUS_CPU_X86 OR OPUS_CPU_X64)
52   cmake_dependent_option(OPUS_X86_MAY_HAVE_SSE
53                          "Does runtime check for SSE1 support"
54                          ON
55                          "SSE1_SUPPORTED"
56                          OFF)
57   cmake_dependent_option(OPUS_X86_MAY_HAVE_SSE2
58                          "Does runtime check for SSE2 support"
59                          ON
60                          "SSE2_SUPPORTED"
61                          OFF)
62   cmake_dependent_option(OPUS_X86_MAY_HAVE_SSE4_1
63                          "Does runtime check for SSE4.1 support"
64                          ON
65                          "SSE4_1_SUPPORTED"
66                          OFF)
67   cmake_dependent_option(OPUS_X86_MAY_HAVE_AVX
68                          "Does runtime check for AVX support"
69                          ON
70                          "AVX_SUPPORTED"
71                          OFF)
72
73   if(OPUS_CPU_X64) # Assume 64 bit has SSE2 support
74     cmake_dependent_option(OPUS_X86_PRESUME_SSE
75                            "Assume target CPU has SSE1 support"
76                            ON
77                            "OPUS_X86_MAY_HAVE_SSE"
78                            OFF)
79     cmake_dependent_option(OPUS_X86_PRESUME_SSE2
80                            "Assume target CPU has SSE2 support"
81                            ON
82                            "OPUS_X86_MAY_HAVE_SSE2"
83                            OFF)
84   else()
85     cmake_dependent_option(OPUS_X86_PRESUME_SSE
86                            "Assume target CPU has SSE1 support"
87                            OFF
88                            "OPUS_X86_MAY_HAVE_SSE"
89                            OFF)
90     cmake_dependent_option(OPUS_X86_PRESUME_SSE2
91                            "Assume target CPU has SSE2 support"
92                            OFF
93                            "OPUS_X86_MAY_HAVE_SSE2"
94                            OFF)
95   endif()
96   cmake_dependent_option(OPUS_X86_PRESUME_SSE4_1
97                          "Assume target CPU has SSE4.1 support"
98                          OFF
99                          "OPUS_X86_MAY_HAVE_SSE4_1"
100                          OFF)
101   cmake_dependent_option(OPUS_X86_PRESUME_AVX
102                          "Assume target CPU has AVX support"
103                          OFF
104                          "OPUS_X86_MAY_HAVE_AVX"
105                          OFF)
106 endif()
107
108 set_package_properties(Git
109                        PROPERTIES
110                        TYPE
111                        REQUIRED
112                        DESCRIPTION
113                        "fast, scalable, distributed revision control system"
114                        URL
115                        "https://git-scm.com/"
116                        PURPOSE
117                        "required to set up package version")
118
119 add_feature_info(STACK_PROTECTOR OPUS_STACK_PROTECTOR "Use stack protection")
120 add_feature_info(USE_ALLOCA OPUS_USE_ALLOCA
121                  "Use alloca for stack arrays (on non-C99 compilers)")
122 add_feature_info(CUSTOM_MODES OPUS_CUSTOM_MODES
123                  "Enable non-Opus modes, e.g. 44.1 kHz & 2^n frames")
124 add_feature_info(BUILD_PROGRAMS OPUS_BUILD_PROGRAMS "Build programs")
125 add_feature_info(
126   FIXED_POINT OPUS_FIXED_POINT
127   "compile as fixed-point (for machines without a fast enough FPU)")
128 add_feature_info(
129   FLOAT_API OPUS_ENABLE_FLOAT_API
130   "compile with the floating point API (for machines with float library)")
131
132 add_feature_info(INSTALL_PKG_CONFIG_MODULE OPUS_INSTALL_PKG_CONFIG_MODULE
133                  "install PkgConfig module")
134 add_feature_info(INSTALL_CMAKE_CONFIG_MODULE OPUS_INSTALL_CMAKE_CONFIG_MODULE
135                  "install CMake package config module")
136
137 if(OPUS_CPU_X86 OR OPUS_CPU_X64)
138   add_feature_info(X86_MAY_HAVE_SSE OPUS_X86_MAY_HAVE_SSE
139                    "does runtime check for SSE1 support")
140   add_feature_info(X86_MAY_HAVE_SSE2 OPUS_X86_MAY_HAVE_SSE2
141                    "does runtime check for SSE2 support")
142   add_feature_info(X86_MAY_HAVE_SSE4_1 OPUS_X86_MAY_HAVE_SSE4_1
143                    "does runtime check for SSE4_1 support")
144   add_feature_info(X86_MAY_HAVE_AVX OPUS_X86_MAY_HAVE_AVX
145                    "does runtime check for AVX support")
146   add_feature_info(X86_PRESUME_SSE OPUS_X86_PRESUME_SSE
147                    "assume target CPU has SSE1 support")
148   add_feature_info(X86_PRESUME_SSE2 OPUS_X86_PRESUME_SSE2
149                    "assume target CPU has SSE2 support")
150   add_feature_info(X86_PRESUME_SSE4_1 OPUS_X86_PRESUME_SSE4_1
151                    "assume target CPU has SSE4_1 support")
152   add_feature_info(X86_PRESUME_AVX OPUS_X86_PRESUME_AVX
153                    "assume target CPU has AVX support")
154 endif()
155
156 feature_summary(WHAT ALL)
157
158 add_library(opus ${opus_sources} ${opus_sources_float})
159
160 set(Opus_PUBLIC_HEADER
161     ${CMAKE_CURRENT_SOURCE_DIR}/include/opus.h
162     ${CMAKE_CURRENT_SOURCE_DIR}/include/opus_custom.h
163     ${CMAKE_CURRENT_SOURCE_DIR}/include/opus_defines.h
164     ${CMAKE_CURRENT_SOURCE_DIR}/include/opus_multistream.h
165     ${CMAKE_CURRENT_SOURCE_DIR}/include/opus_projection.h
166     ${CMAKE_CURRENT_SOURCE_DIR}/include/opus_types.h)
167
168 set_target_properties(opus
169                       PROPERTIES SOVERSION
170                                  ${OPUS_LIBRARY_VERSION_MAJOR}
171                                  VERSION
172                                  ${OPUS_LIBRARY_VERSION}
173                                  PUBLIC_HEADER
174                                  "${Opus_PUBLIC_HEADER}")
175
176 target_include_directories(
177   opus
178   PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
179          $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
180   PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
181           ${CMAKE_CURRENT_SOURCE_DIR}
182           celt
183           silk)
184
185 target_link_libraries(opus PRIVATE ${OPUS_REQUIRED_LIBRARIES})
186 target_compile_definitions(opus PRIVATE OPUS_BUILD ENABLE_HARDENING)
187
188 if(NOT MSVC)
189   target_compile_definitions(opus PRIVATE FORTIFY_SOURCE=2)
190 endif()
191
192 # It is strongly recommended to uncomment one of these VAR_ARRAYS: Use C99
193 # variable-length arrays for stack allocation USE_ALLOCA: Use alloca() for stack
194 # allocation If none is defined, then the fallback is a non-threadsafe global
195 # array
196 if(OPUS_USE_ALLOCA OR MSVC)
197   target_compile_definitions(opus PRIVATE USE_ALLOCA)
198 else()
199   target_compile_definitions(opus PRIVATE VAR_ARRAYS)
200 endif()
201
202 if(OPUS_CUSTOM_MODES)
203   target_compile_definitions(opus PRIVATE CUSTOM_MODES)
204 endif()
205
206 if(BUILD_SHARED_LIBS)
207   if(WIN32)
208     target_compile_definitions(opus PRIVATE DLL_EXPORT)
209   else()
210     include(CheckCCompilerFlag)
211     check_c_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
212     if(COMPILER_HAS_HIDDEN_VISIBILITY)
213       set_target_properties(opus PROPERTIES C_VISIBILITY_PRESET hidden)
214     endif()
215   endif()
216 endif()
217
218 add_sources_group(opus silk ${silk_sources})
219 add_sources_group(opus celt ${celt_sources})
220
221 if(OPUS_FIXED_POINT)
222   add_sources_group(opus silk ${silk_sources_fixed})
223   target_include_directories(opus PRIVATE silk/fixed)
224   target_compile_definitions(opus PRIVATE FIXED_POINT=1)
225 else()
226   add_sources_group(opus silk ${silk_sources_float})
227   target_include_directories(opus PRIVATE silk/float)
228 endif()
229
230 if(NOT OPUS_ENABLE_FLOAT_API)
231   target_compile_definitions(opus PRIVATE DISABLE_FLOAT_API)
232 endif()
233
234 if(OPUS_X86_MAY_HAVE_SSE
235    OR OPUS_X86_MAY_HAVE_SSE2
236    OR OPUS_X86_MAY_HAVE_SSE4_1
237    OR OPUS_X86_MAY_HAVE_AVX)
238   target_compile_definitions(opus PRIVATE OPUS_HAVE_RTCD)
239 endif()
240
241 if(OPUS_X86_MAY_HAVE_SSE)
242   add_sources_group(opus celt ${celt_sources_sse})
243   target_compile_definitions(opus PRIVATE OPUS_X86_MAY_HAVE_SSE)
244 endif()
245 if(OPUS_X86_PRESUME_SSE)
246   target_compile_definitions(opus PRIVATE OPUS_X86_PRESUME_SSE)
247 endif()
248
249 if(OPUS_X86_MAY_HAVE_SSE2)
250   add_sources_group(opus celt ${celt_sources_sse2})
251   target_compile_definitions(opus PRIVATE OPUS_X86_MAY_HAVE_SSE2)
252 endif()
253 if(OPUS_X86_PRESUME_SSE2)
254   target_compile_definitions(opus PRIVATE OPUS_X86_PRESUME_SSE2)
255 endif()
256
257 if(OPUS_X86_MAY_HAVE_SSE)
258   add_sources_group(opus celt ${celt_sources_sse4_1})
259   add_sources_group(opus silk ${silk_sources_sse4_1})
260   if(OPUS_FIXED_POINT)
261     add_sources_group(opus silk ${silk_sources_fixed_sse4_1})
262   endif()
263   target_compile_definitions(opus PRIVATE OPUS_X86_MAY_HAVE_SSE4_1)
264 endif()
265 if(OPUS_X86_PRESUME_SSE4_1)
266   target_compile_definitions(opus PRIVATE OPUS_X86_PRESUME_SSE4_1)
267 endif()
268
269 if(CMAKE_SYSTEM_PROCESSOR MATCHES "(armv7-a)")
270   add_sources_group(opus celt ${celt_sources_arm})
271 endif()
272
273 if(COMPILER_SUPPORT_NEON AND OPUS_USE_NEON)
274
275   if(OPUS_MAY_HAVE_NEON)
276     if(RUNTIME_CPU_CAPABILITY_DETECTION)
277       message(STATUS "OPUS_MAY_HAVE_NEON enabling runtime detection")
278       target_compile_definitions(opus PRIVATE OPUS_HAVE_RTCD)
279     else()
280       message(ERROR "Runtime cpu capability detection needed for MAY_HAVE_NEON")
281     endif()
282     # Do runtime check for NEON
283     target_compile_definitions(opus
284                                PRIVATE
285                                OPUS_ARM_MAY_HAVE_NEON
286                                OPUS_ARM_MAY_HAVE_NEON_INTR)
287   endif()
288
289   add_sources_group(opus celt ${celt_sources_arm_neon_intr})
290   add_sources_group(opus silk ${silk_sources_arm_neon_intr})
291
292   # silk arm neon depends on main_Fix.h
293   target_include_directories(opus PRIVATE silk/fixed)
294
295   if(OPUS_FIXED_POINT)
296     add_sources_group(opus silk ${silk_sources_fixed_arm_neon_intr})
297   endif()
298
299   if(OPUS_PRESUME_NEON)
300     target_compile_definitions(opus
301                                PRIVATE
302                                OPUS_ARM_PRESUME_NEON
303                                OPUS_ARM_PRESUME_NEON_INTR)
304   endif()
305 endif()
306
307 install(TARGETS opus
308         EXPORT OpusTargets
309         ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
310         LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
311         RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
312         PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/opus)
313
314 if(OPUS_INSTALL_PKG_CONFIG_MODULE)
315   set(prefix ${CMAKE_INSTALL_PREFIX})
316   set(exec_prefix ${CMAKE_INSTALL_PREFIX})
317   set(libdir ${CMAKE_INSTALL_FULL_LIBDIR})
318   set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR})
319   set(VERSION ${OPUS_LIBRARY_VERSION})
320   set(VERSION ${OPUS_LIBRARY_VERSION})
321   if(HAVE_LIBM)
322     set(LIBM "-lm")
323   endif()
324   configure_file(opus.pc.in opus.pc)
325   install(FILES ${CMAKE_CURRENT_BINARY_DIR}/opus.pc
326           DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
327 endif()
328
329 if(OPUS_INSTALL_CMAKE_CONFIG_MODULE)
330   set(CMAKE_INSTALL_PACKAGEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
331   install(EXPORT OpusTargets
332           NAMESPACE Opus::
333           DESTINATION ${CMAKE_INSTALL_PACKAGEDIR})
334
335   include(CMakePackageConfigHelpers)
336
337   set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
338   configure_package_config_file(OpusConfig.cmake.in
339                                 OpusConfig.cmake
340                                 INSTALL_DESTINATION
341                                 ${CMAKE_INSTALL_PACKAGEDIR}
342                                 PATH_VARS
343                                 INCLUDE_INSTALL_DIR
344                                 INSTALL_PREFIX
345                                 ${CMAKE_INSTALL_PREFIX})
346   write_basic_package_version_file(OpusConfigVersion.cmake
347                                    VERSION ${PROJECT_VERSION}
348                                    COMPATIBILITY SameMajorVersion)
349   install(FILES ${CMAKE_CURRENT_BINARY_DIR}/OpusConfig.cmake
350                 ${CMAKE_CURRENT_BINARY_DIR}/OpusConfigVersion.cmake
351           DESTINATION ${CMAKE_INSTALL_PACKAGEDIR})
352 endif()
353
354 if(OPUS_BUILD_PROGRAMS)
355   # demo
356   if(OPUS_CUSTOM_MODES)
357     add_executable(opus_custom_demo ${opus_custom_demo_sources})
358     target_include_directories(opus_custom_demo
359                                PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
360     target_link_libraries(opus_custom_demo PRIVATE opus)
361   endif()
362
363   add_executable(opus_demo ${opus_demo_sources})
364   target_include_directories(opus_demo PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
365   target_include_directories(opus_demo PRIVATE silk) # debug.h
366   target_include_directories(opus_demo PRIVATE celt) # arch.h
367   target_link_libraries(opus_demo PRIVATE opus)
368
369   # compare
370   add_executable(opus_compare ${opus_compare_sources})
371   target_include_directories(opus_compare PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
372   target_link_libraries(opus_compare PRIVATE opus)
373 endif()
374
375 if(BUILD_TESTING)
376   enable_testing()
377
378   # tests
379   add_executable(test_opus_decode ${test_opus_decode_sources})
380   target_include_directories(test_opus_decode
381                              PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
382   target_link_libraries(test_opus_decode PRIVATE opus)
383   if(OPUS_FIXED_POINT)
384     target_compile_definitions(test_opus_decode PRIVATE DISABLE_FLOAT_API)
385   endif()
386   add_test(test_opus_decode test_opus_decode)
387
388   add_executable(test_opus_padding ${test_opus_padding_sources})
389   target_include_directories(test_opus_padding
390                              PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
391   target_link_libraries(test_opus_padding PRIVATE opus)
392   add_test(test_opus_padding test_opus_padding)
393
394   if(NOT BUILD_SHARED_LIBS)
395     # disable tests that depends on private API when building shared lib
396     add_executable(test_opus_api ${test_opus_api_sources})
397     target_include_directories(test_opus_api
398                                PRIVATE ${CMAKE_CURRENT_BINARY_DIR} celt)
399     target_link_libraries(test_opus_api PRIVATE opus)
400     if(OPUS_FIXED_POINT)
401       target_compile_definitions(test_opus_api PRIVATE DISABLE_FLOAT_API)
402     endif()
403     add_test(test_opus_api test_opus_api)
404
405     add_executable(test_opus_encode ${test_opus_encode_sources})
406     target_include_directories(test_opus_encode
407                                PRIVATE ${CMAKE_CURRENT_BINARY_DIR} celt)
408     target_link_libraries(test_opus_encode PRIVATE opus)
409     add_test(test_opus_encode test_opus_encode)
410   endif()
411 endif()