具有混合依赖性的 Makefile 模式规则
Makefile pattern rule with mixed dependencies
我在 Makefile 中编写了以下代码行:
PROJECTS = ExamsGenerator ExercisesImporter
VERSION = .v0.0
EXTENSION = .Exe
BINDIR = ../bin
CONFDIR = ../config
DATADIR = ../data
DOCDIR = ../doc
INCDIR = ../include
LIBDIR = ../lib
OBJDIR = ../obj
SRCDIR = ../src
INCDIRS = $(INCDIR:%=-I%)
CC = g++
CCVAR = -D__DATADIR__=\"$(DATADIR)\"
CFLAGS = -g -Wall $(shell root-config --cflags) $(INCDIRS)
LDFLAGS = -g -Wall $(shell root-config --ldflags)
LDLIBS = $(shell root-config --glibs)
MEG_DEP = Functions.h Parser.h Test.h
MEG_DEPS = $(patsubst %,$(INCDIR)/%,$(MEG_DEP))
MEI_DEP = Functions.h Parser.h Exercise.h
MEI_DEPS = $(patsubst %,$(INCDIR)/%,$(MEI_DEP))
MEG_OBJ = mainExamsGenerator.o Parser.o Test.o
MEG_OBJS = $(patsubst %,$(OBJDIR)/%,$(MEG_OBJ))
MEI_OBJ = mainExercisesImporter.o Parser.o Exercise.o
MEI_OBJS = $(patsubst %,$(OBJDIR)/%,$(MEI_OBJ))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(MEG_DEPS) $(MEI_DEPS)
@echo "\nCreating object: $@"
$(CC) $(CCVAR) $(CFLAGS) -c -o $@ $<
all: $(PROJECTS)
@echo "\n"
ExamsGenerator: $(MEG_OBJS)
@echo "\nLinking $@"
$(CC) $(CCVAR) $(CFLAGS) $(LDLIBS) -o $(BINDIR)/$(@)$(VERSION)$(EXTENSION) $^
ExercisesImporter: $(MEI_OBJS)
@echo "\nLinking $@"
$(CC) $(CCVAR) $(CFLAGS) $(LDLIBS) -o $(BINDIR)/$(@)$(VERSION)$(EXTENSION) $^
.SILENT:
.PHONY: clean
clean:
\rm -f $(BINDIR)/*$(EXTENSION) $(OBJDIR)/*.o *~ $(INCDIR)/*~ $(SRCDIR)/*~
我是 Makefile 的新手,所以我从几个地方获得了提示,但我可能没有以最优雅的方式编写它。我有几个问题可以改进它们:
- 我真的需要将 $(OBJDIR)/%.o 添加到依赖项中吗?
- 这样写Parser.h被列了两次。是否可以重写此模式规则来避免它?例如,如果 Exercise.h 被修改,我不想重新编译 MEG 的东西。将添加新的依赖项,我想以一种智能的方式管理它们。
- 还有其他建议吗?
在此先感谢您的帮助。
再见...
不,您不需要(也不希望)将目标列为其自身的先决条件。那没有意义,也行不通。
$(patsubst %,prefix/%,$(var))
可以写成$(addprefix prefix,$(var))
.
您可能想阅读 Auto-Dependency Generation 以了解自动为 .o
文件生成正确依赖项的方法。它将帮助您解决一些问题。
但是,如果您不想那么花哨,那么您需要记住的是,您需要为每个目标列出 所有 文件目标依赖于且没有其他文件。
所以
Parser.o
大概取决于(至少)Parser.h
所以加上$(OBJDIR)/Parser.o: $(INCDIR)/Parser.h
Exercise.o
大概取决于(至少)Exercise.h
(也可能 Parser.h
?)
所以添加 $(OBJDIR)/Exercise.o: $(INCDIR)/Exercise.h
(或者可能 $(OBJDIR)/Exercise.o: $(INCDIR)/Exercise.h $(INCDIR)/Parser.h
)
等...
请注意,先决条件从任何地方组合起来,因此上面建议的行将与 $(OBJDIR)/%.o: $(SRCDIR)/%.cpp
规则组合,形成给定 .o
文件的完整先决条件集。
我在 Makefile 中编写了以下代码行:
PROJECTS = ExamsGenerator ExercisesImporter
VERSION = .v0.0
EXTENSION = .Exe
BINDIR = ../bin
CONFDIR = ../config
DATADIR = ../data
DOCDIR = ../doc
INCDIR = ../include
LIBDIR = ../lib
OBJDIR = ../obj
SRCDIR = ../src
INCDIRS = $(INCDIR:%=-I%)
CC = g++
CCVAR = -D__DATADIR__=\"$(DATADIR)\"
CFLAGS = -g -Wall $(shell root-config --cflags) $(INCDIRS)
LDFLAGS = -g -Wall $(shell root-config --ldflags)
LDLIBS = $(shell root-config --glibs)
MEG_DEP = Functions.h Parser.h Test.h
MEG_DEPS = $(patsubst %,$(INCDIR)/%,$(MEG_DEP))
MEI_DEP = Functions.h Parser.h Exercise.h
MEI_DEPS = $(patsubst %,$(INCDIR)/%,$(MEI_DEP))
MEG_OBJ = mainExamsGenerator.o Parser.o Test.o
MEG_OBJS = $(patsubst %,$(OBJDIR)/%,$(MEG_OBJ))
MEI_OBJ = mainExercisesImporter.o Parser.o Exercise.o
MEI_OBJS = $(patsubst %,$(OBJDIR)/%,$(MEI_OBJ))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(MEG_DEPS) $(MEI_DEPS)
@echo "\nCreating object: $@"
$(CC) $(CCVAR) $(CFLAGS) -c -o $@ $<
all: $(PROJECTS)
@echo "\n"
ExamsGenerator: $(MEG_OBJS)
@echo "\nLinking $@"
$(CC) $(CCVAR) $(CFLAGS) $(LDLIBS) -o $(BINDIR)/$(@)$(VERSION)$(EXTENSION) $^
ExercisesImporter: $(MEI_OBJS)
@echo "\nLinking $@"
$(CC) $(CCVAR) $(CFLAGS) $(LDLIBS) -o $(BINDIR)/$(@)$(VERSION)$(EXTENSION) $^
.SILENT:
.PHONY: clean
clean:
\rm -f $(BINDIR)/*$(EXTENSION) $(OBJDIR)/*.o *~ $(INCDIR)/*~ $(SRCDIR)/*~
我是 Makefile 的新手,所以我从几个地方获得了提示,但我可能没有以最优雅的方式编写它。我有几个问题可以改进它们:
- 我真的需要将 $(OBJDIR)/%.o 添加到依赖项中吗?
- 这样写Parser.h被列了两次。是否可以重写此模式规则来避免它?例如,如果 Exercise.h 被修改,我不想重新编译 MEG 的东西。将添加新的依赖项,我想以一种智能的方式管理它们。
- 还有其他建议吗?
在此先感谢您的帮助。
再见...
不,您不需要(也不希望)将目标列为其自身的先决条件。那没有意义,也行不通。
$(patsubst %,prefix/%,$(var))
可以写成$(addprefix prefix,$(var))
.
您可能想阅读 Auto-Dependency Generation 以了解自动为 .o
文件生成正确依赖项的方法。它将帮助您解决一些问题。
但是,如果您不想那么花哨,那么您需要记住的是,您需要为每个目标列出 所有 文件目标依赖于且没有其他文件。
所以
Parser.o
大概取决于(至少)Parser.h
所以加上
$(OBJDIR)/Parser.o: $(INCDIR)/Parser.h
Exercise.o
大概取决于(至少)Exercise.h
(也可能Parser.h
?)所以添加
$(OBJDIR)/Exercise.o: $(INCDIR)/Exercise.h
(或者可能$(OBJDIR)/Exercise.o: $(INCDIR)/Exercise.h $(INCDIR)/Parser.h
)等...
请注意,先决条件从任何地方组合起来,因此上面建议的行将与 $(OBJDIR)/%.o: $(SRCDIR)/%.cpp
规则组合,形成给定 .o
文件的完整先决条件集。