问题
I'm having a project that does lots of this
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
// do some legacy stuff
#else
// do current stuff
#endif
where KERNEL_VERSION
is defined as
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
I'd like to eliminate the defines that are not relevant for the current version, but tools like sunifdef
don't evaluate the KERNEL_VERSION
macro, so something like
sunifdef --replace -DKERNEL_VERSION\(a,b,c\)=\(\(\(a\)\<\<16\)+\(\(b\)\<\<8\)+\(c\)\) -DLINUX_VERSION_CODE=3.13.1 *
fails with the message
sunifdef: error 0x04200: Garbage in argument "-DKERNEL_VERSION(a,b,c)=(((a)<<16)+((b)<<8)+(c))"
How do I get around this?
回答1:
With sunifdef 3.1.3, you can't do it, as you demonstrated. Nor can you do it with earlier versions of coan
such as 4.2.2.
However, with coan 5.2 (the current version), you can almost do what you are after.
$ 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)
$
This is close to what you want, but not quite. It gives 'correct' output, but maybe not 'helpful' output. It gives you the code that would be compiled for the LINUX_VERSION_CODE
specified on the command line, whereas you'd probably like the conditionals based on LINUX_VERSION_CODE
and KERNEL_VERSION
that are not false to survive into the output.
回答2:
The successor to sunifdef seems to be coan, and the following command seemed to work (on one simple file):
coan source "-DLINUX_VERSION=KERNEL_VERSION(2,18,1)" \
"-DKERNEL_VERSION(a,b,c)=((a)*0x10000 + (b)*0x100 + (c))" \
testfile.c
I think using the KERNEL_VERSION macro to define LINUX_VERSION is prettier, but you might prefer Chris Dodd's version in hex. Two dots in a number is definitely not going to work.
回答3:
The error is coming from the fact that you can't define macros with arguments on the command line with -D
-- you can only define simple macros. However, you shouldn't NEED to define KERNEL_VERSION
on the command line as the #define
in the source should be fine. You should only need -DLINUX_VERSION_CODE=0x30d01
-- you need to define it as a single integer constant (hex is easiest) rather than withs dots.
来源:https://stackoverflow.com/questions/18883193/is-there-a-c-preprocessor-that-eliminates-ifdefs-but-also-evaluates-preprocesso