GNU-Make не перекомпилируется при изменении файла заголовка

GNU-Make не перекомпилируется при изменении файла hdr.h. Как показано ниже, он не пытался перекомпилировать даже файл main.d. Можете ли вы указать мне, почему это произошло?

hdr.h

#ifndef __HDR_H__  

#define LOOP_CNT 1000  

#endif /* __HDR_H__ */  

main.c

#include <stdio.h>  
#include "hdr.h"  

int main(void)  
{  
    int i, sum = 0;  
    for (i = 0; i < LOOP_CNT; i++) sum += i;  
    (void)printf("sum = %d\n", sum);  
    return 0;  
}  

Makefile

SUFFIXES += .d

.PHONY: clean  

OBJECTS = $(patsubst %.c,%.o,$(wildcard *.c))  
CC = armcc  
LD = armcc  
CFLAGS += 

# Default target  
all: sum  

sum : $(OBJECTS)  
    $(CC) $(CFLAGS) -o $@ $^  

$(OBJECTS) : %.o : %.c   
    $(CC) $(CFLAGS) -o $@ -c $<  

# Generating dependency files  
%.d : %.c  
    @$(CC) -M $< > $@  

# Include dependency file to have gcc recompile necessary sources  
include $(patsubst %.c,%.d,$(wildcard *.c))  
#$(info $(patsubst %.c,%.d,$(wildcard *.c)))

clean:  
    rm -f *.o *.d core $(EXEC_NAME)  

Здесь напечатана строка в секунду.

C:\project\dep>make all
Makefile:24: main.d: No such file or directory
armcc    -o main.o -c main.c
armcc    -o sum main.o

C:\project\dep>make all
make: Nothing to be done for `all'. 

Файл main.d генерируется как показано ниже.

__image.axf: main.c
__image.axf: C:\Program Files\ARM\RVCT\Data\4.1\713\include\windows\stdio.h
__image.axf: hdr.h

4 ответа

Решение

Как быстрое и грязное исправление Makefile для восстановления, если заголовки меняются, я просто перечисляю все мои файлы заголовков, а затем добавляю $(HEADERS) как зависимость в части, которая строит объектные файлы из файлов Crc. Это не так эффективно, как могло бы быть, но я считаю, что это достаточно хорошо, то есть

HEADERS = \
    my_header.h \
    my_other_header.h

$(BUILD_DIR)/%.o: %.c $(HEADERS)
    $(LINK.c) $< -c -o $@

Проблема с Makefile заключается в следующем:

Неправильно:

$(OBJECTS) : %.o : %.c
    $(CC) $(CFLAGS) -o $@ -c $<

Исправьте (обратите внимание на добавленную зависимость%.d, %.c не может быть устранена):

$(OBJECTS) : %.o : %.c %.d
    $(CC) $(CFLAGS) -o $@ -c $<

Цепочка зависимостей выглядит следующим образом:

all
+->sum
   +->x.o
      +->x.c
---------------------------------
x.d
+->x.c
[generate rule: "x.d: x.c x.h"]

after include:
x.d
+->x.c
+->x.h

В оригинальной версии %.d правила действительно сработали, я думаю, include директивы несут ответственность (без этого, %.dне будет построен) Но даже если они срабатывают, ничто не связывает их с %.o файлы. Таким образом, даже если они будут восстановлены, из-за изменившихся %.h файлов, нет цепочки зависимостей %.o файлы.

Подключение цепочек зависимостей решает эту проблему.


Обратите внимание, что работает исправлено Makefile после clean сгенерирует сообщения об ошибках, подобные этому:

Makefile:123: x.d: No such file or directory

Как объясняется в документах make, когда include не могу найти Makefile, он выдает сообщение об ошибке, но на этом этапе он не считает это фатальной ошибкой и пытается найти правило, которое создаст отсутствующие файлы.

Добавление

$(info $(shell ls))

Рецепт создания / связывания объектного файла может подтвердить, что правила действительно существуют в то время.

Вообще говоря, если исходный файл необходимо скомпилировать для создания объектного файла, то его файл зависимостей также необходимо перестроить.

Таким образом, вместо того, чтобы иметь отдельную цель для .d файлы, просто восстановить его при компиляции. Чтобы достичь этого, простой подход заключается в замене

$(OBJECTS) : %.o : %.c   
    $(CC) $(CFLAGS) -o $@ -c $<  

# Generating dependency files  
%.d : %.c  
    @$(CC) -M $< > $@  

с

$(OBJECTS) : %.o : %.c   
    $(CC) $(CFLAGS) -o $@ -c $<  
    @$(CC) -M $< > $@  

Обратите внимание, что файл зависимостей будет восстановлен только после успешной компиляции. Если компиляция завершится неудачно, объектный файл будет удален, поэтому перекомпиляция будет принудительной, независимо от того, актуален ли файл зависимости.

Вы пытались очистить, прежде чем строить. Очистить и построить должно работать

Чтобы заставить его перестраивать ваши файлы зависимостей в случае изменения заголовочных файлов, вы можете изменить правило сборки для них примерно так:

%.d : %.c
        $(CC) -M $< > $@
        @$(CC) -M $< -MT $*.d >> $@  

поскольку это также добавит к правилам зависимости, которые говорят, что файл.d построен из файлов.c и.h.

Что касается того, как их заставить (пере) собрать в первую очередь - если ваша версия make слишком старая и не (пересобрать) их автоматически, вы можете получить что-то вроде этого:

all: depend subs

depend: $(patsubst %.c,%.d,$(wildcard *.c))

(Кроме того, я думаю, что это выглядело бы чище, если бы это было в переменной BTW, а также было бы более эффективным)

Или добавьте зависимость к созданию объекта следующим образом:

$(OBJECTS) : %.o : %.c %.d
    $(CC) $(CFLAGS) -o $@ -c $<  

Но оба решения потребуют от вас запустить make дважды, так как это не так include изменения в противном случае

Другие вопросы по тегам