How do I prevent hard coded library path dependencies in my executables created with gcc ?

Posted on 2004-04-22
Last Modified: 2012-05-04
My make file links the executable with shared libraries.  I have set the library search path with the "-L..\lib\x86_64".  The resultant executable then has hard coded dependency to ..\lib\x86_64 which I do not want.  When program loads, I want LD_LIBRARY_PATH to determine which shared library to link with - I do not want it hard coded.

Below is my make file for tgoctest executable.  Along with a "strings" output which proves that the executable is hard wired to a specific path.

PROJ = tgoctest
CC = gcc
LINK = gcc

#default configuation - this should be speciifed when using this makefile
#default platform - this should be specified when using this makefile
TGPLATFORM:=$(shell arch)

LIBS_EXT = -lpthread -lncurses
CFLAGSDEBUG = -g  -D "_DEBUG" -D "UNIX" -D "LINUX" -I ../include
LFLAGSDEBUG = -g -L../lib/$(TGPLATFORM) -ltgoc -ltgjpeg
CFLAGSRELEASE = -O -D "UNIX" -D "LINUX" -I ../include
LFLAGSRELEASE = -L../lib/$(TGPLATFORM) -ltgoc -ltgjpeg

TGOCTEST_DEP = ../include/tgocosdp.h \

all:    checkconfig $(OBJDIR)/$(PROJ)

        @if [[ ! -d $(OBJDIR) ]]; then \
                mkdir $(OBJDIR); \

"tgoctestlinux.mak" 50L, 1116C                      

tyohe@suse64:/yam/tg/source/tgoctest> strings x86_64/tgoctest | grep lib
Zlib Compile Flags =0x%x
Set Zlib compression level
Question by:tomatoyohe
  • 5
  • 4

Expert Comment

ID: 10892028
strings is not the right way of testing.

Use ldd.

Using -L does not hardcode library paths. -R has to be used for this. So, it's not a problem of where your libs are at compile time. If they are somewhere in the LD_LIBRARY_PATH at exec time, they will be used.


Author Comment

ID: 10892324
Thanks for your insight, however it is not quite on target.  ldd shows where the libraries will be loaded from if you were to execute the program and it uses LD_LIBRARY_PATH to help determine this.  When I try to load the executable, it fails even if LD_LIBRARY_PATH is set to a directory where the shared libraries reside.  The strings command shows that the shared libraries must reside in ..\lib\x8_64 relative to the current directory.

The following illustrates this.

tyohe@suse64:~/test> set | grep LD_LIBRARY_PATH
tyohe@suse64:~/test> ls -l junk
total 404
-rwxr-xr-x  1 tyohe users 176803 2004-04-22 14:36 libtgjpeg.a
-rwxr-xr-x  1 tyohe users 230689 2004-04-22 14:36 libtgoc.a
tyohe@suse64:~/test> ls -l
total 200
drwxr-xr-x  2 tyohe users    112 2004-04-22 14:37 junk
-rwxr-xr-x  1 tyohe users 203259 2004-04-22 14:36 tgoctest
tyohe@suse64:~/test> ./tgoctest
./tgoctest: error while loading shared libraries: ../lib/x86_64/libtgoc.a: cannot open shared object file: No such file or directory
tyohe@suse64:~/test> pwd

Previous investigation led me to this article 
 which indicates that ldd does not show hardcoded references - only what would be chosen by dynamic linker.

Expert Comment

ID: 10892669
Oh no !!!

This is totally normal. The libraries you have here are "static libraries". I did not notice it in the first place.

in fact, a ".a" file is an archive file that contains ".o" files.

If you want to link with shared libraries, you have to use the following :

gcc -shared -Xlinker -x -o myobj1.o myobj1.o

Then, link against these.

And, I'm sorry, but ldd is completely on topic. It will show you what will actually be used by the dynamic loader. So, it allows you to see that the libraries are correctly loaded.

A short example :

