Skip to content

Commit

Permalink
BUILD(cmake): Revamp speexdsp build
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Krzmbrzl committed Sep 10, 2022
1 parent 4d05018 commit e7f0a9d
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 205 deletions.
126 changes: 110 additions & 16 deletions 3rdparty/speexdsp-build/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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 <https://www.mumble.info/LICENSE>.

set(SPEEXDSP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../speexdsp")

set(SPEEXDSP_SRC_DIR "${SPEEXDSP_DIR}/libspeexdsp")
Expand All @@ -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})
Expand All @@ -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()

Expand All @@ -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 <alloca.h>\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 <stdint.h>\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")
68 changes: 68 additions & 0 deletions 3rdparty/speexdsp-build/cmake/try_compile_snippet.cmake
Original file line number Diff line number Diff line change
@@ -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 <https://www.mumble.info/LICENSE>.

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()
152 changes: 0 additions & 152 deletions 3rdparty/speexdsp-build/config.h

This file was deleted.

11 changes: 0 additions & 11 deletions 3rdparty/speexdsp-build/speexdsp_config_types.h

This file was deleted.

Loading

0 comments on commit e7f0a9d

Please sign in to comment.