【问题标题】:GNU make loop variable strange behaviorGNU使循环变量奇怪的行为
【发布时间】:2015-03-09 23:57:13
【问题描述】:

在我的 Makefile 中,我试图将文件列表从 location1 复制到 location2,然后从 location2 复制到 location3。我得到了以下奇怪的行为:

    FILES_LIST=dir1/file1 dir2/file2 dir3/file3 ........

    mytarget:
        for file in $(FILES_LIST) ; do \
            #this works
            cp -vf location1/$$file location2/$(shell $$file##*/) ; \
            #this does not work
            cp -vf location2/$(shell $$(file)##*/) location3/ ; \
        done

我正在使用“$(shell $$(file)##/)”来去除 FILES_LIST 中每个项目的“dir1/”部分。 第一个 cp 工作(从位置 1 到 2),但是,发送没有,构建日志显示 "$(shell $$(file)##/)" 被评估为空。

我正在使用 GNU Make 3.81

【问题讨论】:

    标签: shell for-loop makefile gnu


    【解决方案1】:

    问题是$$(file)。这不是变量评估。那是命令替换。你的意思是$${file}(虽然不完全是,但我们会讲到的)。

    也绝对没有理由在这里使用$(shell),因为当这些行运行时,您已经在shell上下文中。

    更不用说那些$(shell) 调用并没有像你想要的那样做任何事情(他们没有在正确的时间运行)。

    你想要这个:

    FILES_LIST=dir1/file1 dir2/file2 dir3/file3 ........
    
    mytarget:
        for file in $(FILES_LIST) ; do \
            #this works
            cp -vf location1/$$file location2/$${file##*/} ; \
            #this does not work
            cp -vf location2/$${file)##*/} location3/ ; \
        done
    

    您的$file 变量是一个shell 变量而不是make 变量。对$(shell) 的调用看不到它。您正在有效地运行$(shell $file##*/),它通过shell 运行$file##*/ 命令。该 shell 没有 $file 变量,因此它变成了 ##*/,这是一个注释,整个事情什么也不返回。 (实际上我认为评论可能会先被删除,但这并不会改变任何事情。)

    【讨论】:

    • 您是对的,先生!感谢您的详细解释。 "cp -vf location2/$${file##*/} location3/ ; \" 为我工作
    【解决方案2】:

    使用 $(notdir $file) 命令。 notdir 将删除目录并返回文件名。例如,$(notdir dir1/file.h) 将返回 file.h

    更多详细信息参考链接: https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html

    【讨论】:

    • 问题是如果我把 $$file 放在括号中,它会被评估为一个空值:这里是日志显示:for header in dir1/file1 dir2/file2 dir3/file3;做\cp -vf /location2/ /location3; \ 完成 cp: 省略目录 '/location2/'
    • 因为文件是在你的 makefile 中定义的,但不是在 shell 环境中,$$(file) 在 shell 中变成 $(file),因此计算为 NULL。使用单个$而不是$$,即“cp -vf location2/$(shell $(file)##*/) location3/”
    • $file 是一个 shell 变量而不是一个 make 变量。
    • 这个答案的方向是错误的。这需要更多地向外壳移动,而不是远离它。 $(notdir) 函数在 make 上下文中没有任何可操作的内容。
    • notdir 应在 make 规则之前使用,如下所示:FILES_ONLY=$(notdir $(FILES_LIST))。现在,FILES_ONLY 将只包含文件名,并且在 make 规则中,应该在循环中使用 FILES_ONLY。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多