Как создать Make-файлы, где цель зависит от нескольких сборок Linux

У меня есть проект на основе Make, где для цели верхнего уровня требуется несколько двоичных файлов vmlinux (ядра linux) в качестве предварительных условий, поэтому это выглядит примерно так:

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

и каждое правило Linux выглядит более или менее так:

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)

Аналогично для ядер Linux и b. Обратите внимание, что у каждого могут быть одинаковые или разные исходные деревья, и почти наверняка они будут иметь разные defconfigs.

Это работает для чистых сборок, но мне не очень нравится делать рекурсивный вызов. В зависимости от того, как я настраиваю вышеупомянутые несколько строк, я, кажется, заканчиваю одним из:

  • ненужные рекурсивные преобразования в деревья linux, даже когда ничего не меняется (на это требуется 7 секунд, чтобы ничего не делать)
  • если я редактирую исходные коды linux, ядра не восстанавливаются, если я не коснусь явно.config или чего-то еще.

В идеале я хотел бы, чтобы мой Makefile верхнего уровня знал о графике внутренней зависимости каждого ядра Linux и "делал все правильно" при любых обстоятельствах. (то есть рекурсивный аргумент "сделай считай вредным").

Хотя я ожидаю, что Linux Makefile верхнего уровня не будет рад, если кто-то еще включит его, особенно несколько раз с разными конфигами и деревьями src! (У меня есть контроль над базой /makefile.inc bar/makefile.inc, поэтому они могут быть написаны так, чтобы они хорошо играли, когда включены верхним уровнем)

Или мне не повезло, и мне просто нужно помнить о прикосновении к.configs, чтобы вызвать достойное включение в каждый каталог сборки Linux?

Спасибо дэйв

РЕДАКТИРОВАТЬ: 7-секундный бесполезный приличный в дерево Linux выглядит так на моем махине:

$ 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

1 ответ

Решение

Для того, чтобы это работало правильно, вам действительно нужно заходить в исходные каталоги ядра при каждой сборке. 7 секунд действительно неплохо для проверки того, изменился ли какой-либо файл в массивном дереве ядра...

Включение make-файла ядра в вашу сборку как-то не поможет, потому что сама сборка ядра использует рекурсивное make.

Возможно, что-то вроде этого:

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

поскольку kernel-a-build является "фальшивой" целью (она не соответствует физическому файлу), она будет запускаться при каждой сборке, позволяя make-файлу ядра замечать изменения в исходных файлах.

Другие вопросы по тегам