[英]Is it possible to tell a linker to use libraries with some duplicated symbols as if the symbols were actually different?
We are distributing four different static libraries to customers:我们正在向客户分发四种不同的 static 库:
The issue is that some customers are also using other libraries in their projects (let's call it X) that include duplicated symbols from A, leading to unexpected crashes (but those may be a different version, so they cannot use A).问题是一些客户也在他们的项目中使用其他库(我们称之为 X),其中包含来自 A 的重复符号,导致意外崩溃(但这些可能是不同的版本,因此他们不能使用 A)。 We do not control these libraries (X), as they are prebuilt open source projects.
我们不控制这些库 (X),因为它们是预构建的开源项目。
We cannot distribute all our libraries linked together (stripping the common libraries symbols) as this would be a waste of resources.我们不能分发所有链接在一起的库(剥离公共库符号),因为这会浪费资源。 Some customers only need C or B or D (together with A).
有些客户只需要C或B或D(连同A)。
We cannot distribute B/C/D with locally static linked A because some customers may be using C and B. This would lead again to wasted resources as when they link their project they will end up with two copies of A.我们不能用本地 static 链接 A 分发 B/C/D,因为一些客户可能正在使用 C 和 B。这将再次导致资源浪费,因为当他们链接他们的项目时,他们最终会得到 A 的两个副本。
Is there any way for our customers to tell the linker that when they are linking against X, A and B, the symbols in A should only be used when resolving undefined symbols in B?有没有办法让我们的客户告诉linker,当他们链接X,A和B时,A中的符号只能在解析B中未定义的符号时使用? Eg
例如
lld -o myprogram main.o helper1.o -L. -lX -lA -lB
should use A only for the unresolved symbols in B, but never for the unresolved symbols in helper1.o.应该只将 A 用于 B 中未解析的符号,但绝不能用于 helper1.o 中的未解析符号。 Is there any combination of flags to achieve so?
是否有任何标志组合可以实现这一目标?
We already considered renaming or prefixing symbols in A, but all the libraries are huge and the process is not trivial.我们已经考虑过对 A 中的符号进行重命名或前缀,但所有的库都非常庞大,而且这个过程并不简单。 Also refactoring the code in A to include namespaces is far from trivial.
重构 A 中的代码以包含名称空间也绝非易事。
Tried different compiler flags, but none of them helped.尝试了不同的编译器标志,但都没有帮助。 I went through linker documentation and found nothing.
我浏览了 linker 文档,但一无所获。
Is there any way for our customers to tell the linker that when they are linking against X, A and B, the symbols in A should only be used when resolving undefined symbols in B?
有没有办法让我们的客户告诉linker,当他们链接X,A和B时,A中的符号只能在解析B中未定义的符号时使用?
No.不。
A common solution to the problem you have is to prefix all non-static symbols in libA.a
with a unique prefix (eg your_company_A_foo()
instead of foo()
).您遇到的问题的一个常见解决方案是为
libA.a
中的所有非静态符号添加唯一前缀(例如your_company_A_foo()
而不是foo()
)。 This makes symbol collisions with other libraries exceedingly unlikely.这使得符号与其他库发生冲突的可能性极小。
And a common way to do that is to define your functions using a macro, eg一种常见的方法是使用宏定义函数,例如
#define PFX_A(name) my_prefix_a_ ## name
int PFX_A(foo) () { return 42; }
int PFX_A(bar) () { return 24; }
Above code defines my_prefix_a_foo()
and my_prefix_a_bar()
when compiled:上面的代码在编译时定义了
my_prefix_a_foo()
和my_prefix_a_bar()
:
$ nm f.o
000000000000000b T my_prefix_a_bar
0000000000000000 T my_prefix_a_foo
During local testing / development you could even remove the prefix completely if desired.在本地测试/开发期间,如果需要,您甚至可以完全删除前缀。
This also makes it easy to ship "version 2" of libA.a
and guarantee that old (version 1) libB.a
will never be linked with new libA.a
-- just change the prefix to include "v2" in it.这也使得发布
libA.a
的“版本 2”变得容易,并保证旧的(版本 1) libB.a
永远不会与新的libA.a
链接——只需更改前缀以在其中包含“v2”。
Update:更新:
The issue is that A is a huge library (including its own version of some popular linux libraries).
问题是 A 是一个巨大的库(包括它自己的一些流行的 linux 库版本)。
libA.a
to have a unique prefix.libA.a
中的所有全局符号,使其具有唯一的前缀。 You just do that using objcopy --prefix-symbol=your_company_A
instead of doing it at the source level.objcopy --prefix-symbol=your_company_A
而不是在源代码级别执行此操作。 Example:例子:
$ gcc -c f.c
$ objcopy --prefix-symbol=my_prefix_a_ f.o f2.o
$ nm f.o f2.o
f.o:
000000000000000b T bar
0000000000000000 T foo
f2.o:
000000000000000b T my_prefix_a_bar
0000000000000000 T my_prefix_a_foo
PS聚苯乙烯
lld -o myprogram main.o helper1.o -L. -lX -lA -lB
You should never link any user-level code with ld
(or lld
) on UNIX -- always use appropriate compiler driver ( gcc
or g++
or clang
).你不应该在UNIX上将任何用户级代码与
ld
(或lld
)链接——总是使用适当的编译器驱动程序( gcc
或g++
或clang
)。 The link command using ld
directly is almost never correct (above link line certainly isn't), as you'll discover when some common feature (like C++
destructors or thread-local storage) mysteriously doesn't work.直接使用
ld
的链接命令几乎永远不会正确(链接行上方肯定不正确),因为您会发现某些常见功能(如C++
析构函数或线程本地存储)神秘地不起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.