Dynamic link locally

Hello all. I’m fairly new to Linux development. So far I’ve been linking static to the SDL2 library, which works great, but I’ve decided to play nice and try linking to a shared lib instead now.

On Windows, I’m accustomed to building a shared library (dll), dropping the library’s dll in my project folder next to the executable, and it just works. This doesn’t appear to be the case for Linux. When I build SDL2 as a shared lib, my program either doesn’t see it, or ignores it and tries to use whatever copy is “installed” on the system.

What do I need to do (either when building SDL2 or when building my project) to get it to use a local copy of a shared lib when it runs? I’ve seen references to changing rpath or LD_LIBRARY_PATH, but they seem to be “during development” things and not “end-user’s computer” things.

My goal is to be able to give someone a copy of my game and have it be self-contained and just work (like you get when you static link the libraries), rather than making sure they have required libraries installed on their system first.

2014-03-22 5:12 GMT+01:00 Nairou :

Hello all. I’m fairly new to Linux development. So far I’ve been linking
static to the SDL2 library, which works great, but I’ve decided to play
nice and try linking to a shared lib instead now.

On Windows, I’m accustomed to building a shared library (dll), dropping
the library’s dll in my project folder next to the executable, and it just
works. This doesn’t appear to be the case for Linux. When I build SDL2 as a
shared lib, my program either doesn’t see it, or ignores it and tries to
use whatever copy is “installed” on the system.

What do I need to do (either when building SDL2 or when building my
project) to get it to use a local copy of a shared lib when it runs? I’ve
seen references to changing rpath or LD_LIBRARY_PATH, but they seem to be
"during development" things and not “end-user’s computer” things.

My goal is to be able to give someone a copy of my game and have it be
self-contained and just work (like you get when you static link the
libraries), rather than making sure they have required libraries installed
on their system first.

If you want it to be “self-contained”, why did you decide to not statically
link?

In any case, to get a similar behavior as on windows, build the executable
with the rpath “$ORIGIN”.

Statically linking SDL on Linux sucks, because you never know which
obscure sound system your users are going to use (or even going to use
in 5 years), so giving the user the possibility to replace the bundled
libSDL2.so.* is the Right Thing To Do.
(In the past this made it possible to play old Loki ports and similar on
newer distributions by replacing the libSDL with something more recent).

Cheers,
DanielAm 22.03.2014 17:56, schrieb Jonas Kulla:

If you want it to be “self-contained”, why did you decide to not
statically link?

2014-03-22 18:09 GMT+01:00 Daniel Gibson :> Am 22.03.2014 17:56, schrieb Jonas Kulla:

If you want it to be “self-contained”, why did you decide to not
statically link?

Statically linking SDL on Linux sucks, because you never know which
obscure sound system your users are going to use (or even going to use in 5
years), so giving the user the possibility to replace the bundled
libSDL2.so.* is the Right Thing To Do.
(In the past this made it possible to play old Loki ports and similar on
newer distributions by replacing the libSDL with something more recent).

Sure, if you’re shipping a commercial product, that’s the way to go. I
assumed he just wanted
to quickly let his friends try out a work-in-progress application.

When linking, make sure ‘-Wl,-path,$ORIGIN’ is on the command line.

And try “readelf -d ./MyExeName” to make sure it worked. The ‘$’ confuses things in some build systems.

rpath $ORIGIN tells the system loader “look for shared libraries in the same directory as this binary.”

I use this on shipping games.

–ryan.> On Mar 22, 2014, at 0:12, “Nairou” wrote:

Hello all. I’m fairly new to Linux development. So far I’ve been linking static to the SDL2 library, which works great, but I’ve decided to play nice and try linking to a shared lib instead now.

On Windows, I’m accustomed to building a shared library (dll), dropping the library’s dll in my project folder next to the executable, and it just works. This doesn’t appear to be the case for Linux. When I build SDL2 as a shared lib, my program either doesn’t see it, or ignores it and tries to use whatever copy is “installed” on the system.

What do I need to do (either when building SDL2 or when building my project) to get it to use a local copy of a shared lib when it runs? I’ve seen references to changing rpath or LD_LIBRARY_PATH, but they seem to be “during development” things and not “end-user’s computer” things.

My goal is to be able to give someone a copy of my game and have it be self-contained and just work (like you get when you static link the libraries), rather than making sure they have required libraries installed on their system first.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

(stupid autocorrect!)

That should read ‘-Wl,-rpath,$ORIGIN’ … the original email said
’-path’, not ‘-rpath’.

–ryan.On 03/22/2014 06:05 PM, Ryan C. Gordon wrote:

When linking, make sure ‘-Wl,-path,$ORIGIN’ is on the command line.

Awesome, thanks!

I finally had a chance to test this out, and I’m still not getting it to find the shared library file:

