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

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
Who is Participating?
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 ?
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.

tomatoyoheAuthor Commented:
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.
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

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 ?
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.
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.
tomatoyoheAuthor Commented:
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
tomatoyoheAuthor Commented:
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
tomatoyoheAuthor Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.