--sysroot=dir 的作用

如果在编译时指定了-sysroot=dir 就是为编译时指定了逻辑目录。编译过程中需要引用的库,头文件,如果要到/usr/include目录下去找的情况下,则会在前面加上逻辑目录。

如此处我们指定 -sysroot=/home/shell.albert/tools/toolschain_arm/4.4.3/arm-none-linux-gnueabi/sys-root
将dir作为逻辑根目录(搜索头文件和库文件)。比如编译器通常会在 /usr/include 和 /usr/lib 中搜索头文件和库,使用这个选项后将在 dir/usr/include 和 dir/usr/lib 目录中搜索。如果使用这个选项的同时又使用了 -isysroot 选项,则此选项仅作用于库文件的搜索路径,而 -isysroot 选项将作用于头文件的搜索路径。这个选项与优化无关,但是在 CLFS 中有着神奇的作用。

 

LD时候的-rpath,-rpath-link 的意思:

-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.

-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.

The difference between -rpath and -rpath-link is that directories specified by -rpath options are included in the executable and used at runtime, whereas the -rpath-link option is only effective at link time. Searching -rpath in this way is only supported by native linkers and cross linkers which have been configured with the --with-sysroot option.

-L: “链接”的时候,去找的目录,也就是所有的 -lFOO 选项里的库,都会先从 -L 指定的目录去找,然后是默认的地方。
-rpath: “运行”的时候,去找的目录。运行的时候,要找 .so 文件,会从这个选项里指定的地方去找。对于交叉编译,只有配合 --sysroot 选项才能起作用。
-rpath_link (或者 -rpath-link):这个也是用于“链接”的时候的,例如你显示指定的需要 FOO.so,但是 FOO.so 本身是需要 BAR.so 的,后者你并没有指定,而是 FOO.so 引用到它,这个时候,会先从 -rpath-link 给的路径里找。

也就是说,-rpath指定的路径会被记录在生成的可执行程序中,用于运行时。
-rpath-link 则只用于链接时。

 

rpath-link的格式:

./configure --cross-prefix=/home/zhou/android/android_adt/ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi- --sysroot=/home/zhou/android/android_adt/ndk/platforms/android-9/arch-arm --disable-shared --disable-symver --disable-everything --enable-gpl --enable-runtime-cpudetect --enable-decoder=h263 --enable-encoder=h263 --enable-encoder=libx264 --enable-parser=h264 --enable-libx264 --enable-decoder=h264 --prefix=/home/hzh/temp/vpu/build/ffmpeg/ --extra-cflags= -DANDROID -D__thumb__ -mthumb -I../build/x264//include --extra-ldflags= -L../build/x264//lib -Wl,-rpath-link,../build/x264//lib --extra-cxxflags=-Wno-multichar -fno-exceptions -fno-rtti

 

如果有多个rpath, 则:

-Wl,-rpath=/home/oracle/db_1/lib -Wl,-rpath=/home/app/oracle
也可以简写,注意是”:”,和PATH的路径分隔符一样,还要注意中英文字符:
-Wl,-rpath=/home/oracle/db_1/lib:/home/app/oracle

另外,如果有多个rpath,路径最好用绝对路径,不然有些时候configure 那一步过不了, 如ffmpeg。

bash 脚本里的到绝对路径的方法:

--sysroot_linux
# bash脚本里 = 前后不能有空格,等号前后不能有空格,赋值
VPU_WRAPPER=../../vpu-helper/vpu_wrapper pushd $VPU_WRAPPER VPU_WRAPPER_DIR=`pwd` popd EXTRA_CFLAGS="$EXTRA_CFLAGS -I$VPU_WRAPPER_DIR" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -L$VPU_WRAPPER_DIR/lib"
echo $EXTRA_LDFLAGS
# pushd 和 popd 会改变当前文件专属的目录路径,只对当前文件有效,退出当前文件的执行后立即失效
--sysroot_linux

makefile里

