我正在使用第三方开源项目,需要去掉不活动的 #ifs、#ifdefs 等以更好地理解代码流程。
有没有办法使用 make 来生成没有这些指令的源文件版本?我想避免扩展宏,只需删除指令即可。
我正在查看 https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html
看起来 -dD 和 -fdirectives-only 是不错的开始选择。
这些预处理过的文件会出现在哪里呢?在哪里添加这些命令以与 Makefile 和“make”一起使用?我尝试运行“make -n”来生成脚本,并在 -Wformat 等之后向脚本中的 g++ 和 gcc 调用添加选项,但我没有注意到任何事情。
我不确定这是否会使任何事情变得复杂,但我也在使用 avr-gcc 和 avr-g++。
我查看了 coan,它不支持 #included #defines,因此它无法用于此目的,并且我无法让 sunifdef 工作。有没有办法用预处理器来做到这一点。
这些定义分散在当前文件、包含的文件以及指定 -Dfoo=opt 选项的包含的 makefile 中。
您的预处理器选项走在正确的轨道上。-D 将定义一个值为 1 的宏,-U 将取消任何先前的定义(它将变为未定义),而 -fdirectives-only 将抑制宏扩展。除此之外,您还可以使用 gcc 的 -E 标志来告诉它以单独的文件形式提供预处理器输出以供您检查。但是,我认为它们不会完全符合您的期望。CPP(C 预处理器)输出可能添加了其他内容,如this SO question所建议的,您应该检查 gnu CPP 输出手册页。这就是你将从 CPP 得到的。
听起来您希望能够一次性剥离这些无关的代码并从那里进行开发。为此,我鼓励您再次尝试 unifdef。这就是 unifdef 的设计目的,而 CPP 的设计目的是为编译准备代码。它们是不同的任务,因此您应该为它们使用正确的工具。它可作为独立应用程序在http://dotat.at/prog/unifdef/上使用,并内置于某些Linux Shell中。
它允许您指定您希望其视为已定义或未定义的宏,并且它会删除条件指令计算结果为 false 的代码块。例如,您可以像这样运行它:
unifdef -I<路径> -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;
Run Code Online (Sandbox Code Playgroud)
如果我们像上面的例子一样调用 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;
Run Code Online (Sandbox Code Playgroud)
请注意,n 的声明已被删除,因为它包含在其控制表达式计算结果为 false 的预处理器#if/#endif块中(我们告诉 unifdef 将 MACRO2 视为未定义)。j 的声明仍然保留,但#ifdefand#endif语句被删除,因为已知控制表达式为 true。
依赖于 MACRO3 的块保持不变,因为它的状态未知。
其运行方式也具有很大的灵活性和控制力。
如果您决定确实希望它成为构建过程的一部分,则可以随时将其添加到 makefile 中。
如果您没有应定义或未定义的宏的列表,您可以使用 unifdef 提供的“unifdefall”脚本,它将使用 CPP 自行发现源代码中的宏定义,并删除/保留根据源代码中包含的定义的代码块。
是的,你可以(某种程度上)使用预处理器来完成它。但 unifdef 和 sunifdef 正是专门用于执行此操作的工具,因此您应该使用它们。