Code:
[nairou at kharik stage]$ ls -la
total 13572
drwxr-xr-x 3 nairou users 4096 Mar 31 15:08 .
drwxr-xr-x 6 nairou users 4096 Mar 31 15:07 …
drwxr-xr-x 2 nairou users 4096 Mar 31 13:23 data
-rwxr-xr-x 1 nairou users 6854944 Mar 31 15:08 game
-rwxr-xr-x 1 nairou users 6159744 Mar 31 15:03 libSDL2-2.0.so.0
lrwxrwxrwx 1 nairou users 16 Mar 31 15:06 libSDL2.so -> libSDL2-2.0.so.0
-rw-r–r-- 1 nairou users 1225 Mar 31 14:38 log.html
[nairou at kharik stage]$ ./game
./game: error while loading shared libraries: libSDL2-2.0.so.0: cannot open shared object file: No such file or directory

Here’s the line from readelf:

Code:
Dynamic section at offset 0x1410c8 contains 31 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libSDL2-2.0.so.0]

And from ldd:

Code:
libSDL2-2.0.so.0 => not found

For confirmation, here’s the rpath flag in my makefile:

Code:
CFLAGS += $(CPPFLAGS) $(ARCH) -Wall -g -std=c++11 -Wno-unused-local-typedefs -Wl,-rpath,$ORIGIN

Any further idea on what I’m not doing right? Does it matter that the build directory and the binary destination (stage) directory are different (I’m not running make from the same folder that the executable ends up in)? Does the compiler need to be able to find the .so file at link time, or is it completely deferred to run time?

2014-03-31 21:22 GMT+02:00 Nairou :

I finally had a chance to test this out, and I’m still not getting it to
find the shared library file:

Code:

[nairou at kharik stage]$ ls -la
total 13572
drwxr-xr-x 3 nairou users 4096 Mar 31 15:08 .
drwxr-xr-x 6 nairou users 4096 Mar 31 15:07 …
drwxr-xr-x 2 nairou users 4096 Mar 31 13:23 data
-rwxr-xr-x 1 nairou users 6854944 Mar 31 15:08 game
-rwxr-xr-x 1 nairou users 6159744 Mar 31 15:03 libSDL2-2.0.so.0
lrwxrwxrwx 1 nairou users 16 Mar 31 15:06 libSDL2.so ->
libSDL2-2.0.so.0
-rw-r–r-- 1 nairou users 1225 Mar 31 14:38 log.html
[nairou at kharik stage]$ ./game
./game: error while loading shared libraries: libSDL2-2.0.so.0: cannot
open shared object file: No such file or directory

Here’s the line from readelf:

Code:

Dynamic section at offset 0x1410c8 contains 31 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libSDL2-2.0.so.0]

And from ldd:

Code:

libSDL2-2.0.so.0 => not found

For confirmation, here’s the rpath flag in my makefile:

Code:

CFLAGS += $(CPPFLAGS) $(ARCH) -Wall -g -std=c++11
-Wno-unused-local-typedefs -Wl,-rpath,$ORIGIN

Any further idea on what I’m not doing right? Does it matter that the
build directory and the binary destination (stage) directory are different
(I’m not running make from the same folder that the executable ends up in)?
Does the compiler need to be able to find the .so file at link time, or is
it completely deferred to run time?

Verify the rpath entry in your exe by running

readelf -d game | grep rpath

Jonas Kulla wrote:

Verify the rpath entry in your exe by running

readelf -d game | grep rpath

Ahh. I get nothing, no mention of rpath.

2014-03-31 21:44 GMT+02:00 Nairou :

Jonas Kulla wrote:

Verify the rpath entry in your exe by running

readelf -d game | grep rpath

Ahh. I get nothing, no mention of rpath.

Can you try compiling again, with this argument form:

-Wl,-rpath,$ORIGIN

(backslash added in front of ‘$’)

Okay, after editing my makefile to specify the rpath in LDFLAGS instead of CFLAGS, it shows up. However it doesn’t look right (and still doesn’t work):

[nairou at kharik stage]$ readelf -d ./game | grep rpath
0x000000000000000f (RPATH) Library rpath: [RIGIN]

I tried adding a backslash in front ($ORIGIN), but I got the same result…

Try something like:
-Wl,-rpath,’$$ORIGIN’
(in ‘’ and two $$) - at least that worked for me in a normal Makefile
you may also have to add -Wl,-z,origin before the other thing to tell
the linker you’re gonna use $ORIGIN

Cheers,
DanielAm 31.03.2014 22:04, schrieb Nairou:

Okay, after editing my makefile to specify the rpath in LDFLAGS instead
of CFLAGS, it shows up. However it doesn’t look right (and still doesn’t
work):

[nairou at kharik stage]$ readelf -d ./game | grep rpath
0x000000000000000f (RPATH) Library rpath: [RIGIN]

I tried adding a backslash in front ($ORIGIN), but I got the same result…


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Daniel Gibson wrote:

Try something like:
-Wl,-rpath,’$$ORIGIN’
(in ‘’ and two $$) - at least that worked for me in a normal Makefile
you may also have to add -Wl,-z,origin before the other thing to tell
the linker you’re gonna use $ORIGIN

Great! Double $$ in quotes did the trick. Thanks!

Caleb