Emscripten项目中SDL2加-pthread编译失败原因及解决方法
问题:Emscripten启用-sUSE_PTHREADS=1编译SDL2时缓存锁冲突失败
CMake配置
set(USE_FLAGS "-sUSE_ZLIB=1 -sUSE_SDL=2 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS=['png,jpg'] -O3 -g -sWASM_WORKERS -sUSE_PTHREADS=1" CACHE STRING "Compilation flags" FORCE) set(LINKING_FLAGS "--preload-file ${ASSETS_PATH}/assets@/assets -sFULL_ES2 -sWASM=1 -sFETCH=1 -sEXIT_RUNTIME=1 -sALLOW_MEMORY_GROWTH=1 -sEXPORTED_FUNCTIONS=['_main','_photoTaken','_malloc','_setNotificationToken','_interceptPushNotification','stackSave','stackRestore','stackAlloc'] -sEXPORTED_RUNTIME_METHODS=[cwrap] -sFORCE_FILESYSTEM=1 -lidbfs.js -O3 -g -sAUDIO_WORKLET=1 -sWASM_WORKERS -sASYNCIFY -sASYNCIFY_STACK_SIZE=131072 -sUSE_SDL=2 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS=['png,jpg'] -sWEBAUDIO_DEBUG=1 -sUSE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8 -sPROXY_TO_PTHREAD" CACHE STRING "Linking flags" FORCE)
错误信息
assert 'EM_CACHE_IS_LOCKED' not in os.environ, f'attempt to lock the cache while a parent process is holding the lock ({reason})' AssertionError: attempt to lock the cache while a parent process is holding the lock (sysroot/lib/wasm32-emscripten/libSDL2.a) em++: error: subprocess 1/19 failed (returned 1)! (cmdline: /../../emsdk/upstream/emscripten/emcc -c /../../emsdk/upstream/emscripten/cache/ports/sdl2_image/SDL_image-release-2.6.0/IMG.c -o /Users/olegparamonov/emsdk/upstream/emscripten/cache/ports-builds/sdl2_image/IMG.c.o -g -sSTRICT -Werror -O2 -I/../../emsdk/upstream/emscripten/cache/ports/sdl2_image/SDL_image-release-2.6.0 -O2 -sUSE_SDL=2 -Wno-format-security -DLOAD_JPG -DLOAD_PNG -sUSE_LIBPNG -sUSE_LIBJPEG)
原因分析
该错误属于Emscripten缓存机制在多线程编译场景下的锁冲突问题:
- 启用
-sUSE_PTHREADS=1后,Emscripten会并行编译SDL2、SDL_image等依赖项,但缓存锁的嵌套处理逻辑存在缺陷,导致子进程尝试获取已被父进程持有的libSDL2.a缓存锁,触发断言失败。 - CMake配置中重复在编译标志和链接标志里设置
-sUSE_PTHREADS=1、-sUSE_SDL=2等参数,进一步加剧了编译流程中的资源竞争。
解决方法
1. 清理缓存并重建
先彻底清除Emscripten缓存,消除残留的锁状态:
emcc --clear-cache
删除CMake构建目录后重新生成配置并编译:
rm -rf build && mkdir build && cd build cmake .. make
2. 合并重复的编译参数
将依赖相关参数(如-sUSE_PTHREADS=1、-sUSE_SDL=2)仅放在编译标志中,链接标志不再重复设置,减少参数冲突:
修改后的CMake配置示例:
set(USE_FLAGS "-sUSE_ZLIB=1 -sUSE_SDL=2 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS=['png,jpg'] -O3 -g -sWASM_WORKERS -sUSE_PTHREADS=1" CACHE STRING "Compilation flags" FORCE) set(LINKING_FLAGS "--preload-file ${ASSETS_PATH}/assets@/assets -sFULL_ES2 -sWASM=1 -sFETCH=1 -sEXIT_RUNTIME=1 -sALLOW_MEMORY_GROWTH=1 -sEXPORTED_FUNCTIONS=['_main','_photoTaken','_malloc','_setNotificationToken','_interceptPushNotification','stackSave','stackRestore','stackAlloc'] -sEXPORTED_RUNTIME_METHODS=[cwrap] -sFORCE_FILESYSTEM=1 -lidbfs.js -O3 -g -sAUDIO_WORKLET=1 -sWASM_WORKERS -sASYNCIFY -sASYNCIFY_STACK_SIZE=131072 -sWEBAUDIO_DEBUG=1 -sPTHREAD_POOL_SIZE=8 -sPROXY_TO_PTHREAD" CACHE STRING "Linking flags" FORCE)
3. 限制并行编译线程数
若上述方法无效,可强制减少CMake并行编译的线程数,降低缓存锁竞争概率:
make -j4 # 根据硬件配置调整线程数,比如4或2
4. 更新Emscripten到最新版本
该锁冲突问题可能是旧版本Emscripten的已知bug,更新到最新稳定版可修复:
cd emsdk ./emsdk update ./emsdk install latest ./emsdk activate latest source ./emsdk_env.sh
内容的提问来源于stack exchange,提问作者oregu1
相关产品推荐
相关产品推荐

