Мой репозиторий выглядит так:
./src/ModuleA/ModuleA.cpp
./src/ModuleA/ModuleA.h
./src/foo/ModuleB.cpp
./src/foo/ModuleB.h
./src/bar/ModuleC.cpp
./src/bar/ModuleC.h
<A few more modules>
./obj
./dep
./makefile
Я хочу создать make-файл, который будет создавать файл depndency (.d) для каждого файла .cpp в ./dep, а затем скомпилировать каждый из этих файлов .cpp в объект в ./obj
Я не хочу явно указывать имя и путь модулей — просто взять все каталоги в ./src, найти файл cpp в каждом и создать целевое правило для него.
Изменить: я использую окна.
Работающий минималистичный Makefile под Windows:
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
вызывается.
ОБНОВИТЬ: Более мощная версия
ОКНА ОКНА (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 SHELL
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
Один из самых простых make-файлов, которые вы можете сделать, выглядит следующим образом:
OBJDIR = .srcobjs
SRCS := $(shell find . -name '*.cpp')
SRCDIRS := $(shell find . -name '*.cpp' -exec dirname {} \; | uniq)
OBJS := $(patsubst %.cpp,$(OBJDIR)/%.o,$(SRCS))
DEPS := $(patsubst %.cpp,$(OBJDIR)/%.d,$(SRCS))
DEBUG = -g
INCLUDES = -I./Include
CXXFLAGS = $(DEBUG) -Wall -pedantic $(INCLUDES) -c
DEPENDS = -MT $@ -MD -MP -MF $(subst .o,.d,$@)
Он найдет все файлы .cpp и скомпилирует их.