具有两个目标和单独的构建文件夹的Makefile

问题描述 投票:0回答:1

我正在尝试将一个Makefile与两个相似的目标以及两个单独的构建文件夹一起使用。目标之间的唯一区别是添加了CFLAG定义。

这里是我所拥有的摘要,但是我无法获取build文件夹来根据目标评估不同的内容。我用foobar代表不同的目标。

...
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 $@ 
makefile gnu
1个回答
0
投票

您有三个要解决的问题。

首先是在构建目录中构建目标文件。首先,我们编写一个模式规则来构建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 $@

第三个问题是使foobar规则要求正确的对象。显然,这条规则:

foo:$(OBJS)
    ...

将无法正常工作,我们需要特定于foo的内容:

foo: $(addprefix $(foo_BUILD_DIR), $(OBJS))
    ...

这是可行的,但是它要求我们编写一个指定foo$(foo_BUILD_DIR)规则,指定一个bar$(bar_BUILD_DIR)规则,依此类推。有懒惰的方式吗?我们需要做的就是取得目标(例如foo)并将其放入先决条件列表。如您所知,automatic variable $@包含目标,但在先决条件列表中不可用,因为先决条件列表在将值分配给该变量之前已展开-除非我们使用[ C0]。这是一项高级技术,但是它使我们可以在以后的阶段中进行第二次扩展(用额外的Secondary Expansion来转义变量,以保护它们免受第一次扩展的影响):

$

并且一旦可行,我们可以添加另一个目标,或者根据需要添加任意数量:

foo: $(addprefix $$($$@_BUILD_DIR)/, $(OBJS))
    ...

可以再进行一到两个改进,但这足以开始。

© www.soinside.com 2019 - 2024. All rights reserved.