具有两个目标和单独构建文件夹的 Makefile
Makefile with two targets and separate build folders
我正在尝试将一个 Makefile 与两个相似的目标和两个单独的构建文件夹一起使用。目标之间的唯一区别是添加了 CFLAG
定义。
这是我所拥有的片段,但是我无法让构建文件夹根据目标评估不同的内容。我使用 foo
和 bar
来表示不同的目标。
...
foo_BUILD_DIR := build_foo/
bar_BUILD_DIR := build_bar/
C_SRCS := main.c
CFLAGS := -std=c99 -Os -Wall
foo_CFLAGS := $(CFLAGS) -DBLE=1
C_OBJS := $(addprefix $(BUILD_DIR),$(subst .c,.o,$(C_SRCS)))
$(BUILD_DIR)%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $^ -o $@
foo:$(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $@
bar:$(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $@
这里有3个问题需要解决。
首先是在构建目录中构建目标文件。首先我们编写一个模式规则来构建 foo 对象:
foo_BUILD_DIR := build_foo # Don't put the trailing slash in the dir name, it's a pain.
CFLAGS := -std=c99 -Os -Wall
foo_CFLAGS := $(CFLAGS) -DBLE=1
$(foo_BUILD_DIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(foo_CFLAGS) $^ -o $@
一旦一切正常,我们就为条形对象编写另一个规则:
$(bar_BUILD_DIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $^ -o $@
第二个问题是整理我们到目前为止所写的内容。 foo_CFLAGS
变量现在是唯一让这两个食谱不同的东西,所以让我们用 target-specific variable assignment:
来摆脱它
$(foo_BUILD_DIR)/%.o: CFLAGS += -DBLE=1
$(foo_BUILD_DIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $^ -o $@
现在我们可以将规则组合成一个具有两个目标的模式规则:
$(foo_BUILD_DIR)/%.o: CFLAGS += -DBLE=1
$(foo_BUILD_DIR)/%.o $(bar_BUILD_DIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $^ -o $@
第三个问题是让 foo
和 bar
规则要求正确的对象。显然这个规则:
foo:$(OBJS)
...
行不通,我们需要一些特定于 foo
的东西:
foo: $(addprefix $(foo_BUILD_DIR)/, $(OBJS))
...
这行得通,但它需要我们编写一个指定 $(foo_BUILD_DIR)
的 foo
规则,一个指定 $(bar_BUILD_DIR)
的 bar
规则,等等。有没有更懒的方法?我们所需要做的就是获取目标(例如 foo
)并将其放入先决条件列表中。如您所知,automatic variable $@
contains the target, but it isn't available in the prerequisite list, because the prerequisite list is expanded before a value is assigned to that variable-- unless we use Secondary Expansion。这是一种高级技术,但它允许我们在后期进行第二次扩展(使用额外的 $
转义我们的变量以保护它们免受第一次扩展):
.SECONDEXPANSION:
foo: $(addprefix $$($$@_BUILD_DIR)/, $(OBJS))
...
一旦成功,我们就可以添加另一个目标,或者添加任意数量的目标:
foo bar: $(addprefix $$($$@_BUILD_DIR)/, $(OBJS))
...
还有一两个可能的改进,但这已经足够了。
我正在尝试将一个 Makefile 与两个相似的目标和两个单独的构建文件夹一起使用。目标之间的唯一区别是添加了 CFLAG
定义。
这是我所拥有的片段,但是我无法让构建文件夹根据目标评估不同的内容。我使用 foo
和 bar
来表示不同的目标。
...
foo_BUILD_DIR := build_foo/
bar_BUILD_DIR := build_bar/
C_SRCS := main.c
CFLAGS := -std=c99 -Os -Wall
foo_CFLAGS := $(CFLAGS) -DBLE=1
C_OBJS := $(addprefix $(BUILD_DIR),$(subst .c,.o,$(C_SRCS)))
$(BUILD_DIR)%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $^ -o $@
foo:$(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $@
bar:$(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $@
这里有3个问题需要解决。
首先是在构建目录中构建目标文件。首先我们编写一个模式规则来构建 foo 对象:
foo_BUILD_DIR := build_foo # Don't put the trailing slash in the dir name, it's a pain.
CFLAGS := -std=c99 -Os -Wall
foo_CFLAGS := $(CFLAGS) -DBLE=1
$(foo_BUILD_DIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(foo_CFLAGS) $^ -o $@
一旦一切正常,我们就为条形对象编写另一个规则:
$(bar_BUILD_DIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $^ -o $@
第二个问题是整理我们到目前为止所写的内容。 foo_CFLAGS
变量现在是唯一让这两个食谱不同的东西,所以让我们用 target-specific variable assignment:
$(foo_BUILD_DIR)/%.o: CFLAGS += -DBLE=1
$(foo_BUILD_DIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $^ -o $@
现在我们可以将规则组合成一个具有两个目标的模式规则:
$(foo_BUILD_DIR)/%.o: CFLAGS += -DBLE=1
$(foo_BUILD_DIR)/%.o $(bar_BUILD_DIR)/%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) $^ -o $@
第三个问题是让 foo
和 bar
规则要求正确的对象。显然这个规则:
foo:$(OBJS)
...
行不通,我们需要一些特定于 foo
的东西:
foo: $(addprefix $(foo_BUILD_DIR)/, $(OBJS))
...
这行得通,但它需要我们编写一个指定 $(foo_BUILD_DIR)
的 foo
规则,一个指定 $(bar_BUILD_DIR)
的 bar
规则,等等。有没有更懒的方法?我们所需要做的就是获取目标(例如 foo
)并将其放入先决条件列表中。如您所知,automatic variable $@
contains the target, but it isn't available in the prerequisite list, because the prerequisite list is expanded before a value is assigned to that variable-- unless we use Secondary Expansion。这是一种高级技术,但它允许我们在后期进行第二次扩展(使用额外的 $
转义我们的变量以保护它们免受第一次扩展):
.SECONDEXPANSION:
foo: $(addprefix $$($$@_BUILD_DIR)/, $(OBJS))
...
一旦成功,我们就可以添加另一个目标,或者添加任意数量的目标:
foo bar: $(addprefix $$($$@_BUILD_DIR)/, $(OBJS))
...
还有一两个可能的改进,但这已经足够了。