Skip to main content
GameDev.net gamedev.net
🔒 Locked

Runtime linking shared objects

Started by Lord_Evil Oct 14, 2008 at 4:34 PM 16 replies 5.6k views
Original Post
Lord_Evil
Lord_Evil
Hi there, I recently started to port my engine from Windows to Linux using Eclipse CDT. However, I have a problem linking/finding the shared objects at runtime. I know I could install the *.so files to /usr/lib but to do that I need root rights and that's something I'd like to avoid. In CDT I can enter post-build commands like "install /usr/lib" but as stated I need root rights, so the call fails. What I'd like to have is: - shared object files in the directory of the executable or a subdirectory (e.g. "lib") - build time linking (avoid dlopen() and the like for core libraries) For a first test I have the following setup: workspace/FileSystem/Debug/libFileSystem.so workspace/Test/Debug/Test (binary) That results in libFileSystem.so no being found at runtime. The setup I'd prefer (binary should be able to find the shared object in relative path "./lib/": workspace/Test/Debug/lib/libFileSystem.so workspace/Test/Debug/Test (binary) Can I do this? How? Thanks in advance. Thomas
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
Null and Void
Null and Void
Not that I'd encourage either solution, but you should probably look into setting either LD_LIBRARY_PATH (set inside a script pre-execution, say) or an RPATH.
Lord_Evil
Lord_Evil
Thanks, I will look into this.

Why solution would you suggest?
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
Yann L
Yann L
Installing into /usr/lib or similar is unacceptable for obvious reasons.

So we use an rpath, and it works very well.
Lord_Evil
Lord_Evil
Quote:

From the wiki article:
The primary disadvantage of using RPATH is that it overrides the LD_LIBRARY_PATH settings which makes things like running a precompiled binary out of a user's home directory or some other non-default location difficult or impossible. Use of RPATH also makes it difficult, if not impossible, to upgrade libraries without forcing a reinstallation of all the software dependent on (even the older versions of) the libraries (see RPATH considered harmful).

I'd like to be independent from the installation directory, so an rpath doesn't seem to be that good a solution.

With LD_LIBRARY_PATH it seems to be possible to set the path at startup and restore the previous path at tear down.
However, I think simultaneously running applications could cause problems.

What do you think?
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
Yann L
Yann L
Quote:
Original post by Lord_Evil
I'd like to be independent from the installation directory, so an rpath doesn't seem to be that good a solution.

The wiki article is incorrect. If you supply '$ORIGIN' as an rpath (through the -R option when linking, ie. -R'$ORIGIN'), it will search the directory where the executable resides in for libraries. This is done at runtime, so it doesn't matter where the user installs your software.

Quote:

Use of RPATH also makes it difficult, if not impossible, to upgrade libraries without forcing a reinstallation of all the software dependent on (even the older versions of) the libraries (see RPATH considered harmful).

This is an advantage, and fully intended behaviour. You wouldn't want anybody except yourself to modify and/or replace the libraries of your engine.
niteice
niteice
I do it like so:

1) Build application and libraries with no mutual knowledge of the other existing outside of shared header files.
2) Manually place libraries into an easily locatable directory (i.e. data/lib/linux-amd64)
3) At runtime:
a) Get the current directory (i.e. /home/niteice/oe)
b) Concatenate the expected directory (i.e. data/lib/linux-amd64) to the current directory (you now have /home/niteice/oe/data/lib/linux-amd64)
c) Concatenate the library you want (i.e. renderer.so) to the path (you now have /home/niteice/oe/data/lib/linux-amd64/renderer.so)
4) Open the library and get pointers to the functions you want

Quite easy to implement and platform-transparent to boot.
Lord_Evil
Lord_Evil
Thank you for your advice guys, I'll look into that.

Yann, your suggestion seems to be what I want. Would the following be possible: -R'$ORIGIN/lib' for searching the libraries in the lib directory?

Niteice, that's what I'd do for plugins but not for the core functionality of my engine. I don't want to get the pointers to functions and class members one by one for use within my engine.

Basically I have mulitple libraries that contain the several subsystems of the engine, like render system, sound system, geometry 'builders' (e.g. a terrain library), file system, physics system etc. Each provides a defined interface and thus might be replaced, e.g. the physics system using either PhysX, ODE or another library. The application will "plug" the different subsystems into the engine as needed (e.g. if you don't need sound, you don't link the sound library into your application).

Additionally I'd like to provide real plugin capabilities, e.g. for adding file codecs, non-scripted ai functionality etc.

So I think I'll use rpaths for the main systems and really dynamic linking (dopen(), ...) for the plugin framework.
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
Yann L
Yann L
niteice's suggestion is the way to go for entirely dynamic linking, ie. plugins, as you mentioned. However, this doesn't work very well with C++ class linking, and it doesn't work with implicit linking.

Quote:

Would the following be possible: -R'$ORIGIN/lib' for searching the libraries in the lib directory?

It should, but I don't know if it does in practice. I'm not really sure who is responsible for parsing the $ORIGIN macro. I would guess the implicit runtime linker, but I'm not sure. I'm also not certain how sophisticated that parsing is.

