【问题标题】:Using eval in make file在 make 文件中使用 eval
【发布时间】:2017-01-10 14:14:25
【问题描述】:

我运行 buildroot make 并在此构建过程中创建一个文本文件。发生这种情况后,作为构建的一部分运行另一个 make。我想将生成的文件的内容读入一个变量并使用它们。这不起作用,因为在我的 buildroot make 开始时它认为文件不存在,所以即使它是在代码运行之前生成的,make 已经确定它不存在。

读取的文件格式:

  str1 str2 1.1.0_nightlybuild (1389:1497M@trunk)

我正在尝试使用 eval(这应该在运行时检查文件内容)。但是问题仍然存在,我似乎无法在创建文件后从文件中读取。似乎 make 可能正在扩展变量,因此 eval 不起作用。

没有从文件内容中设置任何变量。我检查并正确生成了文件,所以如果我再次运行 make,当文件已经生成时,一切正常。 eval 不是正确的方法吗?

所以文件在make开始时不存在,先存在然后运行这段代码:

define EXAMPLE
    $(eval s := $(shell cat output/target/version.txt)) 
    $(eval FILENAME_BIN=$(word 1, $(s)).$(word 2, $(s)).$(word 3, $(s)).bin)
    $(eval FILENAME_JFFS2=$(word 1, $(s)).$(word 2, $(s)).$(word 3, $(s)).jffs2)
    mv $(BINARIES_DIR)/$(BOOTIMAGE) $(BINARIES_DIR)/$(FILENAME_BIN)
    mv $(BINARIES_DIR)/$(JFFS2IMAGE) $(BINARIES_DIR)/$(FILENAME_JFFS2)
endef

它不起作用,文件已生成并且后续构建将起作用,而不是在进程开始时文件不存在的第一个构建。第一次文件被简单地称为...bin...jffs2,因为从文件中读取的变量没有被填充。当它工作时,文件被称为str1.str2.1.1.0_nightlybuild.binstr1.str2. 1.1.0_nightlybuild.jffs2

这是真正的用例 makefile http://pastebin.com/6GdKcUg6 TEST_DEFAULT_RENAME 是我试图读取文件的地方,我正在使用 buildroot(所以很多 make 文件),当我在 buildroot 过程中点击 make 时 version.txt 是在此过程中创建,然后此代码尝试读取此文件,但除非在我在 buildroot 目录中输入 make 之前 version.text 存在,否则它不起作用。如您所见,我通过 cat 在其他地方使用 version.txt,但效果很好。

【问题讨论】:

  • 请发布您的整个 makefile 或更详细地描述您想要实现的目标。如果它是将包含在某些源中的版本文件的生成,那么您可以将版本文件添加为目标文件的依赖项,并提供创建该版本文件的方法。
  • 您的方法可能有问题,因为我相信make 在开始时会解析一次 Makefile,并且程序会扩展所有变量——不是 bash——所以 eval 语句正在对已扩展的变量名称进行操作。
  • 您需要发布 makefile 或(更好)minimal reproducible example
  • @igagis 添加了 make 文件和更多上下文
  • @MikeKinghan 暂时添加了 makefile 并将继续使用

标签: bash variables makefile eval


【解决方案1】:

我运行了一个 buildroot make,并在这个构建过程中创建了一个文本文件。发生这种情况后,作为构建的一部分运行另一个 make。我想将生成的文件的内容读入一个变量并使用它们。这不起作用,因为在我的 buildroot make 开始时它认为文件不存在,所以即使它是在代码运行之前生成的,make 已经确定它不存在。

发生这种情况是因为 另一个 make 不知道 buildroot make 产生什么,即缺少依赖信息(这就是递归 make 有问题的原因)。换句话说,另一个 make 不知道 buildroot make 生成 version.txt

想到几个解决方案:

  1. 有一个 shell 脚本可以按顺序调用 makefile,例如make -f buildroot.mk && make -f another.mk。这样another.mk 就会观察到buildroot.mk 生成的所有文件。

  2. 在评估目标和依赖项之前,在first phase 期间从another.mk 调用buildroot.mk。例如:

    # At the top level, not in a rule.
    $(shell ${MAKE} -f buildroot.mk)
    # now version.txt is available
    version := $(shell cat version.txt)
    
  3. buildroot.mk 完成后,让another.mk 自行重启。做 1 和 2 的更复杂的方法:

    $ cat buildroot.mk 
    version.txt :
        echo "str1 str2 1.1.0_nightlybuild (1389:1497M@trunk)" > $@
    
    $ cat another.mk
    all :
        @echo "$@ has completed."
    
    ifdef MAKE_RESTARTS
    s := $(shell cat version.txt))
    FILENAME_BIN := $(word 1, $(s)).$(word 2, $(s)).$(word 3, $(s)).bin
    FILENAME_JFFS2 := $(word 1, $(s)).$(word 2, $(s)).$(word 3, $(s)).jffs2
    $(info ${FILENAME_BIN})
    $(info ${FILENAME_JFFS2})
    else
    another.mk : version.txt
        touch $@
    endif
    
    version.txt :
        $(MAKE) -f buildroot.mk
    
    .PHONY: all version.txt
    
    $ make -f another.mk 
    make -f buildroot.mk
    make[1]: Entering directory '~/tmp'
    echo "str1 str2 1.1.0_nightlybuild (1389:1497M@trunk)" > version.txt
    make[1]: Leaving directory '~/tmp'
    touch another.mk
    str1.str2.1.1.0_nightlybuild.bin
    str1.str2.1.1.0_nightlybuild.jffs2
    all has completed.
    
    $ make -f another.mk 
    make -f buildroot.mk
    make[1]: Entering directory '~/tmp'
    make[1]: 'version.txt' is up to date.
    make[1]: Leaving directory '~/tmp'
    touch another.mk
    str1.str2.1.1.0_nightlybuild.bin
    str1.str2.1.1.0_nightlybuild.jffs2
    all has completed.
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    • 2010-12-02
    • 1970-01-01
    相关资源
    最近更新 更多