serval:/tmp # cat test.c
doit() {
  printf("test\n") ;

serval:/tmp # cat test2.c
extern doit() ;

main() {

  doit() ;


serval:/tmp # gcc -c test.c
serval:/tmp # gcc -shared -Xlinker -x -o test.o
serval:/tmp # gcc test2.c -o test2 -L/tmp -ltest

serval:/tmp # ls -al test*
-rw-r--r--    1 root     root           32 Apr 22 21:15 test.c
-rw-r--r--    1 root     root          760 Apr 22 21:22 test.o
-rwxr-xr-x    1 root     root         8466 Apr 22 21:22 test2
-rw-r--r--    1 root     root           41 Apr 22 21:16 test2.c

serval:/tmp # mkdir foo
serval:/tmp # cd foo/
serval:/tmp/foo # ldd ../test2 => not found => /lib/i686/ (0x40032000)
        /lib/ => /lib/ (0x40000000)

serval:/tmp/foo # export LD_LIBRARY_PATH=/tmp
serval:/tmp/foo # ldd ../test2 => /tmp/ (0x4001a000) => /lib/i686/ (0x40034000)
        /lib/ => /lib/ (0x40000000)

serval:/tmp/foo # ../test2

See ?
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.


Expert Comment

ID: 10892684
Oh. And, yes. ldd only shows what's used.
But you don't care about static references if your dynamic linker is able to find the libraries where you want them to be.

Expert Comment

ID: 10892752
Sorry. One more.

Works on Linux, but not on all systems.

serval:/tmp # unset LD_LIBRARY_PATH
serval:/tmp # gcc test2.c -o test2 -Wl,-rpath,/tmp -L/tmp -ltest
serval:/tmp # cd foo/
serval:/tmp/foo # ldd ../test2 => /tmp/ (0x4001a000) => /lib/i686/ (0x40034000)
        /lib/ => /lib/ (0x40000000)

Some systems (like Solaris) use the '-R' option to the compiler.

These differences is the reason why most big projects make use of libtool. libtool standardizes the calls to the compiler/linker and adapt to the actual system's options.

Author Comment

ID: 10892860
As far as I know, libtgoc.a is not a static library but a shared library.  When I built it, I thought I specified it to be shared.  Here is pertinent part of the make file:

PROJ = libtgoc.a

CC = gcc
LINK = gcc

#default configuation - this should be speciifed when using this makefile
#default platform - this should be specified when using this makefile
TGPLATFORM:=$(shell arch)


CFLAGSDEBUG = -g -fPIC -D "_DEBUG" -D "UNIX" -D "LINUX" -I ../include
LFLAGSDEBUG = -shared -fPIC -Wl,-Bsymbolic -ldl

CFLAGSRELEASE = -fPIC -O3 -D "UNIX" -D "LINUX" -I ../include
LFLAGSRELEASE = -shared -fPIC -Wl,-Bsymbolic -ldl

LIBS_EXT =  -l m -l c -l pthread

Author Comment

ID: 10892931
Furthermore, objdump utility indicates that the library is dynamic (not static).

tyohe@suse64:~/test/junk> objdump -f libtgoc.a

libtgoc.a:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
start address 0x0000000000007470

Accepted Solution

Alf666 earned 250 total points
ID: 10893848
Ok. Just a naming convention problem then. It should be named .so and not .a. (I'm not sure if it makes a difference, but you might want to try).

Can you show me the output of ldd on tgoctest ?

Author Comment

ID: 10894064
Well after simply renaming the ".a" files to ".so" files the hard coded paths are now removed from the executable!  Thank you.

tyohe@suse64:/yam/tg/source/tgoctest> strings x86_64/tgoctest | grep lib

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Trying to compile syslinux 4.03 on Ubuntu 14.04 14 175
Identify Linux loader 67 181
linux $PWD 2 660
How to ssh into my virtual box linux machine 4 163
Have you ever been frustrated by having to click seven times in order to retrieve a small bit of information from the web, always the same seven clicks, scrolling down and down until you reach your target? When you know the benefits of the command l…
The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question