【问题标题】:Stop shared library linking dropping unused classes停止共享库链接删除未使用的类
【发布时间】:2020-03-18 03:50:32
【问题描述】:

我发现了很多关于消除死代码的相反问题的问题,但我找不到答案:

给定一个类层次结构,如:

BaseView
 +- Base2DView
     +- Concrete2DView
         +- Specialised2DView

我将所有文件链接到view_classes.a,然后添加实例化Concrete2DView 的代码并创建view_renderer.so。接下来,我创建另一个库 specialised_view_renderer.so,它实例化 Specialised2DView 并将 view_renderer.so 列为依赖项。

但是,生成view_renderer.so 的过程已将Specialised2DView.cpp.o 文件作为未使用的代码消除,因为当我使用nm view_renderer.so 时没有任何结果。

我知道链接 view_classes.a 或将 Specialised2DView.cpp 移动到 specialised_view_renderer.so 项目可以解决此问题,但这是我可能不应该过多摆弄的遗留第三方代码。

那么,在构建view_renderer.so 时,是否有一种简单的方法可以将Specialised2DView.cpp.o 或其中的类标记为不会被消除?如果有标准cmaketarget_link_libraries() 线路的选项,则加分。

【问题讨论】:

  • CMP0063 似乎是相关的,因为它提到“但是,某些源可能被编译为静态库或对象库的一部分,然后稍后链接到共享库中。”这是你的用例。您可能还需要将静态库上的CXX_VISIBILITY_PRESET 属性(或全局CMAKE_CXX_VISIBILITY_PRESET)设置为default

标签: c++ linux cmake shared-libraries


【解决方案1】:

我得出的解决方案如下。在我拥有之前:

BaseView
 +-- virtual void foo() = 0;
 +- Base2DView
     +-- virtual void foo() {...}
     +- Concrete2DView
         +-- virtual void foo() {...}
         +- Specialised2DView
             +-- void bar() {foo();}

如果我将叶子调用更改为:

             +-- void bar() {Concrete2DView::foo();}

链接的代码没有问题。

【讨论】:

    【解决方案2】:

    那么,有没有一种简单的方法可以在构建 view_renderer.so 时将 Specialised2DView.cpp.o 或其中的类标记为不被消除?

    是的:

    g++ -shared -o view_renderer.so ... \
      -Wl,--whole-archive view_classes.a -Wl,--no-whole-archive
    

    要了解为什么会发生这种情况以及解决方案为何有效,您需要了解链接器用于选择要包含在链接中的对象的规则。一个很好的描述是here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-18
      • 2017-05-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多