Skip to content

Commit

Permalink
modules: rewrite FindOpenAL to support static and subproject AL Soft.
Browse files Browse the repository at this point in the history
Strange build breakages, I'm ready for you now!
  • Loading branch information
mosra committed Jun 10, 2020
1 parent 23d2ab1 commit 25f7d79
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 155 deletions.
10 changes: 10 additions & 0 deletions doc/changelog.dox
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,16 @@ See also:
- Properly installing plugin binaries in Gentoo packages (see
[mosra/magnum-plugins#85](https://github.com/mosra/magnum-plugins/issues/85))
- Warning fixes for MSVC (see [mosra/magnum#445](https://github.com/mosra/magnum/pull/445))
- `FindOpenAL.cmake` was rewritten from scratch to support linking against
statically built OpenAL Soft (through its CMake config file) as well as
OpenAL Soft added as a CMake subproject. Moreover, when using Magnum as a
CMake subproject, the @ref Audio library now copies the OpenAL DLL to
`CMAKE_RUNTIME_OUTPUT_DIRECTORY` (if set) as a post-build step. The DLL
location, if found, is also available through an `OPENAL_DLL_RELEASE`
variable for use by 3rd party code. See also
[mosra/magnum#402](https://github.com/mosra/magnum/issues/402) and
[mosra/magnum#412](https://github.com/mosra/magnum/issues/412) for more
information.

@subsection changelog-latest-bugfixes Bug fixes

Expand Down
15 changes: 10 additions & 5 deletions doc/namespaces.dox
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,18 @@ find_package(Magnum REQUIRED Audio)
target_link_libraries(your-app PRIVATE Magnum::Audio)
@endcode

Additionally, if you're using Magnum as a CMake subproject, do the following
* *before* calling @cmake find_package() @ce to ensure it's enabled, as the
library is not built by default. Using OpenAL itself as a CMake subproject
isn't tested at the moment, so you need to provide it as a system dependency
and point `CMAKE_PREFIX_PATH` to its installation dir if necessary.
Additionally, if you're using Magnum as a CMake subproject, bundle the
[openal-soft repository](https://github.com/kcat/openal-soft) and do the
following *before* calling @cmake find_package() @ce to ensure it's enabled, as
the library is not built by default. If you want to use system-installed
OpenAL, omit the first part and point `CMAKE_PREFIX_PATH` to its installation
dir if necessary.

@code{.cmake}
set(CMAKE_POSITION_INDEPENDENT_CODE ON) # needed if building dynamic libraries
set(LIBTYPE STATIC) # omit or set to SHARED if you want a shared OpenAL library
add_subdirectory(openal-soft EXCLUDE_FROM_ALL)

set(WITH_AUDIO ON CACHE BOOL "" FORCE)
add_subdirectory(magnum EXCLUDE_FROM_ALL)
@endcode
Expand Down
4 changes: 1 addition & 3 deletions modules/FindMagnum.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -817,9 +817,7 @@ foreach(_component ${Magnum_FIND_COMPONENTS})
elseif(_component STREQUAL Audio)
find_package(OpenAL)
set_property(TARGET Magnum::${_component} APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${OPENAL_INCLUDE_DIR})
set_property(TARGET Magnum::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${OPENAL_LIBRARY} Corrade::PluginManager)
INTERFACE_LINK_LIBRARIES Corrade::PluginManager OpenAL::OpenAL)

# No special setup for DebugTools library

Expand Down
259 changes: 137 additions & 122 deletions modules/FindOpenAL.cmake
Original file line number Diff line number Diff line change
@@ -1,145 +1,160 @@
#.rst:
# FindOpenAL
# ----------
# Find OpenAL
# -----------
#
# Finds the OpenAL library. This module defines:
#
# OpenAL_FOUND - True if the OpenAL library is found
# OpenAL::OpenAL - OpenAL imported target
#
# Locate OpenAL This module defines OPENAL_LIBRARY OPENAL_FOUND, if
# false, do not try to link to OpenAL OPENAL_INCLUDE_DIR, where to find
# the headers
# Additionally these variables are defined for internal usage:
#
# $OPENALDIR is an environment variable that would correspond to the
# ./configure --prefix=$OPENALDIR used in building OpenAL.
# OPENAL_LIBRARY - OpenAL library
# OPENAL_DLL_RELEASE - OpenAL release DLL on Windows, if found. Note that
# (at least in case of the binary OpenAL Soft distribution) it's named
# soft_oal.dll and you need to rename it to OpenAL32.dll to make it work.
# OPENAL_INCLUDE_DIR - Include dir
#
# Created by Eric Wing. This was influenced by the FindSDL.cmake
# module.

#=============================================================================
# CMake - Cross Platform Makefile Generator
# Copyright 2000-2016 Kitware, Inc.
# Copyright 2000-2011 Insight Software Consortium
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.

#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# This file is part of Magnum.
#
# * Neither the names of Kitware, Inc., the Insight Software Consortium,
# nor the names of their contributors may be used to endorse or promote
# products derived from this software without specific prior written
# permission.
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020 Vladimír Vondruš <mosra@centrum.cz>
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#=============================================================================

# This makes the presumption that you are include al.h like
# #include "al.h"
# and not
# #include <AL/al.h>
# The reason for this is that the latter is not entirely portable.
# Windows/Creative Labs does not by default put their headers in AL/ and
# OS X uses the convention <OpenAL/al.h>.
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# For Windows, Creative Labs seems to have added a registry key for their
# OpenAL 1.1 installer. I have added that key to the list of search paths,
# however, the key looks like it could be a little fragile depending on
# if they decide to change the 1.00.0000 number for bug fix releases.
# Also, they seem to have laid down groundwork for multiple library platforms
# which puts the library in an extra subdirectory. Currently there is only
# Win32 and I have hardcoded that here. This may need to be adjusted as
# platforms are introduced.
# The OpenAL 1.0 installer doesn't seem to have a useful key I can use.
# I do not know if the Nvidia OpenAL SDK has a registry key.
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# For OS X, remember that OpenAL was added by Apple in 10.4 (Tiger).
# To support the framework, I originally wrote special framework detection
# code in this module which I have now removed with CMake's introduction
# of native support for frameworks.
# In addition, OpenAL is open source, and it is possible to compile on Panther.
# Furthermore, due to bugs in the initial OpenAL release, and the
# transition to OpenAL 1.1, it is common to need to override the built-in
# framework.
# Per my request, CMake should search for frameworks first in
# the following order:
# ~/Library/Frameworks/OpenAL.framework/Headers
# /Library/Frameworks/OpenAL.framework/Headers
# /System/Library/Frameworks/OpenAL.framework/Headers
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# On OS X, this will prefer the Framework version (if found) over others.
# People will have to manually change the cache values of
# OPENAL_LIBRARY to override this selection or set the CMake environment
# CMAKE_INCLUDE_PATH to modify the search paths.

# This version is modified for Magnum and was forked from
# https://github.com/Kitware/CMake/blob/v3.6.1/Modules/FindOpenAL.cmake
# The file was modified to add a new path suffix for finding OpenAL for
# Emscripten on macOS. Additionally, in case of Emscripten, there's no library
# to find but instead one says -lopenal (and if MINIMAL_RUNTIME is not
# specified, this is implicit).

find_path(OPENAL_INCLUDE_DIR al.h
HINTS
ENV OPENALDIR
# The AL was added in order to make the module working for Emscripten on macOS.
# Not sure why include/AL wasn't enough.
PATH_SUFFIXES include/AL include/OpenAL include AL
PATHS
~/Library/Frameworks
/Library/Frameworks
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir]
)

if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_OpenAL_ARCH_DIR libs/Win64)
else()
set(_OpenAL_ARCH_DIR libs/Win32)

# OpenAL Soft installs cmake package config files which handles dependencies in
# case OpenAL Soft is built statically. Try to find first, quietly, so it
# doesn't print loud messages when it's not found, since that's okay. If the
# OpenAL target already exists, it means we're using it through a CMake
# subproject -- don't attempt to find the package in that case.
if(NOT TARGET OpenAL)
find_package(OpenAL CONFIG QUIET)
endif()

# If either an OpenAL Soft config file was found or we have a subproject, point
# OpenAL::OpenAL to that and exit -- nothing else to do here.
if(TARGET OpenAL OR TARGET OpenAL::OpenAL)
# OpenAL Soft config file already defines this one, so this is just for
# the subproject case.
if(NOT TARGET OpenAL::OpenAL)
# Aliases of (global) targets are only supported in CMake 3.11, so we
# work around it by this. This is easier than fetching all possible
# properties (which are impossible to track of) and then attempting to
# rebuild them into a new target.
add_library(OpenAL::OpenAL INTERFACE IMPORTED)
set_target_properties(OpenAL::OpenAL PROPERTIES INTERFACE_LINK_LIBRARIES OpenAL)

# The OpenAL target doesn't define any usable
# INTERFACE_INCLUDE_DIRECTORIES for some reason (apparently the
# $<BUILD_INTERFACE:> in there doesn't work or whatever), so let's do
# that ourselves.
get_target_property(_OPENAL_SOURCE_DIR OpenAL SOURCE_DIR)
set_target_properties(OpenAL::OpenAL PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${_OPENAL_SOURCE_DIR}/include/AL)
endif()

# Just to make FPHSA print some meaningful location, nothing else.
# Fortunately because of the INTERFACE_INCLUDE_DIRECTORIES workaround above
# we can have the same handling both in case of an imported target and a
# CMake subproject.
get_target_property(_OPENAL_INTERFACE_INCLUDE_DIRECTORIES OpenAL::OpenAL INTERFACE_INCLUDE_DIRECTORIES)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args("OpenAL" DEFAULT_MSG
_OPENAL_INTERFACE_INCLUDE_DIRECTORIES)

if(CORRADE_TARGET_WINDOWS)
# TODO: investigate if OpenAL Soft has IMPORTED_LOCATION_ / IMPLIB like
# GLFW does so we can provide OPENAL_DLL
endif()

return()
endif()

# Under Emscripten, OpenAL is linked implicitly. With MINIMAL_RUNTIME you need
# to specify -lopenal. Simply set the library name to that.
if(CORRADE_TARGET_EMSCRIPTEN)
set(OPENAL_LIBRARY openal CACHE STRING "Path to a library." FORCE)
else()
find_library(OPENAL_LIBRARY
NAMES OpenAL al openal OpenAL32
HINTS
ENV OPENALDIR
PATH_SUFFIXES lib64 lib libs64 libs ${_OpenAL_ARCH_DIR}
PATHS
~/Library/Frameworks
/Library/Frameworks
/sw
/opt/local
/opt/csw
/opt
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir]
)
# OpenAL Soft Windows binary distribution puts the library into a subdir,
# the legacy one from Creative uses the same. OpenAL Soft puts DLLs into
# bin/Win{32,64}/soft_oal.dll
if(WIN32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_OPENAL_LIBRARY_PATH_SUFFIX libs/Win64)
set(_OPENAL_DLL_PATH_SUFFIX bin/Win64)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(_OPENAL_LIBRARY_PATH_SUFFIX libs/Win32)
set(_OPENAL_DLL_PATH_SUFFIX bin/Win32)
endif()
endif()

find_library(OPENAL_LIBRARY
# Names same as in CMake's vanilla FindOpenAL
NAMES OpenAL al openal OpenAL32
# For binary OpenAL Soft distribution on Windows
PATH_SUFFIXES ${_OPENAL_LIBRARY_PATH_SUFFIX}
# The other PATHS from CMake's vanilla FindOpenAL seem to be a legacy
# cruft, skipping those. The Windows registry used by the vanilla
# FindOpenAL doesn't seem to be set anymore either.
)
endif()

unset(_OpenAL_ARCH_DIR)
# Include dir
find_path(OPENAL_INCLUDE_DIR NAMES al.h
# AL/ used by OpenAL Soft, OpenAL/ used by the macOS framework. The legacy
# Creative SDK puts al.h directly into include/, ffs.
PATH_SUFFIXES AL OpenAL
# As above, skipping the obsolete PATHS and registry in vanilla FindOpenAL
)

# OpenAL DLL on Windows
if(CORRADE_TARGET_WINDOWS)
# TODO: debug?
find_file(OPENAL_DLL_RELEASE
NAMES soft_oal.dll
PATH_SUFFIXES ${_OPENAL_DLL_PATH_SUFFIX})
endif()

# handle the QUIETLY and REQUIRED arguments and set OPENAL_FOUND to TRUE if
# all listed variables are TRUE
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenAL DEFAULT_MSG OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
find_package_handle_standard_args(OpenAL DEFAULT_MSG
OPENAL_LIBRARY
OPENAL_INCLUDE_DIR)

if(NOT TARGET OpenAL::OpenAL)
# Work around BUGGY framework support on macOS. Do this also in case of
# Emscripten, since there we don't have a location either.
# http://public.kitware.com/pipermail/cmake/2016-April/063179.html
if((APPLE AND ${OPENAL_LIBRARY} MATCHES "\\.framework$") OR CORRADE_TARGET_EMSCRIPTEN)
add_library(OpenAL::OpenAL INTERFACE IMPORTED)
set_property(TARGET OpenAL::OpenAL APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${OPENAL_LIBRARY})
else()
add_library(OpenAL::OpenAL UNKNOWN IMPORTED)
set_property(TARGET OpenAL::OpenAL PROPERTY
IMPORTED_LOCATION ${OPENAL_LIBRARY})
endif()

set_target_properties(OpenAL::OpenAL PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${OPENAL_INCLUDE_DIR})
endif()

mark_as_advanced(OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
4 changes: 3 additions & 1 deletion package/ci/appveyor-desktop-gles.bat
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2019" call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Auxiliary/Build/vcvarsall.bat" x64 || exit /b
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" call "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Auxiliary/Build/vcvarsall.bat" x64 || exit /b
set PATH=%APPVEYOR_BUILD_FOLDER%/openal/bin/Win64;%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH%
set PATH=%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH%
rem OpenAL DLL is renamed & copied to magnum's bin dir automatically by the
rem buildsystem, no need to do that here anymore

rem Build Corrade
git clone --depth 1 git://github.com/mosra/corrade.git || exit /b
Expand Down
4 changes: 3 additions & 1 deletion package/ci/appveyor-desktop-mingw.bat
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
rem Workaround for CMake not wanting sh.exe on PATH for MinGW. AARGH.
set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
set PATH=C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;%APPVEYOR_BUILD_FOLDER%/openal/bin/Win64;%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH%
set PATH=C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH%
rem OpenAL DLL is renamed & copied to magnum's bin dir automatically by the
rem buildsystem, no need to do that here anymore

rem Build Corrade
git clone --depth 1 git://github.com/mosra/corrade.git || exit /b
Expand Down
2 changes: 1 addition & 1 deletion package/ci/appveyor-desktop-vulkan.bat
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2019" call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Auxiliary/Build/vcvarsall.bat" x64 || exit /b
set PATH=%APPVEYOR_BUILD_FOLDER%/openal/bin/Win64;%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH%
set PATH=%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH%

rem Build Corrade
git clone --depth 1 git://github.com/mosra/corrade.git || exit /b
Expand Down
8 changes: 2 additions & 6 deletions package/ci/appveyor-desktop.bat
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@ if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2019" call "C:/Program File
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" call "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Auxiliary/Build/vcvarsall.bat" %PLATFORM% || exit /b
if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2015" call "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/vcvarsall.bat" %PLATFORM% || exit /b
set PATH=%APPVEYOR_BUILD_FOLDER%\deps\bin;%PATH%
if "%PLATFORM%" == "" set PATH=%APPVEYOR_BUILD_FOLDER%/openal/bin/Win32;%PATH%
rem for SOME FREAKING REASON vcvarsall.bat in MSVC2015 sets %PLATFORM% to
rem X64 while I expect it to be x64. With a 32-bit build it fortunately stays
rem empty. Not a problem on 2017 or 2019. So doing a case-insensitive compare
rem here to make things work properly.
if /I "%PLATFORM%" == "x64" set PATH=%APPVEYOR_BUILD_FOLDER%/openal/bin/Win64;%PATH%
rem OpenAL DLL is renamed & copied to magnum's bin dir automatically by the
rem buildsystem, no need to do that here anymore

rem need to explicitly specify a 64-bit target, otherwise CMake+Ninja can't
rem figure that out -- https://gitlab.kitware.com/cmake/cmake/issues/16259
Expand Down
6 changes: 2 additions & 4 deletions package/ci/appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,10 @@ install:
# For ES builds, otherwise the "%COMPILER:~0,4%" below doesn't work, sigh
- IF "%COMPILER%" == "" set COMPILER=msvc

# OpenAL
# OpenAL. The DLL is copied & renamed by the buildsystem, no need to do that
# here anymore.
- IF NOT "%TARGET%" == "rt" IF NOT EXIST %APPVEYOR_BUILD_FOLDER%\openal-soft-1.19.1-bin.zip appveyor DownloadFile https://openal-soft.org/openal-binaries/openal-soft-1.19.1-bin.zip
- IF NOT "%TARGET%" == "rt" 7z x openal-soft-1.19.1-bin.zip && ren openal-soft-1.19.1-bin openal && echo [General] > %APPDATA%/alsoft.ini & echo drivers=null >> %APPDATA%/alsoft.ini
- IF "%TARGET%" == "desktop" ren openal\bin\Win64\soft_oal.dll OpenAL32.dll
- IF "%TARGET%" == "desktop" ren openal\bin\Win32\soft_oal.dll OpenAL32.dll
- IF "%TARGET%" == "desktop-gles" ren openal\bin\Win64\soft_oal.dll OpenAL32.dll

# Build apps on both GL and Vulkan to verify these can build w/o GL as well.
# Not on GLES, as there's not much GLES-dependent.
Expand Down
Loading

0 comments on commit 25f7d79

Please sign in to comment.