-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Libdl.dlopen
doesn't find shared libraries anymore
#26557
Comments
Yes, you should either (1) use BinDeps (2) specify the name of the correct library version (3) install the |
Seems likely to be due to #22828. |
Reopening because I think this is the canary in the coal mine and we're going to get a lot of people hitting this problem with no clue what to do and there should be some better way of helping them. |
Yeah, I didn't spot anything in NEWS.md about the behaviour change and didn't find anything relevant in a quick search through the PR's and issues. I suspect a lot of package breakage will occur because of this (This example comes from CodecZlib in fact..) and documented alternatives will be very helpful. |
Out of curiousity, why does installing the header files (eg. libz-dev / libz-devel in this case) fix this issue? |
It seems like many of the examples of julia> t = ccall((:clock, "libc"), Int32, ())
ERROR: error compiling top-level scope: could not load library "libc"
/usr/bin/../lib64/libc.so: invalid ELF header
Stacktrace:
[1] macro expansion at /builddir/build/BUILD/julia/build/usr/share/julia/site/v0.7/REPL/src/REPL.jl:117 [inlined]
[2] (::getfield(REPL, Symbol("##28#29")){REPL.REPLBackend})() at ./event.jl:92
julia> t = ccall((:clock, "/usr/lib64/libc.so.6"), Int32, ())
2667541 |
This is a breaking change and should have a deprecation to let people know what they should do. |
Not very many. |
This not only needs docs and NEWS, I really think we should not be just breaking this but providing a proper deprecation. We'll see how it goes but I think this just the first of many complaints we'll see. |
Reading through the linked PR, I disagree that this should have been merged. Yes, there are reasons for wanting to encourage users to use versioned library names when opening them, but we don't force users to specify a major and minor version number of a Julia package when they load it, we just load the latest available and provide the option (through |
That's not what the option did on the majority of platforms / configurations. Instead, we had to explain how it worked on some distributions in ideal circumstances (aka, pretty much just zlib), then explain that if that didn't work for whatever reasons, you should have actually just specified the actual version of the library you wanted in the first place, which would have simply worked on all platforms in the first place. That's also not how package resolution works. We don't just randomly upgrade all of the packages, we explicit list which ones are compatible, and then ensure that the currently visible and enumerable environment is consistent and restricted to the versions that are specified in the local manifest. That's also how our build works now that the linked PR is merged (it creates folders mapping out the currently visible environment and searches that for the requested name). |
That's exactly what we do in Pkg2 😂 |
@vtjnash could you live with the old behaviour being back in the code base if it was well documented that its a bad approach for maintaining binary dependencies? It seems like it was removed in hopes of encouraging better behaviour from package developers, but maybe some documentation could achieve the same result. |
I don't think that writing documentation about how not to do something is particularly advisable. I prefer we don't do it and instead explain up front how to write examples and code that'll work with all platforms. |
For package development, I completely agree. Is it unreasonable to expect that people that aren't package developers are going to be using the C FFI though? Its seems strange that the barrier to entry to the C FFI should be higher than compiling a similar C program. Compare the following for instance: Compiling a C program with libm $ gcc prog.c -o main -lm Calling libm from Julia 0.7.x out = ccall((:sin, "libm.so.6"), Float64, (Float64,), 1.0) Shouldn't Julia have the same basic level of convenience as GCC? |
If we're going to talk about how you would write this in C, why not write it like we're using C and drop the library name. This works on all versions of Julia: ccall(:sin, Float64, (Float64,), 1.0) We can add additional entries to the list of libraries that we want to be visible to packages by default ( Line 175 in 17e9abf
|
In package loading, I just say Regarding @nsmith5's point above, there's actually an important difference as GCC is providing compile-time guarantees here; it compiles against version
Because that doesn't work in the general case? We're not going to symlink a random |
We had a test for it. Not a very good one, but it failed CI pretty frequently anyways, so it was setup internally to return success whenever it failed (specifically, this test https://github.com/JuliaLang/julia/pull/26581/files#diff-bf20429d6316882a26470433941b41c5R204) |
Er, are you not the same staticfloat that's building a package for linking a random libfoo into our library search path in preparation for handling this better in conjunction with Pkg3 :). Reference: the script for testing the installation of an actual libfoo into the library search path: https://github.com/JuliaPackaging/BinaryProvider.jl/tree/e9dd1a8f39ba6ede973165512788cfa374ad7bf6/test/LibFoo.jl/deps |
Is this an argument against the feature or the implementation? I mention the C compiler because the feature is evident. I can understand if our implementation is currently wanting, but is there some technical reason we won't ever be able to implement it properly? |
In this context, isn't "the C compiler + linker + autoconf scripts" == "the BinDeps.jl compiler"? Like the existing meta-build systems for C, I think we've found it's more reliable to run these as a part of the build process, where it is able to run arbitrary user code, cause side-effects, and provide useful debugging information. |
No, in this context the feature set would be just "linker + loader". No autoconf. Its not about being cross platform or reliable. Its a brittle approach to using a C library, but it is very simple. The point I'm making with the C example is that the combined behaviour of the linker, loader and environment (LD_LIBRARY_PATH) hide the details of the library version you're using and where it is on your system. I think that we need the C FFI to have the same feature set. It is the entry point to C programming and it should be the entry point to using the C FFI in Julia. |
Why? Does anyone else do this? What "feature set" are we talking about here? If you just want to make this a feature of the REPL, that's an entirely different question. |
Hmm, sorry about the lack of clarity. Lets establish some more clear language: Lets say that a feature is some bit of code in the Julia landscape that provides some functionality. In your example the BinDep.jl compiler feature provides the functionality of "C Compiler + Linker + Autoconf Scripts". I think there is a demand for the functionality of "Linker + Loader" in the C FFI. To be clear about what that functionality is, you provide,
and the "Linker + Loader" find a valid version of that library and makes calls to the member function you specified. I think the Julia C FFI is the feature that should be providing this functionality. Specifically, Here is a more detailed example of simple C program and equivalent C FFI call in Julia. I've pointed out the functionality I'm talking about in each case. 1.) C Examplefoo.hint foo(int, int); main.c#include <foo.h>
void main() {
int a, b, c;
b = 1;
c = 2;
a = foo(b, c); // Just specify a function name
return
} compile and run$ gcc main.c -lfoo # <-- Just specify a library name
$ ./a.out # <-- works because the linker and loader deal with the details 2.) Julia Examplecompile and runjulia> c = ccall((:foo, "libfoo"), Int, (Int, Int), 1, 2) # <-- This should work as well. I've specified a function name and library name and I want ccall and dlopen deal with the details. Does that help clarify? |
No, it doesn't. Why does the C example require 2 steps (the header file is extraneous), but the Julia example requires doing it in 1 step to achieve "equivalent functionality". |
Julia is at least twice as convenient as C. |
While that's a nice thought, it's worth pointing out that the distribution you are choosing to use is going out of its way to make sure that |
FWIW |
Ok. So let's compare to Python then. Outside of performance, our competition is not (primarily) C. https://docs.python.org/3/library/ctypes.html#finding-shared-libraries
|
@vtjnash I am very sorry. I wouldn't want you to feel like you're being ganged up on. It looks like your opinion in the minority on this topic, but its far from unwelcome in my perspective. In fact, I'd like to know at lot more, because it seems like you have a heap of expertise in this area. Speaking of which, whats the distribution issue you mentioned? Is this problem only faced by Redhat based distros? I'm happy to try to lobby them for a change if it makes our lives easier. |
Having a |
I could definitely get on board with having a |
Also on board with that. In fact |
It could also have a |
I would be happy with a |
The documentation problem that the very first
|
Libdl.dlopen
doesn't seem to be able to find shared libraries the way it did on 0.6.xOn Julia 0.6.x
On Julia 0.7.x-DEV
As you can see, it works once I specify the exact name of the shared library, but not before then.
Other Details
The text was updated successfully, but these errors were encountered: