ref: a0e14e7117fbb05e0ebcfd891188746096531d02
parent: 7628d844b4a0435c676fbe9ef03b3c2f8bf3eb5f
author: Marcus Asteborg <maastebo@microsoft.com>
date: Mon Apr 13 11:51:48 EDT 2020
cmake - Add variable length detection and alloca detection Signed-off-by: Jean-Marc Valin <jmvalin@jmvalin.ca>
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.1)
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(opus_functions.cmake)
@@ -20,7 +21,6 @@
option(OPUS_BUILD_SHARED_LIBRARY "Build shared library" OFF)
option(OPUS_STACK_PROTECTOR "Use stack protection" ON)
-option(OPUS_USE_ALLOCA "Use alloca for stack arrays (on non-C99 compilers)" OFF)
option(OPUS_CUSTOM_MODES "Enable non-Opus modes, e.g. 44.1 kHz & 2^n frames"
OFF)
option(OPUS_BUILD_PROGRAMS "Build programs" OFF)
@@ -40,6 +40,22 @@
include(CMakeDependentOption)
include(FeatureSummary)
+cmake_dependent_option(OPUS_VAR_ARRAYS
+ "Use variable length arrays for stack arrays"
+ ON
+ "VLA_SUPPORTED; NOT OPUS_USE_ALLOCA; NOT OPUS_NONTHREADSAFE_PSEUDOSTACK"
+ OFF)
+cmake_dependent_option(OPUS_USE_ALLOCA
+ "Use alloca for stack arrays (on non-C99 compilers)"
+ ON
+ "USE_ALLOCA_SUPPORTED; NOT OPUS_VAR_ARRAYS; NOT OPUS_NONTHREADSAFE_PSEUDOSTACK"
+ OFF)
+cmake_dependent_option(OPUS_NONTHREADSAFE_PSEUDOSTACK
+ "Use a non threadsafe pseudostack when neither variable length arrays or alloca is supported"
+ ON
+ "NOT OPUS_VAR_ARRAYS; NOT OPUS_USE_ALLOCA"
+ OFF)
+
if(OPUS_BUILD_SHARED_LIBRARY OR BUILD_SHARED_LIBS)
# Global flag to cause add_library() to create shared libraries if on.
set(BUILD_SHARED_LIBS ON)
@@ -68,7 +84,6 @@
endif()
endif()
-
if(OPUS_CPU_X86 OR OPUS_CPU_X64)
cmake_dependent_option(OPUS_X86_MAY_HAVE_SSE
"Does runtime check for SSE1 support"
@@ -140,8 +155,12 @@
add_feature_info(OPUS_BUILD_SHARED_LIBRARY OPUS_BUILD_SHARED_LIBRARY "Build shared library")
add_feature_info(OPUS_STACK_PROTECTOR STACK_PROTECTOR_SUPPORTED "Use stack protection")
+add_feature_info(OPUS_VAR_ARRAYS OPUS_VAR_ARRAYS
+ "Use variable length arrays for stack arrays")
add_feature_info(OPUS_USE_ALLOCA OPUS_USE_ALLOCA
"Use alloca for stack arrays (on non-C99 compilers)")
+add_feature_info(OPUS_NONTHREADSAFE_PSEUDOSTACK OPUS_NONTHREADSAFE_PSEUDOSTACK
+ "Use a non threadsafe pseudostack when neither variable length arrays or alloca is supported")
add_feature_info(OPUS_CUSTOM_MODES OPUS_CUSTOM_MODES
"Enable non-Opus modes, e.g. 44.1 kHz & 2^n frames")
add_feature_info(OPUS_BUILD_TESTING OPUS_BUILD_TESTING "Build test programs")
@@ -215,14 +234,14 @@
target_compile_definitions(opus PRIVATE _FORTIFY_SOURCE=2)
endif()
-# It is strongly recommended to uncomment one of these VAR_ARRAYS: Use C99
-# variable-length arrays for stack allocation USE_ALLOCA: Use alloca() for stack
-# allocation If none is defined, then the fallback is a non-threadsafe global
-# array
-if(OPUS_USE_ALLOCA OR MSVC)
+if(OPUS_VAR_ARRAYS)
+ target_compile_definitions(opus PRIVATE VAR_ARRAYS)
+elseif(OPUS_USE_ALLOCA)
target_compile_definitions(opus PRIVATE USE_ALLOCA)
+elseif(OPUS_NONTHREADSAFE_PSEUDOSTACK)
+ target_compile_definitions(opus PRIVATE NONTHREADSAFE_PSEUDOSTACK)
else()
- target_compile_definitions(opus PRIVATE VAR_ARRAYS)
+ message(ERROR Neet to set a define for stack allocation)
endif()
if(OPUS_CUSTOM_MODES)
--- a/Makefile.am
+++ b/Makefile.am
@@ -217,6 +217,8 @@
opus_functions.cmake \
opus_sources.cmake \
OpusConfig.cmake.in \
+ cmake/CFeatureCheck.cmake \
+ cmake/vla.c \
tests/run_vectors.sh \
celt/arm/arm2gnu.pl \
celt/arm/celt_pitch_xcorr_arm.s \
--- /dev/null
+++ b/cmake/CFeatureCheck.cmake
@@ -1,0 +1,39 @@
+# - Compile and run code to check for C features
+#
+# This functions compiles a source file under the `cmake` folder
+# and adds the corresponding `HAVE_[FILENAME]` flag to the CMake
+# environment
+#
+# c_feature_check(<FLAG> [<VARIANT>])
+#
+# - Example
+#
+# include(CFeatureCheck)
+# c_feature_check(VLA)
+
+if(__c_feature_check)
+ return()
+endif()
+set(__c_feature_check INCLUDED)
+
+function(c_feature_check FILE)
+ string(TOLOWER ${FILE} FILE)
+ string(TOUPPER ${FILE} VAR)
+ string(TOUPPER "${VAR}_SUPPORTED" FEATURE)
+ if (DEFINED ${VAR}_SUPPORTED)
+ set(${VAR}_SUPPORTED 1 PARENT_SCOPE)
+ return()
+ endif()
+
+ if (NOT DEFINED COMPILE_${FEATURE})
+ message(STATUS "Performing Test ${FEATURE}")
+ try_compile(COMPILE_${FEATURE} ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/cmake/${FILE}.c)
+ endif()
+
+ if(COMPILE_${FEATURE})
+ message(STATUS "Performing Test ${FEATURE} -- success")
+ set(${VAR}_SUPPORTED 1 PARENT_SCOPE)
+ else()
+ message(STATUS "Performing Test ${FEATURE} -- failed to compile")
+ endif()
+endfunction()
\ No newline at end of file
--- /dev/null
+++ b/cmake/vla.c
@@ -1,0 +1,7 @@
+int main() {
+ static int x;
+ char a[++x];
+ a[sizeof a - 1] = 0;
+ int N;
+ return a[0];
+}
\ No newline at end of file
--- a/opus_config.cmake
+++ b/opus_config.cmake
@@ -16,6 +16,20 @@
list(APPEND OPUS_REQUIRED_LIBRARIES m)
endif()
+include(CFeatureCheck)
+c_feature_check(VLA)
+
+include(CheckIncludeFile)
+check_include_file(alloca.h HAVE_ALLOCA_H)
+
+include(CheckSymbolExists)
+if(HAVE_ALLOCA_H)
+ add_definitions(-DHAVE_ALLOCA_H)
+ check_symbol_exists(alloca "alloca.h" USE_ALLOCA_SUPPORTED)
+else()
+ check_symbol_exists(alloca "stdlib.h;malloc.h" USE_ALLOCA_SUPPORTED)
+endif()
+
include(CheckFunctionExists)
check_function_exists(lrintf HAVE_LRINTF)
check_function_exists(lrint HAVE_LRINT)