Как включить автоматические зависимости GNU make с пользовательскими шагами сборки

Я пытаюсь создать Makefile с несколькими источниками в нескольких каталогах. Я очень близок, но зависимости работают неправильно. Файлы .d создаются правильно. Он правильно перечисляет sample.o: sample.c options.h. Если я изменяю sample.c, он перекомпилируется и связывается. Если я изменяю options.h, он говорит, что все обновлено. Я считаю, что проблема в том, что явное правило компиляции .c в .o переопределяет правило из файла .d. Вопрос в том, как включить зависимость и определить собственное правило для ее создания?

образец.с:

#include "options.h"
int main(int argc, char** argv) {return(0);}

параметры.ч:

#define SAMPLE 1 

структура каталогов

     ---------- dir1
                options.h      
     ---------- dir2
                sample.c
     ---------- output
                sample.o
                sample.d

Makefile:

TARGET=output/sample
CC=gcc
CFLAGS=-Wall -O2 -g  
LDFLAGS=-g
LIBS+=-lm
PATHS=-Idir1 -Idir1/dir2
CORE_SRC += sample.c  
SRCS+= $(addprefix dir1/dir2/, $(CORE_SRC))  
OBJS:= $(addprefix output/, $(SRCS:.c=.o))
DEPS:= $(OBJS:.o=.d)

.PHONY: all
all: $(TARGET)

$(TARGET) : $(OBJS) $(DEPS)
    @echo "Linking ..."
    $(CC) $(LDFLAGS) -o $@  $(OBJS) 

output/%.d: %.c 
    @echo "generating dependency  $@"
    @mkdir -p output/$(dir $*.d)
    $(CC) -MM $(CFLAGS) $(PATHS) $^ > output/$*.d
    @mv -f output/$*.d output/$*.d.tmp
    @sed -e 's|.*:|$*.o:|' < output/$*.d.tmp > output/$*.d
    @sed -e 's/.*://' -e 's/\\$$//' < output/$*.d.tmp | fmt -1 | \
      sed -e 's/^ *//' -e 's/$$/:/' >> output/$*.d
    @rm -f output/$*.d.tmp

output/%.o: %.c output/%.d
    @echo "Compiling $@ from $*.c"
    @mkdir -p output/$(dir $*.o)
    $(CC) -c $(CFLAGS) $(PATHS) $*.c -o output/$*.o

-include $(DEPS)

person Don Weingarden    schedule 19.12.2014    source источник
comment
Я думаю, что отредактировал это правильно. Пожалуйста, проверьте и исправьте, если я этого не сделал.   -  person Etan Reisner    schedule 20.12.2014


Ответы (1)


Проблема, похоже, в том, что у вашего sample.d есть правило для sample.o:

sample.o: sample.c options.h

но это правило на самом деле не помогает, так как цель, которую вы пытаетесь создать, не sample.o, а output/dir1/dir2/sample.o.

Вы можете повозиться со своим правилом output/%.d, но я думаю, что гораздо проще упростить всю схему. Удалите правило output/%.d и измените эти два:

$(TARGET) : $(OBJS)
    @echo "Linking ..."
    $(CC) $(LDFLAGS) -o $@ $^

output/%.o: %.c
    @echo "Compiling $@ from $*.c"
    @mkdir -p output/$(dir $*.o)
    $(CC) -c $(CFLAGS) $(PATHS) -MMD $< -o $@

Таким образом, Make создаст sample.d как побочный эффект сборки sample.o, и это все, что вам действительно нужно.

person Beta    schedule 20.12.2014
comment
@EtanReisner: он действительно автоматически подбирает новые зависимости заголовков (но только тогда, когда они необходимы) и действительно исправляет пути в файле .d. Попытайся! - person Beta; 21.12.2014
comment
Честно говоря, я не был уверен в содержимом файла .d. Это был настоящий (в стиле lazyweb) вопрос. О, конечно, он подбирает только новые файлы заголовков... вам нужно изменить файл .c, чтобы добавить их. Извините за шум. знак равно - person Etan Reisner; 22.12.2014
comment
@EtanReisner: Это хитрый трюк, не так ли? Хотел бы я сказать, что изобрел его, но заслуга принадлежит Тому Троми. . - person Beta; 22.12.2014
comment
Да. Как только вы объяснили это, я вспомнил, что мне нужно было убедить себя, что сработало чисто, когда я прочитал эту страницу в первую очередь. Я все еще задаюсь вопросом, принесет ли конкретное перечисление файла .d в этой цели какую-то пользу, но я не проработал его полностью. - person Etan Reisner; 22.12.2014
comment
Это определенно чище. Единственная оставшаяся проблема заключается в том, что он не обнаруживает, когда я изменяю options.h. Если отредактировать/пощупать options.h а потом переделать без очистки, то пишет ничего делать не надо для всех. Файл .d правильно указывает options.h как зависимость для sample.o, но он просто не работает. - person Don Weingarden; 22.12.2014