**问题编辑**
这是一个典型的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!"
Run Code Online (Sandbox Code Playgroud)
问题:为什么线路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)
Run Code Online (Sandbox Code Playgroud)
问题:为什么$(CC) $(CFLAGS) $(SOURCES)
要执行n次,其中n是源文件的数量?
**更新2**
这是解决这个问题的好方法吗(似乎有效......)?
$(TARGET): obj
$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
obj: $(SOURCES) $(INCLUDES)
$(CC) $(CFLAGS) $(SOURCES)
Run Code Online (Sandbox Code Playgroud)
该命令$(CC) $(CFLAGS) $(SOURCES)
执行n次,因为该规则执行了n次,因为要构建n个对象,因为该$(TARGET)
规则具有许多对象作为先决条件.如果希望命令仅运行一次,请使用一个PHONY
先决条件替换所有这些先决条件,其先决条件的规则将执行命令.
但是没有理由这样做.您可以使命令更具选择性,以便它只构建一个作为实际目标的对象.这样Make不会浪费时间一遍又一遍地重建相同的对象,如果更改了一个或两个源文件,Make将仅重建相关对象,而不是全部:
$(OBJECTS): %.o : %.c $(INCLUDES)
$(CC) $(CFLAGS) $<
Run Code Online (Sandbox Code Playgroud)
这个规则是保守的 - 它假设每个对象都依赖于每个头,因此它有时会不必要地重建事物.如果您了解真正的依赖关系或使用更高级的技术自动,您可以手动更好.
编辑:
您的"更新2"是一个不错的解决方案,但我建议您添加该行
.PHONY: obj
Run Code Online (Sandbox Code Playgroud)
告诉Make,没有名为"obj"的文件.否则Make会obj
每次运行规则,尝试构建该文件.
这仍然存在这样的问题:如果您更改一个源文件,例如foo.c
,Make将重建所有对象.
在$<
上面使用的I是一个自动可变的.它意味着"第一个先决条件".因此,当Make尝试构建时foo.o
,它将评估为foo.c
.
编辑:
杰克凯利(诅咒他!)已经指出我错误的PHONY目标是如何工作的:obj
规则将始终运行,TARGET
规则也是如此,无论源文件是否发生了变化.所以"更新2"方法是有效的,但粗糙.