递归制造问题

时间:2011-06-07 14:46:30

标签: recursion makefile

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

1 个答案:

答案 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)将获胜。