在 Makefile 函数中读取更新的文件
Reading updated file in the Makefile function
我想从文件 version
中读取一行的一部分(某个版本号)。此功能添加到 makefile 函数中。在此之前,我正在使用新版本号更新文件。但是当我尝试将该新版本分配给某个变量时,它正在读取旧版本号。
为了确保,我添加了 cat verison
命令来验证文件内容。
下面是我写的文件内容
文件:版本
me@linux:temp$ cat version
PROC_V7.1.2.3
文件:生成文件
me@linux:temp$ cat Makefile
include $(shell pwd)/$(wildcard *.mk)
.PHONY: firmware
firmware:
$(call version_replace, 100)
文件:image.mk
me@linux:temp$ cat image.mk
define version_replace
cat version
sed -i 's/V7/V177/g' version
cat version
$(eval NEW_VER:=$(shell cat version | cut -d '_' -f 2 ))
echo $(NEW_VER)
endef
所以当我做 make firmware
时,新变量给出旧值 V7.1.2.3
而不是 V177.1.2.3
。
me@linux:temp$ make firmware
cat version
PROC_V7.1.2.3
sed -i 's/V7/V177/g' version
cat version
PROC_V177.1.2.3
NEW_VER=V7.1.2.3
echo V7.1.2.3
V7.1.2.3
我的理解是,当调用 version_replace
函数时,首先执行的所有赋值和 NEW_VER
已经填充了旧版本号。
那么如何在 make file 函数中从文件中读取更新的版本号?
可能很难让 call
像您一样使用多个命令,所以我发现有时更容易(尽管可能不太便携)改为创建 shell 脚本:
生成文件
EXEC := $(shell sh script.sh)
FILE := new_version
VERS := $(shell cat $(FILE))
.PHONY: firmware
firmware:
$(info $(VERS))
script.sh
#!/bin/bash
sed 's/V7/V177/g' version | cut -d '_' -f 2 > new_version
# optional # mv new_version version
您可以选择覆盖 version
文件,方法是取消注释脚本中的最后一行并将 Makefile
中的 FILE
变量更改为 version
。
$ make firmware
V177.1.2.3
make: Nothing to be done for `firmware'.
我会这样分开这两件事:
.PHONY: firmware
firmware: version
# replace with firmware generation command that reads from $<
@echo FIRMWARE $@ $<
.PHONY: version
version:
# replace with version update command (sequence)
@echo VERSION $@
构建 firmware
将产生以下序列:
$ make firmware
# replace with version update command (sequence)
VERSION version
# replace with firmware generation command that reads from version
FIRMWARE firmware version
编辑: 您对不同版本增量的要求应该是一个变量,用于控制 version:
目标的命令行,例如make VERSION_INCREMENT=200 firmware
.
你的现象可以简化为一个简单但令人费解的例子:
MY_OUTPUT := First line
.PHONY: foo
foo:
@echo $(MY_OUTPUT)
$(eval MY_OUTPUT := $(shell $(info eval-time) echo Second line))
@echo $(MY_OUTPUT)
$(shell read -p "Hit return:")
输出:
$ make foo
eval-time
Hit return:
...waiting for a keystroke
First line
Second line
配方的评估是这样的:分配一个行缓冲区,这些行将保存没有 make 语法的最终配方命令行。然后遍历所有配方行,执行所有已知的 make 语法,从所有引号 ($$
) 中删除一个级别,执行 $(eval)
操作并将行写入缓冲区。 然后 逐步执行生成的命令行列表,并将它们一一提供给 sh
。 $(info)
告诉我们参数字符串已经预先评估,破坏了你的预期顺序。
这是 make
的行为。 make
将在执行之前扩展目标的配方。
配方$(eval NEW_VER:=$(shell cat version | cut -d '_' -f 2 ))
将被扩展,变量NEW_VER
将存储在变量列表中,其值为V7.1.2.3(来自版本文件)。由于版本文件中尚未更新版本。食谱 echo $(NEW_VER)
将替换为 echo V7.1.2.3
。
执行前,目标firmware
的配方将是
cat version
sed -i 's/V7/V177/g' version
cat version
echo V7.1.2.3
因此最后的输出是打印旧版本。
To make this work, have two different targets. One for changing version in file and other for read it.
生成文件:
all: replace_version read_version
replace_version:
cat version
sed -i 's/V7/V177/g' version
read_version:
cat version
$(eval NEW_VER:=$(shell cat version | cut -d '_' -f 2 ))
echo $(NEW_VER)
There is another possible method to make this work with single target.
Change the sed
command as expandable recipe
生成文件:
firmware:
$(call version_replace, 100)
image.mk
define version_replace
$(shell sed -i 's/V7/V177/g' version)
$(eval NEW_VER:=$(shell cat version | cut -d '_' -f 2 ))
echo $(NEW_VER)
endef
我想从文件 version
中读取一行的一部分(某个版本号)。此功能添加到 makefile 函数中。在此之前,我正在使用新版本号更新文件。但是当我尝试将该新版本分配给某个变量时,它正在读取旧版本号。
为了确保,我添加了 cat verison
命令来验证文件内容。
下面是我写的文件内容
文件:版本
me@linux:temp$ cat version
PROC_V7.1.2.3
文件:生成文件
me@linux:temp$ cat Makefile
include $(shell pwd)/$(wildcard *.mk)
.PHONY: firmware
firmware:
$(call version_replace, 100)
文件:image.mk
me@linux:temp$ cat image.mk
define version_replace
cat version
sed -i 's/V7/V177/g' version
cat version
$(eval NEW_VER:=$(shell cat version | cut -d '_' -f 2 ))
echo $(NEW_VER)
endef
所以当我做 make firmware
时,新变量给出旧值 V7.1.2.3
而不是 V177.1.2.3
。
me@linux:temp$ make firmware
cat version
PROC_V7.1.2.3
sed -i 's/V7/V177/g' version
cat version
PROC_V177.1.2.3
NEW_VER=V7.1.2.3
echo V7.1.2.3
V7.1.2.3
我的理解是,当调用 version_replace
函数时,首先执行的所有赋值和 NEW_VER
已经填充了旧版本号。
那么如何在 make file 函数中从文件中读取更新的版本号?
可能很难让 call
像您一样使用多个命令,所以我发现有时更容易(尽管可能不太便携)改为创建 shell 脚本:
生成文件
EXEC := $(shell sh script.sh)
FILE := new_version
VERS := $(shell cat $(FILE))
.PHONY: firmware
firmware:
$(info $(VERS))
script.sh
#!/bin/bash
sed 's/V7/V177/g' version | cut -d '_' -f 2 > new_version
# optional # mv new_version version
您可以选择覆盖 version
文件,方法是取消注释脚本中的最后一行并将 Makefile
中的 FILE
变量更改为 version
。
$ make firmware
V177.1.2.3
make: Nothing to be done for `firmware'.
我会这样分开这两件事:
.PHONY: firmware
firmware: version
# replace with firmware generation command that reads from $<
@echo FIRMWARE $@ $<
.PHONY: version
version:
# replace with version update command (sequence)
@echo VERSION $@
构建 firmware
将产生以下序列:
$ make firmware
# replace with version update command (sequence)
VERSION version
# replace with firmware generation command that reads from version
FIRMWARE firmware version
编辑: 您对不同版本增量的要求应该是一个变量,用于控制 version:
目标的命令行,例如make VERSION_INCREMENT=200 firmware
.
你的现象可以简化为一个简单但令人费解的例子:
MY_OUTPUT := First line
.PHONY: foo
foo:
@echo $(MY_OUTPUT)
$(eval MY_OUTPUT := $(shell $(info eval-time) echo Second line))
@echo $(MY_OUTPUT)
$(shell read -p "Hit return:")
输出:
$ make foo
eval-time
Hit return:
...waiting for a keystroke
First line
Second line
配方的评估是这样的:分配一个行缓冲区,这些行将保存没有 make 语法的最终配方命令行。然后遍历所有配方行,执行所有已知的 make 语法,从所有引号 ($$
) 中删除一个级别,执行 $(eval)
操作并将行写入缓冲区。 然后 逐步执行生成的命令行列表,并将它们一一提供给 sh
。 $(info)
告诉我们参数字符串已经预先评估,破坏了你的预期顺序。
这是 make
的行为。 make
将在执行之前扩展目标的配方。
配方$(eval NEW_VER:=$(shell cat version | cut -d '_' -f 2 ))
将被扩展,变量NEW_VER
将存储在变量列表中,其值为V7.1.2.3(来自版本文件)。由于版本文件中尚未更新版本。食谱 echo $(NEW_VER)
将替换为 echo V7.1.2.3
。
执行前,目标firmware
的配方将是
cat version
sed -i 's/V7/V177/g' version
cat version
echo V7.1.2.3
因此最后的输出是打印旧版本。
To make this work, have two different targets. One for changing version in file and other for read it.
生成文件:
all: replace_version read_version
replace_version:
cat version
sed -i 's/V7/V177/g' version
read_version:
cat version
$(eval NEW_VER:=$(shell cat version | cut -d '_' -f 2 ))
echo $(NEW_VER)
There is another possible method to make this work with single target. Change the
sed
command as expandable recipe
生成文件:
firmware:
$(call version_replace, 100)
image.mk
define version_replace
$(shell sed -i 's/V7/V177/g' version)
$(eval NEW_VER:=$(shell cat version | cut -d '_' -f 2 ))
echo $(NEW_VER)
endef