The way to capture the correct preprocessed translation unit for a kernel source file is to first determine the exact command line that is being used to compile the .o
. Then run the same command line, but add -E
. Also, change the -o
option.
To obtain the full kernel command line you have to add V=1
to the make
command line. To avoid searching through a long, verbose log, build everything first, then just remove the .o
in question, and rebuild with V=1
.
For instance, I'm compiling for arm
using a gcc called arm-linux-gnueabi-gcc
. To get the preprocessed version of kernel/spinlock.c
, this works in my case:
arm-linux-gnueabi-gcc
-E
-B arm-linux-gnueabi- -Wp,-MD,kernel/.spinlock.o.d -nostdinc -isystem /usr/lib/gcc/arm-linux-gnueabi/4.6/include -I/personal/localhome/kaz/git/kernel/arch/arm/include -Iarch/arm/include/generated -Iinclude -include include/generated/autoconf.h -D__KERNEL__ -mlittle-endian -Iarch/arm/mach-capri/include -Iarch/arm/plat-kona/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -O2 -marm -fno-dwarf2-cfi-asm -mabi=aapcs-linux -mno-thumb-interwork -funwind-tables -D__LINUX_ARM_ARCH__=7 -march=armv7-a -Uarm -mfpu=vfp3 -mfloat-abi=softfp -Wframe-larger-than=1024 -fno-stack-protector -Wno-unused-but-set-variable -fomit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fconserve-stack -DCC_HAVE_ASM_GOTO -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(spinlock)" -D"KBUILD_MODNAME=KBUILD_STR(spinlock)" -c
-o kernel/spinlock.prepro.c
kernel/spinlock.c
I cut and pasted the line from the verbose compiler output, added -E
and changed -o
to capture the output in a file. (You can remove the -o <arg>
to get it on standard output, of course).
Of course, many of the options in that command line do not affect preprocessing, but some do, such as anything that defines a macro, alters the include paths.
You don't want to be guessing at these things manually.
Note that if you invoke make
using make -C <dir> ...
, then make
changes directory to <dir>
before doing anything. It reads the Makefile
from that directory, and so forth; it is almost the same as executing the command (cd <dir>; make ...)
. In this case, the command line that you get out of the build output will contain relative paths that only resolve in <dir>
; change to <dir>
before trying to run the command, or wrap it with (cd <dir>; <command>)
.