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

查看:11
本文介绍了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 ?

第二个问题与我读到的有关整体存档选项但无法完全解析的内容有关.如果可执行文件还链接到共享库,而共享库又(部分)与静态库.那就是共享库和静态库在目标代码方面有重叠.使用此选项将强制在可执行文件中解析所有符号(无论是否使用).这应该避免目标代码重复.这很令人困惑,如果在程序中引用了一个符号,它必须在链接时唯一地解析,这个关于复制的业务是什么?(如果这一段不是很清楚的缩影,请原谅我)

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天全站免登陆