Make 删除中间文件
Make removes files as intermediate
尝试将编译输出组织到构建目录时,make
不断删除目标文件。 Makefile
是:
MPI_INSTALLATION=/home/gkaf/Software/MPI
IDIR=$(MPI_INSTALLATION)/include
LDIR=$(MPI_INSTALLATION)/lib
CC=gcc
CFLAGS=-I$(IDIR)
LDFLAGS=-L$(LDIR) -Wl,-rpath=$(LDIR)
BUILD_DIR=build
OBJ_DIR=$(BUILD_DIR)/obj
BIN_DIR=$(BUILD_DIR)/bin
SRC_DIR=src
LIBS=-lmpi
.PHONY: all
all: test-mpi
.PHONY: test-mpi
test-mpi: prepare $(BIN_DIR)/test-mpi
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) -c -o $@ $< $(CFLAGS)
$(BIN_DIR)/%: $(OBJ_DIR)/%.o
$(CC) -o $@ $^ $(LDFLAGS) $(LIBS)
prepare: $(BUILD_DIR) $(OBJ_DIR) $(BIN_DIR)
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
$(BIN_DIR):
mkdir -p $(BIN_DIR)
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)
编译过程中生成的目标文件build/obj/test-mpi.o
在创建可执行文件build/bin/test-mpi
后删除。
我认为 make
将 build/obj/test-mpi.o
视为 intermediate file。但是,我期望 build/obj/test-mpi.o
不会被视为中间文件,因为它明确出现在目标 $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
中并且 gnu make 文档指出“通常,如果文件在将 makefile 作为目标或先决条件。
这种行为 has been reported 在一个类似的问题中,但我认为在这两种情况下,文件不应被视为中间文件,因为它们出现在目标中。我错过了什么吗?
I believe that make treats build/obj/test-mpi.o as an intermediate file.
是的,看起来不错。
However, I was expecting that build/obj/test-mpi.o
would not be treated as an intermediate file since it appears explicitly in the target $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
[...]
鉴于 $(OBJ_DIR)
扩展为 build/obj
, 模式 $(OBJ_DIR)/%.o
匹配 build/obj/test-mpi.o
。这与明确出现的 build/obj/test-mpi.o
相反。
即便如此,您已正确阅读 GNU make
文档:如果 make
被提及为某些目标或先决条件,则 make
不会将 build/obj/test-mpi.o
视为中间文件其他规则。但事实并非如此。如果 make
完全构建该文件,那完全是 make
的想法,尽管事实上您为其做出该决定奠定了基础。这正是中间文件的含义。
Am I missing something?
显然,正如 GNU 文档所说,您没有理解文件在 makefile 中“提及”的含义。这意味着文件名在宏扩展后作为规则的目标或先决条件出现在 makefile 文本中。示例:
$(BIN_DIR)/test-mpi: $(OBJ_DIR)/test-mpi.o
或
$(OBJ_DIR)/test-mpi.o: $(SRC_DIR)/test-mpi.c
匹配隐式(“模式”)规则的目标或先决条件模式是不够的。事实上,正是 make
旨在删除的隐式规则链中作为中间体生成的文件。在这方面,makefile 中定义的隐式规则与 make
的内置隐式规则没有区别。
但是,尽管像您询问的文件这样的文件肯定是中间文件,因为 GNU make
定义了该术语,make
在这里还有一项额外的功能可能会满足您的目的。如果要使用模式指定要保留的中间目标,则可以通过将模式指定为特殊目标的先决条件来实现 .PRECIOUS
,如下所示:
.PRECIOUS: $(OBJ_DIR)/%.o
匹配这种模式的中间文件将免于自动删除,否则它们将受到自动删除。
尝试将编译输出组织到构建目录时,make
不断删除目标文件。 Makefile
是:
MPI_INSTALLATION=/home/gkaf/Software/MPI
IDIR=$(MPI_INSTALLATION)/include
LDIR=$(MPI_INSTALLATION)/lib
CC=gcc
CFLAGS=-I$(IDIR)
LDFLAGS=-L$(LDIR) -Wl,-rpath=$(LDIR)
BUILD_DIR=build
OBJ_DIR=$(BUILD_DIR)/obj
BIN_DIR=$(BUILD_DIR)/bin
SRC_DIR=src
LIBS=-lmpi
.PHONY: all
all: test-mpi
.PHONY: test-mpi
test-mpi: prepare $(BIN_DIR)/test-mpi
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) -c -o $@ $< $(CFLAGS)
$(BIN_DIR)/%: $(OBJ_DIR)/%.o
$(CC) -o $@ $^ $(LDFLAGS) $(LIBS)
prepare: $(BUILD_DIR) $(OBJ_DIR) $(BIN_DIR)
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
$(BIN_DIR):
mkdir -p $(BIN_DIR)
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)
编译过程中生成的目标文件build/obj/test-mpi.o
在创建可执行文件build/bin/test-mpi
后删除。
我认为 make
将 build/obj/test-mpi.o
视为 intermediate file。但是,我期望 build/obj/test-mpi.o
不会被视为中间文件,因为它明确出现在目标 $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
中并且 gnu make 文档指出“通常,如果文件在将 makefile 作为目标或先决条件。
这种行为 has been reported 在一个类似的问题中,但我认为在这两种情况下,文件不应被视为中间文件,因为它们出现在目标中。我错过了什么吗?
I believe that make treats build/obj/test-mpi.o as an intermediate file.
是的,看起来不错。
However, I was expecting that
build/obj/test-mpi.o
would not be treated as an intermediate file since it appears explicitly in the target$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
[...]
鉴于 $(OBJ_DIR)
扩展为 build/obj
, 模式 $(OBJ_DIR)/%.o
匹配 build/obj/test-mpi.o
。这与明确出现的 build/obj/test-mpi.o
相反。
即便如此,您已正确阅读 GNU make
文档:如果 make
被提及为某些目标或先决条件,则 make
不会将 build/obj/test-mpi.o
视为中间文件其他规则。但事实并非如此。如果 make
完全构建该文件,那完全是 make
的想法,尽管事实上您为其做出该决定奠定了基础。这正是中间文件的含义。
Am I missing something?
显然,正如 GNU 文档所说,您没有理解文件在 makefile 中“提及”的含义。这意味着文件名在宏扩展后作为规则的目标或先决条件出现在 makefile 文本中。示例:
$(BIN_DIR)/test-mpi: $(OBJ_DIR)/test-mpi.o
或
$(OBJ_DIR)/test-mpi.o: $(SRC_DIR)/test-mpi.c
匹配隐式(“模式”)规则的目标或先决条件模式是不够的。事实上,正是 make
旨在删除的隐式规则链中作为中间体生成的文件。在这方面,makefile 中定义的隐式规则与 make
的内置隐式规则没有区别。
但是,尽管像您询问的文件这样的文件肯定是中间文件,因为 GNU make
定义了该术语,make
在这里还有一项额外的功能可能会满足您的目的。如果要使用模式指定要保留的中间目标,则可以通过将模式指定为特殊目标的先决条件来实现 .PRECIOUS
,如下所示:
.PRECIOUS: $(OBJ_DIR)/%.o
匹配这种模式的中间文件将免于自动删除,否则它们将受到自动删除。