Question

I have a Make-based project where the top-level target requires multiple vmlinux binaries (linux kernels) as pre-requisites, so it looks something like:

all: bigfile
bigfile: bigfile.cfg a/vmlinux b/vmlinux c/vmlinux foo bar baz
    sometool -obigfile -ibigfile.cfg # other inputs referenced from within the config

and each linux rule looks more or less like:

a/vmlinux: a/.config
    $(MAKE) -C $(A_LINUX_SRC) O=$(PWD)/a vmlinux
a/.config
    mkdir -p a
    $(MAKE) -C $(A_LINUX_SRC) O=$(PWD)/a $(A_LINUX_DEFCONFIG)

Similarly for b and c linux kernels. Note each may have the same or different source trees, and almost certainly will have different defconfigs.

This works for clean builds but I don't really like the recursive call to make. Depending on how I tweak the above few lines, I seem to end up with either one of:

  • unnecessary recursive makes into linux trees even when nothing changes (which takes 7 seconds to do nothing)
  • if I edit linux sources, kernel's aren't re-generated unless I explicitly touch the .config or something.

Ideally, I'd like my top level Makefile to be aware of the interior dependancy graph of each linux kernel and "do the right thing" under all circumstances. (i.e the recursive-make-considered-harmful argument).

Although I expect the top-level Linux Makefile won't be happy to be included by some one else, especially multiple times with different configs and src trees! (I have control over baz/makefile.inc bar/makefile.inc so they can be written to play nice when included by the top level)

Or am I out of luck, and will just have to remember to touch .configs to trigger a decent into each linux build dir?

Thanks, Dave

EDIT: the 7-second useless decent into a linux tree looks like this on my mahchine:

$ time make
make -C /home/davidm/md/tests/linux O=/home/davidm/md/tests/linux_a vmlinux 
make[1]: Entering directory `/home/davidm/linux-2.6.38'
  Using /home/davidm/linux-2.6.38 as source for kernel
  GEN     /home/davidm/md/tests/linux_a/Makefile
  CHK     include/linux/version.h
  CHK     include/generated/utsrelease.h
make[3]: `include/generated/mach-types.h' is up to date.
  CALL    /home/davidm/md/linux-2.6.38/scripts/checksyscalls.sh
  CHK     include/generated/compile.h
make[1]: Leaving directory `/home/davidm/md/linux-2.6.38'

real    0m6.577s
user    0m2.930s
sys 0m1.360s
Was it helpful?

Solution

In order for this to work correctly, you really do have to recurse into the kernel source directories on every build. 7 seconds really isn't that bad for checking whether any file in the massive kernel tree has changed...

Including the kernel makefile in your build somehow wouldn't actually help, because the kernel build itself uses recursive make.

Perhaps something like this:

a/.config
        mkdir -p a
        $(MAKE) -C $(A_LINUX_SRC) O=$(PWD)/a $(A_LINUX_DEFCONFIG)

.PHONY: kernel-a-build
kernel-a-build: a/.config
        $(MAKE) -C $(A_LINUX_SRC) O=$(PWD)/a vmlinux

bigfile: kernel-a-build

Since kernel-a-build is a "phony" target (it doesn't correspond to a physical file), it will be run on every single build, allowing the kernel makefile to notice changes to the source files.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top