作为测试套件的make install规则的一部分,我想将一个目录(src目录)中的所有二进制可执行文件移动到bin目录。我认为一种简单的方法是简单地循环遍历src
目录中的每个文件,然后使用patsubst
将src
替换为每个路径中的bin
。不幸的是,我无法让它工作,因为我无法在每次循环迭代中获得make
来评估当前FILE的名称。我有权访问的是bash shell变量$$FILE
,但当我将其与make
patsubst
函数一起使用时,它实际上并没有评估 shell变量$$FILE
...而是,patsubst
函数似乎只看到字符串"$FILE"
。
所以,这就是我正在尝试的:
install :
-- irrelevant stuff snipped --
for FILE in $(BINARY_TARGETS); do \
if [ -f $$FILE ]; then mv -f $$FILE $(patsubst %/src/,%/bin/,$$FILE); fi \
done
这会导致每个文件出错:
mv: ‘./src/foo/bar’ and ‘./src/foo/bar’ are the same file
这个错误让我明白patsubst
中的make
函数实际上并没有评估shell变量,只是看到了$FILE
,结果就是它没有&#39}。找到替换模式,传递给mv
的最终命令将源和目标路径作为相同的字符串。
那么,有没有办法让patsubst
来评估shell变量的值?或者是否有更好的方法来实现我在这里尝试实现的目标?
答案 0 :(得分:1)
(let [nums (range)]
(time (nth nums 1e8))
(time (nth (range) 1e8)))
"Elapsed time: 2127.814253 msecs"
"Elapsed time: 2042.608043 msecs"
处理优先于将命令传递给shell。并且,一旦通过,它们将由shell执行。因此,首先make
处理命令并在:
make
$(patsubst %/src/,%/bin/,$$FILE)
由$$FILE
代替,然后按字面处理。因此,没有匹配的模式,实际上$FILE
返回patsubst
。请参阅以下示例:
$FILE
它给出了:
bar:
echo $(patsubst %/src/,%/bin/,$$whatever)
作为makefile规则的结果,bash按以下命令执行:
arturcz@szczaw:/tmp/m$ make bar
echo $whatever
arturcz@szczaw:/tmp/m$
这就是你得到结果的原因。
您可以依靠for FILE in src/a src/b src/c; do \
if [ -f $FILE ]; then mv -f $FILE $FILE; fi \
done
进行正确的替换,但您需要将其强制为shell(默认情况下为bash
,缺少某些必需的功能):
sh
您也可以要求SHELL=bash
install:
for FILE in $(BINARY_TARGETS); do \
if [ -f $$FILE ]; then echo $$FILE $${FILE/\/src\//\/bin\/}; fi \
done
进行循环和替换。你可以通过几种方法实现这一目标。这个正在进行所有替换和准备命令。
make
您可以使用`$(通配符)函数停止检查文件是否存在install:
$(foreach d,$(BINARY_TARGETS),if [ -f $(d) ]; then mv -f $(d) $(d:./src/%=./bin/%);fi;)
:
make
最后,我个人更喜欢的解决方案 - 使用适当的依赖关系和规则以install:
$(foreach d,$(wildcard $(BINARY_TARGETS)),mv -f $(d) $(d:./src/%=./bin/%);)
方式进行。
make
如果install: $(BINARY_TARGETS:./src/%=./bin/%)
bin/%: src/%
mv -f $< $@
中存在任何文件是可选的,您可能需要再次使用BINARY_TARGET
技巧:
$(wildcard)