怎样用 Clang 为 JLL 包编写封装器

我在为 C 库 zbar 编写 Julia 的封装器,通过 Build_tarball 脚本 构建了 JLL 包,products 有两个内容:

...
products = [
    LibraryProduct("libzbar", :libzbar),
    ExecutableProduct("zbarimg", :zbarimg),
]

通过 run 可以将 zbarimg 简单地封装为 Julia 函数。

Q1:libzbar 中的函数怎么用 Clang 自动封装?


我尝试了 Clang 文档写的 generator.tomlgenerator.jl

# generator.toml

[general]
library_name = "libzbar"
output_file_path = "./Libzbar.jl"
module_name = "Libzbar"
jll_pkg_name = "zbar_jll"
# generator.jl

using Clang.Generators
using zbar_jll

cd(@__DIR__)

include_dir = normpath(zbar_jll.artifact_dir, "include")

# wrapper generator options
options = load_options(joinpath(@__DIR__, "generator.toml"))

# add compiler flags, e.g. "-DXXXXXXXXX"
args = get_default_args()
push!(args, "-I$include_dir")

# only wrap libclang headers in include/zbar
header_dir = joinpath(include_dir, "zbar")
headers = [joinpath(header_dir, header) for header in readdir(header_dir) if endswith(header, ".h")]

# create context
ctx = create_context(headers, args, options)

# run generator
build!(ctx)

但执行命令 julia --project generator.jl 后只得到了空白的 Libzbar.jl

module Libzbar

using zbar_jll
export zbar_jll

using CEnum

end # module

执行过程存在警告 error: "include zbar.h in your application, **not** zbar/Decoder.h"

