递归问题

问题描述:

我正在尝试使用递归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。我真的不确定我能从哪里开始弄清楚什么是不正确的。

+0

'main.d'是否按预期包含在内?修改该文件并在文件末尾添加'$(info included main.d ...)',并确保在尝试重新构建时看到该消息。另外,请验证.d文件包含您希望它包含的所有内容,并且所有路径都是正确的。 – bta 2011-06-07 17:20:47

+0

要生成依赖关系并在一次编译中添加'-MD'选项(http://www.gnu.org/software/gcc/news/dependencies.html)。 – bta 2011-06-07 17:30:31

我创造了一个怪物。

当我在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)将赢得。

+0

谢谢Beta :) – 2011-06-07 16:38:48

+0

好吧,它似乎没有识别什么时候的东西改变。如果我删除构建目录中的每个目标文件,它们都会被重建。但是如果我删除其中的一半,它不会认为任何错误。直到我删除Main.o(我怀疑这是因为它是列表中的第一个元素)。此时Main.o被编译。其余的仍然失踪。没有链接发生。真的没有任何意义。 – 2011-06-07 20:16:02