是否可以基于宏或变量有条件地编译/运行代码?

时间:2011-07-06 15:23:43

标签: c++ macros c-preprocessor conditional-compilation

我们在开发中有几个项目共享相同的代码库。某些代码只与这些项目中的一个或另一个相关。

我们有几个要求:

第一个要求是我们希望我们的最终版本不要在其他项目的代码中编译。

一个解决方案(我们喜欢的解决方案)是使用预处理器来删除代码:(这是我们在某些地方所做的)。

#if defined PROJECT1
{
    // some code
}
#endif

第二个要求是,在我们开发过程中,确保代码更改仍适用于所有项目是有帮助的,因此我们希望立即编译所有项目代码,并能够在没有重新编译的项目 - 所以在我们代码的其他地方,我们使用变量来确定项目:

if (project == 1)
{
    // some code
}

我希望能够做到的是结合两者的好处 - 代码在某些情况下(假设由#define REMOVECODE决定)根本不包含在最终的exe中,但在其他情况下(由REMOVECODE定义的非定义确定)将代码包含在已编译的.exe

还有一件事 - 有时我们会在几个项目中存在代码,因此解决方案需要处理“if project == 1 || project == 2”等测试

我认为它看起来像下面这样(这不起作用,因为我认为你不能嵌套预处理程序指令),但我不确定它是否甚至可以用于宏。也许有某种模板解决方案?

#ifdef REMOVECODE
    #define BEGINTEST #if
    #define ENDTEST   #endif
    #define CONDITION1 defined PROJECT1
#else
    #define BEGINTEST if
    #define ENDTEST
    #define CONDITION1 project == 1
#endif

BEGINTEST(CONDITION1)
{
    // some code
}
ENDTEST

如果有人可以提供帮助,我会非常感激。

6 个答案:

答案 0 :(得分:4)

如果测试中的条件是编译时常量,那么任何半好的优化编译器都会从目标文件中完全删除死代码。

因此,这样简单的事应该可以正常工作:

#ifdef REMOVECODE

#ifdef PROJECT1
#define CONDITION1 1
#else
#define CONDITION1 0
#endif

#else
#define CONDITION1 project == 1
#endif

...

if (CONDITION1)
{
    ...
}

使用-S(或等效的)运行编译器并查看生成的程序集以进行确认。

答案 1 :(得分:1)

它不起作用;你不能从宏等内部生成“预处理器指令”。

或者,更准确地说(因为你可以生成看起来像预处理器的指令,如图所示),如果你通过宏,标准生成看起来像预处理器指令的东西,符合预处理器的人不会将其识别为指令。

相同的评论适用于C和C ++:

ISO / IEC 14882:1998(C ++标准)

  

16.3.4重新扫描并进一步更换[cpp.rescan]

     

¶3由此产生的完全宏替换   预处理令牌序列不作为预处理进行处理   指令即使它类似于指令。

ISO / IEC 9899:1999(C标准)

  

6.10.3.4重新扫描和进一步更换

     

¶3不处理由此产生的完全宏替换的预处理标记序列   作为预处理指令,即使它类似于一个......,

(省略号继续提及C99 _Pragma功能。)

答案 2 :(得分:1)

如何让另一个定义说“构建一切”。然后使用

#if defined(PROJECT1) || defined(BUILDALL)
    ...
#endif

或者为了避免在任何地方添加|| defined(BUILDALL),您可以将其粘贴在可见的位置:

#ifdef BUILDALL
    #define PROJECT1
    #define PROJECT2
    //...
#endif

或者只使用定义的所有项目宏进行编译

答案 3 :(得分:0)

有一个夜间自动化的理智,重建所有项目并在每个项目上运行自动测试套件,你会知道是否有什么东西被打破了,这有什么不对?

我在这里看到的内容可能最终会出现在#ifdef群集中,或者出现额外的代码复杂性+错误。

答案 4 :(得分:0)

重构您的设计。将代码分解为更小的独立库。只链接每个项目所需的内容。否则,你最终会陷入非常复杂的混乱。

答案 5 :(得分:0)

定义控制操作 要么定义这些与否 如果未定义HARD_P1,则排除代码块。因此可以从编译结果中取出一个函数。 如果定义了SOFT_P1,则包含代码行。 如果未定义SOFT_P1,则会注释掉这些行。

#define HARD_P1
#define SOFT_P1

然后

#ifdef HARD_P1
#define P1
#ifdef SOFT_P1
#define USEP1
#else
#define USEP1 /##/
#endif
#endif

注意使用/ ## /,预处理器将用/ ## /粘贴/替换USEP1来生成// //然后将注释掉该行的其余部分。所以这可以用来排除单独的代码行。

代码

#ifdef P1
void test()
{
USEP1 if(project==1)
    {
    }
}
#endif