41 linker build-process static-libraries
--whole-archive我见过的唯一真正使用的链接器选项是从静态库创建共享库.最近我遇到了Makefile(s),它在链接内部静态库时总是使用这个选项.这当然会导致可执行文件不必要地引入未引用的目标代码.我对此的反应是,这是完全错误的,我在这里遗漏了什么吗?
我的第二个问题与我读到的有关整个存档选项的内容有关,但无法完全解析.--whole-archive如果可执行文件还链接到共享库,而该共享库又(部分地)具有与静态库相同的目标代码,则在与静态库链接时应该使用该 选项.这是共享库,静态库在目标代码方面有重叠.使用此选项将强制在可执行文件中解析所有符号(无论使用情况).这应该避免目标代码重复.这是令人困惑的,如果一个符号在程序中被引用,它必须在链接时唯一地解决,这个关于复制的业务是什么?(如果这一段不是清晰的缩影,请原谅我)
谢谢
Emp*_*ian 67
--whole-archive将可执行文件与静态库链接时有合法用途.一个例子是构建C++代码,其中全局实例在其构造函数中"注册"自己(警告:未经测试的代码):
main.cc
typedef void (*handler)(const char *data);
void register_handler(const char *protocol, handler h);
handler get_handler(const char *protocol);
Run Code Online (Sandbox Code Playgroud)
http.cc(libhttp.a的一部分)
typedef map<const char*, handler> HandlerMap;
HandlerMap m;
void register_handler(const char *protocol, handler h) {
m[protocol] = h;
}
handler get_handler(const char *protocol) {
HandlerMap::iterator it = m.find(protocol);
if (it == m.end()) return nullptr;
return it->second;
}
Run Code Online (Sandbox Code Playgroud)
请注意,http.cc该main.cc需求中没有符号.如果你把它链接为
#include <handlers.h>
class HttpHandler {
HttpHandler() { register_handler("http", &handle_http); }
static void handle_http(const char *) { /* whatever */ }
};
HttpHandler h; // registers itself with main!
Run Code Online (Sandbox Code Playgroud)
你不会得到一个链接到主可执行文件的http处理程序,并且将无法调用handle_http().将此与您链接时发生的情况进行对比:
#include <handlers.h>
int main(int argc, char *argv[])
{
for (int i = 1; i < argc-1; i+= 2) {
handler h = get_handler(argv[i]);
if (h != nullptr) h(argv[i+1]);
}
}
Run Code Online (Sandbox Code Playgroud)
在plain-C中也可以使用相同的"自注册"样式,例如使用__attribute__((constructor))GNU扩展.
小智 11
另一个合法用途--whole-archive是工具包开发人员在一个静态库中分发包含多个功能的库.在这种情况下,提供者不知道消费者将使用该库的哪些部分,因此必须包括所有内容.
我同意使用—whole-archive来构建可执行文件可能不是您想要的(由于链接了不需要的代码并创建了臃肿的软件)。如果他们有充分的理由这样做,他们应该将其记录在构建系统中,因为现在您只能猜测了。
至于你问题的第二部分。如果一个可执行文件同时链接了一个静态库和一个与静态库具有(部分)相同目标代码的动态库,那么—whole-archive将确保在链接时来自静态库的代码是首选的。当您进行静态链接时,这通常是您想要的。
另一个很好用的场景--whole-archive是处理静态库和增量链接。
让我们假设:
libA实现a()和b()功能。libA仅链接,例如由于某些函数包装使用--wrap(一个经典的例子是malloc)libC实现c()功能和用途a()a()和c()增量链接步骤可以是:
ld -r -o step1.o module1.o --wrap malloc --whole-archive -lA
ld -r -o step2.o step1.o module2.o --whole-archive -lC
cc step3.o module3.o -o program
Run Code Online (Sandbox Code Playgroud)
未能插入 --whole-archive 将剥离c()无论如何使用的函数program,从而阻止正确的编译过程。
当然,这是一个特殊的极端情况,必须进行增量链接以避免将所有调用包装malloc在所有模块中,但--whole-archive.
| 归档时间: |
|
| 查看次数: |
50835 次 |
| 最近记录: |