Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: Don WeingardenОтветов: 1

Я пытаюсь создать 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)
  • Я думаю, что отредактировал это правильно. Пожалуйста, проверьте и исправьте, если я этого не сделал. Etan Reisner 20.12.2014

dependenciesmakefilegnu

Ответы

Ответ 1 · рейтинг 1 · Beta

Проблема, похоже, в том, что у вашего 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, и это все, что вам действительно нужно.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы