When I include boost library hpp header in two translation units, does the boost code compile twice (and the binary size is double, comparing to the traditional precompiled library?)?
当我在两个转换单元中包含boost库hpp头时,boost代码是否会编译两次(并且二进制大小是两倍,与传统的预编译库相比?)?
2 个解决方案
#1
3
You've asked two distinct questions:
你问了两个截然不同的问题:
does the boost code compile twice? Yes it does. The net effect is that compilation time is probably a little longer as the compiler has to digest all the headers for each compilation unit.
boost代码编译两次吗?是的,它确实。实际效果是编译时间可能要长一些,因为编译器必须为每个编译单元消化所有头文件。
the binary size is double? No it probably does not, but that will come down to your choice of optimisation flags. A template instantiated in unit A will notionally share the same implementation code as one instantiated in unit B with exact same type parameters.
二进制大小是双倍?不,它可能没有,但这将取决于您选择的优化标志。在单元A中实例化的模板将在理论上共享与在单元B中实例化的具有完全相同类型参数的模板相同的实现代码。
Whether it actually shares the same code will depend on whether your optimisation flags permit inlining of the template implementation. If you have allowed inlining and the compiler has chosen to do it then your binary size will increase as the compiler places the template implementation inline with your code in order to achieve your stated optimisation goals.
它是否实际共享相同的代码将取决于您的优化标志是否允许内联模板实现。如果您已允许内联并且编译器已选择执行此操作,那么随着编译器将模板实现与代码内联,您的二进制大小将会增加,以实现您声明的优化目标。
Inlining is never possible with a binary-only library and so this is one reason why your binary size could grow when using header-only libraries.
使用仅二进制库永远不可能进行内联,因此这是使用仅限标头库时二进制大小增加的原因之一。
Here's an example to show how gcc shares template implementation when inlining is not enabled:
下面是一个示例,说明在未启用内联时gcc如何共享模板实现:
a.cpp
a.cpp
#include <vector>
void test1() {
std::vector<int> myvec;
myvec.push_back(1);
}
b.cpp
b.cpp
#include <vector>
void test2() {
std::vector<int> myvec;
myvec.push_back(1);
}
m.cpp
m.cpp
extern void test1(),test2();
main() {
test1();
test2();
}
compilation
汇编
g++ -g -O0 -fno-inline -c m.cpp
g++ -g -O0 -fno-inline -c a.cpp
g++ -g -O0 -fno-inline -c b.cpp
g++ -o a.out a.o b.o m.o
objdump -S a.out |less
analysis of objdump
对objdump的分析
void test1() {
// [snip]
myvec.push_back(1);
// [snip]
4008a0: e8 d1 00 00 00 callq 400976 <_ZNSt6vectorIiSaIiEE9push_backERKi>
void test2() {
// [snip]
myvec.push_back(1);
// [snip]
401548: e8 29 f4 ff ff callq 400976 <_ZNSt6vectorIiSaIiEE9push_backERKi>
Note how the same implementation of push_back
is used (location 400976) even though it was compiled into completely separate compilation units.
注意如何使用push_back的相同实现(位置400976),即使它被编译成完全独立的编译单元。
#2
2
There are some boost header files which are particularly large(I'm looking at you boost/lexical_cast.hpp), which will cause the binary to be larger. However, compilers offer some options to help:
有一些提升头文件特别大(我正在看你boost / lexical_cast.hpp),这将导致二进制文件更大。但是,编译器提供了一些选项来帮助:
MSVC has an option /LTCG (Link-time Code Generation)
MSVC有一个选项/ LTCG(链接时代码生成)
GCC has -flto(I believe is enabled with -O3)
GCC有-flto(我认为是-O3启用)
These options generally permit the linker to discard unused components and reduce duplication across the compilation unit.
这些选项通常允许链接器丢弃未使用的组件并减少编译单元的重复。
#1
3
You've asked two distinct questions:
你问了两个截然不同的问题:
does the boost code compile twice? Yes it does. The net effect is that compilation time is probably a little longer as the compiler has to digest all the headers for each compilation unit.
boost代码编译两次吗?是的,它确实。实际效果是编译时间可能要长一些,因为编译器必须为每个编译单元消化所有头文件。
the binary size is double? No it probably does not, but that will come down to your choice of optimisation flags. A template instantiated in unit A will notionally share the same implementation code as one instantiated in unit B with exact same type parameters.
二进制大小是双倍?不,它可能没有,但这将取决于您选择的优化标志。在单元A中实例化的模板将在理论上共享与在单元B中实例化的具有完全相同类型参数的模板相同的实现代码。
Whether it actually shares the same code will depend on whether your optimisation flags permit inlining of the template implementation. If you have allowed inlining and the compiler has chosen to do it then your binary size will increase as the compiler places the template implementation inline with your code in order to achieve your stated optimisation goals.
它是否实际共享相同的代码将取决于您的优化标志是否允许内联模板实现。如果您已允许内联并且编译器已选择执行此操作,那么随着编译器将模板实现与代码内联,您的二进制大小将会增加,以实现您声明的优化目标。
Inlining is never possible with a binary-only library and so this is one reason why your binary size could grow when using header-only libraries.
使用仅二进制库永远不可能进行内联,因此这是使用仅限标头库时二进制大小增加的原因之一。
Here's an example to show how gcc shares template implementation when inlining is not enabled:
下面是一个示例,说明在未启用内联时gcc如何共享模板实现:
a.cpp
a.cpp
#include <vector>
void test1() {
std::vector<int> myvec;
myvec.push_back(1);
}
b.cpp
b.cpp
#include <vector>
void test2() {
std::vector<int> myvec;
myvec.push_back(1);
}
m.cpp
m.cpp
extern void test1(),test2();
main() {
test1();
test2();
}
compilation
汇编
g++ -g -O0 -fno-inline -c m.cpp
g++ -g -O0 -fno-inline -c a.cpp
g++ -g -O0 -fno-inline -c b.cpp
g++ -o a.out a.o b.o m.o
objdump -S a.out |less
analysis of objdump
对objdump的分析
void test1() {
// [snip]
myvec.push_back(1);
// [snip]
4008a0: e8 d1 00 00 00 callq 400976 <_ZNSt6vectorIiSaIiEE9push_backERKi>
void test2() {
// [snip]
myvec.push_back(1);
// [snip]
401548: e8 29 f4 ff ff callq 400976 <_ZNSt6vectorIiSaIiEE9push_backERKi>
Note how the same implementation of push_back
is used (location 400976) even though it was compiled into completely separate compilation units.
注意如何使用push_back的相同实现(位置400976),即使它被编译成完全独立的编译单元。
#2
2
There are some boost header files which are particularly large(I'm looking at you boost/lexical_cast.hpp), which will cause the binary to be larger. However, compilers offer some options to help:
有一些提升头文件特别大(我正在看你boost / lexical_cast.hpp),这将导致二进制文件更大。但是,编译器提供了一些选项来帮助:
MSVC has an option /LTCG (Link-time Code Generation)
MSVC有一个选项/ LTCG(链接时代码生成)
GCC has -flto(I believe is enabled with -O3)
GCC有-flto(我认为是-O3启用)
These options generally permit the linker to discard unused components and reduce duplication across the compilation unit.
这些选项通常允许链接器丢弃未使用的组件并减少编译单元的重复。