我正在尝试使用递归make来消除诸如具有多个CFLAGS
变量之类的事情,每个目标一个变量。只有一个级别的递归,这里没有发生疯狂的目录树遍历。我只想将我的目标文件转储到他们的目标特定文件夹中。
到目前为止,我已经提出了一些非常优雅的东西(编辑:好吧,它比我以前的单一makefile解决方案更优雅。重复过多了!)但不幸的是没有用。
我认为通过在此处发布格式,我将尝试做什么是显而易见的。
# ./makefile
.PHONY: all clean
export CC = g++
export INCLUDE = -I ../include/
export SRC = Main.cpp Graphics.cpp Thread.cpp Net.cpp Otherstuff.cpp
export LINKEROPT = -lglew32 -lopengl32 -lsdl -lws2_32 -lglu32 -lmorelibraries
test:
$(MAKE) -f make.unittest
all:
$(MAKE) -f make.unittest
$(MAKE) -f make.debug
$(MAKE) -f make.release
clean:
-rm -rf build_* *.exe
# I am on windows so the targets are .exe's
这是文件make.debug:
### sub-makefile for the debug build target. Contains target specific build settings.
DIRNAME = build_debug
TARGETNAME = program_debug
TARGETDESCR = DEBUG
CFLAGS = -Wextra -Wall -O0 -g3 -DDEBUG
### EVERYTHING AFTER THIS POINT IS A TEMPLATE
# my goal is to have as much of my makefile code being "reusable" as possible
# so that I can easily add targets.
OBJ = $(patsubst %.cpp,$(DIRNAME)/%.o,$(SRC))
DEPS = $(patsubst %.cpp,$(DIRNAME)/%.d,$(SRC))
-include $(DEPS)
# default behavior. Set up the build directory. Then build the debug target.
all: $(DIRNAME) $(TARGETNAME)
# this is the build dir
$(DIRNAME):
mkdir $(DIRNAME)
$(DIRNAME)/%.o: %.cpp
@echo -e "Compiling for $(TARGETDESCR): $< --> $@"
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
@echo -e "Generating dependencies: $< --> $(patsubst %.o,%.d,$@)"
$(CC) $(CFLAGS) $(INCLUDE) -MM -MT $@ -MF $(patsubst %.o,%.d,$@) $<
# I realize there is a way to generate the deps while compiling in one pass
# but I'll figure it out later
$(TARGETNAME): $(OBJ)
@echo -e "Linking $(TARGETDESCR): $@.exe"
$(CC) -L ../lib/win32/ -o $@ $(OBJ) $(LINKEROPT)
正如您所看到的,通过复制子makefile并轻轻修改它,然后在主makefile中添加一些条目,我可以非常快速地添加一个具有自己的CFLAGS
集的新构建目标。
所以这里的问题是它无法识别文件中的变化。只有当我编辑Main.cpp时,它才会重新编译build_debug / Main.o。我真的不确定我在哪里可以开始弄清楚什么是不正确的。
答案 0 :(得分:2)
我创造了一个怪物。
当我在that other post中建议递归make时,它是处理一个特定的 - 而且非常奇怪 - 包含的问题。我不赞同递归制作纯粹邪恶的教条,但它确实有缺点,不应该用作万灵药。
首先,让我们消除一个糟糕的(并且正在进行的)冗余源。在你的主makefile中,而不是
$(MAKE) -f make.debug
使用
$(MAKE) -f makefile.sub DIRNAME = build_debug TARGETNAME = program_debug TARGETDESCR = DEBUG CFLAGS = -Wextra -Wall -O0 -g3 -DDEBUG
其中makefile.sub
是各种子文件的“模板”部分。我知道这看起来不像是一种改进,但是这样你只有一个子makefile,而不是N.(我也认为你使用了太多特定于目标的变量,但我们可以稍后再讨论。)
如果您对此感到满意,可以在makefile.sub
中使用target-specific variables,以便在主makefile中替换
all:
$(MAKE) -f makefile.sub DIRNAME=build_unittest ...
$(MAKE) -f makefile.sub DIRNAME=build_debug ...
$(MAKE) -f makefile.sub DIRNAME=build_release ...
与
all:
$(MAKE) -f makefile.sub unittest debug release
我不清楚您在识别文件中的更改时遇到了什么问题(如果build_debug/Main.o
没有更改,应该何时重建Main.cc
?),但这可能是由于使用make递归(参见上面的“缺点”),我们可以修复它而不会有太多的悲伤。
修改:
在子makefile中,将all
规则放在-include
行之前,以便它成为默认规则。当您调用$(MAKE)
时,您没有指定目标,因此Make选择默认目标,即(通常)首先出现的目标。 %.d
文件的内容具有规则形式,因此,如果您先include
个,则其中一个(即build_debug/Main.o: Main.cpp
)将获胜。