184 lines
12 KiB
Plaintext
184 lines
12 KiB
Plaintext
linux使用最佳实践:
|
||
1.使用稳定linux发行版。
|
||
2.永远不要把库下载到自己的系统目录下,要安装到自己定义的--installroot里,而且尽量使用装系统的iso源,永远不更新
|
||
3.自己编译安装的库,不要放入--installroot里,要放入单独的目录中
|
||
并且目录结构遵循
|
||
├─best_env
|
||
│ ├─iso_repo //挂载装系统的iso,或者直接就是iso的文件
|
||
│ └─iso_root //从iso源下载的库,目录结构和系统根目录一样
|
||
│ ├─...
|
||
│ └─...
|
||
│ └─src //存放源码的tar.gz,和加压后的源码
|
||
│ └─build //源码的构建目录
|
||
│ └─install //从源码编译安装的库,或者安装包安装的库,里面的第一层是库的名字,下面是版本号,如果是编译安装的库,就保持它原始的结构
|
||
│ ├─Library_A
|
||
│ │ ├─v2
|
||
│ │ └─v3
|
||
│ ├─Library_B
|
||
│ │ ├─v10
|
||
│ │ └─v12
|
||
│ └─Library_C
|
||
│ ├─v4
|
||
│ ├─v5
|
||
│ └─v6
|
||
|
||
==================== glibc 动态加载器找库规则 ====================
|
||
官方文档:
|
||
当链接器需要额外的共享库时,搜索顺序如下:
|
||
1.通过 -rpath-link 指定的目录。
|
||
2.通过 -rpath 指定的目录(这些目录会被包含在可执行文件中,并在运行时使用)。
|
||
3.在 ELF 系统中,如果没有使用 -rpath 和 -rpath-link,则会检查环境变量 LD_RUN_PATH 的内容。
|
||
4.在 SunOS 系统中,如果没有使用 -rpath,则会搜索 -L 选项指定的目录。
|
||
5.对于本地链接器,搜索环境变量 LD_LIBRARY_PATH 中的目录。
|
||
6.在本地 ELF 系统中,搜索共享库的 DT_RUNPATH 或 DT_RPATH 中的目录(如果 DT_RUNPATH 存在,则忽略 DT_RPATH)。
|
||
7.对于 Linux 系统的链接器,如果存在 /etc/ld.so.conf 文件,则搜索该文件中列出的目录。
|
||
8.在 FreeBSD 系统上,搜索 _PATH_ELF_HINTS 宏定义的目录。
|
||
9.通过链接器脚本中的 SEARCH_DIR 命令指定的目录,包括 -T 选项提供的脚本。
|
||
10.默认目录,如 /lib 和 /usr/lib。
|
||
11.由插件 LDPT_SET_EXTRA_LIBRARY_PATH 指定的目录。
|
||
12.默认链接器脚本中的 SEARCH_DIR 命令指定的目录。
|
||
查阅非官方文档的补充:
|
||
1.linux关于查库的规则主要是由glibc里的链接器(不仅能运行时查找库,还能编译时链接库)实现的,
|
||
2. rpath和runpath对间接依赖库的作用。 在搜索程序或库的间接依赖时,rpath和runpath是不同的,rpath设置的路径对间接库的搜索也生效。
|
||
即搜索间接库时,也会优先从rpath指定的路径中搜索。而runpath设置的路径在对间接库搜索时是不起作用的。
|
||
所谓的间接库是指一个库所依赖的库中又依赖的别的库,如test程序依赖liba.so,而liba.so又依赖libb.so,
|
||
那么对于test程序来说,libb.so就是一个间接依赖库。那么加载器在加载test程序时,寻找libb.so的时候,rpath和runpath的作用是不同的
|
||
3. runpath和rpath的行为,和linux发行版中链接器的实现有关,不同的发行版,可能实现并不相同(elf文件格式,也属于用户空间,但是是标准化比较好的,各个发行版通用)
|
||
==================== 动态链接器找库规则 ====================
|
||
|
||
任务:打包可执行文件EXE到目录DIR下
|
||
首先把EXE间接或直接依赖的库,按文件结构复制到DIR/root下(注意:软连接的处理)
|
||
然后把DIR/root下所有的库的RPATH和RUNPATH的所有绝对路径换成相对与这个root的路径
|
||
然后把/etc/ld.so.cache转换为相对与这个root的路径存入PATHS里
|
||
然后为EXE下所有库的RPATH添加PATHS路径
|
||
|
||
这样的话只要我开发环境的内核 与 我发布环境的内核 二进制兼容 我就可以在任何地方跑
|
||
LD_DEBUG=libs来帮助调试库的加载过程
|
||
|
||
-rpath=dir
|
||
将目录添加到运行时库搜索路径。在将 ELF 可执行文件与共享目标文件链接时,将使用此选项。
|
||
所有 -rpath 参数都连接在一起并传递给运行时链接程序,运行时链接程序使用它们在运行时查找共享目标文件。
|
||
在查找链接中显式包含的共享对象所需的共享对象时,也会使用 -rpath 选项;请参阅 -rpath-link 选项的说明。
|
||
以这种方式搜索 -rpath 仅支持配置了 --with-sysroot 选项的本机链接器和交叉链接器。
|
||
如果在链接 ELF 可执行文件时未使用 -rpath,则将使用环境变量 “LD_RUN_PATH” 的内容(如果已定义)
|
||
-rpath选项也可以在SunOS上使用。在SunOS上默认情况下,链接器将从所有-L中形成一个运行时搜索路径
|
||
它提供了选项。如果使用-rpath选项,运行时搜索路径将仅使用-rpath选项形成,忽略-L选项。这在使用gcc时很有用
|
||
添加了许多-L选项,这些选项可能位于NFS挂载的文件系统上。
|
||
为了与其他 ELF 链接器兼容,如果 -R 选项后跟目录名称而不是文件名,则会将其视为 -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. Searching -rpath in
|
||
this way is only supported by native linkers and cross linkers
|
||
which have been configured with the --with-sysroot 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
|
||
使用 ELF 或 SunOS 时,一个共享库可能需要另一个共享库。当 “ld -shared” 链接包含共享库作为输入文件之一时,会发生这种情况。
|
||
当链接器在执行非共享、不可重定位的链接时遇到此类依赖项时,它将自动尝试查找所需的共享库并将其包含在链接中(如果未显式包含)。
|
||
在这种情况下,-rpath-link 选项指定要搜索的第一组目录。-rpath-link 选项可以通过指定以冒号分隔的名称列表或多次出现来
|
||
指定目录名称序列。
|
||
令牌 $ORIGIN 和 $LIB 可以显示在这些搜索目录中。对于 $ORIGIN,它们将被替换为包含程序或共享目标文件的目录的完整路径,
|
||
如果是 $LIB,则为 lib - 对于 32 位二进制文件,或 lib64 - 对于 64 位二进制文件。
|
||
也可以使用这些令牌的替代形式 - ${ORIGIN} 和 ${LIB}。不支持令牌 $PLATFORM。
|
||
应谨慎使用此选项,因为它会覆盖可能已硬编译到共享库中的搜索路径。在这种情况下,可能会无意中使用与运行时链接程序不同的搜索路径。
|
||
链接器使用以下搜索路径来查找所需的共享库:
|
||
1. 由 -rpath-link 选项指定的任何目录。
|
||
2. 由 -rpath 选项指定的任何目录。-rpath 和 -rpath-link 之间的区别在于,
|
||
由 -rpath 选项指定的目录包含在可执行文件中并在运行时使用,而 -rpath-link 选项仅在链接时有效。
|
||
以这种方式搜索 -rpath 仅支持配置了 --with-sysroot 选项的本机链接器和交叉链接器。
|
||
3. 在 ELF 系统上,对于本机链接器,如果未使用 -rpath 和 -rpath-link 选项,请搜索环境变量 “LD_RUN_PATH” 的内容。
|
||
4. 在 SunOS 上,如果未使用 -rpath 选项,请搜索使用 -L 选项指定的任何目录。
|
||
5. 对于本机链接器,搜索环境变量 “LD_LIBRARY_PATH” 的内容。
|
||
6. 对于本机 ELF 链接器,将在共享库的 “DT_RUNPATH” 或 “DT_RPATH” 中的目录中搜索其所需的共享库。
|
||
如果存在 “DT_RPATH” 条目,则忽略 DT_RUNPATH 条目。
|
||
7. 默认目录,通常为 lib 和 usr/lib。
|
||
8. 对于 ELF 系统上的本机链接器,如果文件 etcld.so.conf 存在,则为该文件中找到的目录列表。
|
||
如果未找到所需的共享库,链接器将发出警告并继续链接。
|
||
|
||
-rpath-link=dir
|
||
When using ELF or SunOS, one shared library may require another.
|
||
This happens when a "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.
|
||
|
||
The tokens $ORIGIN and $LIB can appear in these search directories.
|
||
They will be replaced by the full path to the directory containing
|
||
the program or shared object in the case of $ORIGIN and either lib
|
||
- for 32-bit binaries - or lib64 - for 64-bit binaries - in the
|
||
case of $LIB.
|
||
|
||
The alternative form of these tokens - ${ORIGIN} and ${LIB} can
|
||
also be used. The token $PLATFORM is not supported.
|
||
|
||
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 linker uses the following search paths to locate required
|
||
shared libraries:
|
||
|
||
1. Any directories specified by -rpath-link options.
|
||
|
||
2. Any directories specified by -rpath options. 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.
|
||
|
||
3. On an ELF system, for native linkers, if the -rpath and
|
||
-rpath-link options were not used, search the contents of the
|
||
environment variable "LD_RUN_PATH".
|
||
|
||
4. On SunOS, if the -rpath option was not used, search any
|
||
directories specified using -L options.
|
||
|
||
5. For a native linker, search the contents of the environment
|
||
variable "LD_LIBRARY_PATH".
|
||
|
||
6. For a native ELF linker, the directories in "DT_RUNPATH" or
|
||
"DT_RPATH" of a shared library are searched for shared
|
||
libraries needed by it. The "DT_RPATH" entries are ignored if
|
||
"DT_RUNPATH" entries exist.
|
||
|
||
7. The default directories, normally /lib and /usr/lib.
|
||
|
||
8. For a native linker on an ELF system, if the file
|
||
/etc/ld.so.conf exists, the list of directories found in that
|
||
file.
|
||
|
||
If the required shared library is not found, the linker will issue
|
||
a warning and continue with the link.
|