Bazel下gcc编译正常的C++目标用emscripten编译缺失pnglibconf.h怎么办
Bazel + Emscripten 构建 WebAssembly 时 libpng 头文件缺失问题解决方案
问题说明
现有Bazel构建配置包含两类目标:
- 原生C编译目标
devMain,使用g编译正常 - Emscripten编译目标,用于输出WebAssembly,编译时报错
fatal error: 'pnglibconf.h' file not found
两类目标均依赖公共库myAPI,该库依赖libpng、zlib、OpenCV等第三方组件。
根因定位
该问题并非链接问题,而是编译阶段头文件查找失败,核心原因有三个:
- 原生编译时你配置的libpng目标的
linkopts = ["-lpng", "-lz"]会强制链接系统安装的libpng,系统自带pnglibconf.h所以编译正常;但Emscripten编译时不会使用系统原生库,只会用源码编译的第三方依赖,你现有libpng配置没有生成和暴露pnglibconf.h这个必须的配置头文件。 - zlib配置错误,zlib源码为C文件,现有配置中
srcs = glob(["*.cpp"])无法匹配到任何zlib源码,导致依赖缺失。 - OpenCV配置中的
-ldl、-lpthread等链接参数是Linux原生平台参数,Emscripten不支持,会导致后续链接阶段出错。
修复步骤
修复libpng配置
首先在libpng的BUILD文件中添加pnglibconf.h的生成规则,libpng源码包中默认带预编译的配置模板,直接复用即可:genrule( name = "gen_pnglibconf", srcs = ["scripts/pnglibconf.h.prebuilt"], # 按实际源码中的模板路径调整 outs = ["pnglibconf.h"], cmd = "cp $< $@", )再修改libpng的cc_library配置:
cc_library( name = "libpng", srcs = glob(["*.c"]), # 新增生成的pnglibconf.h到头文件列表 hdrs = glob(["*.h"]) + [":gen_pnglibconf"], copts = [ "-w", "-O3", "-pthread", "-Iexternal", ], includes = [ ".", ], # 删除错误的系统库链接参数,不需要链接系统libpng和zlib # linkopts = ["-lpng", "-lz"], visibility = ["//visibility:public"], deps = [ "@zlibRepo//:zlib", ], )修复zlib配置
修改zlib的源码匹配规则,匹配C文件:cc_library( name = "zlib", # 把*.cpp改为*.c srcs = glob(["*.c"]), hdrs = glob(["*.h"]), copts = [ "-w", "-O3", "-pthread", "-Iexternal", ], visibility = ["//visibility:public"], )修复OpenCV平台兼容配置
修改opencv_core的链接参数,增加Emscripten平台分支,移除不支持的参数:# 先定义Emscripten平台判断 config_setting( name = "emscripten", values = {"crosstool_top": "@emsdk//emscripten_toolchain:everything"}, ) cc_library( name = "opencv_core", # 其余配置保持不变 linkopts = select({ ":emscripten": [], ":arm": ["-llog"], "//conditions:default": ["-ldl", "-lpthread"], }), # 其余配置保持不变 )可选调整Emscripten参数
现有配置中-s ASSERTIONS=1的注释标注为关闭断言,实际参数值为1是开启断言,不需要的话可改为-s ASSERTIONS=0。
验证
执行以下命令清理缓存后重新构建即可:
bazel clean --expunge bazel build //:setupModel-wasm
内容的提问来源于stack exchange,提问作者Harry R.
相关产品推荐
相关产品推荐

