Makefile先决条件中的目标名称

时间:2016-06-21 00:12:21

标签: makefile

我有一些像这样的规则

foo_%: $(BIN_DIR) $(LIB_DIR) $(OBJ_DIR)
    gcc stuff

目录变量如下:

BIN_DIR := $(BUILD_DIR)/$@/$(TARGET)/bin

制定目录的规则:

$(BIN_DIR) $(LIB_DIR) $(OBJ_DIR):
    mkdir -p $@

我希望(扩展的)foo_%部分替换目录名称中的$@,但现在$@将被替换为任何内容。

现在我可以在BIN_DIR var中用$@替换%

    BIN_DIR := $(BUILD_DIR)/%/$(TARGET)/bin

但是这省略了我想要包含的foo_部分。

最后的方法是在每条规则中包含三个mkdir -p语句,但我不愿意!

1 个答案:

答案 0 :(得分:1)

扩展无法工作,因为在处理语法时会扩展规则中的先决条件和目标列表。换句话说,静态地,在编译时" makefile规则。而$@参数是动态的;当评估规则树时,它会在makefile"运行时"中获取值。那时,它不能代替目标和先决条件。

由于这只是为了确保某些目录存在,您可以将make -p移动到配方中,并像这样执行。请注意,我们仍需将BIN_DIR :=分配更改为非展开式BIN_DIR =分配:

TARGET := target
LIB_DIR := lib_dir
OBJ_DIR := obj_dir
BUILD_DIR := build_dir

BIN_DIR = $(BUILD_DIR)/$@/$(TARGET)/bin

foo: | $(LIB_DIR) $(OBJ_DIR)  # see text below for explanation of | symbol
        mkdir -p $(BIN_DIR)
        echo other steps

$(LIB_DIR) $(OBJ_DIR):
        mkdir -p $@

在这里,我们使用制作规则处理来创建$(LIB_DIR)$(OBJ_DIR)。但$(BIN_DIR)只是通过在食谱中运行mkdir -p来以行人方式处理。 $@的扩展在这里起作用,因为BIN_DIR是一个传统的未展开式make变量,当它被替换时会经历扩展。在处理规则语法时,它仍然是静态扩展的,但重点是它保留了插入$@配方行的未展开make -p。因为$@在配方行中,所以它有效。它只是在目标或先决条件列表中不起作用。

我使用|符号将$(LIB_DIR) $(OBJ_DIR)指定为仅限订单的先决条件。 Read about this in the GNU Make manual。仅订单的先决条件仅在缺少时才会更新。如果它们已经存在,则会被忽视。

如果我们不允许这些目录仅按顺序排列,那么每当它们的时间戳发生变化时,它们就会触发重建目标,使其比目标更新。

最好不要将目录命名为先决条件,只需将恰当的mkdir -p放入配方即可。就像在,简单地说:

TARGET := target
LIB_DIR := lib_dir
OBJ_DIR := obj_dir
BUILD_DIR := build_dir

BIN_DIR = $(BUILD_DIR)/$@/$(TARGET)/bin

foo:
        mkdir -p $(LIB_DIR) $(OBJ_DIR) $(BIN_DIR)
        echo other step

执行命令

$ make
mkdir -p lib_dir obj_dir build_dir/foo/target/bin
echo other steps
other steps