From e7f0a9d3a61281e3e0e4883dfbc67ace1f96bd00 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sat, 10 Sep 2022 10:04:49 +0200 Subject: [PATCH] BUILD(cmake): Revamp speexdsp build This commit overhauls our custom CMakeLists file used for building the speexdsp library. Instead of relying on pre-configured files, we now perform explicit checks for whether specific features are available and if they are, we set the appropriate flags. --- 3rdparty/speexdsp-build/CMakeLists.txt | 126 +++++++++++++-- .../cmake/try_compile_snippet.cmake | 68 ++++++++ 3rdparty/speexdsp-build/config.h | 152 ------------------ .../speexdsp-build/speexdsp_config_types.h | 11 -- 3rdparty/speexdsp-build/win32/config.h | 26 --- 5 files changed, 178 insertions(+), 205 deletions(-) create mode 100644 3rdparty/speexdsp-build/cmake/try_compile_snippet.cmake delete mode 100644 3rdparty/speexdsp-build/config.h delete mode 100644 3rdparty/speexdsp-build/speexdsp_config_types.h delete mode 100644 3rdparty/speexdsp-build/win32/config.h diff --git a/3rdparty/speexdsp-build/CMakeLists.txt b/3rdparty/speexdsp-build/CMakeLists.txt index d93780bd613..470444fdf3c 100644 --- a/3rdparty/speexdsp-build/CMakeLists.txt +++ b/3rdparty/speexdsp-build/CMakeLists.txt @@ -1,3 +1,8 @@ +# Copyright 2020-2022 The Mumble Developers. All rights reserved. +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file at the root of the +# Mumble source tree or at . + set(SPEEXDSP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../speexdsp") set(SPEEXDSP_SRC_DIR "${SPEEXDSP_DIR}/libspeexdsp") @@ -7,11 +12,16 @@ if(NOT EXISTS "${SPEEXDSP_DIR}/COPYING") "${SPEEX_DIR} or ${SPEEXDSP_DIR} was not found. You need to do one of the following:\n" "Option 1: Checkout the submodule:\n" "git submodule update --init --recursive\n" - "Option 2: Use system Speex and SpeexDSP (v1.2 or later):\n" - "cmake .. -Dbundled-speexdsp=OFF" + "Option 2: Use system SpeexDSP (v1.2 or later):\n" + "cmake .. -Dbundled-speex=OFF" ) endif() +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +include(try_compile_snippet) +include(CheckIncludeFile) + if(WIN32) add_library(speexdsp SHARED) set_target_properties(speexdsp PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) @@ -23,23 +33,17 @@ else() add_library(speexdsp STATIC) endif() -# Speex doesn't use include guards in its headers, so unity builds will fail -set_target_properties(speexdsp PROPERTIES UNITY_BUILD FALSE) - -target_compile_definitions(speexdsp PRIVATE "HAVE_CONFIG_H") +CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H) -target_include_directories(speexdsp PRIVATE SYSTEM "${SPEEX_DIR}/libspeex" "${SPEEXDSP_DIR}/libspeexdsp") -target_include_directories(speexdsp PUBLIC SYSTEM "${SPEEX_DIR}/include" "${SPEEXDSP_DIR}/include") - -if(MSVC) - # We include "win32" only for MSVC because MinGW uses the "config.h" for Unix-like systems. - target_include_directories(speexdsp PRIVATE SYSTEM BEFORE "${CMAKE_CURRENT_SOURCE_DIR}/win32") -else() - target_include_directories(speexdsp PUBLIC SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}) +if(NOT HAVE_STDINT_H) + message(FATAL_ERROR "Assumed header stdint.h to be available") endif() +target_include_directories(speexdsp PRIVATE SYSTEM "${SPEEXDSP_DIR}/libspeexdsp") +target_include_directories(speexdsp PUBLIC SYSTEM "${SPEEXDSP_DIR}/include") + if(WIN32) - target_compile_definitions(speexdsp PRIVATE "_USE_MATH_DEFINES" "USE_SMALLFT") + target_compile_definitions(speexdsp PRIVATE "_USE_MATH_DEFINES") target_sources(speexdsp PRIVATE "mumble_speex_init.c") endif() @@ -56,4 +60,94 @@ set(SPEEXDSP_SOURCES target_sources(speexdsp PRIVATE ${SPEEXDSP_SOURCES} "speexdsp.def") -target_disable_warnings(speexdsp) +########################################################## +####### Check whether given features are available ####### +########################################################## + +try_compile_snippet( + RESULT_VAR VARIABLE_SIZE_ARRAYS_SUPPORTED + LANG C + STATEMENTS + "int size = 4;" + "int array[size];" +) + +message(STATUS "speexdsp: Variable sized arrays supported: ${VARIABLE_SIZE_ARRAYS_SUPPORTED}") +if(VARIABLE_SIZE_ARRAYS_SUPPORTED) + target_compile_definitions(speexdsp PRIVATE "VAR_ARRAYS") +endif() + +try_compile_snippet( + RESULT_VAR ALLOCA_AVAILABLE + LANG C + INCLUDES + "#ifdef HAVE_ALLOCA_H\n#include \n#endif" + INCLUDE_HEADERS + "stdlib.h" + STATEMENTS + "int size = 10;" + "int *array = alloca(size);" +) + +message(STATUS "speexdsp: alloca available: ${ALLOCA_AVAILABLE}") +if(ALLOCA_AVAILABLE AND NOT VARIABLE_SIZE_ARRAYS_SUPPORTED) + # If available, variable-sized arrays should be preferred + target_compile_definitions(speexdsp PRIVATE "USE_ALLOCA") +endif() + +try_compile_snippet( + RESULT_VAR SSE_AVAILABLE + LANG C + INCLUDE_HEADERS + "xmmintrin.h" + STATEMENTS + "float a = 0.8;" + "float b = 0.5;" + "_mm_add_ps(_mm_loadu_ps(&a), _mm_loadu_ps(&b));" +) + +message(STATUS "speexdsp: SSE available: ${SSE_AVAILABLE}") +if(SSE_AVAILABLE) + target_compile_definitions(speexdsp PRIVATE "USE_SSE") +endif() + +try_compile_snippet( + RESULT_VAR SSE2_AVAILABLE + LANG C + INCLUDE_HEADERS + "emmintrin.h" + STATEMENTS + "double a = 0.8;" + "double b = 0.5;" + "_mm_add_pd(_mm_loadu_pd(&a), _mm_loadu_pd(&b));" +) + +message(STATUS "speexdsp: SSE2 available: ${SSE2_AVAILABLE}") +if(SSE2_AVAILABLE) + target_compile_definitions(speexdsp PRIVATE "USE_SSE2") +endif() + +# We simply assume that any machine this runs on has a floating point unit (FPU) available and +# thus we'll always use the floating point implementation, for which smallft is the default +# FFT implementation. +target_compile_definitions(speexdsp PRIVATE "FLOATING_POINT") +target_compile_definitions(speexdsp PRIVATE "USE_SMALLFT") + +# Define empty EXPORT macro, as we don't care about messing with symbol visibility +target_compile_definitions(speexdsp PRIVATE EXPORT=) + + +# Generate a header with the necessary type definitions for fixed-width integers. We have +# checked before, that stdint.h is available, so we'll just default to using that. +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/include/speexdsp_config_types.h" +"#ifndef SPEEXDSP_CONFIGTYPES_H__\n\ +#define SPEEXDSP_CONFIGTYPES_H__ +#include \n\ +\n\ +typedef int16_t spx_int16_t;\n\ +typedef uint16_t spx_uint16_t;\n\ +typedef int32_t spx_int32_t;\n\ +typedef uint32_t spx_uint32_t;\n\ +#endif\n") + +target_include_directories(speexdsp PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/include") diff --git a/3rdparty/speexdsp-build/cmake/try_compile_snippet.cmake b/3rdparty/speexdsp-build/cmake/try_compile_snippet.cmake new file mode 100644 index 00000000000..de9c590f407 --- /dev/null +++ b/3rdparty/speexdsp-build/cmake/try_compile_snippet.cmake @@ -0,0 +1,68 @@ +# Copyright 2022 The Mumble Developers. All rights reserved. +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file at the root of the +# Mumble source tree or at . + +function(try_compile_snippet) + set(options) + set(oneValueArgs RESULT_VAR LANG) + set(multiValueArgs INCLUDES INCLUDE_HEADERS STATEMENTS COMPILE_DEFINITIONS LINK_OPTIONS LINK_LIBRARIES OUTPUT_VARIABLE CMAKE_FLAGS) + + cmake_parse_arguments(COMPILE_SNIPPET "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(COMPILE_SNIPPET_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "try_compile_snippet: Unrecognized arguments: ${COMPILE_SNIPPET_UNPARSED_ARGUMENTS}") + endif() + + set(REQUIRED_ARGS ${oneValueArgs} STATEMENTS) + foreach(CURRENT IN LISTS REQUIRED_ARGS) + if(NOT COMPILE_SNIPPET_${CURRENT}) + message(FATAL_ERROR "try_compile_snippet: Missing argument ${CURRENT}") + endif() + endforeach() + + list(JOIN COMPILE_SNIPPET_INCLUDES "\n" INCLUDE_STATEMENTS) + string(APPEND INCLUDE_STATEMENTS "\n") + foreach(CURRENT IN LISTS COMPILE_SNIPPET_INCLUDE_HEADERS) + string(APPEND INCLUDE_STATEMENTS "\n#include <${CURRENT}>") + endforeach() + + list(JOIN COMPILE_SNIPPET_STATEMENTS ";\n" JOINED_STATEMENTS) + set(SOURCE_CODE "\ + ${INCLUDE_STATEMENTS}\n\ + \n\ + int main() {\n\ + ${JOINED_STATEMENTS};\n\ + \n\ + return 0;\n\ + }" + ) + + string(TOLOWER "${COMPILE_SNIPPET_LANG}" COMPILE_SNIPPET_LANG) + + if("${COMPILE_SNIPPET_LANG}" MATCHES "^(cxx|cpp|c\\+\\+)$") + set(FILE_EXTENSION "cpp") + elseif("${COMPILE_SNIPPET_LANG}" MATCHES "^(c)$") + set(FILE_EXTENSION "c") + else() + message(FATAL_ERROR "try_compile_snippet: Unsupported language ${COMPILE_SNIPPET_LANG}") + endif() + + set(FILENAME "${CMAKE_CURRENT_BINARY_DIR}/try_compile_snippet.${FILE_EXTENSION}") + + file(WRITE "${FILENAME}" "${SOURCE_CODE}") + + try_compile(COMPILE_SUCCESS "${CMAKE_CURRENT_BINARY_DIR}" + SOURCES "${FILENAME}" + CMAKE_FLAGS ${COMPILE_SNIPPET_CMAKE_FLAGS} + COMPILE_DEFINITIONS ${COMPILE_SNIPPET_COMPILE_DEFINITIONS} + LINK_OPTIONS ${COMPILE_SNIPPET_LINK_OPTIONS} + LINK_LIBRARIES ${COMPILE_SNIPPET_LINK_LIBRARIES} + OUTPUT_VARIABLE BUILD_OUTPUT + ) + + set(${COMPILE_SNIPPET_RESULT_VAR} ${COMPILE_SUCCESS} PARENT_SCOPE) + if(COMPILE_SNIPPET_OUTPUT_VARIABLE) + set(${COMPILE_SNIPPET_OUTPUT_VARIABLE} ${BUILD_OUTPUT} PARENT_SCOPE) + endif() +endfunction() diff --git a/3rdparty/speexdsp-build/config.h b/3rdparty/speexdsp-build/config.h deleted file mode 100644 index 7b3f42b682f..00000000000 --- a/3rdparty/speexdsp-build/config.h +++ /dev/null @@ -1,152 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Make use of ARM4 assembly optimizations */ -/* #undef ARM4_ASM */ - -/* Make use of ARM5E assembly optimizations */ -/* #undef ARM5E_ASM */ - -/* Make use of Blackfin assembly optimizations */ -/* #undef BFIN_ASM */ - -/* Enable valgrind extra checks */ -/* #undef ENABLE_VALGRIND */ - -/* Debug fixed-point implementation */ -/* #undef FIXED_DEBUG */ - -/* Compile as fixed-point */ -/* #undef FIXED_POINT */ - -/* Compile as floating-point */ -#define FLOATING_POINT - -/* Define to 1 if you have the header file. */ -#define HAVE_ALLOCA_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the `getopt_long' function. */ -#define HAVE_GETOPT_LONG 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `m' library (-lm). */ -#define HAVE_LIBM 1 - -/* Define to 1 if you have the `winmm' library (-lwinmm). */ -/* #undef HAVE_LIBWINMM */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIOIO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOUNDCARD_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* Version extra */ -#define SPEEX_EXTRA_VERSION "-git" - -/* Version major */ -#define SPEEX_MAJOR_VERSION 1 - -/* Version micro */ -#define SPEEX_MICRO_VERSION 15 - -/* Version minor */ -#define SPEEX_MINOR_VERSION 1 - -/* Complete version string */ -#define SPEEX_VERSION "1.2beta3" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Enable support for TI C55X DSP */ -/* #undef TI_C55X */ - -/* Make use of alloca */ -/* #undef USE_ALLOCA */ - -/* Use C99 variable-size arrays */ -#define VAR_ARRAYS - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* Enable SSE support */ -#ifdef __SSE__ -#define _USE_SSE -#endif - -#ifdef __SSE2__ -#define _USE_SSE2 -#endif - -#define EXPORT - -#define USE_SMALLFT - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to equivalent of C99 restrict keyword, or to nothing if this is not - supported. Do not define if restrict is supported directly. */ -#define restrict __restrict diff --git a/3rdparty/speexdsp-build/speexdsp_config_types.h b/3rdparty/speexdsp-build/speexdsp_config_types.h deleted file mode 100644 index bd548546b0a..00000000000 --- a/3rdparty/speexdsp-build/speexdsp_config_types.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __SPEEX_TYPES_H__ -#define __SPEEX_TYPES_H__ - -/* these are filled in by configure */ -typedef short spx_int16_t; -typedef unsigned short spx_uint16_t; -typedef int spx_int32_t; -typedef unsigned int spx_uint32_t; - -#endif - diff --git a/3rdparty/speexdsp-build/win32/config.h b/3rdparty/speexdsp-build/win32/config.h deleted file mode 100644 index 47a4ffd1386..00000000000 --- a/3rdparty/speexdsp-build/win32/config.h +++ /dev/null @@ -1,26 +0,0 @@ -// Microsoft version of 'inline' -#define inline __inline - -// In Visual Studio, _M_IX86_FP=1 means /arch:SSE was used, likewise -// _M_IX86_FP=2 means /arch:SSE2 was used. -// Also, enable both _USE_SSE and _USE_SSE2 if we're compiling for x86-64 -#if _M_IX86_FP >= 1 || defined(_M_X64) -#define _USE_SSE -#endif - -#if _M_IX86_FP >= 2 || defined(_M_X64) -#define _USE_SSE2 -#endif - -// Visual Studio support alloca(), but it always align variables to 16-bit -// boundary, while SSE need 128-bit alignment. So we disable alloca() when -// SSE is enabled. -#ifndef _USE_SSE -# define USE_ALLOCA -#endif - -/* Default to floating point */ -#define FLOATING_POINT - -/* We don't support visibility on Win32 */ -#define EXPORT