我有一个由2部分组成的库。一个是直接链接到应用程序的静态“存根”(并包含“ main”功能-应用程序由该处的回调组成)。其余的库模块包含在共享库中。这都是在AIX上建立的,在AIX上,共享库通过引用“导出”文件进行链接。因此,第二个库未遵循正常的lib.so命名约定。实际名称是在链接时从导出文件中提取的。因此,在AIX上,库为libemapp.a和shlibemapp.o。通过此变量,makefile中仅引用libemapp.a:
LINKEMAPP = -L$(LIBDIR) -lemapp -bI:$(LIBDIR)/shlibemapp.exp
现在,我将该混乱移植到linux,并且需要对共享部分使用常规的lib.so命名约定(我假设)。我的第一个直觉是为静态存根和共享主库使用相同的名称。而且我发现在/ usr / lib / ...中有一些情况,其中2个库使用相同的名称。我认为这些实际上是同一代码的静态版本和共享版本-不是两个不同的库。
-rw-r--r-- 1 root root 103370 May 23 2018 libtic.a
lrwxrwxrwx 1 root root 11 May 23 2018 libtic.so -> libtic.so.5
lrwxrwxrwx 1 root root 13 May 23 2018 libtic.so.5 -> libtic.so.5.9
-rw-r--r-- 1 root root 63488 May 23 2018 libtic.so.5.9
我可以轻松使用不同的名称,但我只是想知道。如何在链接时指定-ltic引入两个库中的哪个?并且您可以覆盖任何默认选择吗?
[如果可能,我可以有一个静态的libemapp.a和一个共享的libemapp.so,并将它们都链接到一个应用程序。大概不是吧?
您如何在链接时指定-ltic引入两个库中的哪个?
([libtic.a
和libtic.so
在同一链接程序搜索目录中时。
默认情况下,GNU binutils linker ld
首先通过搜索指定的目录来遵循选项ld
-ltic
按照其命令行顺序,然后在其默认搜索目录中文件-Ldir
(共享库)或libtic.so
的配置顺序(静态库)。除非找到两者,否则将找到它找到的第一个并将其输入到链接中在相同的搜索目录中,在这种情况下选择了libtic.a
。
您是否可以覆盖默认选择?
是。有三种可能的方式:-
1
[如果通过通常的方式通过GCC前端之一调用链接器(libtic.so
,gcc
,g++
等),则可以将选项gfortran
传递到前端。这将指示它将选项-static
(也称为-static
)插入到为其生成的命令行-Bstatic
在任何输入文件之前。链接器将通过忽略共享库来遵守ld
随后通过图书馆搜索发现,直到且除非它消耗了抵消-(static|Bstatic)
选项。因此:
-Bdynamic
将强制gcc ... -static -ltic ...
优先于libtic.a
,并且同样对链接中的每个libtic.so
选项(包括前端静默附加的默认值,而不仅仅是您指定的默认值)
2
-lname
的任何选项opt0[,...,optN]
可以通过传递给链接具有ld
选项的GCC前端,其用法如下;
-Wl
所以:
-Wl,opt0[,...,optN]
等效于1中的插图(前提是该命令的结尾...部分不包含gcc ... Wl,-Bstatic -ltic ...
。
3
Wl,-Bdynamic
选项ld
是-l:name
的变体,同样被接受由GCC前端传递,并保持不变。 -lname
导演链接器在每个目录中搜索名称为[[精确 -l:name
的文件。所以
name
将使gcc ... -l:libtic.a ...
优先于libtic.a
输入,即使后者存在于同一目录中并且可以链接。但是,
libtic.so
将导致链接错误:
gcc ... -static -l:libtic.so
即使找到了attempted static link of dynamic object `./libtic.so'
,因为libtic.so
在-Bstatic
时有效考虑。除了
-l:libtic.so
选项的所有这些变体之外,您当然可以简单地指定一个不连续的-l
作为链接参数,链接器将尝试将[path/]name
解析为绝对文件名并输入该文件[path/]name
有效时,它不会解析为共享库。我可以拥有一个静态的libemapp.a和一个共享的libemapp.so,并将它们都链接到一个应用程序。是。链接器每次出现时都会重新考虑每个
-Bstatic
选项。
-l
仅仅是一个实例:
gcc ... -ltic ... -ltic ......
并且很可能导致与以下内容的链接不同:
gcc ... -lx ... -ly ......
即使gcc ... -ltic ......
每次都解析为相同的文件,因为未定义的集合链接程序尝试解析为提供的定义的引用当一个库被同一库引用时,它可能是一组不同的未定义引用在链接的不同位置考虑。但是
-ltic
不必每次都解析为相同的文件。因此,只要-ltic
和libtic.a
存在于链接器在哪里找到它们,无论是否在同一搜索目录中:
libtic.so
将导致gcc -o prog .... -Wl,-Bstatic -ltic ... -Wl,-Bdynamic -ltic
首先输入到链接中,然后输入libtic.a
。这种链接的作用将是:
libtic.so
将在可能的情况下静态绑定到定义由在-ltic
1中归档的目标文件提供。 2libtic.a
时引用它们。那些未解析的符号将在可能的情况下动态绑定到定义由-ltic
libtic.so
然后链接libtic.a
可能有用
libtic.so
定义的全局符号集与libtic.a
定义的动态符号集不同。但显然,当他们俩都称他们为libtic.so
时,也是错误的甚至没有相同的API。可以想象,同时链接静态和动态版本可能也很有用libtic.?
库的库,例如以以下形式的链接:tic
假设在这种情况下,gcc -o prog main.o ... -Wl,-Bstatic -ltic ... -Wl,-Bdynamic -lfoo -ltic
是由x
定义为libtic
中有未解决的引用,main.o
中有未解决的引用它在成员libtic.a
中定义。然后libtic.a(x.o)
将是合并到libtic.a(x.o)
中,并且对prog
的引用将被静态绑定到定义。并假设此定义引入了对共享库x
中定义的符号,以及
those定义又引入了libfoo.so
中定义的新引用。然后链接将产生对
libtic
的所有引用从目标文件中静态解析libtic
之前-Wl,-Bstatic
,之后还会累积所有其他libtic.a(x.o), libtic.a(y.o)...
在-Wl,-Bdynamic
中动态解析。链接将与:
libtic.so
您总有一天会遇到的可能性不超过建议将gcc -o prog main.o ... x.o y.o... -lfoo -ltic
和libtic.a
都链接到那样。但我对此表示怀疑,即使您这样做,您也应该主张任何合理的选择。不太违反常规做法的替代方法。
[1]提供的目标文件这些定义(没有其他定义)将从
libtic.so
和物理合并到程序中,就像这些目标文件一样在链接命令中单独命名,而不是libtic.a
[2]该程序将带有那些注释动态绑定,使运行时加载程序可以将-ltic
加载到程序的过程,并使用以下代码的运行时地址修补动态引用他们的定义。