C++ 如何管理C++;跨共享对象的仅标题库

C++ 如何管理C++;跨共享对象的仅标题库,c++,linker,shared-libraries,eigen,C++,Linker,Shared Libraries,Eigen,我正在开发一个大型软件包,它由许多编译成共享对象的包组成。出于性能方面的考虑,我想用向量指令编译Egeng 3(一个只包含头的库),但是模板化方法到处都在编译。如何确保将特征函数编译到特定的对象文件中 该软件由约2000个独立软件包组成。为了使开发以合理的速度进行,推荐的编译程序的方法是稀疏地签出一些包并编译它们,然后可以使用预编译(由某些CI系统)共享库执行程序 问题是我的部分责任是优化程序的CPU时间。为了做到这一点,我想用-march标志编译我正在开发的包(我们称之为A.so),以便Eig

我正在开发一个大型软件包,它由许多编译成共享对象的包组成。出于性能方面的考虑,我想用向量指令编译Egeng 3(一个只包含头的库),但是模板化方法到处都在编译。如何确保将特征函数编译到特定的对象文件中

该软件由约2000个独立软件包组成。为了使开发以合理的速度进行,推荐的编译程序的方法是稀疏地签出一些包并编译它们,然后可以使用预编译(由某些CI系统)共享库执行程序

问题是我的部分责任是优化程序的CPU时间。为了做到这一点,我想用
-march
标志编译我正在开发的包(我们称之为
A.so
),以便Eigen可以利用现代SIMD处理器扩展

不幸的是,由于Eigen是一个只包含头的库,因此Eigen函数被编译成许多不同的共享对象。例如,在
A.so
中调用的CPU最密集的方法之一是在
B.so
中编译的矩阵多动作内核。许多其他本征函数被编译成
C.so
D.so
等。由于这些对象是为较旧的、更广泛实现的指令集扩展而编译的,因此它们不是用AVX、AVX2等编译的

当然,一个可能的解决方案是将包
B
C
D
等包含到我自己的稀疏编译中,但这否定了只编译项目一部分的优势。此外,如果我真的想在包
A
的代码中对所有线性代数运算进行向量化,那么它会让我包含越来越多的包


我要寻找的是一种方法,将包
a
使用的所有本征函数编译成
a.so
,就好像本征函数是用static关键字定义的一样。这可能吗?编译器/链接器中是否有某种机制可以用来实现这一点?

一个显而易见的解决方案是隐藏这些符号。发生这种情况(如果我正确理解问题的话)是因为这些函数被导出,并且可以被其他随后加载的库使用

当您构建库并针对其他库进行链接时,链接器将重用它所能重用的内容。还有旧的包裹。我希望您自己的构建不需要这些库

因此,有两种选择:

  • 在其他库之前强制加载
    A
    (但是如果您需要其他库,我认为这是不可行的)
  • 告诉链接器其他库不应看到这些函数(默认情况下,
    visibility=hidden

我在一个糟糕的第三方库中看到了类似的情况。它是在调试模式下构建的,在产品中发布,突然我们的一个库出现了速度减慢。映射文件标识了罪魁祸首调试函数的来源,因为默认情况下它导出了所有符号。

在不修改代码的情况下更改可见性的另一种方法是在链接阶段使用版本脚本->过滤符号。你需要像这样的东西

{
全球:*;
本地:
外部“C++”
{
特征::*;
*本征::内部::*;
};

};

如果在Linux上,也可以考虑使用<代码>可见性< /代码>;请看@Basile的确,这就是我所想的
可见性
,谢谢你的链接。谢谢你建议使用符号隐藏。如果我理解正确,我必须在所有对象上配置特征符号的隐藏,对吗?有没有一种方法可以防止链接器在不更改这些对象的源代码的情况下重用其他对象中的特征符号?我不这么认为,但也许有人会用银弹来回答!