Hầu hết các câu trả lời đều phức tạp hoặc sai một cách đáng ngạc nhiên. Tuy nhiên, các ví dụ đơn giản và mạnh mẽ đã được đăng ở nơi khác [ codereview ]. Phải thừa nhận rằng các tùy chọn được cung cấp bởi bộ tiền xử lý gnu hơi khó hiểu. Tuy nhiên, việc xóa tất cả các thư mục khỏi mục tiêu xây dựng với -MM
được ghi lại và không phải là lỗi [ gpp ]:
Theo mặc định, CPP lấy tên của tệp đầu vào chính, xóa bất kỳ
thành phần thư mục nào và bất kỳ hậu tố tệp nào chẳng hạn như '.c' và thêm vào hậu tố đối tượng thông thường của nền tảng.
-MMD
Tùy chọn (hơi mới hơn) có thể là những gì bạn muốn. Để có tính hoàn chỉnh, hãy lấy một ví dụ về makefile hỗ trợ nhiều mã src và xây dựng các dirs với một số chú thích. Đối với một phiên bản đơn giản không có trình xây dựng, hãy xem [ codereview ].
CXX = clang++
CXX_FLAGS = -Wfatal-errors -Wall -Wextra -Wpedantic -Wconversion -Wshadow
# Final binary
BIN = mybin
# Put all auto generated stuff to this build dir.
BUILD_DIR = ./build
# List of all .cpp source files.
CPP = main.cpp $(wildcard dir1/*.cpp) $(wildcard dir2/*.cpp)
# All .o files go to build dir.
OBJ = $(CPP:%.cpp=$(BUILD_DIR)/%.o)
# Gcc/Clang will create these .d files containing dependencies.
DEP = $(OBJ:%.o=%.d)
# Default target named after the binary.
$(BIN) : $(BUILD_DIR)/$(BIN)
# Actual target of the binary - depends on all .o files.
$(BUILD_DIR)/$(BIN) : $(OBJ)
# Create build directories - same structure as sources.
mkdir -p $(@D)
# Just link all the object files.
$(CXX) $(CXX_FLAGS) $^ -o $@
# Include all .d files
-include $(DEP)
# Build target for every single object file.
# The potential dependency on header files is covered
# by calling `-include $(DEP)`.
$(BUILD_DIR)/%.o : %.cpp
mkdir -p $(@D)
# The -MMD flags additionaly creates a .d file with
# the same name as the .o file.
$(CXX) $(CXX_FLAGS) -MMD -c $< -o $@
.PHONY : clean
clean :
# This should remove all generated files.
-rm $(BUILD_DIR)/$(BIN) $(OBJ) $(DEP)
Phương pháp này hoạt động bởi vì nếu có nhiều dòng phụ thuộc cho một mục tiêu duy nhất, các dòng phụ thuộc sẽ được nối đơn giản, ví dụ:
a.o: a.h
a.o: a.c
./cmd
tương đương với:
a.o: a.c a.h
./cmd
như đã đề cập tại: Makefile nhiều dòng phụ thuộc cho một mục tiêu duy nhất?