Question about .so files, their location and naming conventions

Started by
5 comments, last by KnolanCross 10 years, 2 months ago

Hi,

I have a small app in Ubuntu 13.10 which just inits SDL2 ,checks for errors, deinits it and quits, to test my SDL2 installation. I did the normal configure, make, make install thing and it seems to have placed the file libSDL2-2.0.so.0 in /usr/local/lib and the headers in usr/local/include/SDL2.

All over the web I have seen people posting things about SDL2 and mentioning the paths /usr/lib and /usr/include/SDL2, ie. the paths I mentioned but without the local subfolder. Is there a specific convention on what is supposed to be placed where, and in that case, which one is the correct place for SDL2?

My next question is about the end user's setup. If I make a game using SDL2 and distribute it in binary form, how does it know where to find SDL2 on the end user's machine? When linking to the SDL2 library I put the following line in my Qt creator project file:

LIBS += -L /usr/local/lib -lSDL2

I guess that -lSDL2 is what tells the linker to link against the SDL library, but how does it know where to actually find the library? As a long time windows developer, I am used to DLLs and linker libraries, and I usually just put the DLLs next to the EXEs.

After I built SDL2 I actually got an error when running my app. I cannot remember the exact line but it was complaining about not being able to find the file "libSDL2-2.0.so.0". I restarted my Linux machine and it started working. The questions is; how did it know to look for the file "libSDL2-2.0.so.0"? I have not (to my knowledge) specified that exact file name anywhere. The final question is; what does that ".0" at the end mean?

Thanks a lot for your help!

Advertisement

When, this is more a build question than a programming one.

Anyway, AFAIK ubuntu will look for libraries at /usr/lib or at the running path. You may specify other places to look for libraries with -L<path> in the Makefile or by setting the LD_LIBRARY_PATH in your env (be careful not to override the custom settings).

The problem you had with the library not being seem is probably because you didn't run ldconfig after instaling new libraries.

For the distributable version you can place the needed shared objects in your project and compile your code with -Wl,-rpath=<path>, this should make the OS look for the library in the right path. I would advise against it otherwise you will need to have multiple distributables for different archs.

On the naming, mostly when you install a library it will install the actual file "libSDL2-2.0.so.0" and create links for libSDL2-2.0.so and libSDL2.so (both pointing to libSDL2-2.0.so.0). This happens because if you update the library, it will keep the original file, but the links will be recreated and will point to the most updated version and use it instead. The advantage of this system is that you can fallback to an older version by simply recreating the links.

I am not an expert on builds, but I hope this helps.

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

Cheers, that helps a lot.

I did not know about ldconfig and -WI,-rpath. Need to look into those. I have read the line "I would advise against it otherwise you will need to have multiple distributables for different archs." many times but I am still not sure what you mean :) Perhaps there was some punctuation lost or something? Is your advice to use -rpath or not?

have a small app in Ubuntu 13.10 which just inits SDL2 ,checks for errors, deinits it and quits, to test my SDL2 installation. I did the normal configure, make, make install thing and it seems to have placed the file libSDL2-2.0.so.0 in /usr/local/lib and the headers in usr/local/include/SDL2.

All over the web I have seen people posting things about SDL2 and mentioning the paths /usr/lib and /usr/include/SDL2, ie. the paths I mentioned but without the local subfolder. Is there a specific convention on what is supposed to be placed where, and in that case, which one is the correct place for SDL2?

SDL2 uses the autotools for building on POSIX systems like Ubuntu. The autotools will set $libdir to /usr/local/ by default, which is the conventional place for local-only system libraries on most POSIX systems, including most GNU/Linux distributions. The conventional place for packaged and distributed libraries is /usr/lib according to the FHS (filesystem heirarchy standard), a convention followed by many GNU/Linux distributions, which is why you see references to it on the Internet. On Debian-based systems, including Ubuntu, the convention is /usr/lib/$triple, where $triple is something like x86_64-linux-gnu for a 64-bit x86 system -- this allows multi-arch installations, since some non-free software bundles 32-bit-only blobs.

If you want to build your custom SDL2 libraries to follow the Ubuntu convention, you need to specify the installation path at configure time. For example, use this command to configure for building.


 ./configure --libdir=/usr/lib/x86_64-linux-gnu

When you install (sudo make install) your shared objects will be installed in the place found automatically by the runtime link-loader (ld.so) without having to do a fancy dance with ldconfig, LD_LIBRARY_PATH, or rpath.

Of course, this raises the question: why are you building your own SDL2 from source when it's already packaged, tested, and supported in the Ubuntu 13.10 archives?

Stephen M. Webb
Professional Free Software Developer

My next question is about the end user's setup. If I make a game using SDL2 and distribute it in binary form, how does it know where to find SDL2 on the end user's machine? When linking to the SDL2 library I put the following line in my Qt creator project file:

LIBS += -L /usr/local/lib -lSDL2

I guess that -lSDL2 is what tells the linker to link against the SDL library, but how does it know where to actually find the library? As a long time windows developer, I am used to DLLs and linker libraries, and I usually just put the DLLs next to the EXEs.

When you link your program, the linker remembers all of the DSOs (shared libraries) used to resolve external symbols. In your case, it used the DSO search path (-L/usr/local/lib) and the library name (-lSDL2 means libSDL2.so) to find libSDL2.so, which is a soft link to /usr/local/lib/libSDL2-2.0.so.0.1.1 (or something like that). It opens that file and reads a tag from the DYNAMIC header of type SONAME, which would contain the string libSDL2-2.0.so.0. The linker emits that string as a tag of type NEEDED into the DSO it's building. A DSO could be a shared library or an executable, they work the same in ELF systems.

At runtime when the dynamic link-loader (as determined by the INTERP tag, on my systems it's /lib64/ld-linux-x86-64.so.2) loads the program and tries to resolve external symbols, it reads all the NEEDED tags and looks for files that satisfy them through a set of configured search paths. the configuration is done through a program called ldconfig, which reads a set of configuration files in /etc/ld.conf.d and the file ld.so.conf and writes the results out to the file ld.so.cache. That list of libraries is augmented by the environment variable LD_LIBRARY_PATH. Those sources are search in order until a matching filename is loaded or the startup fails.

So, to summarize: when a shared library is built, it gets a special tag added called its SONAME. When something is built against that library, the SONAME is saved in that something as a NEEDED tag. When the time comes to resolve runtime dependencies in that something, the NEEDED tags are matched against a set of directories to find the original libraries (or a replacement).

The -rpath embeds a specific path into the final executable. It's not a good idea to use it for anything except private libraries (eg. plugins).

Stephen M. Webb
Professional Free Software Developer

Excellent description Bregma, much appreciated!

This sheds light on the concept (as well as opens up new questions), but at least now I know that to google for, so thank you :)

The rpath will be put in the executable to search at an specific place for a specific library. You can create a folder with the needed libraries and link them with rpath, then distribute your game with the libraries.

The problem I was refering to is that if you link this way, you will need to consider that your game must run on a 64 bits or a 32 bits OS and produce different versions of each library for each arch.

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

This topic is closed to new replies.

Advertisement