How Kernel's Makefile Specify Output Directory
Posted on 21 Jan 2013, tagged kernelmake
When compiling Linux kernel, we could output files to a separate directory with “make O=”. The kernel’s way to do it is a little tricky. Since kernel’s Makefile is very big, we could have a simpler version to analyze:
ifeq ($(KBUILD_SRC),)
ifeq ("$(origin O)", "command line")
KBUILD_OUTPUT := $(O)
endif
ifneq ($(KBUILD_OUTPUT),)
$(filter-out submake $(CURDIR)/Makefile, $(MAKECMDGOALS)): sub-make
@:
sub-make:
make -C $(KBUILD_OUTPUT) -f /home/wangbin/maketest/Makefile \
KBUILD_SRC=$(PWD) \
$(MAKECMDGOALS)
@echo " sub-make KBUILD_OUTPUT: $(KBUILD_OUTPUT)"
skip-makefile := 1
endif #end KBUILD_OUTPUT
endif #end KBUILD_SRC
ifeq ($(skip-makefile),)
target1:
touch target1
@echo "target KBUILD_OUTPUT: $(KBUILD_OUTPUT)"
target2:
touch target2
@echo "target KBUILD_OUTPUT: $(KBUILD_OUTPUT)"
endif
You could try to execute make O=../build target1, it will output files to ../build. Let’s see how it works.
When you execute make, KBUILD_SRC is not defined at first, so it will make sub-make as a dependency of any target you input(except some filter-out target such as sub-make). Change the directory to KBUILD_OUTPUT(-C option), set KBUILD_SRC and then invoke itself again(-f option).
At the second time, KBUILD_SRC is defined so it will make the real targets.
The thing to notice is, while you make the real target1, variables between ifeq ($(KBUILD_SRC),) are not defined. You could see the output:
make -C ../build -f /home/wangbin/maketest/Makefile \
KBUILD_SRC=/home/wangbin/maketest \
target1
make[1]: Entering directory `/home/wangbin/build'
touch target1
target KBUILD_OUTPUT:
make[1]: Leaving directory `/home/wangbin/build'
sub-make KBUILD_OUTPUT: ../build