这是 makefile:
.PHONY: all clean
CC = gcc
CFLAGS = -g -m32 -std=c17
BIN = bin
ALG_SRCS = $(wildcard alg/*.c)
COMMON_SRCS = $(wildcard *.c)
ALG_OBJS = $(patsubst alg/%.c, $(BIN)/%.o, $(ALG_SRCS))
COMMON_OBJS = $(patsubst %.c, $(BIN)/%.o, $(COMMON_SRCS))
ALG_EXES = $(patsubst alg/%.c, $(BIN)/%, $(ALG_SRCS))
all: $(ALG_EXES)
$(BIN)/%: $(BIN)/%.o $(COMMON_OBJS) | $(BIN)
$(CC) $(CFLAGS) -o $@ $^ -lncursesw
$(BIN)/%.o: %.c | $(BIN)
$(CC) $(CFLAGS) -c $< -o $@
$(BIN)/%.o: alg/%.c | $(BIN)
$(CC) $(CFLAGS) -c $< -o $@
$(BIN):
mkdir -p $(BIN)
clean:
rm -rf $(BIN)
执行示例:
$ make
mkdir -p bin
gcc -g -m32 -std=c17 -c alg/basic.c -o bin/basic.o
gcc -g -m32 -std=c17 -c graph.c -o bin/graph.o
gcc -g -m32 -std=c17 -c grid.c -o bin/grid.o
gcc -g -m32 -std=c17 -c main.c -o bin/main.o
gcc -g -m32 -std=c17 -o bin/basic bin/basic.o bin/graph.o bin/grid.o bin/main.o -lncursesw
gcc -g -m32 -std=c17 -c alg/colors.c -o bin/colors.o
gcc -g -m32 -std=c17 -o bin/colors bin/colors.o bin/graph.o bin/grid.o bin/main.o -lncursesw
rm bin/main.o bin/graph.o bin/basic.o bin/colors.o bin/grid.o
我没有要求删除目标文件,也没有叫“干净”。为什么还是会出现
rm bin/main.o bin/graph.o bin/basic.o bin/colors.o bin/grid.o
?
您确定您向我们展示了该输出的正确 makefile 吗? 这对我来说看起来非常错误,当我在本地重新创建你的 makefile 和设置时,我没有看到你看到的行为。 您有什么版本的 GNU Make?
我得到的
rm
命令,以及我完全预期并且看起来正确的命令是:
rm bin/basic.o bin/colors.o
这是有道理的,因为这两个文件被视为中间文件(请参阅上面评论中发布的链接 urznow)。
其他目标文件不能是中间文件,因为它们在
$(BIN)/%: $(BIN)/%.o $(COMMON_OBJS)
规则中被明确列为先决条件。
无论如何,为了避免事情被认为是中间的,您可以将它们列为 makefile 中某些规则的先决条件(注意,该规则实际上不必运行,它只需要存在即可)。 因此,一种选择是添加一个“帮助程序”规则,如下所示:
objs: $(COMMON_OBJS) $(ALG_OBJS)
.PHONY: objs
(但是,正如我所说,在我的 makefile 重现中,这里只需要
$(ALG_OBJS)
)。 这列出了所有目标文件作为显式目标的先决条件,这使得它们成为非中间文件。
另一种选择是使用静态模式规则:
将构建二进制文件的规则从隐式规则(此处为模式规则)更改为显式规则。$(ALG_EXES): $(BIN)/%: $(BIN)/%.o $(COMMON_OBJS) | $(BIN)
$(CC) $(CFLAGS) -o $@ $^ -lncursesw
任何一种都可以。
顺便说一句,您可能希望在 makefile 中使用
:=
赋值,至少对于 wildcard
函数来说,只是为了获得一点效率。