是否有一个C预处理器可以消除#ifdefs但还会评估预处理器宏?

我有一个项目,做了很多这个

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) // do some legacy stuff #else // do current stuff #endif 

其中KERNEL_VERSION定义为

 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) 

我想消除与当前版本无关的定义,但像sunifdef这样的工具不会评估KERNEL_VERSION宏,所以类似于

  sunifdef --replace -DKERNEL_VERSION\(a,b,c\)=\(\(\(a\)\<\<16\)+\(\(b\)\<\<8\)+\(c\)\) -DLINUX_VERSION_CODE=3.13.1 * 

失败了

sunifdef:错误0x04200:参数中的垃圾“-DKERNEL_VERSION(a,b,c)=(((a)<< 16)+((b)<< 8)+(c))”

我该如何解决这个问题?

对于sunifdef 3.1.3,你无法做到,正如你所展示的那样。 你也不能用早期版本的coan做到这一点,比如4.2.2。

但是,使用coan 5.2(当前版本),您几乎可以完成您所追求的目标。

 $ cat legacy.c #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) do(some,legacy,stuff) #else do(current,stuff) #endif $ coan source -DLINUX_VERSION_CODE=0x020635 legacy.c coan: /Users/jleffler/soq/legacy.c: line 1: warning 0x0041c: "-DKERNEL_VERSION(a,b,c)=(((a) << 16) + ((b) << 8) + (c))" has been assumed for the current file #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) do(current,stuff) $ coan source -DLINUX_VERSION_CODE=0x020624 legacy.c coan: /Users/jleffler/soq/legacy.c: line 1: warning 0x0041c: "-DKERNEL_VERSION(a,b,c)=(((a) << 16) + ((b) << 8) + (c))" has been assumed for the current file #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) do(some,legacy,stuff) $ 

这很接近你想要的,但并不完全。 它给出了'正确'输出,但可能不是'有用'输出。 它为您提供了为命令行中指定的LINUX_VERSION_CODE编译的代码,而您可能希望基于LINUX_VERSION_CODEKERNEL_VERSION的条件不是错误的,可以存入输出。

sunifdef的继任者似乎是coan ,以下命令似乎有效(在一个简单的文件上):

 coan source "-DLINUX_VERSION=KERNEL_VERSION(2,18,1)" \ "-DKERNEL_VERSION(a,b,c)=((a)*0x10000 + (b)*0x100 + (c))" \ testfile.c 

我认为使用KERNEL_VERSION宏来定义LINUX_VERSION比较漂亮,但你可能更喜欢Chris Dodd的hex版本。 一个数字中的两个点绝对不会起作用。

该错误来自于您无法使用-D在命令行上使用参数定义宏 – 您只能定义简单宏。 但是,您不应该在命令行上定义KERNEL_VERSION ,因为源中的#define应该没问题。 你应该只需要
-DLINUX_VERSION_CODE=0x30d01 – 您需要将其定义为单个整数常量(hex最简单)而不是带点。