When a program is loaded the linker will check three places for library dependencies:
- the directories specified in the executable's runtime library search path, which is compiled in during linking using the -rpath option.
- The directories specified in the library run path environment variable (LD_RUN_PATH).
- The list of libraries stored in /etc/ld.so.cache.
Common use of the -rpath option is to specify fixed library search directories using a PREFIX. However, you may also specify the $ORIGIN token to represent the location of the executable at runtime. Using this technique, you can easily produce binary software packages that are completely relocatable. Well almost...
It must have been someone's joke to use the '$' in $ORIGIN, which
denotes the location of a binary to the dynamic loader.
Because of this depending on whether you are compiling from the command line,
from within a Makefile, or directly calling gcc/g++ using exec you need
to use a different command.
This page is intended to provide a resource for people to quickly check which is the right command for different situations.
Note that all the following examples contain a comma ',' between the "-R" and the "$ORIGIN". This does not seem to be necessary, but I guess some compilers/linkers may think differently.
From the command line (bash)
Bash treats the '$' character as the start of a variable, therefore it is necessary to quote the $ORIGIN using single quotes ie. '$ORIGIN', which stop substitution.
Use-Wl,-R,'$ORIGIN/../lib'Example
$ g++ myprog.cpp -lmylib -Llib -Wl,-R,'$ORIGIN/../lib' -o bin/myprog
As will be seen in the last example the position of the single quotes don't seem to be important.
Example 2$ g++ myprog.cpp -lmylib -Llib '-Wl,-R,$ORIGIN/../lib' -o bin/myprog
From within a Makefile
Make also uses the '$' character to denote variables, but doesn't use single quotes to turn of substitution. Make, however, does recognize that if another '$' is immediately before a '$' that the '$' is not intended to denote a variable. Therefore you must use two dollar signs.
However, make still passes the command line to bash for execution so you still need to keep the single quotes.
Use-Wl,-R,'$$ORIGIN/../lib'Example
all: g++ myprog.cpp -lmylib -Llib -Wl,-R,'$$ORIGIN/../lib' -o bin/myprogor
RUNDIRFLAGS=-Wl,-R,'$$ORIGIN/../lib'
all:
g++ myprog.cpp -lmylib -Llib ${RUNDIRFLAGS} -o bin/myprog
From within a bash script that calls make
This is useful if you are using a shell script to compile multiple packages which don't use $ORIGIN themselves. It seems that by quoting with double quotes that the single quotes are included as part of the value. The double dollar signs ($$) are still needed for the command to work in the makefile, however they must each also be escaped with a slash so they are not interpreted as something (I know not) within bash.
UseLDFLAGS="'-Wl,-R,\$\$ORIGIN/../lib'"Example
#!/bin/bash ./configure --prefix=/opt/myprogram make LDFLAGS="'-Wl,-R,\$\$ORIGIN/../lib'" make install
Alternatively it seems you can also export the variable directly.
#!/bin/bash export LDFLAGS="'-Wl,-R,\$\$ORIGIN/../lib'"
Of course either way requires the makefile to have a compile line that looks something like that below ie. includes the ${LDFLAGS} variable for substitution:
all:
g++ myprog.cpp -lmylib -Llib ${LDFLAGS} -o bin/myprog
From within a bash script that calls gcc/g++
This is similar to the first situation, but will be compared against the previous for completeness. As the argument is not being passed again to bash later on we need to remove the double quotes else it will pass a singled quoted block to gcc. As we are not passing to make we do not need two dollar signs ($$). And as we do not have two dollar signs we do not need to escape them.
UseLDFLAGS='-Wl,-R,$ORIGIN/../lib'Example
#!/bin/bash LDFLAGS='-Wl,-R,$ORIGIN/../lib' g++ myprog.cpp -lmylib -Llib $LDFLAGS -o bin/myprog
