zyedidia / SFML.jl

A binding of the game and multimedia library SFML for Julia
Other
93 stars 22 forks source link

Linux: Show dependencies if they are not installed #6

Closed CarloLucibello closed 9 years ago

CarloLucibello commented 9 years ago

I'm on Linux and I have SFML 2.3 installed, but I cannot run any of the examples since I get errors of the type

libsfml-graphics.so.2.2.0:  cannot open shared object file: No such file or directory.

Also it would be good for SFML.jl to check for library requirements at installation time.

Cheers, and thanks for your work.

zyedidia commented 9 years ago

The reason I have not updated to SFML 2.3 is because of an OpenAL bug they have on Mac. It causes some of the audio features (like recording) not to work.

I don't think SFML.jl should conflict if you already have SFML 2.3 installed (it should install its own version locally). Are you on master or v0.0.8?

Also, I'm not sure what you mean by "library requirements," I didn't think SFML.jl had any. I don't use Linux very much, so could you please elaborate, because it may be a bug on my part.

CarloLucibello commented 9 years ago

I see now that it does not rely on an independent installation of libsfml/libcsfml libraries on the machine (which was what I meant by requirements), but it downloads its own copy, so ok with that.

Even after your last commit though, the problem with dlopen persists.

[carlo@x1 deps]$ julia ../examples/Graphics/square.jl 
/home/carlo/.julia/v0.4/SFML/deps
/home/carlo/.julia/v0.4/SFML/deps/libsfml-graphics
ERROR: InitError: could not load library "/home/carlo/.julia/v0.4/SFML/deps/libcsfml-graphics"
/home/carlo/.julia/v0.4/SFML/deps/libcsfml-graphics: impossibile aprire il file oggetto condiviso: File o directory non esistente
 in dlopen at ./libdl.jl:36
during initialization of module SFML

I did some trials, it appears to be a problem related to relative/absolute paths, in fact:

julia> pwd()
"/home/carlo/.julia/v0.4/SFML/deps"

julia> Libdl.dlopen("libcsfml-graphics.so")
Ptr{Void} @0x00000000017bcc70

julia> Libdl.dlopen("/home/carlo/.julia/v0.4/SFML/deps/libcsfml-graphics.so")
ERROR: could not load library "/home/carlo/.julia/v0.4/SFML/deps/libcsfml-graphics.so"
libsfml-graphics.so.2.2.0: impossibile aprire il file oggetto condiviso: File o directory non esistente
 in dlopen at ./libdl.jl:36

I generated a dummy .so file for testing and both the absolute and relative path version of the dlopen worked, so I am kinda puzzled.

CarloLucibello commented 9 years ago

Also, i tried to substitute Libdl.dlopen("$deps/libsfml-graphics", Libdl.RTLD_GLOBAL) with Libdl.dlopen("libsfml-graphics", Libdl.RTLD_GLOBAL) in SFML.jl and obtained

[carlo@x1 deps]$ julia ../examples/Graphics/square.jl 
/home/carlo/.julia/v0.4/SFML/deps
Something has gone wrong with the SFML installation. Please rebuild.
ErrorException("could not load library \"libsfml-graphics\"\nlibGLEW.so.1.10: impossibile aprire il file oggetto condiviso: File o directory non esistente")
ERROR: LoadError: UndefVarError: libcsfml_graphics not defined
 in call at /home/carlo/.julia/v0.4/SFML/src/julia/Graphics/image.jl:12
 in call at /home/carlo/.julia/v0.4/SFML/src/julia/Graphics/renderWindow.jl:31
 in call at /home/carlo/.julia/v0.4/SFML/src/julia/Graphics/renderWindow.jl:38
while loading /home/carlo/.julia/v0.4/SFML/examples/Graphics/square.jl, in expression starting on line 3

The problem seems to be only posponed here.

zyedidia commented 9 years ago

Hmm, I'm not too sure what's going on here. dlopen seems to behave differently on every operating system. But you said that you were able to load the library if you ran dlopen in the Julia shell from inside the deps folder? That's surprising to me given that it gave you an error later saying it couldn't find libGLEW.

You can get a list of all the dependencies the shared library has with ldd, so try running

$ ldd deps/libsfml-graphics.so

Could you tell me what version of Linux you have?

Also you can try running the commands listed here to install packages. Hopefully this fixes your problem.

CarloLucibello commented 9 years ago

Ok, I tricked it into working.

I am running Arch Linux and have glew 1.12 installed, while SFML requires 1.10. Therefore for the time being I went with

sudo cp /usr/lib/libGLEW.so.1.12 /usr/lib/libGLEW.so.1.10

and used relative paths in SFML.jl

module SFML

import Base: display, isopen, close, reset, copy, launch, start, listen,
       accept, connect, write, send, bind, download, scale, contains,
       +, -, *, /

