правило makefile для создания нескольких целей без промежуточного файла

Я в тупике, придумывая правило makefile, чтобы иметь несколько исполняемых файлов, каждый из которых зависит от соответствующего исходного файла. Существует общая для всех библиотека, и каждая программа имеет один исходный файл: a.c, скомпилированный и связанный с библиотекой, выдает исполняемый файл a и т. д.

LIB_C_FILES = f1.c f2.c f3.c
LIB_H_FILES = f1.h f2.h f3.h
TARGETS = a b c
CFLAGS = -g -O0 -DDEBUG

.PHONY : all clean

.c.o:
    g++ -c $(CFLAGS) -o $@ $<

all:    $(TARGETS)

${TARGETS} : lib.a ${@:%=%.c}
        g++ $(CFLAGS) ${@:=.c} -o $@ lib.a

lib.a:  ${LIB_C_FILES:.c=.o}  $(LIB_H_FILES)
        ar r $@ $?

Библиотечная часть работает нормально. И когда исполняемый файл не существует, он также отлично работает. Но когда один из автономных исходных файлов изменяется, он говорит make: Nothing to be done for 'all'.

Я не понимаю, как правильно сделать так, чтобы цель a зависела от источника a.c отдельно в списке. Что мне не хватает?


person wallyk    schedule 03.04.2013    source источник
comment
Для справки: у этого вопроса было чрезмерное редактирование. В вопросе использовались заглавные расширения .C для файлов C. Это объясняет некоторую путаницу ниже.   -  person Peter    schedule 23.09.2013


Ответы (2)


Во-первых, я предполагаю, что fio.a была опечаткой (вы, вероятно, имели в виду lib.a).

Во-вторых, я думаю, что самая сложная часть — это ваше условие ${@:%=%.c}. Насколько я знаю, $@ нельзя использовать таким образом.

Я думаю, что вы можете получить поведение, которое ищете, используя .SECONDEXPANSION.

Пытаться:

.SECONDEXPANSION:
${TARGETS} : lib.a $$(patsubst %,%.c,$$@)

Для этого может существовать старый способ подстановки, но я считаю, что строка patsubst более читабельна, чем ${@:%=%.c}.

(Я должен добавить, что это относится к Gnu make 3.82. YMMV со старыми версиями Gnu make или [не дай Бог] версиям make, отличным от Gnu).

person Eric Miller    schedule 03.04.2013
comment
Действительно, fio.a должно быть lib.a. Имена были изменены, чтобы защитить невиновных. Я никогда раньше не сталкивался с SECONDEXPANSION. Я действительно использую make 3.82, так что попробую. - person wallyk; 04.04.2013
comment
Ура! Оно работает! Есть идеи, во что это расширяется? Казалось бы, очень похоже на мое правило.... - person wallyk; 04.04.2013
comment
Без .SECONDEXPANSION make пытается расширить $@ до того, как станут известны цели. С .SECONDEXPANSION $$@ расширяется до $@ при первом проходе, а затем, как только цели становятся известны, $@ может быть расширен, как и ожидалось. - person Eric Miller; 04.04.2013
comment
@bobbogo Я нахожу ваше правило статического шаблона более простым для понимания, чем мой метод .SECONDEXPANSION. Спасибо! - person Eric Miller; 04.04.2013

Просто для полноты: вы можете делать все, что хотите, с простыми старыми правилами статического шаблона, если вы можете сопоставить все ${TARGETS} с сопоставлением шаблона make (noddy).

${TARGETS}: %: %.C lib.a
    g++ ${CFLAGS} $< -o $@ lib.a

lib.a: ...
    ar ...

Чуть более читаемый и, возможно, более совместимый, чем .SECONDEXPANSION?

person bobbogo    schedule 04.04.2013
comment
Спасибо. Это более читабельно, но, увы, демонстрирует исходную проблему: обновление a.c не запускает правило. - person wallyk; 05.04.2013
comment
Извините, это была опечатка выше (слишком поздно для редактирования). Это действительно a.C. - person wallyk; 05.04.2013
comment
@wallyk: Хммм, не уверен, что верю вам --- в вашей среде должно быть что-то тонкое (у вас правильный Linux или это cygwin/migw и т. д.?). Попробуйте make -Rr -d --warn all. - person bobbogo; 05.04.2013
comment
Это Linux Fedora 16 (32-разрядная версия) и GNU Make 3.82. Что означает последовательность с несколькими двоеточиями? Я не видел этого раньше. - person wallyk; 05.04.2013
comment
Это правило статического шаблона (см. Сделать вручную). По сути, они точно такие же, как и обычные правила, но дают вам возможность указать зависимости, используя % в качестве подстановочного знака. (Опять же, для полноты: в рецепте вы можете использовать $* для расширения до любого текста, совпадающего с % в правиле.) Это намного приятнее, чем шаблонные правила (или неявные правила, как было бы в руководстве make это), и недостаточно используемая область make ИМХО. - person bobbogo; 05.04.2013