Makefile编译多次相同的源

时间:2010-11-06 01:57:11

标签: makefile

** 编辑问题 **

以下是典型的Makefile模板:

TARGET   = my_prog               # project name

CC       = gcc -o
CFLAGS   = -Wall
SOURCES  := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS  := $(SOURCES:.c=*.o)
rm       = rm -f

$(TARGET): $(OBJECTS)
    @$(CC) $(TARGET) $(CFLAGS) $(SOURCES)
    @echo "Compilation complete!"

clean:
    @$(rm) $(TARGET) $(OBJECTS)
    @echo "Cleanup complete!"

问题:为什么第11行(@S(CC) $(TARGET) ...)在调用make时仍然回响?

答案:因为问题出在默认规则中,第11行也没问题。

** 更新 **

我现在有Makefile

# project name
TARGET   = my_prog

CC       = gcc -c
CFLAGS   = -Wall -I.
LINKER   = gcc -o
LFLAGS   = -Wall
SOURCES  := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS  := $(SOURCES:.c=*.o)
rm       = rm -f

$(TARGET): $(OBJECTS)
    $(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)

$(OBJECTS): $(SOURCES) $(INCLUDES)
    $(CC) $(CFLAGS) $(SOURCES)

clean:
    $(rm) $(TARGET) $(OBJECTS)

问题:为什么$(CC) $(CFLAGS) $(SOURCES)被执行 n 次,其中 n 是源文件的数量?

** 更新2 **

这是解决这个问题的好方法吗(似乎有效......)?

$(TARGET): obj
    $(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)

obj: $(SOURCES) $(INCLUDES)
    $(CC) $(CFLAGS) $(SOURCES)

2 个答案:

答案 0 :(得分:5)

命令$(CC) $(CFLAGS) $(SOURCES)执行n次,因为规则执行了n次,因为要构建n个对象,因为$(TARGET)规则有很多对象作为先决条件。如果希望命令仅运行一次,请将所有这些先决条件替换为单个PHONY先决条件,其规则执行命令。

但是没有理由这样做。您可以使命令更具选择性,以便它只构建一个作为实际目标的对象。这样Make不会浪费时间一遍又一遍地重建相同的对象,如果更改了一个或两个源文件,Make将仅重建相关对象,而不是全部:

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

这条规则是保守的 - 它假设每个对象都依赖于每个标题,因此它有时会不必要地重建事物。如果您了解真正的依赖关系,或者使用更先进的技术自动完成,您可以更好地实现它。

修改:

您的“更新2”是一个不错的解决方案,但我建议您添加一行

.PHONY: obj

告诉Make,没有名为“obj”的文件。否则,Make每次都会运行obj规则,尝试构建该文件。

如果您更改一个源文件,例如, foo.c,Make将重建所有对象。

我上面使用的$<automatic variable。它意味着“第一个先决条件”。因此,当Make尝试构建foo.o时,它将评估为foo.c

修改:

Jack Kelly(诅咒他!)指出我错误的PHONY目标是如何工作的:obj规则将始终运行,TARGET规则也是如此,无论是否源文件是否已更改。所以“更新2”方法是有效的,但很粗糙。

答案 1 :(得分:1)

我认为输出来自生成.o文件,而不是geverating my_prog

您似乎没有创建.o文件的规则,因此make使用的是默认值。

尝试这个:

@echo "starting compilation"

在第11行构建命令之前的行

你可以看到在gcc行之后输出“开始编译”。

也许第10行应该是:

$(TARGET): $(SOURCES)