繁体   English   中英

如何使用gcc / g ++预处理器去除非活动的#if指令?

[英]How do I strip out inactive #if directives with the gcc/g++ preprocessor?

我正在使用第三方开源项目,需要删除不活动的#ifs,#ifdefs等,以便更好地理解代码流。

有没有办法使用make来生成没有这些指令的源文件版本? 我想避免扩展宏,只需删除指令。

我在看https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html

似乎-dD和-fdirectives只是开始的好选择。

这些预处理文件将出现在哪里? 我在哪里添加这些命令以用于Makefile和“make”? 我尝试运行“make -n”来生成脚本并在-Wformat之后在脚本中添加g ++和gcc调用选项,但我没有注意到任何事情。

我不确定这是否复杂,但我也使用avr-gcc和avr-g ++。

我看过coan,它不支持#included #defines所以它不能用于此目的,我无法让sunifdef工作。 是否有一种方法可以使用预处理器执行此操作。

定义分散在当前文件,包含的文件和包含指定-Dfoo = opt选项的makefile之间。

您可以使用预处理器选项走上正轨。 -D将定义一个值为1的宏,-U将取消任何先前的定义(它将变为未定义),-fdirectives-only将禁止宏扩展。 除此之外,您可以将-E标志与gcc一起使用,以告诉它将预处理器输出作为单独的文件提供给您进行检查。 但是,我认为它们不会像你期望的那样。 CPP(C预处理器)输出可能会添加其他内容, 如此SO问题所示 ,您应该检查gnu CPP输出手册页 这就是你从CPP得到的东西。

听起来你想要能够剥离这个无关的代码并从那里开发。 要做到这一点,我会鼓励你再试一次unifdef。 这就是unifdef的目的,而CPP旨在为编译准备代码。 它们是不同的任务,因此您应该使用正确的工具。 它可以作为http://dotat.at/prog/unifdef/上的独立应用程序使用,并且内置于一些Linux Shell中

它允许您指定希望它定义或未定义的宏,并删除条件指令评估为false的代码块。 例如,您可以像这样运行它:

unifdef -I <path> -DMACRO1 -UMACRO2

它将通过C / C ++源文件搜索<path>指定的目录,查找#if#ifdef#ifndef等。当遇到它们时,它将评估条件表达式并有选择地删除由该控制的代码。表达。 考虑使用此代码的输入文件:

int i = 0;
#ifdef MACRO1
int j = 0;
#endif /* ifdef MACRO1 */
int k = 0;

int m = 0;
#if (MACRO1 && MACRO2)
int n = 0;
#endif /* if (MACRO1 && MACRO2) */
int p = 0;

int q = 0;
#ifdef MACRO3
int r = 0;
#endif /* ifdef MACRO3 */
int t = 0;

如果我们像上面的例子一样调用unifdef,输出将是这样的:

int i = 0;
int j = 0;
int k = 0;

int m = 0;
int p = 0;

int q = 0;
#ifdef MACRO3
int r = 0;
#endif /* ifdef MACRO3 */
int t = 0;

请注意,n的声明已被删除,因为它包含在预处理器#if / #endif块中,其控制表达式的计算结果为false(我们告诉unifdef将MACRO2视为未定义)。 j的声明仍然存在,但#ifdef#endif语句被删除,因为已知控制表达式为真。

取决于MACRO3的块保持不变,因为其状态未知。

对于其运行方式,还有很大的灵活性和控制力。

如果你决定希望它是构建过程的一部分,你可以随时把它添加到你的makefile。

如果您没有可定义或未定义的宏的列表,您可以使用unifdef提供的“unifdefall”脚本,它将使用CPP自己发现源代码中的宏定义,并删除/保留代码块根据源代码中包含的定义。

TL; DR

是的,你可以(有点)用预处理器来做。 但unifdef和sunifdef是完成这个的工具,所以你应该使用它们。

假设

  1. 这个练习的目的是生成一个C / C ++源代码体,删除了大部分条件编译,并编译成相同的二进制文件。
  2. 这是第三方源代码,您了解合并后续更新的问题。
  3. 这是开源的,但您无意分发修改后的源代码。
  4. 这些程序是任意复杂的,由任意复杂的makefile或类似工具构建,具有命令行符号定义和/或配置包含文件。

我的策略是使用像unifdef这样的程序。 我第一次这样做,我自己编写,你可能需要修改程序以产生所需的结果。

核心战略是:

  1. 确定单个可能定义的符号(需要实验或试验和错误)。
  2. 通过unifdef运行代码。
  3. 可选地,在视觉上比较源之前和之后以发现明显的问题。
  4. 构建after版本以确保正确构建。
  5. 编译之前和之后的版本以使用相同的makefile生成预处理的输出。
  6. 比较预处理源之前和之后的对。 它们应该相同,给予或占用一些空白区域。
  7. 根据需要通过编辑版本之前或之后来解决问题。
  8. (可选)从所有makefile中删除对该符号的所有引用。 [它应该没有区别。]
  9. 重复,使用after版本和不同的符号。

一次一个符号,每次都要彻底测试。 有些符号可能会变得太难,如果你有超过一百万行的源代码和一百多个符号,它们都会失控。

最后一步:如果您修改unifdef,请随时将您的更改贡献给社区。 做得好是一项非常具有挑战性的任务!

使用make -n创建makefile生成的shell脚本。 转到运行avr-g ++的行并在所有其他选项之前添加-dM -E。 转到-o之后的文件,#define的列表就在那里(它应该是something.o)使用unifdef -f defineFile.o filename

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM