6

当 hdr.h 文件更改时,GNU-Make 不会重新编译。如下打印的行,即使生成了 main.d 文件,它也没有尝试重新编译。你能指导我为什么会这样吗?

硬盘驱动器

#ifndef __HDR_H__  

#define LOOP_CNT 1000  

#endif /* __HDR_H__ */  

主程序

#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;  
}  

生成文件

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

5 回答 5

3

作为一个快速而肮脏的 Makefile 修复,如果头文件发生变化,我只是列出我所有的头文件,然后$(HEADERS)作为依赖项添加到从 C src 文件构建目标文件的部分中。它没有尽可能高效,但我发现它足够好,即

HEADERS = \
    my_header.h \
    my_other_header.h

$(BUILD_DIR)/%.o: %.c $(HEADERS)
    $(LINK.c) $< -c -o $@
于 2017-05-17T10:30:51.080 回答
1

一般来说,如果需要编译一个源文件来创建一个目标文件,那么它的依赖文件也需要重建。

因此,与其为.d文件设置单独的目标,不如在编译时简单地重新生成它。为此,一个简单的方法是替换

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

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

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

请注意,仅当编译成功时才会重新生成依赖文件。如果编译失败,目标文件将被删除,因此无论依赖文件是否是最新的,都会强制重新编译。

于 2017-05-17T09:56:08.467 回答
1

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-s 将不会被构建)。但即使它们被触发,也没有任何东西将它们连接到%.o文件。因此,即使它们被重建,由于文件的改变%.h,文件也没有依赖链%.o

连接依赖链可以解决这个问题。


请注意,Makefile在 a 之后运行更正后clean会生成如下错误消息:

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

正如make docs中所解释的,当include找不到 a时Makefile,它会发出一条错误消息,但此时它并不认为这是一个致命错误,并尝试找到一个会创建丢失文件的规则。

添加

$(info $(shell ls))

到目标文件创建/链接配方可以确认当时确实存在规则。

于 2019-04-06T01:18:21.113 回答
0

如果头文件发生更改,要让它重建您的依赖文件,您可以将它们的构建规则更改为以下内容:

%.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改变

于 2017-05-17T11:16:14.270 回答
0

您是否在构建之前尝试过 make clean 。清理和构建应该可以工作

于 2017-05-17T09:36:28.350 回答