如果函数已经优化,编译时测试

时间:2016-05-01 01:18:54

标签: c gcc optimization compiler-optimization

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

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

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

实现这一目标的方法并不理想:

  • 让用户明确启用他们需要的模块(使用#define),并使用#if仅在调试控制台中包含对它们的支持(如果已启用)。我不喜欢这种方法,因为目前用户不必这样做,我宁愿保持这种方式。

  • 让模块在启动时向调试模块注册函数指针。这并不理想,因为它会增加一些运行时开销,并意味着调试代码会分散在多个文件中。

  • 执行与上面相同的操作,但使用弱符号而不是指针。但我仍然不确定如何实现这一目标。

  • 在调试代码中进行编译时测试,例如:

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

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

1 个答案:

答案 0 :(得分:1)

这似乎是一个有趣的问题。这是一个想法,虽然它并不完美:

双程编译。

您可以做的是首先使用FINDING_DEPENDENCIES=1之类的标志编译程序。用#if s围绕所有依赖性检查(我假设你不关心在那里添加额外的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?