通过读取另一个文件的内容在makefile中创建变量


81

如何从makefile即时创建变量,其值将是另一个数据文件的全部内容。

Answers:


49

我猜想您想在Makefile中将一个变量设置为另一个文件的内容:

FILE=test.txt
VARIABLE=`cat $(FILE)`

target:
    echo $(VARIABLE)

3
实际上,我不能将VARIABLE定义放在首位:因为PATH_TO_MY_DATA_FILE直到在all:目标中运行了某些命令才存在。作为替代方案,我所做的是将东西分成两个makefile(创建了一个子make),并在子make的顶部声明了VARIABLE,现在它就像一个吊饰一样工作。
Srinath

26
这是一个错误的答案。的值VARIABLE是一个字符串cat $(FILE)(用引号引起来),仅在外壳程序的配方中进行扩展。尝试像一样打印它的值$(info ${VARIABLE})
Maxim Egorushkin

3
@MaximEgorushkin没错。您只需要考虑VARIABLE一个诺言。这是与旧版本兼容的唯一版本make。这两个:=$(shell ...)是GNU扩展。
2015年

7
不赞成投票。这将在cat每次执行规则时执行。通常不打算这样做,应该警告它,因为它很慢。此外,如果文件是管道,则具有意外的副作用。分配应为with,:=以便在替换变量时而不是在定义变量时不会评估规则。替换值应该是$(shell cat $(FILE))这样,以便cat命令可以通过make就地执行,而不是稍后由配方规则执行。
Christian Hujer '17

2
@antred,make是标准UNIX / POSIX工具集的一部分,该工具集还包括cat。如果您进行安装,则可以正常安装所有其他基本工具,并且在极少数情况下会造成任何困难。依靠cat而不是复杂的替代规则将使您的makefile更加易于理解,并且几乎可以移植,有时甚至可以移植。
迈克尔

81

假设GNU make:

file := whatever.txt
variable := $(shell cat ${file})

4
@ceving使用标准的GNU make。Solaris make是不可移植的应用程序。
Maxim Egorushkin 2015年

7
Gnu品牌既不是标准的,也不是比solaris品牌的便携式。“受欢迎”是您的词。如果我们认真考虑可移植性和标准配置,请坚持使用posix。
把友情留在无盐

3
在这种情况下,我会选择“ Popular”-非GNU Make太原始了。如果您打算继续支持1990年代的操作系统,那么@ bb-generation的答案可能就是您所需要的(尽管在许多情况下它会给您带来麻烦)。在所有其他情况下,GNU Make要么很容易获得,要么(很可能是)默认值,因此请使用它。
古斯

1
GNU make可以在任何地方运行,因此,它比任何其他make都更具可移植性。“标准”可以是主观的,可以接受的。
MarcH

26

GNU make 4.2版支持文件读取操作,因此对于Maxim Egorushkin的一个很好的答案,现在有一种解决此问题的可选方法:

FILE     := test.txt
variable :=$(file < $(FILE))

修复了一个错误。变量名称区分大小写。名称“ foo”,“ FOO”和“ Foo”均指代不同的变量。(gnu.org/software/make/manual/html_node/Using-Variables.html
雅罗Nikitenko

也不需要引号,$(file <“ $(FILE)”)尝试打开“ test.txt”。
cagney

14

catWindows上不存在。适用于Linux和Windows的解决方案:

cat := $(if $(filter $(OS),Windows_NT),type,cat)
variable := $(shell $(cat) filename)

说明:好像在Windows上,总是将OS环境变量定义为等于“ Windows_NT”。这样,对于Windows使用type命令,对于非Windowscat使用。



4

如果您使用的是GNU make,则获得此效果的另一种方法是使用另一个makefile的make“ include”:

从Makefile:

include "./MyFile.mak"

创建一个包含内容的文件“ MyFile.mak”:

FILE := "my file content"
FILE += "more content 1"
FILE += "more content 2"

这似乎不起作用,我知道Makefile:1: "./MyFile.mak": No such file or directory
knocte

这可能意味着您使用的是非GNU版本的make ....或旧版本的GNU make ...尝试:“ make -v”
Bill Moore

在Mac中使用make,不确定是否由自制软件捆绑或安装,make -v给出GNU Make 3.81
knocte

您确定没有在Makefile中将TAB字符意外转换为SPACE字符吗?在这方面,make几乎像python一样令人讨厌。
比尔·摩尔

通过删除引号,我在Mac上可以使用此功能,例如: include ./MyFile
Charlie Tran

3

由于尚未指定平台,因此这是在Solaris上的工作方式:

VERSION:sh = cat VERSION

all:
        echo $(VERSION)

0

这是一种更可移植的解决方案,可与MAKE版本3一起使用,该版本的file指令不可用。缺点是它需要在该过程中创建一个临时文件。

$(shell echo define my_variable > file.tmp)
$(shell cat my_file.txt >> file.tmp)
$(shell echo endef >> file.tmp)
include file.tmp

主要思想是使用define伪指令,该伪指令专门用于声明多行变量。当然,shell如果可以显式写入文件内容以供Makefile使用,则可以避免使用和使用临时文件。

请记住,如果您的文件包含 $符号,MAKE则在扩展时my_variable(或使用定义时:=),将尝试将它们扩展为变量/伪指令。如果要避免这种情况,则需要在包含文件内容之前对它们进行转义。例如,cat您可以执行以下操作:

$(shell sed 's/\$$/$$$$/g' my_file.txt >> file.tmp)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.