JuliaPackaging / BinaryBuilder.jl

Binary Dependency Builder for Julia
https://binarybuilder.org
Other
391 stars 99 forks source link

Use of _jll on Alpine / linux-musl. #1320

Closed grasph closed 6 months ago

grasph commented 6 months ago

Hello,

I've observed the following issue with Alpine when testing a binary package I produced.

Philippe.

Issue summary

Fails to install BinaryBuilder on Alpine Linux and more generally a package with two or more levels of _jll dependencies.

Reproducing the issue

ZMQ is the first package that fails to precompile in the BinaryBuilder dependency chain, so in the example below we just install ZMQ. The Julia docker image for Alpine linux can be used for the test.

$ docker run -it --rm julia:alpine sh
$ julia
julia> ]
pkg> add ZMQ

Precompiling project...
  ✗ ZMQ
  4 dependencies successfully precompiled in 3 seconds. 1 already precompiled.
  1 dependency errored.
  For a report of the errors see `julia> err`. To retry use `pkg> precompile`

pkg> precompile
Precompiling project...
  ✗ ZMQ
  0 dependencies successfully precompiled in 1 seconds. 5 already precompiled.

ERROR: The following 1 direct dependency failed to precompile:
ZMQ [c2297ded-f4af-51ae-bb23-16f91089e4e1]

Failed to precompile ZMQ [c2297ded-f4af-51ae-bb23-16f91089e4e1] to "/root/.julia/compiled/v1.10/ZMQ/jl_gIdfoD".
ERROR: LoadError: InitError: could not load library "/root/.julia/artifacts/f76461361541d6b33f20b7189a030375b94795bf/lib/libzmq.so"
Error loading shared library libsodium.so.23: No such file or directory (needed by /root/.julia/artifacts/f76461361541d6b33f20b7189a030375b94795bf/lib/libzmq.so)
Stacktrace:
``` [1] dlopen(s::String, flags::UInt32; throw_error::Bool) @ Base.Libc.Libdl ./libdl.jl:117 [2] dlopen(s::String, flags::UInt32) @ Base.Libc.Libdl ./libdl.jl:116 [3] macro expansion @ ~/.julia/packages/JLLWrappers/pG9bm/src/products/library_generators.jl:63 [inlined] [4] __init__ @ ~/.julia/packages/ZeroMQ_jll/qEoK6/src/wrappers/x86_64-linux-musl-cxx11.jl:9 [5] run_module_init(mod::Module, i::Int64) @ Base ./loading.jl:1134 [6] register_restored_modules(sv::Core.SimpleVector, pkg::Base.PkgId, path::String) @ Base ./loading.jl:1122 [7] _include_from_serialized(pkg::Base.PkgId, path::String, ocachepath::String, depmods::Vector{Any}) @ Base ./loading.jl:1067 [8] _require_search_from_serialized(pkg::Base.PkgId, sourcepath::String, build_id::UInt128) @ Base ./loading.jl:1581 [9] _require(pkg::Base.PkgId, env::String) @ Base ./loading.jl:1938 [10] __require_prelocked(uuidkey::Base.PkgId, env::String) @ Base ./loading.jl:1812 [11] #invoke_in_world#3 @ ./essentials.jl:926 [inlined] [12] invoke_in_world @ ./essentials.jl:923 [inlined] [13] _require_prelocked(uuidkey::Base.PkgId, env::String) @ Base ./loading.jl:1803 [14] macro expansion @ ./loading.jl:1790 [inlined] [15] macro expansion @ ./lock.jl:267 [inlined] [16] __require(into::Module, mod::Symbol) @ Base ./loading.jl:1753 [17] #invoke_in_world#3 @ ./essentials.jl:926 [inlined] [18] invoke_in_world @ ./essentials.jl:923 [inlined] [19] require(into::Module, mod::Symbol) @ Base ./loading.jl:1746 [20] include @ ./Base.jl:495 [inlined] [21] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt128}}, source::Nothing) @ Base ./loading.jl:2222 [22] top-level scope @ stdin:3 during initialization of module ZeroMQ_jll in expression starting at /root/.julia/packages/ZMQ/lrABE/src/ZMQ.jl:3 in expression starting at stdin: ```

If the path to libsodium.so.23 is added to the linker search paths, then the precompilation succeeds:

pkg> <CONTROL-D>
$ LD_LIBRARY_PATH=/root/.julia/artifacts/a61d6c438960fc6e2ca699758c0647acef4c9e1d/lib julia
julia>]
pkg> precompile

Precompiling project...
  1 dependency successfully precompiled in 2 seconds. 5 already precompiled.

Not specific to the docker image

Tested with qemu and alpine 3.19 standard x86_64 iso image and same observation.

Further investigations:

The following works on glibc-based distributions (validated on Devuan), but not on Alpine.

$ julia
julia> using Libdl
julia> dlopen("/root/.julia/artifacts/a61d6c438960fc6e2ca699758c0647acef4c9e1d/lib/libsodium.so")
Ptr{Nothing} @0x00007f24055b20b0

julia> dlopen("/root/.julia/artifacts/f76461361541d6b33f20b7189a030375b94795bf/lib/libzmq.so")
ERROR: could not load library "/root/.julia/artifacts/f76461361541d6b33f20b7189a030375b94795bf/lib/libzmq.so
Error loading shared library libsodium.so.23: No such file or directory (needed by /root/.julia/artifacts/f76461361541d6b33f20b7189a030375b94795bf/lib/libzmq.so)
[...]

It looks for the library file although it was dlopen'ed beforehand.

giordano commented 6 months ago

I believe you're observing https://github.com/JuliaLang/julia/issues/40556, can't do much about it here.

grasph commented 6 months ago

Thanks for the link. I was expecting the problem was already observed but I hadn't found any report.

One solution is to maintain a directory with links to libraries of all installed _jll.

If supporting installation of _jll sharing libraries with same name is needed, then the directory can contain links to the different artifact directories: we only need the relative paths between the libraries to be fixed, such that rpath can be used (with $ORIGIN). This would also save the need of long LD_LIBRARY_PATH to run _jll executables.

Philippe.

grasph commented 6 months ago

Closed as duplicate of JuliaLang/julia#40556