说,有一个第三方库在头文件中包含以下内容:
foo.h
namespace tpl {
template <class T, class Enable = void>
struct foo {
static void bar(T const&) {
// Default implementation...
};
};
}
在我自己的库的界面中,我应该为我自己的类型提供此foo
的部分特化。所以,让我们说我有:
xxx.h
# include <foo.h>
namespace ml {
struct ML_GLOBAL xxx {
// Whatever...
};
}
namespace tpl {
template <>
struct ML_GLOBAL foo<::ml::xxx> {
static void bar(::ml::xxx const&);
};
}
其中ML_GLOBAL
是特定于编译器的可见性属性,以确保符号可用于动态链接(默认情况下,我的构建系统隐藏生成的共享中的所有符号库)。
现在,我不想透露我对bar
的实施情况,因此我使用显式模板实例化:
xxx.cpp
# include "xxx.h"
namespace tpl {
void foo<::ml::xxx>::bar(::ml::xxx const&) {
// My implementation...
}
extern template struct foo<::ml::xxx>;
}
在某些消费者应用程序(我的共享库也链接在一起)实际使用此tpl::foo<::ml::xxx>::bar
函数的时候,我得到了{{1>未定义的引用错误{{1符号。实际上,在生成的共享库上运行tpl::foo<::ml::xxx, void>::bar
不会显示nm -CD
符号的痕迹。
我到目前为止所尝试的是关于放置tpl::foo<::ml::xxx, void>
的位置的不同组合(例如关于显式模板实例化本身,关于GCC明显抱怨与Clang不同的内容)以及是否有第二个模板参数{ {1}}。
问题在于这是否与原始定义没有通过来自第三方库附加的可见性属性(ML_GLOBAL
)这一事实相关,或者我是否真的错过了这里的内容?如果我没有错过任何东西,那么我真的被迫在这种情况下暴露我的实现吗? [... * 咳嗽 *看起来更像是编译器缺陷,说实话* 咳嗽 * ...]
答案 0 :(得分:3)
--version-script
第三方符号(或根据您的情况设置)设置global
可见性。在我的情况下,我最初有以下内容:
tpl::foo*
我显然必须改为
{
global:
extern "C++" {
ml::*;
typeinfo*for?ml::*;
vtable*for?ml::*;
};
local:
extern "C++" {
*;
};
};
为了正确地链接所有内容并获得预期的结果。
希望这会有所帮助。
一个好奇的读者可以问,&#34;为什么你在组合显式可见性属性和链接器/版本脚本来控制符号的可见性,当已经存在{
global:
extern "C++" {
tpl::foo*;
ml::*;
typeinfo*for?ml::*;
vtable*for?ml::*;
};
local:
extern "C++" {
*;
};
};
和-fvisibility=hidden
时应该做的那些选择?&#34;。
答案是他们当然这样做,我确实使用它们来构建我的共享库。但是,有一个问题。通常的做法是将您的共享库静态使用的某些内部库(私有)链接到该库中(主要是为了完全隐藏这些依赖项)(但请记住,共享库附带的头文件也应该是设计合理,以实现这一目标)。好处很明显:ABI干净且可控,减少了共享库消费者的编译时间。
以Boost为例,作为此类用例的最广泛候选者。将Boost中所有经过严格模板化的代码私有封装到您的共享库中并从ABI中删除任何Boost符号将大大减少共享库消费者的界面污染和编译时间,而不包括您的软件组件看起来也是专业开发的事实。
无论如何,事实证明,除非您想要链接到共享库的静态库本身也使用-fvisibility-inlines-hidden
和-fvisibility=hidden
选项构建(是一个荒谬的期望,因为没有人会默认分配带有隐藏接口符号的静态库,因为它会破坏它们的目的),它们的符号将不可避免地仍然可见(例如,通过-fvisibility-inlines-hidden
),无论事实上,您正在使用这些选项构建共享库本身。也就是说,在这种情况下,您有两种方法可以解决它:
nm -CD <shared-library>
和-fvisibility=hidden
选项手动重建这些静态库(您的共享库依赖项),鉴于其潜在的第三方来源,显然并非总是可行/实用。