开发者

Recursive Make issue

I'm trying my hand at using recursive make to eliminate things like having multiple CFLAGS variables, one for each target. There is only one level of recursion, there is no crazy directory tree traversal happening here. I just want to dump my object files into their target specific folders.

So far I have come up with something that is really elegant (edit: alright it's more elegant than the single-makefile solution i had from before. Which had way too much repetition!) but unfortunately does not work.

I think that by posting the format here it will be apparent what it is that I am trying to do.

# ./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

Here is the file 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 "Generat开发者_开发问答ing 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)

As you can see, I can very quickly add a new build target with its own set of CFLAGS by copying over the sub-makefile and lightly modifying it, and then adding a few entries to the main makefile.

So the problem here is that it doesn't recognize changes in files. Only when I edit Main.cpp will it recompile build_debug/Main.o. I'm really unsure about where I can start to figure out what's incorrect.


I've created a monster.

When I suggested recursive make in that other post it was to deal with a specific -- and very strange -- problem of inclusion. I do not subscribe to the dogma that recursive make is pure evil, but it does have disadvantages, and should not be used as a cure-all.

First, let's eliminate a bad (and ongoing) source of redundancy. In you main makefile, instead of

$(MAKE) -f make.debug

use

$(MAKE) -f makefile.sub DIRNAME = build_debug TARGETNAME = program_debug TARGETDESCR = DEBUG CFLAGS = -Wextra -Wall -O0 -g3 -DDEBUG

where makefile.sub is the "template" part of your various sub-makefiles. I know that doesn't look like an improvement, but this way you have only one sub-makefile, not N. (I also think you're using too many target-specific variables, but we can discuss that later.)

Once you're comfortable with this, you can use target-specific variables within makefile.sub, so that in the main makefile you can replace

all: 
    $(MAKE) -f makefile.sub DIRNAME=build_unittest ...
    $(MAKE) -f makefile.sub DIRNAME=build_debug ...
    $(MAKE) -f makefile.sub DIRNAME=build_release ...

with

all: 
    $(MAKE) -f makefile.sub unittest debug release

It's not clear to me what problem you're having with recognizing changes in files (when should Make rebuild build_debug/Main.o, if Main.cc hasn't changed?), but it's probably a direct consequence of using make recursively (see "disadvantages", above) and we can probably fix it without too much grief.

EDIT:

In your sub-makefile, put the all rule before the -include line, so that it will be the default rule. When you call $(MAKE), you don't specify a target, so Make chooses the default target, which is (usually) whichever one comes first. The contents of the %.d files have the form of rules, so if you include them first, one of them (i.e. build_debug/Main.o: Main.cpp) will win.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