使用Emscripten SDK的emmake编译libpd失败的问题求助
初始编译错误:No byte order defined
我尝试用Emscripten SDK把libpd编译成JavaScript或WebAssembly。根据文档,因为项目自带Makefile,我直接用了emmake make命令(没有./configure文件,所以没用到emconfigure),但编译时抛出了如下错误:
/home/ian/Documents/emsdk/emscripten/1.37.37/emcc.py -DPD -DHAVE_UNISTD_H -DUSEAPI_DUMMY -I./pure-data/src -I./libpd_wrapper -I./libpd_wrapper/util -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -fPIC -I"/usr/lib/jvm/default-java/include/linux" -DHAVE_LIBDL -ffast-math -funroll-loops -fomit-frame-pointer -O3 -DLIBPD_EXTRA -c -o pure-data/src/d_array.o pure-data/src/d_array.c pure-data/src/d_array.c:523:2: error: No byte order defined #error No byte order defined ^ 1 error generated. ERROR:root:compiler frontend failed to generate LLVM bitcode, halting <integrado>: fallo en las instrucciones para el objetivo 'pure-data/src/d_array.o' make: *** [pure-data/src/d_array.o] Error 1
想请教下有没有解决思路?这个库能不能被编译呢?
更新1:修改后出现stdatomic.h找不到的错误
按照@zakki的回答修改完所有报错文件后,又碰到了新的错误:
libpd_wrapper/util/ringbuffer.c:18:12: fatal error: 'stdatomic.h' file not found #include <stdatomic.h>
对应的文件片段如下:
#if __STDC_VERSION__ >= 201112L // use stdatomic if C11 is available #include <stdatomic.h> // HERE IS WHERE ERROR GOES #define SYNC_FETCH(ptr) atomic_fetch_or((_Atomic int *)ptr, 0) #define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \ atomic_compare_exchange_strong((_Atomic int *)ptr, &oldval, newval) //Some other definitions that I didn't put here
我之前了解过一些C++11相关的问题讨论,该怎么修复这个错误呢?
更新2:编译完成但出现动态库相关警告
添加&& !defined(__EMSCRIPTEN__)到条件判断后,编译终于完成了,但出现了一段不太理解的警告:
WARNING:root:Dynamic libraries (.so, .dylib, .dll) are currently not supported by Emscripten. For build system emulation purposes, Emscripten will now generate a static library file (.bc) with the suffix '.so'. For best practices, please adapt your build system to directly generate a static LLVM bitcode library by setting the output suffix to '.bc.')
针对上述问题的解决思路与解释
1. 解决初始的字节序定义错误
这个错误是因为Emscripten编译环境下,目标平台的字节序宏没有被正确识别。WebAssembly标准默认采用小端序,所以我们可以手动给Emscripten环境添加字节序定义:
- 打开
pure-data/src/d_array.c,找到触发#error No byte order defined的条件分支; - 添加对
__EMSCRIPTEN__宏的判断,明确指定字节序:#ifdef __linux__ # include <endian.h> #elif defined(__APPLE__) # include <machine/endian.h> #elif defined(__EMSCRIPTEN__) # define LITTLE_ENDIAN 1234 # define BYTE_ORDER LITTLE_ENDIAN #else # error No byte order defined #endif - 放心,libpd是可以被编译到WebAssembly的,社区里已经有不少成功案例,不用怀疑可行性。
2. 修复stdatomic.h找不到的问题
你用的Emscripten 1.37.37版本比较旧,对C11标准库的stdatomic.h支持不完善。你已经尝试的方法完全正确:
- 修改
ringbuffer.c中的条件判断,排除Emscripten环境:#if __STDC_VERSION__ >= 201112L && !defined(__EMSCRIPTEN__) - 这样编译时会跳过C11原子操作的代码,libpd本身已经提供了非C11环境下的同步逻辑 fallback,不会影响功能正常运行。
3. 解释最终的动态库警告
这个警告是Emscripten的正常提示,不用太在意:
- Emscripten目前不支持生成动态链接库(.so/.dylib/.dll);
- 为了兼容你的Makefile里生成动态库的逻辑,它把原本要输出的.so文件替换成了静态LLVM字节码文件(.bc),但保留了.so后缀;
- 如果想消除这个警告,可以修改Makefile,把输出文件的后缀改成
.bc,不过即使不改,生成的文件也可以正常用于后续的Emscripten编译流程。
内容的提问来源于stack exchange,提问作者Mr_LinDowsMac

