分离特定的#ifdef分支。

6
简而言之:我希望仅根据一个预处理器宏的定义和另一个未定义,从当前源代码树中生成两个不同的源代码树,而不对源代码进行其他更改。
如果您有兴趣,这是我的故事...
一开始,我的代码很清晰。然后我们推出了一个新产品,这确实更好。但代码只涉及相同的外围设备,所以我们可以保持相同的代码。
好吧,几乎是这样。
有一个小条件需要更改,因此我添加了:
#if defined(PRODUCT_A)
condition = checkCat();
#elif defined(PRODUCT_B)
condition = checkCat() && checkHat();
#endif

将所有源文件包含到一个且仅一个源文件中。在通用的所有源文件都包含此头文件中,我有:

#if !(defined(PRODUCT_A)||defined(PRODUCT_B))
#error "Don't make me replace you with a small shell script. RTFM."
#endif

...以便人们无法编译它,除非他们明确定义了产品类型。

一切都很好。哦...除了进行了修改、更改了组件,并且由于新的硬件效果更好,我们可以显着地重写控制系统。现在当我看着这段代码时,有60多个不同的区域被划分为:

#ifdef PRODUCT_A
...
#else
...
#endif

...或者相同的内容,但是针对PRODUCT_B。甚至可以是:

#if defined(PRODUCT_A)
...
#elif defined(PRODUCT_B)
...
#endif

当然,有时候理智会休息更长的时间,比如:
#ifdef PRODUCT_A
...
#endif
#ifdef PRODUCT_B
...
#endif

这些条件涵盖了从一到两百行不等的内容(你可能认为最后一个可以通过切换头文件来完成,但函数名称需要相同)。
这太疯狂了。我最好在源代码库中维护两个单独的基于产品的分支,并移植任何通用更改。我现在意识到了这一点。
是否有什么东西可以根据仅定义“PRODUCT_A”和未定义“PRODUCT_B”(反之亦然)来生成我需要的两个不同的源代码树,而不接触其他任何东西(即没有头文件包含、没有宏扩展等)?

2
这就是分支的作用。 - rlbond
起初,为了一个不同的条件而创建一个包含72个源文件和头文件的树新分支似乎有些愚蠢。我们认为,对两个产品都通用的更改会更加普遍,而且如果使用单独的分支,我们需要一直进行更改的移植。然而,现实显然是不同的。 - detly
源代码就像你的房间,你必须定期清理它。否则你最终会得到一个又大又臭的混乱。分支是为了处理这种复杂性而产生的。最好的部分是,在良好的版本控制系统中跨分支合并错误修复是微不足道的。 - Sam Post
可能是 https://dev59.com/TXRB5IYBdhLWcg3wv5tA 的重复问题,是否有一个 C 预处理器可以根据定义的值消除 ifdef 块? - Michael Burr
1
好像是这样。说实话,那个标题并没有太大帮助。 - detly
1个回答

6
我相信Coan可以完成你所需的功能。从链接中可以得知:
给定配置和一些源代码,Coan可以回答一系列关于如果预先应用这些符号配置,源代码将如何出现在C/C++预处理器中的问题。
此外,由Coan重写的源代码不是由C预处理器生成的预处理代码。它仍然包含注释、宏调用和#-指令。它仍然是源代码,但根据所选配置进行了简化。
因此,您可以先运行它一次,指定产品A,然后再运行一次,指定产品B。

我希望我能够点两次这个。 - detly
我最终为Coan创建了一个PPA(个人软件包存档),因为我经常使用它。 - detly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接