How Kernel's Makefile Specify Output Directory

Posted on 21 Jan 2013, tagged kernelmake

When compile Linux kernel, we could output files to a split 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 analyse:

 1ifeq ($(KBUILD_SRC),)
 2ifeq ("$(origin O)", "command line")
 3        KBUILD_OUTPUT := $(O)
 4endif
 5
 6ifneq ($(KBUILD_OUTPUT),)
 7$(filter-out submake $(CURDIR)/Makefile, $(MAKECMDGOALS)): sub-make
 8        @:
 9
10sub-make:
11        make -C $(KBUILD_OUTPUT) -f /home/wangbin/maketest/Makefile \
12                KBUILD_SRC=$(PWD) \
13                $(MAKECMDGOALS)
14        @echo " sub-make KBUILD_OUTPUT: $(KBUILD_OUTPUT)"
15skip-makefile := 1
16endif #end KBUILD_OUTPUT
17endif #end KBUILD_SRC
18
19ifeq ($(skip-makefile),)
20
21target1:
22        touch target1
23        @echo "target KBUILD_OUTPUT: $(KBUILD_OUTPUT)"
24
25target2:
26        touch target2
27        @echo "target KBUILD_OUTPUT: $(KBUILD_OUTPUT)"
28endif

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),) is not defined. You could see the output:

1make -C ../build -f /home/wangbin/maketest/Makefile \
2                KBUILD_SRC=/home/wangbin/maketest \
3                target1
4make[1]: Entering directory `/home/wangbin/build'
5touch target1
6target KBUILD_OUTPUT: 
7make[1]: Leaving directory `/home/wangbin/build'
8sub-make KBUILD_OUTPUT: ../build
comments powered by Disqus