The problem with rpath is that its implementation is very hackish. The whole concept is very alien to the common Linux open source folks, because it promotes proprietary libraries that are locked to a certain application. For us, this is exactly what we're looking for. Bur for most FOSS people, this is against their ideology. That's why this rpath mechanism is often considered evil (don't worry, it's not) and doesn't get the attention it should from the maintainers of the linking subsystem.

Now, you could simply supply the current directory in the rpath: '.' or './libs'. However, this will add the directory the user is currently in when he launches your app, and not the directory where the app is located. It works as long as the user always launches your app from its own directory (eg. "./mygame") but not if he is somewhere else (eg. "./coolgame/mygame"). It will also introduce security issues, because it can allow an attacker to perform a type of DLL-injection on system libraries, possibly using your software to gain root privileges. Not good. As I said, the whole thing wasn't very well thought out.

The $ORIGIN feature was hacked in to address this issue, against the will of a number of FOSS fanatics. It works, but it's considered a second class citizen.

Oh, and if you are porting a C++ engine from Windows to Linux and intend to support C++ plugins, then you might also want to look into fvisibility. This feature is extremely important. Again, it's something that's not widely publicized in the Linux community (due to, again, resistance from some fanatics), but developing/porting a good plugin system without it is next to impossible. I almost went insane back when I tried it, until I finally found this feature...
Lord_Evil
Lord_Evil
Thanks for the explanation Yann. I'll have a look at that.
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
swiftcoder
swiftcoder
Quote:
Original post by Yann L
Oh, and if you are porting a C++ engine from Windows to Linux and intend to support C++ plugins, then you might also want to look into fvisibility. This feature is extremely important. Again, it's something that's not widely publicized in the Linux community (due to, again, resistance from some fanatics), but developing/porting a good plugin system without it is next to impossible. I almost went insane back when I tried it, until I finally found this feature...
I still wonder why this isn't catching on faster outside of OS X? Various versions of XCode have marked all symbols private by default, so it was pretty much a forced adoption there - but it is a very useful feature across the board.
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
Yann L
Yann L
Quote:
Original post by swiftcoder
I still wonder why this isn't catching on faster outside of OS X?

I think that like most things in Linux, it's more about ideology than about technology. If you consider that many Linux programmers still consider C as the epitome of perfection, it's no wonder that adoption of such features is stagnant. Also, the fact that these features originated from proprietary Microsoft language extensions (and the cognitive dissonance it induced in some FSF people) is probably another important factor.

But well, fortunately Niall Douglas managed to push his (immensely useful) patch through to the gcc trunk.
Bregma
Bregma
Quote:
Original post by Yann L
Quote:
Original post by swiftcoder
I still wonder why this isn't catching on faster outside of OS X?

I think that like most things in Linux, it's more about ideology than about technology.

What a warm and steaming moist pile of crap.

The reason -rpath is not used much is purely historical.

(1) Fast internet connections are not only recent, but still not widespread downloading a gigabyte of libraries for each application is a nonstarter.
(2) Huge disks are relatively recent and still not widespread. I used to administer a Unix system with 150 MB shared between 30 developers. You're promoting a single application taking upwards of 300 MB.
(3) Many different linkers has an "rpath" argument, but it works completely differently on different platforms (consider how the -rpath argument wored on Digital/Tru64 Unix, and again on HP-UX 10. or how it blows up on AIX pre-4.0) so it was never made the default for source builds. Because it's not the default, few developers used it. Few developers ever go beyond the default settings, even on Microsoft Windows.

About the visibility modifier in GCC: it's new. So new that most developers don't have access to a compiler that supports it. It's true that if you have a huge hard drive and a high speed internet connection you could download the source and build one or else download a new distro and install one, but most professionals have better things to do with their time (although some of us are paid to do just that on a regular basis, but we're the exception).

I would also like to point out that you will find no greater an evangelist for using the visibility modifier than Ulrich Drepper of Red Hat, maintainer of the GNU C runtime. The visibility modifier is primarily for the C language.
Quote:
If you consider that many Linux programmers still consider C as the epitome of perfection, it's no wonder that adoption of such features is stagnant.

There's a value judgment based in prejudice.
Quote:
Also, the fact that these features originated from proprietary Microsoft language extensions (and the cognitive dissonance it induced in some FSF people) is probably another important factor.