[ Info: Parsing headers...
/home/rex/.julia/artifacts/ae0ec45fea87ed0c66d1c51f18e96ffa0deedb2c/include/zbar/Decoder.h:30:3: error: "include zbar.h in your application, **not** zbar/Decoder.h"

Q2:generator 文件应该怎么修改 ?

附:zbar 的头文件路径

include/
├── config.h
├── config.h.in
├── Makefile.am.inc
├── stamp-h1
├── zbar
│   ├── Decoder.h
│   ├── Exception.h
│   ├── Image.h
│   ├── ImageScanner.h
│   ├── Processor.h
│   ├── QZBar.h
│   ├── QZBarImage.h
│   ├── Scanner.h
│   ├── Symbol.h
│   ├── Video.h
│   ├── Window.h
│   └── zbargtk.h
└── zbar.h

另外,在 ./configure 构建时,我没有启用所有参数,而只指定了 zbarimg

  ```bash
  => zbarcam video scanner will *NOT* be built
  => libv4l will *NOT* be used
  => JPEG image conversions will *NOT* be supported
  => GTK support will *NOT* be built
  => the Qt widget will *NOT* be built
  => the Java interface will *NOT* be built
  => the Java unit test will *NOT* be enabled
  ```

这个操作可能影响了 JLL 包产生的 lib 文件?

2 个赞

这个lib只需要include top-level的头文件zbar.h

1 个赞

遇到了个奇怪的问题:执行二进制文件 zbarimg 出错:

dyld[38973]: Library not loaded: @rpath/libMagickWand-6.Q16.7.dylib

该错误有时出现,有时正常,不知道是封装方式的问题还是 JLL 包的问题。

复现方式:

git clone https://github.com/RexWzh/ZBar.jl.git
cd ZBar.jl
git checkout bug # 切换分支
julia --project
using ZBar
run(`$(zbarimg()) --help`);


但 test 模式能正常执行和打印

# ]test

res = execute(`$(zbarimg()) --help`)
@test res.code == 0
println(res.stdout)

此外,不加 --project 直接 using zbar_jll 也不会报错。

在 Mac-julia1.8 和 Ubuntu-julia1.7 上均遇到这个问题。

Ygg里build script的ImageMagic依赖加上版本号限制,或者将出错的那个环境用的ImageMagic的JLL的版本和zbar_jll依赖的那个版本保持一致。

1 个赞

这下面的截图错误没截全,关键点在于linker去搜索的artifacts那些path。

确实是 ImageMagick_jll 的版本问题,我在构建 tarball 的时候也遇到过(zbar 仅支持到 6.9)。看来除了 Project.toml,还要排除次级依赖的版本问题。非常感谢!


完整的报错信息:

julia> run(`$(zbarimg()) --help`);
dyld[42075]: Library not loaded: @rpath/libMagickWand-6.Q16.7.dylib
  Referenced from: <7ABC40BE-44A7-38B1-96CA-AD0CF16F78BB> /Users/wangzhihong/.julia/artifacts/dae83bf9ccbccd5baf5312032f22cbd3339688f3/bin/zbarimg
  Reason: tried: '/Users/wangzhihong/.julia/artifacts/dae83bf9ccbccd5baf5312032f22cbd3339688f3/bin/../lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/dae83bf9ccbccd5baf5312032f22cbd3339688f3/bin/../lib/libMagickWand-6.Q16.7.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS@rpath/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/dae83bf9ccbccd5baf5312032f22cbd3339688f3/bin/../lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/dae83bf9ccbccd5baf5312032f22cbd3339688f3/bin/../lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/b917751a0a1532e56881e471e0f9b441460f2295/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/2f38ae8b406b01e85a4f0e165d3976d8f6bf80c9/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/b450526929615030746974fd622effa333c2c87a/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/1b3d05e1af5571e3dc596223ea161ce78ad30e1c/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/e0874abced850b5bab1921e0f028d50861af3e18/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/0d9e7c35bc21411c7d9c194f790e30a95a4a5795/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/825c20e9fb9976a6dc62e1a442018fed80992c1b/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/3e6cbbf76c070bcec6c7db17999b509ac4b46c0d/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/bf6a8a991cf4ddbca411ad026e1839f5251ed85b/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/.julia/artifacts/dae83bf9ccbccd5baf5312032f22cbd3339688f3/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Applications/Julia-1.8.app/Contents/Resources/julia/bin/../lib/julia/libMagickWand-6.Q16.7.dylib' (no such file), '/Applications/Julia-1.8.app/Contents/Resources/julia/bin/../lib/libMagickWand-6.Q16.7.dylib' (no such file), '/Users/wangzhihong/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/usr/local/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/lib/libMagickWand-6.Q16.7.dylib' (no such file), '/usr/lib/libMagickWand-6.Q16.7.dylib' (no such file, not in dyld cache)
ERROR: failed process: Process(setenv(`/Users/wangzhihong/.julia/artifacts/dae83bf9ccbccd5baf5312032f22cbd3339688f3/bin/zbarimg --help`,["XPC_FLAGS=0x0", "_CE_M=", "PATH=/Users/wangzhihong/.julia/artifacts/2f38ae8b406b01e85a4f0e165d3976d8f6bf80c9/bin:/Users/wangzhihong/.julia/artifacts/1b3d05e1af5571e3dc596223ea161ce78ad30e1c/bin:/Users/wangzhihong/.julia/artifacts/0d9e7c35bc21411c7d9c194f790e30a95a4a5795/bin:/Users/wangzhihong/.julia/artifacts/825c20e9fb9976a6dc62e1a442018fed80992c1b/bin:/Users/wangzhihong/.julia/artifacts/3e6cbbf76c070bcec6c7db17999b509ac4b46c0d/bin:/Users/wangzhihong/.julia/artifacts/bf6a8a991cf4ddbca411ad026e1839f5251ed85b/bin:/Users/wangzhihong/.julia/artifacts/dae83bf9ccbccd5baf5312032f22cbd3339688f3/bin:/Users/wangzhihong/opt/anaconda3/bin:/Users/wangzhihong/opt/anaconda3/condabin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/wangzhihong/.local/bin", "CONDA_PROMPT_MODIFIER=(base) ", "PWD=/Users/wangzhihong/workspace/julia/ZBar.jl", "LSCOLORS=Gxfxcxdxbxegedabagacad", "EDITOR=code", "XPC_SERVICE_NAME=0", "TERM_PROGRAM=Apple_Terminal", "HOMEBREW_PREFIX=/opt/homebrew"  …  "CONDA_DEFAULT_ENV=base", "_CE_CONDA=", "USER=wangzhihong", "CONDA_SHLVL=1", "CONDA_EXE=/Users/wangzhihong/opt/anaconda3/bin/conda", "TERM=xterm-256color", "HOME=/Users/wangzhihong", "TERM_PROGRAM_VERSION=447", "LESS=-R", "ZSH=/Users/wangzhihong/.oh-my-zsh"]), ProcessSignaled(6)) [0]

Stacktrace:
 [1] pipeline_error
   @ ./process.jl:565 [inlined]
 [2] run(::Cmd; wait::Bool)
   @ Base ./process.jl:480
 [3] run(::Cmd)
   @ Base ./process.jl:477
 [4] top-level scope
   @ REPL[2]:1