Awesome work! I will definitely be checking this out and would be willing to lend a hand (time permitting).
![]()
Thanks, that would be awesome!
I think you should be able to implement change_dir_if_bundle() and handle updating the SDL library paths using @loader_path or @executable_path (see man dyld for more info).
Alternatively, adding your local bundle’s resources path to DYLD_LIBRARY_PATH might fix the SDL library location issue in a more generic fashion (so that even dependencies not using BinDeps.jl should work).
Sadly, I don’t think that is sufficient in this case, at least not without some changes to julia. The problem is that ccall compiles the paths its given directly into the machine code, not using @ paths at all. That means that resultant binary will look for those paths exactly, even if the lib is present in an @ path.
For example:
julia> using SDL2; init() = ccall((:SDL_Init,SDL2.libSDL2), Int32, (Int32,), 0)
>> init (generic function with 1 method)
julia> @code_typed init()
>> CodeInfo(:(begin
SSAValue(0) = (Base.checked_trunc_sint)(Int32, 0)::Int32
return $(Expr(:foreigncall, (:SDL_Init, "/Users/daly/.julia/v0.6/Homebrew/deps/usr/lib/libSDL2.dylib"), Int32, svec(Int32), SSAValue(0), 0))
end))=>Int32
And so unfortunately that string ends up in the binary, in a way that can’t be changed without recompiling.
I’m sure there is a better way to show this, but I found the string using $ hexdump sdl_test.dylib. You can see that the .dylib contains the string literal (scroll right):
...
026b4d50 5f 63 63 61 6c 6c 6c 69 62 5f 2f 55 73 65 72 73 |_ccalllib_/Users|
026b4d60 2f 64 61 6c 79 2f 2e 6a 75 6c 69 61 2f 76 30 2e |/daly/.julia/v0.|
026b4d70 36 2f 48 6f 6d 65 62 72 65 77 2f 64 65 70 73 2f |6/Homebrew/deps/|
026b4d80 75 73 72 2f 6c 69 62 2f 6c 69 62 53 44 4c 32 2e |usr/lib/libSDL2.|
026b4d90 64 79 6c 69 62 00 5f 63 63 61 6c 6c 5f 53 44 4c |dylib._ccall_SDL|
026b4da0 5f 47 4c 5f 53 65 74 41 74 74 72 69 62 75 74 65 |_GL_SetAttribute|
...
And you can see that the .dylib is not recorded as a binary dependency in the normal way:
$ otool -L -v ./sdl_test.dylib
./sdl_test.dylib:
@rpath/sdl_test.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libjulia.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)
So I do change the binary’s @ paths to look inside the binary (here), but you have to also change the code to use relative paths so it will look in the @ paths.
And it’s even harder for Blink, since it’s opening file resources through an absolute path, not calling a unix-style dll (As one example, it opens Electron.app, which was renamed to Julia.app when installing Blink).
So sadly I don’t think that would work. That said, you did make me think that maybe this could be somewhat automated by overriding or modifying BinDeps.jl, so that it produces relative paths when being compiled ApplicationBuilder.jl! That way the user wouldn’t have to make this change themselves… It would only work for dependencies using BinDeps (so not Blink files, for example), but it could make it easier in some cases! I’ve opened an issue for that idea here: