Date: Fri, 7 Jul 2006 16:46:16 +0300 From: Giorgos Keramidas <keramida@ceid.upatras.gr> To: nospam@mgedv.net Cc: freebsd-questions@freebsd.org Subject: Re: shared library loader configuration Message-ID: <20060707134616.GA3807@gothmog.pc> In-Reply-To: <000001c6a1c5$079d0cc0$01010101@avalon.lan> References: <20060707122812.GB3330@gothmog.pc> <000001c6a1c5$079d0cc0$01010101@avalon.lan>
next in thread | previous in thread | raw e-mail | index | archive | help
On 2006-07-07 14:58, "no@spam@mgedv.net" <nospam@mgedv.net> wrote: >Giorgos Keramidas wrote: >>On 2006-07-07 14:22, "no@spam@mgedv.net" <nospam@mgedv.net> wrote: >>> dunno, if it's a misunderstanding, but my only question "how to tell >>> the system where to load libraries and in which order to prefer >>> paths" seems to be still open. >>> >>> anyway, thx for the reply ;-) >>> >>> ps: i already RdTFM ;-) >> >> You don't. Unless you modify the /etc/rc.d/ldconfig script manually, >> /lib and /usr/lib will always be the first to search. >> >> I'm still not convinced that "telling the system where to load >> libraries from" is the solution to you problem, but I don't know what >> the problem is. You have to describe first *WHAT* the real problem >> is and *WHY* you think modifying the library path is a solution. > > i found the ldconfig rc-script but i thought there might be a > "cleaner" way of telling the system where the shared libraries are to > be found. > > any way to tell the system: take /usr/local/lib first w.o. changing > the ldconfig rc-scripts or developing own startup scripts that achieve > that? no way of changing some default configuration file that is > avail. for that purpose? No. For a very good reason too. If you change the default loader path to use /usr/local/lib first then *ALL* the programs are affected. Even those that are part of the base system. This is, in general, a very bad idea as the base-system programs may depend on particular versions of the libraries to work correctly and those libraries are in /lib:/usr/lib. > some additional thoughts (a little bit of phil.): > > i wonder, that anybody scripts such hardcoded stuff into a script > because the environment /etc/ld*conf* exists, and at least for a clear > and proper way for the admin to define what to load from where it > should be possible, to override a default configuration via the > config-files, and not with modifications to rc-scripts which are gone > by default after each upgrade. There's a reason why /lib:/usr/lib take precedence over /usr/local. Don't change that, or be prepared to debug all the potential bugs that may start appearing. > to satisfy your couriosity :-) This description is much better. > i'd like to compile openssl 0.9.8 and a newer zlib for testing some > software that does crypto & compression using these libs. and i > wanted to keep the servers as clean as possible from changing > rc-scripts, etc... to ensure we're able to transfer the outcoming > piece of program to other boxes w'out much effort. i know it's inside > the ports but the problem is, we'd like to tes some sort of code > that's not enabled by default in the ports. You can always install your own version of openssl and zlib and use an explicit -R option to tell the linker where to find libraries. There are two steps involved in linking and distributing an executable: * Build-time linking, where the compiler/linker has to be explicitly pointed at teh right place with -L/foo/lib paths. * Runtime linking, where the runtime linker-loader has to lookup and locate the library. You can affect the first one with explicit -L/foo/lib options. You can also hardcode one or more paths to the binary -- solving the second problem too -- if you use -R/distrib/lib options while building. Your problems are only a matter of using the proper build options. See for example the ldd output near the end of the following log: # root@gothmog:/home/giorgos/tmp/foo# make cleandir # ===> lib (cleandir) # ===> lib/libz (cleandir) # rm -f a.out foo.o foo.o.tmp # rm -f foo.po foo.po.tmp # rm -f foo.So foo.so foo.So.tmp # rm -f libz.so # rm -f libz.so.* libz.so # rm -f libz.a libz_p.a libz.so.1 # rm -f .depend GPATH GRTAGS GSYMS GTAGS # ===> bin (cleandir) # ===> bin/foo (cleandir) # rm -f foo foo.o # rm -f .depend GPATH GRTAGS GSYMS GTAGS # root@gothmog:/home/giorgos/tmp/foo# make cleandir # ===> lib (cleandir) # ===> lib/libz (cleandir) # rm -f a.out foo.o foo.o.tmp # rm -f foo.po foo.po.tmp # rm -f foo.So foo.so foo.So.tmp # rm -f libz.so # rm -f libz.so.* libz.so # rm -f libz.a libz_p.a libz.so.1 # rm -f .depend GPATH GRTAGS GSYMS GTAGS # ===> bin (cleandir) # ===> bin/foo (cleandir) # rm -f foo foo.o # rm -f .depend GPATH GRTAGS GSYMS GTAGS # root@gothmog:/home/giorgos/tmp/foo# make obj # ===> lib (obj) # ===> lib/libz (obj) # /home/giorgos/tmp/foo/obj/home/giorgos/tmp/foo/lib/libz created for /home/giorgos/tmp/foo/lib/libz # ===> bin (obj) # ===> bin/foo (obj) # /home/giorgos/tmp/foo/obj/home/giorgos/tmp/foo/bin/foo created for /home/giorgos/tmp/foo/bin/foo # root@gothmog:/home/giorgos/tmp/foo# make # ===> lib (all) # ===> lib/libz (all) # cc -O2 -fno-strict-aliasing -pipe -I/home/giorgos/tmp/foo/lib/libz -g -Wsystem-headers -Werror -Wall -Wno-format-y2k -Wno-uninitialized -c /home/giorgos/tmp/foo/lib/libz/foo.c # building static z library # ranlib libz.a # cc -pg -O2 -fno-strict-aliasing -pipe -I/home/giorgos/tmp/foo/lib/libz -g -Wsystem-headers -Werror -Wall -Wno-format-y2k -Wno-uninitialized -c /home/giorgos/tmp/foo/lib/libz/foo.c -o foo.po # building profiled z library # ranlib libz_p.a # cc -fpic -DPIC -O2 -fno-strict-aliasing -pipe -I/home/giorgos/tmp/foo/lib/libz -g -Wsystem-headers -Werror -Wall -Wno-format-y2k -Wno-uninitialized -c /home/giorgos/tmp/foo/lib/libz/foo.c -o foo.So # building shared library libz.so.1 # ===> bin (all) # ===> bin/foo (all) # cc -O2 -fno-strict-aliasing -pipe -I/home/giorgos/tmp/foo/bin/foo/../../lib/libz -g -c /home/giorgos/tmp/foo/bin/foo/foo.c # cc -O2 -fno-strict-aliasing -pipe -I/home/giorgos/tmp/foo/bin/foo/../../lib/libz -g -L- -L/home/giorgos/tmp/foo/bin/foo/../../lib/libz -L/home/giorgos/tmp/foo/obj/home/giorgos/tmp/foo/bin/foo/../../lib/libz -L/usr/lib -R/tmp/lib -o foo foo.o -lz # root@gothmog:/home/giorgos/tmp/foo# make install # ===> lib (install) # ===> lib/libz (install) # install -C -o root -g wheel -m 444 libz.a /tmp/lib # install -C -o root -g wheel -m 444 libz_p.a /tmp/lib # install -o root -g wheel -m 444 libz.so.1 /tmp/lib # ln -fs libz.so.1 /tmp/lib/libz.so # ===> bin (install) # ===> bin/foo (install) # install -o root -g wheel -m 555 foo /tmp/bin # root@gothmog:/home/giorgos/tmp/foo# ldd /tmp/bin/foo # /tmp/bin/foo: # libz.so.1 => /tmp/lib/libz.so.1 (0x2807c000) # libc.so.7 => /lib/libc.so.7 (0x2807e000) # root@gothmog:/home/giorgos/tmp/foo# Note how the /tmp/bin/foo executable depends on `libz' but it knows where to pick it up from. No conflict with the system version of libz.so and certainly no problems when the utility runs: # root@gothmog:/home/giorgos/tmp/foo# /tmp/bin/foo # 1 # 0 # 1 # 0 # 1 # 0 # 1 # 0 # 1 # 0 # root@gothmog:/home/giorgos/tmp/foo# The Makefile of this `foo' program and the library it uses can be found online at: http://people.freebsd.org/~keramida/files/foo-rtld.tgz What you can do to override on a _per_program_ basis the location of libraries is to use: * Proper -L/build/path/lib options when compiling to let the compiler file the build-time version of the library. * Proper -R/runtime/path/lib options when compiling to add hints about the location of the libraries in the binary. This way, the runtime linker will know where to look for shared libs. > my (very subjective) point of view currently is, that the dynamic > loading environment could rely on just one (or 2 if you care for > elf/aout anymore) configuration file, which is being taken care of the > libexec-stuff. It does. These paths are /lib and /usr/lib, and there is no good reason to change them to satisfy just one program. > and assume the following: > you're compiling ~10 libraries in series (all go to /usr/local) and > they're some sort of connected to each other, you'll always have to > exec ldconfig -blabla... to ensure, the loader knows about the new > lib? Nope. The libraries should include -R options that point to the right place for their dependencies. It's the responsibility of the builder & packager to make sure these thigns are done Right(TM), so you won't have to fiddle with tons of conflicting options and LD_LIBRARY_PATH trickery to have something that sort of works. Just think about it... [case 1] Let's say that today you install something that requires /usr/local/lib to be the first, just because the guy who compiled libfoo.so thought this was a good idea. Then you have to install something else, which depends on /usr/lib being first because another developer thought this was a good idea too (or simpe because his program has been built with the system version of the same library). Suddenly, you can only have *one* of these working. [case 2] You install FreeBSD, which comes with a few dozen tools that use Gzip compression. FreeBSD comes bundled with a carefully tuned, debugged, tested and QA'd version of libz.so -- a library which works 100% as expected with the system binaries. Then one day, you install software package Frobnic Express, from a company who thought it is a marvelous idea to depend on /usr/local being the first library lookup path. You switch, and suddenly nothing from the base system works correctly. Programs crash, create bogus output files, or randomly misbehave. After a week of effort, you find that this is because Frobnic Express installed an incompatible libz.so in /usr/local/lib which the system binaries can never work well with. It's just not a good idea. Avoid it. At all costs. The hell of maintenance effort you will have to go through when things go wrong is not nice. Trust me when I say you won't like it at all :-) > hey, i'm not a real developer (as you can see) and i really > am sure that there was a reason for developing that way. > i'm also sure, that you can explain good reasons for doing > it that way (and i wouldn't ever say "i don't care 'bout that!") > > but from a more or less "user's" point of view, it's admin- > overhead which could (theoretically) be avoided. > > i'll STFU know - things are going too theoretically ;-) This may sound a bit harsh, but if you are not a developer, why are you compiling things? On the other hand, look at the sample `foo-rtld.tgz' tarball I created. See how the fake `libz' and the `foo' utility that depend on it work. See how they are compiled, and try to use a similar scheme :) I hope this clarifies a bit why I think you are headed down a very wrong path by trying to override /lib and /usr/lib's precedence... Regards, Giorgos
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060707134616.GA3807>