递归问题
我正在尝试使用递归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): $< --> [email protected]"
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o [email protected]
@echo -e "Generating dependencies: $< --> $(patsubst %.o,%.d,[email protected])"
$(CC) $(CFLAGS) $(INCLUDE) -MM -MT [email protected] -MF $(patsubst %.o,%.d,[email protected]) $<
# 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): [email protected]"
$(CC) -L ../lib/win32/ -o [email protected] $(OBJ) $(LINKEROPT)
正如你所看到的,我可以很快用自己的一套CFLAGS
通过复制在子Makefile中添加一个新的构建目标和稍微修改它,然后在主makefile中添加一些条目。
所以这里的问题是,它无法识别文件中的更改。只有当我编辑Main.cpp时,它才会重新编译build_debug/Main.o。我真的不确定我能从哪里开始弄清楚什么是不正确的。
我创造了一个怪物。
当我在that other post中建议递归制作时,它是处理一个特殊的 - 非常奇怪的包含问题。我不赞同递归式纯粹是邪恶的教条,但它确实有缺点,不应该被用作治愈所有的东西。
首先,让我们消除一个不好的(和正在进行的)冗余源。在你的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的 “模板” 部分。我知道这看起来不像是一种改进,但这样你只有一个子makefile,而不是N.(我也认为你使用了太多的特定于目标的变量,但我们可以在以后讨论它。)
一旦你适应了这一点,你可以在makefile.sub
使用target-specific variables,所以在主makefile文件,你可以用
all:
$(MAKE) -f makefile.sub unittest debug release
更换
all:
$(MAKE) -f makefile.sub DIRNAME=build_unittest ...
$(MAKE) -f makefile.sub DIRNAME=build_debug ...
$(MAKE) -f makefile.sub DIRNAME=build_release ...
目前尚不清楚对我有什么问题,你”重新识别文件中的变化(w如果Main.cc
没有改变,那么母鸡应该重建build_debug/Main.o
?),但这可能是递归使用make的直接后果(参见上文的“缺点”),我们可以在不太痛苦的情况下修复它。
编辑:
在你的子生成文件,把all
规则-include
前行,所以,这将是默认的规则。当你打电话给$(MAKE)
时,你没有指定目标,所以Make选择默认的目标,这通常是(无论哪个先来的)。 %.d
文件的内容具有规则的形式,所以如果您include
他们第一,其中一个(即build_debug/Main.o: Main.cpp
)将赢得。
谢谢Beta :) – 2011-06-07 16:38:48
好吧,它似乎没有识别什么时候的东西改变。如果我删除构建目录中的每个目标文件,它们都会被重建。但是如果我删除其中的一半,它不会认为任何错误。直到我删除Main.o(我怀疑这是因为它是列表中的第一个元素)。此时Main.o被编译。其余的仍然失踪。没有链接发生。真的没有任何意义。 – 2011-06-07 20:16:02
'main.d'是否按预期包含在内?修改该文件并在文件末尾添加'$(info included main.d ...)',并确保在尝试重新构建时看到该消息。另外,请验证.d文件包含您希望它包含的所有内容,并且所有路径都是正确的。 – bta 2011-06-07 17:20:47
要生成依赖关系并在一次编译中添加'-MD'选项(http://www.gnu.org/software/gcc/news/dependencies.html)。 – bta 2011-06-07 17:30:31