我在 MacOS 中的makefile中使用了以下示例代码来构造路径,但它始终不起作用。
all:
ROOT=$(shell pwd)
@echo $(ROOT)
AGENT:=$(ROOT)/agent
@echo $(AGENT)
@mkdir -p $(AGENT)
它将输出为AGENT:=/agent
,显然,AGENT
变量未扩展为ROOT
答案 0 :(得分:1)
这里有几个常见错误:
$(shell...)
make函数:配方已经是shell脚本。var=xxx
(=
周围没有空格)。它们使用$var
或${var}
进行扩展,但从未使用$(var)
进行扩展,仍然几乎仅在配方中扩展。var := xxx
或var = xxx
(在:=
或=
周围有或没有空格)分配制造变量,仅在配方之外(几乎,仅)。它们使用$(var)
或${var}
进行扩展,而从未使用$var
进行扩展。请注意,=
和:=
不同,但这超出了范围。如果您是初学者,请忽略以上说明中的“ 几乎”,您现在将不需要此。
Makefile用两种不同的语言编写:配方中的shell语言和其他地方的make语言。有点像网页是用HTML和CSS编写的。 Shell语言和make语言有时看起来相似,但有所不同。需要考虑的重要一点是,make首先将其扩展以替换make变量或make函数,然后将这些食谱传递给shell。因此,经常有必要保护外壳语法的某些部分免受这种make扩展的影响(请参见下面的示例)。
无论如何,尝试这样的事情,也许:
ROOT := $(shell pwd)
AGENT := $(ROOT)/agent
all:
@echo $(ROOT)
@echo $(AGENT)
@mkdir -p $(AGENT)
ROOT
和AGENT
是make变量,使用:=
在任何配方之外分配,并且可以在任何地方使用,包括在配方中。它们用$(var)
扩展。在将配方传递给外壳之前,make会将其展开为:
echo /some/where
echo /some/where/agent
mkdir -p /some/where/agent
每行将在单独的shell中执行,但这没关系,因为它们之间没有传递shell变量。
注意:如果使用的是GNU make,将定义CURDIR
make变量并将其扩展为当前工作目录。无需使用pwd
,只需使用$(CURDIR)
而不是$(ROOT)
:
AGENT := $(CURDIR)/agent
all:
@echo $(CURDIR)
@echo $(AGENT)
@mkdir -p $(AGENT)
注意:如果ROOT
指向Makefile所在的位置,并且如果您使用-f
的make选项从其他地方调用make,则$(CURDIR)
不再起作用,因为它指向哪里您从而不是在Makefile所在的位置调用make。但是您也可以使用以下方法获得正确的ROOT
:
ROOT := $(dir $(lastword $(MAKEFILE_LIST)))
在Makefile的开头(在任何include
语句之前)。
仅使用shell语法和单行代码:
all:
@ROOT="`pwd`"; AGENT="$$ROOT"/agent; echo "$$ROOT"; echo "$$AGENT"; mkdir -p "$$AGENT"
ROOT
和AGENT
是外壳变量,在配方内部用=
分配,并且仅在配方的同一行中可用。请注意,双$
用于扩展shell变量。在将结果传递到外壳程序之前,需要它们先退出make性能的第一个扩展。通过make扩展后,配方以以下方式传递到外壳:
ROOT="`pwd`"; AGENT="$ROOT"/agent; echo "$ROOT"; echo "$AGENT"; mkdir -p "$AGENT"
(make将$$
展开为$
并停在那里)是您想要的。它在单个shell中执行,这就是为什么将shell变量从列表的一个命令传递到下一个命令的原因。
如果希望获得更好的可读性,可以使用\
行继续行将配方拆分为多行,但在一个外壳程序中仍然只执行一个配方:
all:
@ROOT="`pwd`"; \
AGENT="$$ROOT/agent"; \
echo "$$ROOT"; \
echo "$$AGENT"; \
mkdir -p "$$AGENT"
这与其他形式严格等效,只是更易于阅读。但这完全不同于:
all:
@ROOT="`pwd`"
@AGENT="$$ROOT/agent"
@echo "$$ROOT"
@echo "$$AGENT"
@mkdir -p "$$AGENT"
因为这是最后一种形式,所以5行由5个不同的shell执行。例如,当第二个运行时,不再定义第一个外壳分配的ROOT
外壳变量,其结果与以下内容相同:
AGENT="/agent"
然后,两条echo
行根本没有回声,只是换行了。最后,您得到一个错误,因为:
mkdir -p
无效。