【问题标题】:How to pass for loop variable to shell function in makefile如何将for循环变量传递给makefile中的shell函数
【发布时间】:2017-11-17 19:39:59
【问题描述】:

考虑下面的makefile:

CFG_DIR = /media/test/
all:
    for list in $(CFG_DIR); do \
      echo "list is $$list"; \
      for file in $(shell ls $${list}); do \
        echo "file is $$file"; \
      done \
    done

执行make时会产生以下结果:

list is /media/test/
file is Makefile

不是打印 /media/test/ 目录的目录列表,而是打印执行 make 命令的当前目录的目录列表。

似乎在 shell 函数中 $$list 被评估为一个空值。如果有人能指出在 shell 函数中访问 for 循环变量的正确方法,那将会很有帮助。

【问题讨论】:

标签: loops makefile scripting gnu-make


【解决方案1】:

您不能在 make 函数中使用 shell 变量。

考虑 make 是如何工作的:当它想运行一个配方命令时,它首先扩展命令中的所有 make 变量和函数,然后它获取结果字符串并将其传递给 shell 以运行,然后它等待 shell退出。如果 shell 以成功代码 (0) 退出,那么 make 会说“是的,它成功了!”如果 shell 以失败代码(非 0)退出,那么 make 会说“boo it failed”。

这是你的食谱:

for list in $(CFG_DIR); do \
  echo "list is $$list"; \
  for file in $(shell ls $${list}); do \
    echo "file is $$file"; \
  done \
done

因此,FIRST make 将扩展它,包括所有变量和函数。你有一个$(CFG_DIR) 变量和一个$(shell...) 函数。变量只是/media/test/。当 make 扩展函数时,它看到传递给 shell 的命令是ls ${list}。所以运行:

/bin/sh -c 'ls ${list}'

好吧,除非您在环境中某处设置了 shell 变量 list,否则它是空字符串,因此 shell 执行 ls 并返回当前目录的所有内容。然后,将其替换为您的配方,并将结果交给 shell 运行:

/bin/sh -c 'for list in /media/test; do
  echo "list is $list";
  for file in <current-wd-files>; do
    echo "file is $file";
  done
done'

所以。故事的寓意:在配方命令中,您已经在 shell 中。所以你应该永远不要使用$(shell ...) make 函数。它只会导致混乱和悲伤。

你应该使用 shell 语法,因为你已经有了一个 shell:

all:
      for list in $(CFG_DIR); do \
          echo "list is $$list"; \
          for file in `ls $${list}`; do \
            echo "file is $$file"; \
          done \
        done

【讨论】:

    猜你喜欢
    • 2021-06-21
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 1970-01-01
    相关资源
    最近更新 更多