同时使用GNU Make构建调试和发布目标(扩展版)

4
我是一位有益的助手,可以为您翻译文本。

我希望跟进这个问题和它的答案...现在我可以构建两个不同的可执行文件,我想根据一个变量在不同的目录中构建可执行文件。

我想从以下内容开始:

EXEDIR     = bin/release/
EXE        = $(EXEDIR)AmiModRadio
SOURCES    = $(wildcard *.c)
OBJECTSDIR = o/release/
OBJECTS    = $(addprefix $(OBJECTSDIR), $(SOURCES:.c=.o))

CC = vbcc:bin/vc
LD = vbcc:bin/vc

release : $(EXE) 
$(OBJECTS) : $(OBJECTSDIR)%.o : %.c
    $(CC) $(shell vbccprefs) -c $< -o $@
$(EXE) : $(OBJECTS)
    $(LD) $(shell vbccprefs) -o $(EXE) $(OBJECTS)

变成类似这样:

EXE        = $(EXEDIR)AmiModRadio
SOURCES    = $(wildcard *.c)
OBJECTS    = $(addprefix $(OBJECTSDIR), $(SOURCES:.c=.o))

CC = vbcc:bin/vc
LD = vbcc:bin/vc

release : EXEDIR = bin/release/
release : OBJECTSDIR = o/release/
release : $(EXE) 

release : EXEDIR = bin/debug/
release : OBJECTSDIR = o/debug/
release : $(EXE) 

$(OBJECTS) : $(OBJECTSDIR)%.o : %.c
    $(CC) $(shell vbccprefs) -c $< -o $@
$(EXE) : $(OBJECTS)
    $(LD) $(shell vbccprefs) -o $(EXE) $(OBJECTS)

上述最后一个makefile无法工作,因为据我所知,在规则releasedebug中设置变量EXEDIROBJECTSDIR太晚了。那么,我是否遗漏了一些简单的东西?有没有办法让两个规则releasedebug使用相同的规则,但在两个不同的目录集中生成文件,包括作为主要目标的可执行文件?
2个回答

5
您可以按照以下方式调用Makefile:
make release
make debug

-- OR --

make BUILD=release
make BUILD=debug

Makefile

ifneq ($(BUILD),release)
    BUILD = debug
endif

EXEDIR      = bin/$(BUILD)/
OBJDIR      = o/$(BUILD)/

EXE         = $(EXEDIR)AmiModRadio
SOURCES     = $(wildcard *.c)
OBJECTS     = $(addprefix $(OBJDIR), $(SOURCES:.c=.o))

CC = vbcc:bin/vc
LD = vbcc:bin/vc

CFLAGS  = $(shell vbccprefs)
LDFLAGS = $(shell vbccprefs)

all : $(EXE)

.PHONY : release debug    
release debug :
    $(MAKE) BUILD=$@

$(EXE) : $(OBJECTS)
    $(LD) $(LDFLAGS) -o $@ $^

$(OBJDIR)%.o : %.c
    $(CC) $(CFLAGS) -o $@ -c $<

谢谢Ziffusion,有了你和Daniel的帮助,我成功地让我的makefile按照我想要的方式工作。我接受Daniel的答案,因为它不需要“BUILD=”(不知何故,在执行make releasemake debug时,$(BUILD)为空)。 - Yann-Gaël Guéhéneuc
没问题。但请注意,Makefile 不需要传递 BUILD=<type> 参数。我的第一个解决方案需要,但我已经改变了。无论如何,了解这两种方法都是好的。 - Ziffusion

2
我会使用条件语句来确定目标并相应地设置变量。
ifeq "$(strip $(filter debug,$(MAKECMDGOALS)))" "debug"
EXEDIR = bin/release/
OBJECTSDIR = o/release/
endif
ifeq "$(strip $(filter release,$(MAKECMDGOALS)))" "release"
EXEDIR = bin/debug/
OBJECTSDIR = o/debug/
endif

我看到你的代码存在一个大问题,即你在发布和调试路径上都指定了发布目标。因此,GNU Make使用它遇到的最后一个赋值。但是,使用我这里提供的内容应该可以正常工作,因为我在我的make文件中也做了类似的事情。
这样做的话,你不能同时在命令行上指定发布和调试,因为它们是互斥的。strip函数会剥离参数中的前导和尾随空格,而参数是filter函数的输出。filter函数获取字符串debug并查找它是否存在于预定义变量MAKECMDGOALS中。MAKECMDGOALS是在命令行上指定的所有目标(目标)的列表。
希望对你有所帮助。

感谢Daniel的帮助,有了你和Ziffusion的帮助,我的makefile可以正常工作,并且对我的构建链做出了最小的更改。 - Yann-Gaël Guéhéneuc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接