function __init__()
    old = pwd()
    deps = Pkg.dir("SFML")*"/deps"
    println(deps)
    push!(Libdl.DL_LOAD_PATH, deps)
    try
        @unix_only begin
            cd(deps)
            @osx_only begin
                Libdl.dlopen("freetype.framework/freetype")
                Libdl.dlopen("sndfile.framework/sndfile")
            end
            Libdl.dlopen("libsfml-system", Libdl.RTLD_GLOBAL)
            Libdl.dlopen("libsfml-network", Libdl.RTLD_GLOBAL)
            Libdl.dlopen("libsfml-audio", Libdl.RTLD_GLOBAL)
            Libdl.dlopen("libsfml-window", Libdl.RTLD_GLOBAL)
            Libdl.dlopen("libsfml-graphics", Libdl.RTLD_GLOBAL)
            Libdl.dlopen("libcsfml-system", Libdl.RTLD_GLOBAL)
            Libdl.dlopen("libcsfml-network", Libdl.RTLD_GLOBAL)
            Libdl.dlopen("libcsfml-audio", Libdl.RTLD_GLOBAL)
            Libdl.dlopen("libcsfml-window", Libdl.RTLD_GLOBAL)
            Libdl.dlopen("libcsfml-graphics", Libdl.RTLD_GLOBAL)
            global const libcsfml_system = "libcsfml-system"
            global const libcsfml_audio = "libcsfml-audio"
            global const libcsfml_network = "libcsfml-network"
            global const libcsfml_window = "libcsfml-window"
            global const libcsfml_graphics = "libcsfml-graphics"
        end

        @windows_only begin
            global const libcsfml_system = "csfml-system-2"
            global const libcsfml_audio = "csfml-audio-2"
            global const libcsfml_network = "csfml-network-2"
            global const libcsfml_window = "csfml-window-2"
            global const libcsfml_graphics = "csfml-graphics-2"
        end

        @unix_only begin
            global const libjuliasfml_ptr = Libdl.dlopen("libjuliasfml")
        end
        global const libjuliasfml = "libjuliasfml"
        cd(old)
    catch exception
        println("Something has gone wrong with the SFML installation. Please rebuild.")
        println(exception)
        cd(old)
    end
end

include("julia/System/vector.jl")
include("julia/System/time.jl")
include("julia/System/thread.jl")
include("julia/System/clock.jl")

include("julia/Network/networkStruct.jl")
include("julia/Network/packet.jl")
include("julia/Network/ipAddress.jl")
include("julia/Network/socketStatus.jl")
include("julia/Network/udpSocket.jl")
include("julia/Network/tcpSocket.jl")
include("julia/Network/tcpListener.jl")
include("julia/Network/http.jl")
include("julia/Network/ftp.jl")

include("julia/Audio/soundStatus.jl")
include("julia/Audio/music.jl")
include("julia/Audio/soundBuffer.jl")
include("julia/Audio/sound.jl")
include("julia/Audio/soundBufferRecorder.jl")

include("julia/Graphics/drawable.jl")
include("julia/Graphics/transform.jl")
include("julia/Graphics/blendMode.jl")
include("julia/Graphics/videoMode.jl")
include("julia/Graphics/color.jl")
include("julia/Graphics/image.jl")
include("julia/Graphics/font.jl")
include("julia/Graphics/text.jl")
include("julia/Graphics/rect.jl")
include("julia/Graphics/view.jl")
include("julia/Graphics/types.jl")
include("julia/Graphics/texture.jl")
include("julia/Graphics/shader.jl")
include("julia/Graphics/renderStates.jl")
include("julia/Graphics/sprite.jl")
include("julia/Graphics/convexShape.jl")
include("julia/Graphics/rectangleShape.jl")
include("julia/Graphics/vertexArray.jl")
include("julia/Graphics/circleShape.jl")
include("julia/Graphics/renderTexture.jl")

include("julia/Window/joystick.jl")
include("julia/Window/event.jl")

include("julia/Graphics/renderWindow.jl")
include("julia/Graphics/line.jl")

include("julia/Window/mouse.jl")
include("julia/Window/keyboard.jl")

include("exports.jl")

function make_gif(window::RenderWindow, width, height, duration, filename="sfmlgif.gif", delay=0.06)
    textures = Texture[]
    duration_clock = Clock()
    delay_clock = Clock()

    @async begin
        println("Taking pictures")
        while as_seconds(get_elapsed_time(duration_clock)) <= duration
            sleep(0)
            print("$(round(as_seconds(get_elapsed_time(duration_clock))/duration*100))% done\r")
            if as_seconds(get_elapsed_time(delay_clock)) >= delay
                restart(delay_clock)
                window_size = get_size(window)
                texture = Texture(window_size.x, window_size.y)
                update(texture, window)
                push!(textures, texture)
            end
        end
        make_gif(textures, width, height, filename, delay)
    end
    nothing
end

function make_gif(textures::Array{Texture}, width, height, filename="plot.gif", delay=0.06)
    images = Image[]
    for i = 1:length(textures)
        push!(images, copy_to_image(textures[i]))
    end

    println("Done taking pictures")
    make_gif(images, width, height, filename, delay)
end

