如何将模板实例化导出为非弱?
How to export template instantiation as non weak?
C++ 模板函数导出为弱符号以解决单一定义规则 ()。在为每个用例显式实例化函数的情况下,有没有办法将符号导出为非弱?
示例用例:
// foo.hpp
template<typename T>
void foo();
// All allowed instantiations are explicitly listed.
extern template void foo<int>();
extern template void foo<short>();
extern template void foo<char>();
// foo.cpp
template<typename T>
void foo()
{
// actual implementation
}
// All explicit instantiations.
template void foo<int>();
template void foo<short>();
template void foo<char>();
当我用 GCC 或 ICC 编译上面的代码时,它们被标记为弱:
$ nm foo.o
U __gxx_personality_v0
0000000000000000 W _Z3fooIcEvv
0000000000000000 W _Z3fooIiEvv
0000000000000000 W _Z3fooIsEvv
有什么办法可以避免吗?因为它们实际上是确定的,所以我不希望它们成为替代的候选对象。
objcopy
支持 --weaken
选项,但你想要相反的选项。
它也支持 --globalize-symbol
,但似乎对弱符号没有影响:
gcc -c t.cc
readelf -Ws t.o | grep _Z3fooI
14: 0000000000000000 7 FUNC WEAK DEFAULT 7 _Z3fooIiEvv
15: 0000000000000000 7 FUNC WEAK DEFAULT 8 _Z3fooIsEvv
16: 0000000000000000 7 FUNC WEAK DEFAULT 9 _Z3fooIcEvv
objcopy -w --globalize-symbol _Z3fooI* t.o t1.o &&
readelf -Ws t1.o | grep _Z3fooI
14: 0000000000000000 7 FUNC WEAK DEFAULT 7 _Z3fooIiEvv
15: 0000000000000000 7 FUNC WEAK DEFAULT 8 _Z3fooIsEvv
16: 0000000000000000 7 FUNC WEAK DEFAULT 9 _Z3fooIcEvv
不被吓倒,我们可以先本地化符号,然后再全球化:
objcopy -w -L _Z3fooI* t.o t1.o &&
objcopy -w --globalize-symbol _Z3fooI* t1.o t2.o &&
readelf -Ws t2.o | grep _Z3fooI
14: 0000000000000000 7 FUNC GLOBAL DEFAULT 7 _Z3fooIiEvv
15: 0000000000000000 7 FUNC GLOBAL DEFAULT 8 _Z3fooIsEvv
16: 0000000000000000 7 FUNC GLOBAL DEFAULT 9 _Z3fooIcEvv
瞧:符号现在已被严格定义。
The problem I am trying to solve is that the link time is too slow and I want to reduce the work of the linker to the minimum.
如果这会使链接器做更少的工作(我对此表示怀疑),我会认为这是链接器中的错误——如果符号被定义一次,那么该定义是否对链接器来说无关紧要强或弱。
C++ 模板函数导出为弱符号以解决单一定义规则 (
示例用例:
// foo.hpp
template<typename T>
void foo();
// All allowed instantiations are explicitly listed.
extern template void foo<int>();
extern template void foo<short>();
extern template void foo<char>();
// foo.cpp
template<typename T>
void foo()
{
// actual implementation
}
// All explicit instantiations.
template void foo<int>();
template void foo<short>();
template void foo<char>();
当我用 GCC 或 ICC 编译上面的代码时,它们被标记为弱:
$ nm foo.o
U __gxx_personality_v0
0000000000000000 W _Z3fooIcEvv
0000000000000000 W _Z3fooIiEvv
0000000000000000 W _Z3fooIsEvv
有什么办法可以避免吗?因为它们实际上是确定的,所以我不希望它们成为替代的候选对象。
objcopy
支持 --weaken
选项,但你想要相反的选项。
它也支持 --globalize-symbol
,但似乎对弱符号没有影响:
gcc -c t.cc
readelf -Ws t.o | grep _Z3fooI
14: 0000000000000000 7 FUNC WEAK DEFAULT 7 _Z3fooIiEvv
15: 0000000000000000 7 FUNC WEAK DEFAULT 8 _Z3fooIsEvv
16: 0000000000000000 7 FUNC WEAK DEFAULT 9 _Z3fooIcEvv
objcopy -w --globalize-symbol _Z3fooI* t.o t1.o &&
readelf -Ws t1.o | grep _Z3fooI
14: 0000000000000000 7 FUNC WEAK DEFAULT 7 _Z3fooIiEvv
15: 0000000000000000 7 FUNC WEAK DEFAULT 8 _Z3fooIsEvv
16: 0000000000000000 7 FUNC WEAK DEFAULT 9 _Z3fooIcEvv
不被吓倒,我们可以先本地化符号,然后再全球化:
objcopy -w -L _Z3fooI* t.o t1.o &&
objcopy -w --globalize-symbol _Z3fooI* t1.o t2.o &&
readelf -Ws t2.o | grep _Z3fooI
14: 0000000000000000 7 FUNC GLOBAL DEFAULT 7 _Z3fooIiEvv
15: 0000000000000000 7 FUNC GLOBAL DEFAULT 8 _Z3fooIsEvv
16: 0000000000000000 7 FUNC GLOBAL DEFAULT 9 _Z3fooIcEvv
瞧:符号现在已被严格定义。
The problem I am trying to solve is that the link time is too slow and I want to reduce the work of the linker to the minimum.
如果这会使链接器做更少的工作(我对此表示怀疑),我会认为这是链接器中的错误——如果符号被定义一次,那么该定义是否对链接器来说无关紧要强或弱。