Your argument would be stronger if it was not based on incorrect premises. I used similar directives programming in FORTRAN IV on a PDP-11 running RSX before Bill Gates even dropped out of college. There is no political objection to symbol visibility coming from the FSF -- if there were, the strip command would have been neutered long ago. The symbol versioning in ELF binaries would have been boycotted (and Microsoft's linker does not even have the equivalent).

I would like to point out that a paper was even presented at the last C++ standard committee meeting proposing that such directives be made adopted into the next revision of the C++ language (in what, 10 years or so).
Stephen M. Webb
Professional Free Software Developer
swiftcoder
swiftcoder
Quote:
Original post by Bregma
Quote:
Original post by Yann L
Quote:
Original post by swiftcoder
I still wonder why this isn't catching on faster outside of OS X?

I think that like most things in Linux, it's more about ideology than about technology.

What a warm and steaming moist pile of crap. The reason -rpath is not used much is purely historical.
I was referring to -fvisibility, not rpath.

Quote:
About the visibility modifier in GCC: it's new. So new that most developers don't have access to a compiler that supports it.
GCC 4.0 is so hard to find? Most of the major linux distros seem to have adopted GCC 4, as well as OS X - there are even a few MinGW binaries floating around as well.
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
Bregma
Bregma
Quote:
Original post by swiftcoder
Quote:
Original post by Bregma
About the visibility modifier in GCC: it's new. So new that most developers don't have access to a compiler that supports it.
GCC 4.0 is so hard to find? Most of the major linux distros seem to have adopted GCC 4, as well as OS X - there are even a few MinGW binaries floating around as well.

It was broken until 4.3. That's the latest-and-greatest version of GCC. Consider Debian Etch and RHEL4 (which account for a big chunk of professional Linux installations) use 4.1. If you want to distribute software, you want to target the LSB and that means using GCC 3.4.

Another lesson that Microsoft learned was that if you distribute a binary with visible symbols, people will use the "undocumented API" and you're stuck supporting cruft until you're brave enough to break ABI. That means anyone who shipped libraries or a plugin interface prior to GCC 4.3 can't use the visibility specifiers without risking alienating their existing userbase. I speak from experience here.

Either way, the lack of use of the visibility specifiers in free software is not beacuse a bunch of foaming-at-the-mouth pigheaded free software zealots have raged against it because someone at Microsoft implemented an existing and widely-used idea. It's because it's a new feature that has technical barriers to widespread dissemination.

I will also point out that the foaming-at-the-mouth free software zealots are among the most prominent evangelists of its use.
Stephen M. Webb
Professional Free Software Developer
Yann L
Yann L
Quote:
Original post by Bregma
What a warm and steaming moist pile of crap.

The reason -rpath is not used much is purely historical.

We were talking about fvisivility, but well, my arguments also hold for rpath. Even more so, actually.

Quote:
Original post by Bregma
(1) Fast internet connections are not only recent, but still not widespread downloading a gigabyte of libraries for each application is a nonstarter.

What are you talking about ? A gigabyte of libraries ?! Show me one professional application or game that ships with a gigabyte of executable code. Just one. You might not be aware of it, but 'rpath-alike' distribution is entirely common in the Windows world. And, *gasp*, it works there !

Quote:
Original post by Bregma
(2) Huge disks are relatively recent and still not widespread. I used to administer a Unix system with 150 MB shared between 30 developers. You're promoting a single application taking upwards of 300 MB.

I'm sorry, but you are not my target base. And probably not the target base of 99.9% of all modern application or game developers. Especially not in times where a terrabyte harddisk costs almost less than the gas to fill up my car twice.

Quote:
Original post by Bregma
(3) Many different linkers has an "rpath" argument, but it works completely differently on different platforms (consider how the -rpath argument wored on Digital/Tru64 Unix, and again on HP-UX 10. or how it blows up on AIX pre-4.0) so it was never made the default for source builds.

Watch me how much I care about a version of AIX that was released in 1992 or about a '95 vintage HPUX... Oh, right, not at all. In fact, I couldn't care less about anything that is not x86 or x64 compatible. We're a game developer board, remember ?

Quote:
Original post by Bregma
Few developers ever go beyond the default settings, even on Microsoft Windows.

Well, incompetence isn't OS dependent.

Quote:
Original post by Bregma
About the visibility modifier in GCC: it's new. So new that most developers don't have access to a compiler that supports it. It's true that if you have a huge hard drive and a high speed internet connection you could download the source and build one or else download a new distro and install one, but most professionals have better things to do with their time (although some of us are paid to do just that on a regular basis, but we're the exception).

Oh cry me a river. You're a professional developer, but can't be bothered to download an up-to-date compiler ? And internet connection speed ? You mean that internet that 10 year olds use to download gigabytes of warez, pirated DVDs and porn movies ? And you're telling me a professional programmer is unable to get hold of the latest version of a free compiler ?

Quote:
Original post by Bregma
Quote:
If you consider that many Linux programmers still consider C as the epitome of perfection, it's no wonder that adoption of such features is stagnant.

There's a value judgment based in prejudice.

Oh, you mean prejudice like that one ?

Quote:

If you want to distribute software, you want to target the LSB and that means using GCC 3.4.

No it doesn't. Not everyone wants to ship source, you know ?

Anyway, I think I had enough fighting with FOSS zealots lately. It's a bit tiring to be honest, since it's always about the same old recycled arguments. So, Lord_Evil, if you have any further problems with rpath or fvisibility, just PM me.
Yann L
Yann L
Oh, just to add this:

Quote:
Original post by Bregma
It was broken until 4.3.

Wrong. It works fine on 4.2.1, for example. And that's the gcc version shipped with OpenSuse 10.3, which isn't that fresh anymore (current one is 11.1).
Lord_Evil
Lord_Evil
Quote:
Original post by Yann L
So, Lord_Evil, if you have any further problems with rpath or fvisibility, just PM me.

Thanks :)

If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.