Fix OpenAL symbol conflict in libretro Emscripten build

This commit is contained in:
刘皓 2025-01-30 21:25:20 -05:00
parent 1f13a834d1
commit e598114a73
No known key found for this signature in database
GPG key ID: 7901753DB465B711
4 changed files with 58 additions and 11 deletions

View file

@ -800,6 +800,7 @@ jobs:
cd ..
done
find ./ -type f -name '*.o' -print0 | xargs -0 emcc -r -o ${{ runner.temp }}/libretro-mkxp-z.bc
../../retro/emscripten-patch.sh ${{ runner.temp }}/libretro-mkxp-z.bc
- name: Build RetroArch
run: |

View file

@ -170,16 +170,8 @@ if get_option('retro') == true
retro_link_args += '-static-libstdc++'
endif
# Enable C++ exceptions when targeting Emscripten because they're disabled by default
if host_system == 'emscripten'
compilers['cpp'].has_argument('-fexceptions', required: true)
compilers['cpp'].has_link_argument('-fexceptions', required: true)
retro_cppflags += '-fexceptions'
retro_link_args += '-fexceptions'
endif
# If possible, stop the linker from reexporting the symbols from the static libraries we use (e.g. zlib)
if compilers['cpp'].has_link_argument('-Wl,--version-script,' + join_paths(meson.current_source_dir(), 'retro/link.T')) # Only works with GNU linker and LLVM linker
if host_system != 'emscripten' and compilers['cpp'].has_link_argument('-Wl,--version-script,' + join_paths(meson.current_source_dir(), 'retro/link.T')) # Only works with GNU linker and LLVM linker
retro_link_args += '-Wl,--version-script,' + join_paths(meson.current_source_dir(), 'retro/link.T')
endif

31
retro/emscripten-patch.sh Executable file
View file

@ -0,0 +1,31 @@
#!/bin/sh
#
# emscripten-patch.sh
#
# This file is part of mkxp.
#
# Copyright (C) 2013 - 2021 Amaryllis Kulla <ancurio@mapleshrine.eu>
#
# mkxp is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# mkxp is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with mkxp. If not, see <http://www.gnu.org/licenses/>.
# This file looks for all the symbols in the input file that begin with "al" or "alc" (i.e. OpenAL functions) and changes the "a" at the beginning of each symbol into "A".
# This is to work around a symbol conflict with Emscripten's OpenAL implementation by renaming all the symbols in the OpenAL implementation we use.
set -e
for symbol in $(emnm "$1" | cut -d ' ' -f 3 | grep '^alc\?[A-Z]' | awk '{ print length, $0 }' | sort -n -r | cut -d ' ' -f 2)
do
new_symbol="A$(echo $symbol | cut -c 2-)"
echo "[emscripten-patch.sh] Replacing '$symbol' with '$new_symbol'"
sed -i "s/$symbol/$new_symbol/g" "$1"
done

View file

@ -59,6 +59,7 @@ static size_t frame_number = 0;
static ALCdevice *al_device = NULL;
static ALCcontext *al_context = NULL;
static LPALCRENDERSAMPLESSOFT alcRenderSamplesSOFT = NULL;
static LPALCLOOPBACKOPENDEVICESOFT alcLoopbackOpenDeviceSOFT = NULL;
static int16_t *sound_buf;
static void fallback_log(enum retro_log_level level, const char *fmt, ...) {
@ -139,6 +140,8 @@ static bool init_sandbox() {
}
fs.reset();
log_printf(RETRO_LOG_INFO, "Initializing filesystem\n");
fs.emplace((const char *)NULL, false);
{
@ -163,9 +166,27 @@ static bool init_sandbox() {
fs->createPathCache();
alcRenderSamplesSOFT = (LPALCRENDERSAMPLESSOFT)alcGetProcAddress(NULL, "alcRenderSamplesSOFT");
log_printf(RETRO_LOG_INFO, "Initializing audio\n");
al_device = ((LPALCLOOPBACKOPENDEVICESOFT)alcGetProcAddress(NULL, "alcLoopbackOpenDeviceSOFT"))(NULL);
alcLoopbackOpenDeviceSOFT = (LPALCLOOPBACKOPENDEVICESOFT)alcGetProcAddress(NULL, "AlcLoopbackOpenDeviceSOFT");
if (alcLoopbackOpenDeviceSOFT == NULL) {
alcLoopbackOpenDeviceSOFT = (LPALCLOOPBACKOPENDEVICESOFT)alcGetProcAddress(NULL, "alcLoopbackOpenDeviceSOFT");
if (alcLoopbackOpenDeviceSOFT == NULL) {
log_printf(RETRO_LOG_ERROR, "OpenAL implementation does not support `alcLoopbackOpenDeviceSOFT`\n");
return false;
}
}
alcRenderSamplesSOFT = (LPALCRENDERSAMPLESSOFT)alcGetProcAddress(NULL, "AlcRenderSamplesSOFT");
if (alcRenderSamplesSOFT == NULL) {
alcRenderSamplesSOFT = (LPALCRENDERSAMPLESSOFT)alcGetProcAddress(NULL, "alcRenderSamplesSOFT");
if (alcRenderSamplesSOFT == NULL) {
log_printf(RETRO_LOG_ERROR, "OpenAL implementation does not support `alcRenderSamplesSOFT`\n");
return false;
}
}
al_device = alcLoopbackOpenDeviceSOFT(NULL);
if (al_device == NULL) {
log_printf(RETRO_LOG_ERROR, "Failed to initialize OpenAL loopback device\n");
return false;
@ -232,6 +253,8 @@ static bool init_sandbox() {
audio.emplace();
log_printf(RETRO_LOG_INFO, "Initializing sandbox\n");
SharedState::initInstance(NULL);
try {