如何在静态库中单独的cpp文件中链接未引用的变量?

时间:2016-01-16 08:00:20

标签: c++ xcode gcc

这是一个类定义,如下所示" init。 cpp ":

//-------------------init.cpp-----------------
// ...
class CNetInit {
public:
CNetInit(){::WSAStartup();}
~CNetInit() {...}
};

static CNetInit s_initor;
// ...
//---------------------------------------------

我刚刚将这个cpp添加到静态库中,并将此lib引用到我的项目中,但是CNetInit的构造函数永远不会被执行,因为没有对此cpp的引用。如何在不添加对此cpp的无用引用只是为了导入此单元的情况下使其工作?

评论:实际上这只是一个示例,我的代码将在xcode和gcc中编译,是否有任何标准或非标准方式(如编译器选项)来执行此操作?

2 个答案:

答案 0 :(得分:0)

您必须编译此文件并将输出与其他目标文件链接在一起。这是将其中定义的变量添加到应用程序的唯一方法。

答案 1 :(得分:0)

图书馆的全部意义在于,只有在必要时才包含其中的模块。指示模块必要的规范方法是ODR使用模块中定义的某个名称。

如果您想无条件地将模块链接到可执行文件中,您可以这样做(在大多数构建系统上),只需将已编译模块的文件名添加到要链接到最终可执行文件的文件名列表中。这意味着每次添加新模块时都要修改构建指令。

如果要将模块存储在库中并仍然将其链接到可执行文件中,则可以向可执行文件添加一个小模块,该模块引用您希望包含的每个模块中的某些符号。这需要在每次添加新模块时修改参考模块。

如果你真的想用命令行执行此操作,并且碰巧使用的选项与GNU php app/console doctrine:schema:update --force兼容的链接器和其选项与gcc / g ++兼容的编译器,则可以这样做如下:

ld

在这里,您可以根据需要随时重复选项(当然除了gcc -o MAIN MAIN.cc -Wl,-u,SYMBOL -lLIBRARY之外)。链接器选项-o MAIN导致-u SYMBOL被标记为未定义,这将导致链接器包含一个模块,该模块从提供的库中定义它。因为它不是常见的链接器选项,并且SYMBOL隐式调用链接器,所以我们需要使用特定于gcc的gcc语法,该语法将逗号分隔列表中的每个选项添加到链接器命令。

此解决方案还要求每次添加模块时都要修改构建指令,并且需要以更复杂的形式修改,而不仅仅是将模块对象文件的名称添加到要包含的目标文件列表中。

由于所有三种解决方案都需要某种形式的提供模块索引,因此您可能希望能够通过构建规则以解决方案指定的任何形式构建索引。这可能会影响您对解决方案的偏好。

作为概念验证的完整示例:

文件:regmain.cc

-Wl,option,option,...

文件:register.cc

#include <iostream>

int main(int argc, char** argv) {
  std::cout << "Starting " << argv[0] << '\n';
  return 0;
}

构建并运行:

#include <iostream>
class Register {
  public:
    Register() {
      std::cout << "Registered\n";
    }
};

Register registry;