我如何配置我的 makefile 以调试和发布构建到具有多个可执行文件的更复杂的项目?

How can I configure my makefile for debug and release builds to more complex projects with multiple executables?

中postHow can I configure my makefile for debug and release builds?, I find the answer 完美!

但它似乎只适用于一个最终目标。

我尝试将此 makefile 扩展到我的项目,但没有成功,因为我的项目有多个可执行文件作为目标。

我应该对此示例进行哪些更改,以便我可以有多个最终目标并使用

make

make all

我可以生成所有目标(在调试或发布模式下),或者

make test

针对特定目标?

编辑: 我所做的其中一项尝试没有产生任何结果,但可以更好地说明其意图:

(...)
OBJS = $(SRCS:.c=.o)
EXE=$($(TARGET)_EXE)

sample1_EXE=sample1
sample2_EXE=sample2

sample1: TARGET=sample1
sample1: debug

sample2: TARGET=sample2
sample2: debug

all: prep debug sample1 sample2

问题分为两个部分:指定模式和协调构建。

(这会很棘手,所以我们会分阶段进行。)

首先是模式。在命令中设置 mode 的值,并使用 debug 作为默认值,很容易。我们把它放在 makefile 中:

mode = debug

make sailfish mode=release 这样的命令会覆盖它。

现在使用模式:

mode = debug

ifeq ($(mode),debug)
 BUILDDIR := debug
 CFLAGS += -g -O0 -DDEBUG
else
 ifeq ($(mode),release)
  BUILDDIR := release
  CFLAGS += -O3 -DNDEBUG
 else
  $(error unknown mode: $(mode))
 endif
endif

请注意,我添加了 error 语句来捕获 make mode=testmake mode=releas 等错误。如果这样的错误导致 Make 当场中止,那么 更容易发现和更正。 (另请注意,前导空格不是必需的,它对执行没有影响,但它使 makefile 更易于阅读。)

现在开始构建。假设我们执行make sailfish,那么mode就是debug。首先注意,虽然我们给sailfish作为目标,但我们实际上并不是在构建sailfish,而是在构建debug/sailfish。这很重要,因此我们将 sailfish 设为需要我们实际需要的文件的 PHONY 目标:

.PHONY: sailfish

sailfish: $(BUILDDIR)/sailfish

相关对象是sailfish.oseaThing.o。 (你必须自己编写这个列表,Make 几乎不可能推导出它。)我们可以将对象作为一个不同的变量放在 makefile 中:

sailfish_OBJS := sailfish.o seaThing.o

但如果我们把它变成 target-specific variable:

以后事情会变得更简单
$(BUILDDIR)/sailfish: $(addprefix $(BUILDDIR)/,sailfish.o seaThing.o)
    $(CC) $(CFLAGS) -o $@ $^

我们仍然需要一个规则来构建目标文件,我们注意到链接答案中的两个模式规则合并为一个:

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

这足以构建 debug/sailfishrelease/sailfish。要添加可执行文件 catamaran,我们添加:

.PHONY: catamaran

catamaran: $(BUILDDIR)/catamaran

$(BUILDDIR)/catamaran: $(addprefix $(BUILDDIR)/,catamaran.o boatThing.o seaThing.o)
    $(CC) $(CFLAGS) -o $@ $^

但是我们注意到这里有些冗余,所以我们合并了 PHONY 声明:

.PHONY: sailfish catamaran

然后我们注意到,如果我们将可执行文件的名称放在一个变量中:

EXECUTABLES := sailfish catamaran

我们可以在 PHONY 声明中使用它:

.PHONY: $(EXECUTABLES)

我们也可以将这两个PHONY规则组合成一个static pattern rule:

$(EXECUTABLES): %: $(BUILDDIR)/%

我们可以将先决条件行与配方分开,并为两者使用一个配方:

$(BUILDDIR)/sailfish: $(addprefix $(BUILDDIR)/,sailfish.o seaThing.o)
$(BUILDDIR)/catamaran: $(addprefix $(BUILDDIR)/,catamaran.o boatThing.o seaThing.o)

$(addprefix $(BUILDDIR)/,$(EXECUTABLES)):
    $(CC) $(CFLAGS) -o $@ $^

现在,要添加另一个可执行文件,如 seagull,我们只需将 seagull 添加到 EXECUTABLES := ... 行,然后再写一行:

    $(BUILDDIR)/seagull: $(addprefix $(BUILDDIR)/,seagull.o birdThing.o seaThing.o)

还可以进行一些改进,但现在应该足够了。