链接自行注册,抽象工厂(linking a self-registering, abstract f

2019-07-28 21:25发布

我一直使用和测试自行注册,这里描述基于一个抽象工厂:

https://stackoverflow.com/a/582456

在我所有的测试案例,它就像一个魅力,提供的功能和重用我想要的。

在我的项目使用cmake在这家工厂链接已经相当棘手的(尽管它似乎更多的AR的问题)。

我具有相同base.hpp,derivedb.hpp / CPP,具有同等的deriveda.hpp / CPP到示例相连。 在主,我简单地初始化工厂和调用的createInstance()两次,一次每个“DerivedA”和“DerivedB”。

由线创建可执行文件:

g++ -o testFactory main.cpp derivedb.o deriveda.o

按预期工作。 移动我的派生类到库(使用cmake,但我已经与AR单独以及测试这一点),然后链接失败:

ar cr libbase.a deriveda.o derivedb.o
g++ -o testFactory libbase.a main.cpp

只要求第一个静态实例(从derivedA.cpp),从来没有第二个静态实例,即

// deriveda.cpp (if listed first in the "ar" line, this gets called)
DerivedRegister<DerivedA> DerivedA::reg("DerivedA");

// derivedb.cpp (if listed second in the "ar" line, this does not get called)
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");

需要注意的是,在AR线交换两个只调用derivedb.cpp静态实例,而不是deriveda.cpp实例。

我失去了与AR或静态库的东西,不知何故没有发挥好与C ++静态变量?

Answer 1:

与直觉相反,其中包括一个链接命令档案是不一样的,包括所有的对象文件,这些文件在归档中。 只需要在归档中的目标文件来解决未定义的符号都包括在内。 这是一个很好的事情,如果你认为,一旦没有动态链接和任何其他方式图书馆的整体(认为C库)将被复制到每一个可执行文件。 下面介绍一下LD(1)用户手册(在Linux GNU LD)不得不说:

链接器将搜索归档,只有一次,在它是在命令行上指定的位置。 如果存档限定其在一些对象,它在命令行上的归档之前出现未定义一个符号,链接器将包括从存档适当的文件(多个)。 然而,在后来的对象在命令行上出现一个未定义的符号不会使链接器再次搜索存档。

不幸的是,包括在链接的可执行文件归档的每个成员都没有标准的方式。 在Linux上,你可以使用g++ -Wl,-whole-archive和Mac OS X,你可以使用g++ -all_load

因此,与GNU binutils的LD,链接命令应该是

g++ -o testFactory -Wl,-whole-archive libbase.a -Wl,-no-whole-archive main.cpp

-Wl,-no-whole-archive确保任何档案由++将以正常方式被链接克生成的最终链接命令后面出现。



文章来源: linking a self-registering, abstract factory
标签: c++ g++ cmake ar