编译时测试是否优化了功能

我正在为C中的微控制器编写一个小型操作系统(不是C,所以我不能使用模板).它大量使用了一些
gcc功能,其中最重要的是删除未使用的代码.操作系统在运行时不加载任何内容;用户程序和OS源一起编译形成一个二进制文件.

此设计允许gcc仅包含程序实际使用的OS功能.因此,如果程序从不使用i2c或USB,那么对二进制文件的支持将不会包含在二进制文件中.

问题是当我想在不引入依赖项的情况下包含对这些功能的可选支持时.例如,调试控制台应该提供调试i2c的功能,如果它正在被使用,但是如果程序没有使用它,包括调试控制台也不应该拉入i2c.

想到达到这个目的的方法并不理想:

>让用户明确启用他们需要的模块(使用#define),并使用#if在调试控制台中仅包括对它们的支持(如果已启用).我不喜欢这种方法,因为目前用户不必这样做,我宁愿保持这种方式.
>让模块在启动时向调试模块注册函数指针.这并不理想,因为它会增加一些运行时开销,并意味着调试代码会分散在多个文件中.
>与上面相同,但使用弱符号而不是指针.但我仍然不确定如何实现这一目标.
>在调试代码中进行编译时测试,例如:

if(i2cInit is used) {
    debugShowi2cStatus();
}

最后一种方法似乎很理想,但有可能吗?

最佳答案 这似乎是一个有趣的问题.这是一个想法,虽然它并不完美:

双程编译.

您可以做的是首先使用FINDING_DEPENDENCIES = 1等标志编译程序.用#ifs围绕所有依赖性检查(我假设你不关心在那里添加额外的ifs.)

然后,当编译完成(没有任何可选功能)时,使用nm或类似函数检测程序中函数/功能的使用(例如i2cInit),并将此信息格式化为.h文件.

#ifndef FINDING_DEPENDENCIES
#include "dependency_info.h"
#endif

现在已知可选的依赖项.

这仍然不是一个完美的解决方案,但最终,它主要是一个鸡与蛋的问题.编译时,编译器不知道gc将会是什么符号.您基本上需要从链接器阶段获取此信息并将其反馈到编译阶段.

从理论上讲,这可能不会大幅增加构建时间,特别是如果您为生成的h使用了临时文件,那么只有在它不同时才替换它.但是,您需要使用不同的对象目录.

这也许会有所帮助(当然还有预剥离):
How can I view function names and parameters contained in an ELF file?

点赞