gcc 中的-L、-rpath和 -rpath-link的区别

本文将通过实验的方法找到三种方式的区别。

文章目录

    • -L
    • -rpath 或者 -rpath-link

-L

1.1 deps.cc

#include 

void deps() {
	printf("deps.\n");
}

parent.cc

#include 

void deps();

void parent() {
 printf("parent.\n");
 deps();
}

test.cc

#include 
void parent();

int main(void) {
  parent();
  return 0;
}

a.首先编译汇编代码,得到deps.o 和 parent.o

 gcc -c deps.cc parent.cc

查看编译得到的object file

nm -C parent.o

输出

  U _GLOBAL_OFFSET_TABLE_
                 U deps()
0000000000000000 T parent()
                 U puts

b. 其次生成共享库

gcc -shared -o libparent.so parent.o
gcc -shared -o libdeps.so deps.o

为了达到使libparent.so依赖于libdeps.so的目的,在生成libparent.so时要链接到libdeps.so:

gcc -shared -o libmain.so  parent.o  -ldeps -L .

ldd libmain.so
输出:

linux-vdso.so.1 (0x00007ffd4855c000)
	libdeps.so (0x00007fa99459f000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa9941ae000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fa9949a3000)

此时libmain.so已经依赖于libdeps.so。

  1. 编译test.cc
    由于test.c直接依赖于libmain.so,因此使用-lmain -L
gcc test.cc -lmain -L.

或者

gcc test.cc -lparent -ldeps -L.

得到可执行程序 a.out
ldd a.out

linux-vdso.so.1 (0x00007ffeb632a000)
	libmain.so (0x00007f0d9c701000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0d9c310000)
	libdeps.so (0x00007f0d9c10e000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f0d9cb05000)

由上可见,libmain.so,并且libdeps.so也出现在a.out的依赖中!

-rpath 或者 -rpath-link

1.移动libmain.so 和 libdeps.so 到当前目录的子目录./lib
如果执行gcc test.cc -lmain -L./lib,则会报错:

/usr/bin/ld: warning: libdeps.so, needed by ./lib/libmain.so, not found (try using -rpath or -rpath-link)
./lib/libmain.so: undefined reference to `deps()'
collect2: error: ld returned 1 exit status

可以看出 libmain.so 找不到 libdeps.so,所以需要通过 -rpath 执行 libdeps.so 的路径。

gcc test.cc -lmain -L ./lib -Wl,-rpath=./lib

编译成功!
执行:

export LD_LIBRARY_PATH=./lib
./a.out

-rpath和-rpath-link都可以在链接时指定库的路径;但是运行可执行文件时,-rpath-link指定的路径就不再有效(链接器没有将库的路径包含进可执行文件中),而-rpath指定的路径还有效(因为链接器已经将库的路径包含在可执行文件中了。)

-rpath=dir

Add a directory to the runtime library search path.  This is used when linking an ELF executable with shared objects.  
All -rpath arguments are concatenated and passed to the runtime linker, which uses them to locate shared objects at  
runtime.  The -rpath option is also used when locating shared objects which are needed by shared objects explicitly  
included in the link; see the description of the -rpath-link option.  If -rpath is not used when linking an ELF  
executable, the contents of the environment variable "LD_RUN_PATH" will be used if it is defined.  
  
The -rpath option may also be used on SunOS.  By default, on SunOS, the linker will form a runtime search path out of  
all the -L options it is given.  If a -rpath option is used, the runtime search path will be formed exclusively using  
the -rpath options, ignoring the -L options.  This can be useful when using gcc, which adds many -L options which may  
be on NFS mounted file systems.  
  
For compatibility with other ELF linkers, if the -R option is followed by a directory name, rather than a file name, it  
is treated as the -rpath option.  

-rpath-link=dir

When using ELF or SunOS, one shared library may require another.  This happens when an "ld -shared" link includes a  
shared library as one of the input files.  
  
When the linker encounters such a dependency when doing a non-shared, non-relocatable link, it will automatically try  
to locate the required shared library and include it in the link, if it is not included explicitly.  In such a case,  
the -rpath-link option specifies the first set of directories to search.  The -rpath-link option may specify a sequence  
of directory names either by specifying a list of names separated by colons, or by appearing multiple times.  
  
This option should be used with caution as it overrides the search path that may have been hard compiled into a shared  
library. In such a case it is possible to use unintentionally a different search path than the runtime linker would do.  

你可能感兴趣的:(c-c++编译)