如何区分具有相同名称的共享库和静态库

问题描述 投票:1回答:1

我有一个由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,并将它们都链接到一个应用程序。大概不是吧?

shared-libraries
1个回答
0
投票

您如何在链接时指定-ltic引入两个库中的哪个?

([libtic.alibtic.so在同一链接程序搜索目录中时。

默认情况下,GNU binutils linker ld首先通过搜索指定的目录来遵循选项ld-ltic按照其命令行顺序,然后在其默认搜索目录中文件-Ldir(共享库)或libtic.so的配置顺序(静态库)。除非找到两者,否则将找到它找到的第一个并将其输入到链接中在相同的搜索目录中,在这种情况下选择了libtic.a

您是否可以覆盖默认选择?

是。有三种可能的方式:-

1

[如果通过通常的方式通过GCC前端之一调用链接器(libtic.sogccg++等),则可以将选项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不必每次都解析为相同的文件。因此,只要-lticlibtic.a存在于链接器在哪里找到它们,无论是否在同一搜索目录中:

libtic.so

将导致gcc -o prog .... -Wl,-Bstatic -ltic ... -Wl,-Bdynamic -ltic
首先输入到链接中,然后输入libtic.a

这种链接的作用将是:

  • 程序中有未解析引用的符号首先看到libtic.so将在可能的情况下静态绑定到定义由在-ltic

    1中归档的目标文件提供。

  • 之后,将有0个或多个尚未解析的符号程序中第二次显示libtic.a时引用它们。那些未解析的符号将在可能的情况下动态绑定到定义由-ltic

    2

    提供。链接器将不会审阅或修改它已经建立的任何静态或动态绑定。
  • 显然,链接libtic.so然后链接libtic.a可能

    有用

    ,反之亦然,如果它们分别是同一库的静态和动态版本,则为[[not
特别是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加载到程序的过程,并使用以下代码的运行时地址修补动态引用他们的定义。
© www.soinside.com 2019 - 2024. All rights reserved.