ld 链接器问题:--whole-archive 选项 [英] ld linker question: the --whole-archive option

查看:38
本文介绍了ld 链接器问题:--whole-archive 选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我见过的 --whole-archive 链接器选项的唯一真正用途是从静态库创建共享库.最近我遇到了 Makefile(s),它在与内部静态库链接时总是使用这个选项.这当然会导致可执行文件不必要地引入未引用的目标代码.我对此的反应是这完全是错误的,我在这里遗漏了什么吗?

The only real use of the --whole-archive linker option that I have seen is in creating shared libraries from static ones. Recently I came across Makefile(s) which always use this option when linking with in house static libraries. This of course causes the executables to unnecessarily pull in unreferenced object code. My reaction to this was that this is plain wrong, am I missing something here ?

我的第二个问题与我阅读的有关整个存档选项的内容有关,但无法完全解析.如果可执行文件也链接到共享库,而共享库又具有(部分)与静态库相同的目标代码,则在链接静态库时应使用 --whole-archive 选项静态库.即共享库和静态库在目标代码方面有重叠.使用此选项将强制在可执行文件中解析所有符号(无论使用).这应该是为了避免目标代码重复.这是令人困惑的,如果一个符号在程序中被引用,它必须在链接时唯一地解析,这与重复有什么关系?(如果这一段不够清晰,请原谅我)

The second question I have has to do with something I read regarding the whole-archive option but couldn't quite parse. Something to the effect that --whole-archive option should be used while linking with a static library if the executable also links with a shared library which in turn has (in part) the same object code as the static library. That is the shared library and the static library have overlap in terms of object code. Using this option would force all symbols(regardless of use) to be resolved in the executable. This is supposed to avoid object code duplication. This is confusing, if a symbol is refereed in the program it must be resolved uniquely at link time, what is this business about duplication ? (Forgive me if this paragraph is not quite the epitome of clarity)

谢谢

推荐答案

在将可执行文件与静态库链接时,--whole-archive 的使用是合法的.一个例子是构建 C++ 代码,其中全局实例注册"他们自己在他们的构造函数中(警告:未经测试的代码):

There are legitimate uses of --whole-archive when linking executable with static libraries. One example is building C++ code, where global instances "register" themselves in their constructors (warning: untested code):

handlers.h

typedef void (*handler)(const char *data);
void register_handler(const char *protocol, handler h);
handler get_handler(const char *protocol);

handlers.cc(libhandlers.a 的一部分)

handlers.cc (part of libhandlers.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;
}

http.cc(libhttp.a 的一部分)

http.cc (part of libhttp.a)

#include <handlers.h>
class HttpHandler {
    HttpHandler() { register_handler("http", &handle_http); }
    static void handle_http(const char *) { /* whatever */ }
};
HttpHandler h; // registers itself with main!

main.cc

#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]);
    }
}

注意http.cc中没有main.cc需要的符号.如果您将其链接为

Note that there are no symbols in http.cc that main.cc needs. If you link this as

g++ main.cc -lhttp -lhandlers

您将不会获得链接到主可执行文件的 http 处理程序,并且将无法调用 handle_http().将此与链接为以下内容时发生的情况进行对比:

you will not get an http handler linked into the main executable, and will not be able to call handle_http(). Contrast this with what happens when you link as:

g++ main.cc -Wl,--whole-archive -lhttp -Wl,--no-whole-archive -lhandlers

同样的自注册"样式也可以在普通 C 中使用,例如使用 __attribute__((constructor)) GNU 扩展.

The same "self registration" style is also possible in plain-C, e.g. with the __attribute__((constructor)) GNU extension.

这篇关于ld 链接器问题:--whole-archive 选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