Построение иерархического Makefile с помощью GNU Make - PullRequest
2 голосов
/ 05 апреля 2011

У меня есть проект, разделенный на модули, каждый из которых размещен в каталоге, скажем:

root
|_module_A
 |_module.cpp
 |_Makefile
|_module_B
 |_Makefile
|_main.c
|_Makefile

main.c зависит от целей, определенных в Makefiles, связанных с module_A и module_B.

Я хочу написать свой root/Makefile относительно целей, определенных в Makefiles обоих модулей.

Теперь я знаю, что мог бы использовать директиву include, но проблема здесь в том, что цели и имена файлов в module_A и module_B не предшествуют их каталогу, поэтому я получаю что-то вроде этого:

make: *** No rule to make target `module.o', needed by `main.c'.  Stop.

Есть хороший способ решить эту проблему?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 06 апреля 2011

Есть несколько способов сделать это, но ни один из них не совершенен. Основная проблема в том, что Make хорош в использовании вещей там для создания вещей здесь , но не наоборот.

Вы не сказали, каковы цели в module_B; Я буду пессимистичен и предположу, что у module_A и module_B есть цели, называемые module (разные исходные файлы, разные рецепты), поэтому вы действительно не можете использовать include.

Самый большой выбор, который вам нужно сделать, - использовать ли рекурсивный Make:

Если вы этого не сделаете, тогда root/Makefile должен знать, как создавать module_A/module и module_B/module, поэтому вам просто нужно будет вставить эти правила. Затем вы должны либо оставить избыточные правила в make-файлах подкаталога. (и рискуют, что они дойдут до несогласия с основным make-файлом), или устранят их, или заставят их рекурсивно вызывать главный make-файл (что вам не придется делать очень часто, но это будет выглядеть глупо) .

Если вы это сделаете, то root/Makefile будет выглядеть примерно так:

main: main.o module_A/module.o Module_B/module.o
    ...

main.o: main.c
    ...

%/module.o:
    $(MAKE) -C $(@D) $(@F)

Это будет работать достаточно хорошо, но он ничего не будет знать о зависимостях в подкаталогах, поэтому иногда не удается восстановить устаревший объект. Вы можете make clean (рекурсивно) заранее каждый раз, просто чтобы быть в безопасности, грубо, но эффективно. Или примените правило %/module.o, которое менее расточительно, но немного сложнее. Или скопируйте информацию о зависимостях в root/Makefile, что утомительно и неопрятно.

Это просто вопрос ваших приоритетов.

1 голос
/ 08 апреля 2011

Разве вы не можете написать make-файл нерекурсивным способом?

Рекурсивное создание считается вредным

...