我如何配置我的 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=test
和 make mode=releas
等错误。如果这样的错误导致 Make 当场中止,那么 更 更容易发现和更正。 (另请注意,前导空格不是必需的,它对执行没有影响,但它使 makefile 更易于阅读。)
现在开始构建。假设我们执行make sailfish
,那么mode就是debug
。首先注意,虽然我们给sailfish
作为目标,但我们实际上并不是在构建sailfish
,而是在构建debug/sailfish
。这很重要,因此我们将 sailfish
设为需要我们实际需要的文件的 PHONY 目标:
.PHONY: sailfish
sailfish: $(BUILDDIR)/sailfish
相关对象是sailfish.o
和seaThing.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/sailfish
和 release/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)
还可以进行一些改进,但现在应该足够了。
中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=test
和 make mode=releas
等错误。如果这样的错误导致 Make 当场中止,那么 更 更容易发现和更正。 (另请注意,前导空格不是必需的,它对执行没有影响,但它使 makefile 更易于阅读。)
现在开始构建。假设我们执行make sailfish
,那么mode就是debug
。首先注意,虽然我们给sailfish
作为目标,但我们实际上并不是在构建sailfish
,而是在构建debug/sailfish
。这很重要,因此我们将 sailfish
设为需要我们实际需要的文件的 PHONY 目标:
.PHONY: sailfish
sailfish: $(BUILDDIR)/sailfish
相关对象是sailfish.o
和seaThing.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/sailfish
和 release/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)
还可以进行一些改进,但现在应该足够了。