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

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

问题描述

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

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

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

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