使用Emscripten编译SoLoud示例失败,求解决方法
使用Emscripten移植SoLoud库到Web端的编译错误解决方案
问题描述
我正尝试使用Emscripten将个人项目移植到Web端,项目中用到了SoLoud库。编译该库本身没有报错,但编译其simplest示例时出现大量编译错误。
构建库的步骤:
- 下载并构建genie
- 下载soloud,将
genie可执行文件放入build文件夹 - 运行
./genie --with-miniaudio-only gmake - 进入
gmake目录并执行emmake make
库编译顺利无错,但执行命令emcc main.cpp libsoloud_static.a -I ../include -o index.html构建simplest示例时,出现以下错误:
emcc: warning: libsoloud_static.a: archive is missing an index; Use emar when creating libraries to ensure an index is created [-Wemcc] emcc: warning: libsoloud_static.a: adding index [-Wemcc] error: undefined symbol: _ZN6SoLoud6Soloud19getActiveVoiceCountEv (referenced by top-level compiled C/C++ code) warning: Link with `-sLLD_REPORT_UNDEFINED` to get more information on undefined symbols warning: To disable errors for undefined symbols use `-sERROR_ON_UNDEFINED_SYMBOLS=0` warning: __ZN6SoLoud6Soloud19getActiveVoiceCountEv may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library error: undefined symbol: _ZN6SoLoud6Soloud4initEjjjjj (referenced by top-level compiled C/C++ code) warning: __ZN6SoLoud6Soloud4initEjjjjj may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library error: undefined symbol: _ZN6SoLoud6Soloud4playERNS_11AudioSourceEffbj (referenced by top-level compiled C/C++ code) warning: __ZN6SoLoud6Soloud4playERNS_11AudioSourceEffbj may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library error: undefined symbol: _ZN6SoLoud6Soloud6deinitEv (referenced by top-level compiled C/C++ code) warning: __ZN6SoLoud6Soloud6deinitEv may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library error: undefined symbol: _ZN6SoLoud6SoloudC1Ev (referenced by top-level compiled C/C++ code) warning: __ZN6SoLoud6SoloudC1Ev may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library error: undefined symbol: _ZN6SoLoud6SoloudD1Ev (referenced by top-level compiled C/C++ code) warning: __ZN6SoLoud6SoloudD1Ev may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library error: undefined symbol: _ZN6SoLoud6Speech7setTextEPKc (referenced by top-level compiled C/C++ code) warning: __ZN6SoLoud6Speech7setTextEPKc may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library error: undefined symbol: _ZN6SoLoud6SpeechC1Ev (referenced by top-level compiled C/C++ code) warning: __ZN6SoLoud6SpeechC1Ev may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library error: undefined symbol: _ZN6SoLoud6SpeechD1Ev (referenced by top-level compiled C/C++ code) warning: __ZN6SoLoud6SpeechD1Ev may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library error: undefined symbol: _ZN6SoLoud6Thread5sleepEi (referenced by top-level compiled C/C++ code) warning: __ZN6SoLoud6Thread5sleepEi may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library Error: Aborting compilation due to previous errors
疑问
请问我哪里操作错了?
解决方案
这些错误的核心原因是SoLoud库的编译配置未适配Emscripten环境,且链接时未导出必要的符号,具体修正步骤如下:
1. 重新编译适配Emscripten的SoLoud库
生成Makefile时需明确指定Emscripten平台,确保编译参数符合WebAssembly要求:
./genie --with-miniaudio-only --platform=emscripten gmake
进入gmake目录后,执行编译并添加位置无关代码参数:
emmake make CXXFLAGS="-fPIC"
-fPIC是WebAssembly静态库的必要参数,确保代码可以正确链接。
2. 链接示例时添加Emscripten专属配置
编译示例时,必须导出所有用到的SoLoud符号,并添加Web环境必要参数:
emcc main.cpp libsoloud_static.a -I ../include \ -sEXPORTED_FUNCTIONS='["_main","_ZN6SoLoud6SoloudC1Ev","_ZN6SoLoud6SoloudD1Ev","_ZN6SoLoud6Soloud4initEjjjjj","_ZN6SoLoud6Soloud6deinitEv","_ZN6SoLoud6Soloud4playERNS_11AudioSourceEffbj","_ZN6SoLoud6Soloud19getActiveVoiceCountEv","_ZN6SoLoud6SpeechC1Ev","_ZN6SoLoud6SpeechD1Ev","_ZN6SoLoud6Speech7setTextEPKc","_ZN6SoLoud6Thread5sleepEi"]' \ -sEXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' \ -sALLOW_MEMORY_GROWTH=1 \ -o index.html
EXPORTED_FUNCTIONS:将报错中所有未定义的符号添加进去,防止Emscripten编译时剥离这些符号EXPORTED_RUNTIME_METHODS:提供JS与C/C++交互的基础接口ALLOW_MEMORY_GROWTH:允许WebAssembly内存动态增长,避免内存溢出
3. 修复静态库索引警告
如果仍出现库索引缺失的警告,用emar重新生成索引:
emar s libsoloud_static.a
额外提示
- SoLoud的
Thread::sleep在Web环境下会被Emscripten转换为JS的setTimeout,无需额外修改代码 - 测试时用
emrun index.html启动本地服务器,规避浏览器跨域限制
内容的提问来源于stack exchange,提问作者der
相关产品推荐
相关产品推荐

