Сборка нескольких конфигураций из одного исходного кода в одном make-файле - PullRequest
3 голосов
/ 14 ноября 2011

У меня есть небольшой набор файлов исходного кода для C. Я пытаюсь собрать для них Makefile, который создает несколько разных выходных данных из одного и того же набора исходного кода. Каждый вывод настраивается с использованием переменных, специфичных для цели.

(Реальный пример - микропрограмма, которая работает на нескольких разных версиях печатной платы, но построена из того же исходного кода и настроена с использованием условной компиляции.)

Вот пример Makefile, иллюстрирующий проблемы, с которыми я столкнулся:

CINPUTFILES = Testfile.c

all: v12target v13target

# the same source code is built several different ways depending on a
# list of preset configurations
v12target: lots_of_common_variables = hello
v12target: more_variables = v12_specific
v12target: Rev12Output.mycommontargets

v13target: lots_of_common_variables = hello
v13target: more_variables = v13_specific
v13target: Rev13Output.mycommontargets

# (more vXXtarget targets omitted)

# TODO:  why is @echo required?
%.mycommontargets: %.hex %.elf
    @echo

# TODO: why are these output files deleted?
%.elf: $(CINPUTFILES)
    cp $< $@

%.hex: %.elf
    cp $< $@

# TODO: correct way of adding the dummy mycommontargets to PHONY?
.PHONY : all clean

Идея состоит в том, что цель all создает несколько различных целей - по одной для каждой аппаратной ревизии. Поскольку процесс сборки для каждого идентичен, за исключением списка переменных конфигурации, он вызывает число vXXtarget целей, которые устанавливают переменные, а затем вызывает общую цель: %.mycommontargets. Затем эта цель приступает к генерации фактических выходных файлов.

Обратите внимание на отметки TODO ...

  1. %.mycommontargets: по какой-то причине, если я удаляю @echo, я получаю сообщение об ошибке:

    make: *** No rule to make target `Rev12Output.mycommontargets', needed by `v12target'.  Stop.
    

    Почему это происходит и что мне нужно сделать, чтобы от него избавиться?

  2. Если я оставлю @echo на месте, сборка будет успешно завершена. Но затем make решает все равно удалить и удалить!

    $ make
    cp Testfile.c Rev12Output.elf
    cp Rev12Output.elf Rev12Output.hex
    
    cp Testfile.c Rev13Output.elf
    cp Rev13Output.elf Rev13Output.hex
    
    rm Rev12Output.hex Rev12Output.elf Rev13Output.hex Rev13Output.elf
    

    Почему заставляет это делать? Что решает, когда он это сделает, а когда нет? Я никогда раньше не понимал, что у make даже была возможность удалять такие файлы; это противоречит всей идее инкрементных сборок, которая, как я думал, должна была помочь make. Я бы предпочел сохранить все промежуточные и выходные файлы ...

  3. Как правильно добавить шаблон mycommontargets в .PHONY?

Полагаю, я мог бы оставить @echo на месте, а затем добавить каждую цель к .PRECIOUS. Но хотя у меня нет большого опыта работы с make, у меня есть сильное чувство, что я делаю это неправильно, если мне нужно использовать хак, например @echo, и использовать более неясную специальную цель, такую ​​как .PRECIOUS. Просто не чувствую себя хорошо.

(Извиняюсь за то, что задаю 3 вопроса в одном месте, но у меня такое чувство, что они тесно связаны ...)

1 Ответ

1 голос
/ 14 ноября 2011
  1. Проблема в том, что для каждой не фальшивой цели необходимо создать правило. Однако вы не можете сделать цели шаблонных правил фальшивыми. В вашем случае я бы посоветовал оставить @echo (лучше: замените его на @true, чтобы избежать ложной строки вывода).
  2. Выходные файлы являются промежуточными файлами, то есть не упоминаются явно в Makefile, но требуются по шаблонным правилам. По умолчанию make удаляет все промежуточные файлы. Самый простой способ отключить автоматическое удаление здесь - это упомянуть цель .SECONDARY без предварительных условий, то есть добавить строку где-то, просто говоря:

    .SECONDARY:

  3. Если вам действительно нужен .PHONY здесь, вы должны жить без шаблонных правил. Что совершенно нежелательно в вашем макете, так что лучше пусть будет.

В целом, я бы предложил более ортодоксальный макет здесь. Обычно вы бы исключили проблемы кросс-компиляции из Makefile и указали бы хост-плату (на языке autotools: хост-плата - это плата, на которой будет работать программное обеспечение) в качестве аргумента configure. Давайте сконфигурируем генерацию одного дерева сборки для каждой платы хоста из центрального дерева исходников и встраивание в эти деревья сборки.

...