--sysroot_linux
CROSS_DIR    = ../arm-2012.09/bin
CROSS_PREFIX = arm-none-linux-gnueabi-
CC    = $(shell cd $(CROSS_DIR) && pwd)/$(CROSS_PREFIX)gcc
AR    = $(shell cd $(CROSS_DIR) && pwd)/$(CROSS_PREFIX)ar
STRIP = $(shell cd $(CROSS_DIR) && pwd)/$(CROSS_PREFIX)strip
RANLIB= $(shell cd $(CROSS_DIR) && pwd)/$(CROSS_PREFIX)ranlib
@echo "CC is: '$(CC)'"
$(warning "CC is: $(CC)")
# $(shell cd $(CROSS_DIR)),改变目录只针对当前语句有效,退出当前语句后目录改变结果立即失效,即这一句不影响文件里的目录路径,只影响自己这一句。
--sysroot_linux

 

 

下面是转债的别人写的rpath的其中一个作用示例:

问题来源
最近在做一个项目的客户端的SDK,实现为一个动态链接库,其依赖于其他的若干个动态库文件。那么在利用SDK开发应用程序的时候,编译的时候除了链接SDK库本身,还得链接SDK库所依赖的库,这样编译命令里面得一一的添加这些库。 

比如,SDK库的名称为liba.so, 其依赖于libb.so和libc.so,那么在编译应用程序的时候使用以下命令:

$ gcc -o test test.c -I. -L. -la -lb -lc

意编译的时候,只显示地链接liba.so。那么该怎么做呢?利用rpath这个链接选项!

解决方法
首先来man ld,查找链接选项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 environ-
           ment variable "LD_RUN_PATH" will be used if it is defined.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

简单翻译下, rpath链接选项主要有两个功能:

(1)程序运行时,优先到rpath指定的目录去寻找依赖库

(2)程序链接时,在指定的目录中,隐式的链接那些动态库所需要的链接库。

将liba.so,libb.so 和 libc.so拷贝的同一个目录中,然后利用rpath链接应用程序,这样编译便不需要显示的去链接liba.so所依赖的库了。

gcc -o test test.c -I. -L. -la -Wl,-rpath=.

 

 

 

rpath的详细规则文档:

https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling

What is RPATH?

If an executable "foo" links to the shared library "bar", the library "bar" has to be found and loaded when the executable "foo" is executed. This is the job of the linker, under Linux this is usually ld.so. The linker searches a set of directories for the library bar, which will under most UNIXes have the name libbar.so. The linker will search the libraries in the following directories in the given order:

  • RPATH - a list of directories which is linked into the executable, supported on most UNIX systems. It is ignored if RUNPATH is present.
  • LD_LIBRARY_PATH - an environment variable which holds a list of directories
  • RUNPATH - same as RPATH, but searched after LD_LIBRARY_PATH, supported only on most recent UNIX systems, e.g. on most current Linux systems
  • /etc/ld.so.conf - configuration file for ld.so which lists additional library directories
  • builtin directories - basically /lib and /usr/lib

There are different reasons why search directories additional to the builtin ones can be needed - a user may install a library privately into his home directory, e.g. ~/lib/, or there may be two or more versions of the same library installed, e.g. /opt/kde3/lib/libkdecore.so and /opt/kde4/lib/libkdecore.so.

For the first case it would work if the user would set LD_LIBRARY_PATH accordingly:

export LD_LIBRARY_PATH=$HOME/lib:$LD_LIBRARY_PATH

This will break for the second case, where for some programs /opt/kde3/lib has to be searched and for other applications /opt/kde4/lib has to be searched, but in no case both. The only way to have an executable-dependent library search path is by using RPATH (or RUNPATH, but this isn't supported everywhere).

/etc/ld.so.cache中缓存了动态库路径,可以通过修改配置文件/etc/ld.so.conf中指定的动态库搜索路径,然后执行ldconfig命令来改变,以后系统启动后就会自动到这些目录里去找so库。