考虑以下情况:
main.c包含以下内容:
#include "sub.h"
main(){
int i = 0;
while(i < 1000000000){
f();
i++;
}
}
而sub.h包含:
void f();
和sub.c包含这样的内容:
void f(){
int a = 1;
}
现在,如果这些都在一个源文件中,编译器(在我的情况下为gcc)会注意到f()实际上没有做任何事情并优化循环。但由于编译在链接之前发生,因此在这种情况下不会发生优化。
对于本地包含文件,可以通过包含原始.c文件而不是标题来避免这种情况,但是当包含来自其他库的标题时,这变得不可能。有没有办法解决这个问题?
答案 0 :(得分:3)
如果我理解正确,您只想链接程序正在使用的库函数。使用GCC工具链可以使用优化标志:
-O2 -fdata-sections -ffunction-sections
第一个标志应该优化远离无效的循环。其他两个标志将每个函数或数据项放入编译输出文件中的自己的部分。这允许链接器执行优化。注意:编译需要更长时间,而您无法使用gprof。
您还需要将链接器传递-gc-sections
标志,以便它不会包含未使用的函数和数据部分。
总而言之,你会执行:
gcc -O2 -fdata-sections -ffunction-sections main.c sub.c -Wl,-gc-sections
如果您要调用GCC来生成汇编文件,您可以检查它们以发现_main不执行循环或调用函数f():
$ gcc -O2 -S -fdata-sections -ffunction-sections main.c sub.c -Wl,-gc-sections
$ cat main.s
来源:
答案 1 :(得分:2)
编译器无法猜测,也无法对其编译的单个翻译单元之外的内容做出假设。一些工具链(端到端编译器+链接器+支持实用程序)可以检测在从源构建的项目中的某些这样的情况,取决于他们的优化复杂程度。这不常见,也不保证。它肯定不会,也不会适用于链接的不透明第三方库。
在实践中,您是否真的使用第三方库导出一些无操作功能,希望有人(您的工具链)注意到并安全地优化它?
答案 2 :(得分:0)
在Windows中,vs系统具有整个程序优化
Sqlite使用脚本构建单个C文件进行编译