在 Windows 下工作的极简 Makefile:
SRC := $(patsubst $(shell CHDIR )\\%.cpp,%.cpp,$(shell DIR *.cpp /S /B))
OBJ := $(addprefix obj\, $(SRC:.cpp=.o))
DEP := $(addprefix dep\, $(SRC:.cpp=.d))
CPPFLAGS = -MMD -MP -MF dep\$(<:.cpp=.d)
all: $(OBJ)
obj\\%.o: %.cpp
@IF NOT EXIST obj\$(<D) MKDIR obj\$(<D)
@IF NOT EXIST dep\$(<D) MKDIR dep\$(<D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<
-include $(DEP)
在obj 和dep 中创建子目录,以避免两个文件共享相同文件名但位于不同子目录中时发生冲突。它还避免了每次调用 make 时都重新编译子目录中的源文件。
更新:更强大的版本
WINDOWS SHELL(Vista 和更新,因为FORFILE 命令)
SRCDIR := .
OBJDIR := obj
DEPDIR := dep
SRCS := $(shell FORFILES /P $(SRCDIR) /S /M *.cpp /C "CMD /C ECHO @relpath")
SRCS := $(patsubst ".\\%",$(SRCDIR)\\%,$(SRCS))
OBJS := $(SRCS:$(SRCDIR)\\%.cpp=$(OBJDIR)\\%.o)
DEPS := $(SRCS:$(SRCDIR)\\%.cpp=$(DEPDIR)\\%.d)
TREE := $(patsubst %\,%,$(dir $(OBJS)))
CPPFLAGS = -MMD -MP -MF $(<:$(SRCDIR)\\%.cpp=$(DEPDIR)\\%.d)
.PHONY: all clean
all: $(OBJS)
.SECONDEXPANSION:
$(OBJDIR)\\%.o: $(SRCDIR)\%.cpp | $$(@D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<
$(TREE): %:
MKDIR $@
MKDIR $(@:$(OBJDIR)%=$(DEPDIR)%)
clean:
IF EXIST $(OBJDIR) RMDIR /S /Q $(OBJDIR)
IF EXIST $(DEPDIR) RMDIR /S /Q $(DEPDIR)
ifeq "$(MAKECMDGOALS)" ""
-include $(DEPS)
endif
UNIX 外壳
SRCDIR := .
OBJDIR := obj
DEPDIR := dep
SRCS := $(shell find $(SRCDIR) -name "*.cpp")
OBJS := $(SRCS:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEPS := $(SRCS:$(SRCDIR)/%.cpp=$(DEPDIR)/%.d)
TREE := $(patsubst %/,%,$(dir $(OBJS)))
CPPFLAGS = -MMD -MP -MF $(@:$(OBJDIR)/%.o=$(DEPDIR)/%.d)
.PHONY: all clean
all: $(OBJS)
.SECONDEXPANSION:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $$(@D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<
$(TREE): %:
mkdir -p $@
mkdir -p $(@:$(OBJDIR)%=$(DEPDIR)%)
clean:
$(RM) -r $(OBJDIR) $(DEPDIR)
ifeq "$(MAKECMDGOALS)" ""
-include $(DEPS)
endif