function make_gif(images::Array{Image}, width, height, filename="plot.gif", delay=0.06)
    println("Please wait while your gif is made... This may take awhile")
    dir = mktempdir()
    name = filename[1:search(filename, '.')-1]
    imgsize = "$width" * "x" * "$height"

    for i = 1:length(images)
        save_to_file(images[i], "$dir/$name$i.png")
        cmd = `convert $dir/$name$i.png -resize $imgsize\! $dir/$name$i.png`
        run(cmd)
        print("$(round(i/length(images)*100))% done\r")
    end
    println("Assembling gif (this may take awhile)")
    args = reduce(vcat, [[joinpath("$dir", "$name$i.png"), "-delay",
           "$(delay * 100)", "-alpha", "remove"] for i in 1:length(images)])

    imagemagick_cmd = `convert $args $filename`
    run(imagemagick_cmd)
    rm(dir)
    println("Created gif $filename")
end

function screenshot(window::RenderWindow, filename::String)
    screenshot_img = capture(window)
    save_to_file(screenshot, filename)
end

end
CarloLucibello commented 9 years ago

I post this just in case it could be useful

[carlo@x1 deps]$ ldd libsfml-graphics.so 
ldd: attenzione: permessi di esecuzione mancanti per `./libsfml-graphics.so'
    linux-vdso.so.1 (0x00007fff64141000)
    libsfml-window.so.2.2.0 => not found
    libsfml-system.so.2.2.0 => not found
    libGLEW.so.1.10 => /usr/lib/libGLEW.so.1.10 (0x00007fa591b11000)
    libGL.so.1 => /usr/lib/libGL.so.1 (0x00007fa591879000)
    libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x00007fa5915be000)
    libjpeg.so.8 => /usr/lib/libjpeg.so.8 (0x00007fa591365000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fa590fe3000)
    libm.so.6 => /usr/lib/libm.so.6 (0x00007fa590ce5000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fa590acf000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007fa59072b000)
    libX11.so.6 => /usr/lib/libX11.so.6 (0x00007fa5903e9000)
    libexpat.so.1 => /usr/lib/libexpat.so.1 (0x00007fa5901bf000)
    libglapi.so.0 => /usr/lib/libglapi.so.0 (0x00007fa58ff91000)
    libXext.so.6 => /usr/lib/libXext.so.6 (0x00007fa58fd7f000)
    libXdamage.so.1 => /usr/lib/libXdamage.so.1 (0x00007fa58fb7c000)
    libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0x00007fa58f976000)
    libX11-xcb.so.1 => /usr/lib/libX11-xcb.so.1 (0x00007fa58f774000)
    libxcb-glx.so.0 => /usr/lib/libxcb-glx.so.0 (0x00007fa58f55a000)
    libxcb-dri2.so.0 => /usr/lib/libxcb-dri2.so.0 (0x00007fa58f355000)
    libxcb-dri3.so.0 => /usr/lib/libxcb-dri3.so.0 (0x00007fa58f152000)
    libxcb-present.so.0 => /usr/lib/libxcb-present.so.0 (0x00007fa58ef4f000)
    libxcb-randr.so.0 => /usr/lib/libxcb-randr.so.0 (0x00007fa58ed41000)
    libxcb-xfixes.so.0 => /usr/lib/libxcb-xfixes.so.0 (0x00007fa58eb39000)
    libxcb-render.so.0 => /usr/lib/libxcb-render.so.0 (0x00007fa58e92f000)
    libxcb-shape.so.0 => /usr/lib/libxcb-shape.so.0 (0x00007fa58e72b000)
    libxcb-sync.so.1 => /usr/lib/libxcb-sync.so.1 (0x00007fa58e524000)
    libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00007fa58e302000)
    libxshmfence.so.1 => /usr/lib/libxshmfence.so.1 (0x00007fa58e0ff000)
    libXxf86vm.so.1 => /usr/lib/libXxf86vm.so.1 (0x00007fa58def9000)
    libdrm.so.2 => /usr/lib/libdrm.so.2 (0x00007fa58dceb000)
    libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fa58dace000)
    libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fa58d8ca000)
    libz.so.1 => /usr/lib/libz.so.1 (0x00007fa58d6b4000)
    libbz2.so.1.0 => /usr/lib/libbz2.so.1.0 (0x00007fa58d4a4000)
    libpng16.so.16 => /usr/lib/libpng16.so.16 (0x00007fa58d26f000)
    libharfbuzz.so.0 => /usr/lib/libharfbuzz.so.0 (0x00007fa58d010000)
    /usr/lib64/ld-linux-x86-64.so.2 (0x00007fa59200f000)
    libXau.so.6 => /usr/lib/libXau.so.6 (0x00007fa58ce0c000)
    libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007fa58cc06000)
    libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0x00007fa58c8f8000)
    libgraphite2.so.3 => /usr/lib/libgraphite2.so.3 (0x00007fa58c6ca000)
    libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007fa58c45a000)
zyedidia commented 9 years ago

With my most recent commits, SFML.jl will now use relative paths, and will tell you if any libraries from the output of ldd are not found (except the other libsfml libraries). So if you did not have libGLEW.1.10 installed, it would have said on startup:

Could not resolve dependencies:
libGLEW.so.1.10 => not found
zyedidia commented 9 years ago

Please reopen this issue if you still have problems.