Makefile 在Make规则中拆分字符串

Makefile 在Make规则中拆分字符串,makefile,gnu-make,Makefile,Gnu Make,我试图在Make target中拆分一个带有冒号分隔值的字符串 当我尝试使用for循环、EVE、Shell分割目标食谱中的字符串时,得到空白值。其中,当我使用shell命令在目标结果之外拆分字符串时,结果为正 谁能帮我修改一下目标配方吗 下面是片段 notebooks=new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd j=new:e7e45d89-94cc-4783-86c5-22

我试图在Make target中拆分一个带有冒号分隔值的字符串

当我尝试使用for循环、EVE、Shell分割目标食谱中的字符串时,得到空白值。其中,当我使用shell命令在目标结果之外拆分字符串时,结果为正

谁能帮我修改一下目标配方吗

下面是片段

notebooks=new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd
j=new:e7e45d89-94cc-4783-86c5-2236d9904a24
f1=$(shell echo $j | cut -d: -f 1)
test1:
    @for i in $(notebooks); \
    do \
        $(eval f=$(shell echo $i | cut -d: -f 1))  \
        $(eval fid=$(shell echo $i | cut -d: -f 2)) \
        echo $(f) $(fid) $(f1) ;\
    done
输出为

new
new
而期望的输出是

new e7e45d89-94cc-4783-86c5-2236d9904a24 new 
test 2af1d689-98c3-48f2-984d-2ea21c5135dd new

这是关于makefile最常见的混淆:用shell语法编写的配方和make构造之间的区别

make的工作方式是,配方中的所有make构造(变量和函数)首先由make计算,然后将得到的扩展字符串传递给shell,shell执行它

在您的示例中,您试图创建一个包含make变量和函数的shell脚本循环:该循环无法工作(shell是一个新的forked进程,它如何要求make基于shell变量重新扩展某些值?)

当make想要运行此配方时:

@for i in $(notebooks); \
do \
    $(eval f=$(shell echo $i | cut -d: -f 1))  \
    $(eval fid=$(shell echo $i | cut -d: -f 2)) \
    echo $(f) $(fid) $(f1) ;\
done
它首先展开所有makefile变量和函数。记住,这里只是扩展一个字符串,它没有运行shell,所以没有调用shell命令。前两行按如下方式展开:

@for i in new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd; \
do \
@for i in $(notebooks); \
do \
    f=`echo $$i | cut -d: -f 1`;  \
    fid=`echo $$i | cut -d: -f 2`; \
    echo $$f $$fid $(f1) ;\
done
然后展开下一行:

    $(eval f=$(shell echo $i | cut -d: -f 1))  \
这里的
$i
只是一个make变量
i
,您从未设置过它,所以它是空的。因此,make运行以下shell命令:

echo | cut -d: -f 1
它不会产生任何结果,因此展开
$(eval f=)
,并将make变量
f
设置为空字符串

类似地,这一行:

    $(eval fid=$(shell echo $i | cut -d: -f 2)) \
fid
设置为空字符串

然后这条线就扩大了

    echo $(f) $(fid) $(f1) ;\
扩展至:

    echo   new ;\
因为这里只有
f1
有任何值。最后一行:

done
因此,在所有扩展之后,传递给要运行的shell的字符串是:

@for i in new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd; \
do \
    echo   new; \
done
在配方中使用
$(shell…
)是毫无意义的;你已经在壳里了,为什么还需要另一个呢?类似地,您不需要
eval
来设置make变量,您需要使用shell变量

写下你的食谱如下:

@for i in new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd; \
do \
@for i in $(notebooks); \
do \
    f=`echo $$i | cut -d: -f 1`;  \
    fid=`echo $$i | cut -d: -f 2`; \
    echo $$f $$fid $(f1) ;\
done

这是关于makefile最常见的混淆:用shell语法编写的配方和make构造之间的区别

make的工作方式是,配方中的所有make构造(变量和函数)首先由make计算,然后将得到的扩展字符串传递给shell,shell执行它

在您的示例中,您试图创建一个包含make变量和函数的shell脚本循环:该循环无法工作(shell是一个新的forked进程,它如何要求make基于shell变量重新扩展某些值?)

当make想要运行此配方时:

@for i in $(notebooks); \
do \
    $(eval f=$(shell echo $i | cut -d: -f 1))  \
    $(eval fid=$(shell echo $i | cut -d: -f 2)) \
    echo $(f) $(fid) $(f1) ;\
done
它首先展开所有makefile变量和函数。记住,这里只是扩展一个字符串,它没有运行shell,所以没有调用shell命令。前两行按如下方式展开:

@for i in new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd; \
do \
@for i in $(notebooks); \
do \
    f=`echo $$i | cut -d: -f 1`;  \
    fid=`echo $$i | cut -d: -f 2`; \
    echo $$f $$fid $(f1) ;\
done
然后展开下一行:

    $(eval f=$(shell echo $i | cut -d: -f 1))  \
这里的
$i
只是一个make变量
i
,您从未设置过它,所以它是空的。因此,make运行以下shell命令:

echo | cut -d: -f 1
它不会产生任何结果,因此展开
$(eval f=)
,并将make变量
f
设置为空字符串

类似地,这一行:

    $(eval fid=$(shell echo $i | cut -d: -f 2)) \
fid
设置为空字符串

然后这条线就扩大了

    echo $(f) $(fid) $(f1) ;\
扩展至:

    echo   new ;\
因为这里只有
f1
有任何值。最后一行:

done
因此,在所有扩展之后,传递给要运行的shell的字符串是:

@for i in new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd; \
do \
    echo   new; \
done
在配方中使用
$(shell…
)是毫无意义的;你已经在壳里了,为什么还需要另一个呢?类似地,您不需要
eval
来设置make变量,您需要使用shell变量

写下你的食谱如下:

@for i in new:e7e45d89-94cc-4783-86c5-2236d9904a24 test:2af1d689-98c3-48f2-984d-2ea21c5135dd; \
do \
@for i in $(notebooks); \
do \
    f=`echo $$i | cut -d: -f 1`;  \
    fid=`echo $$i | cut -d: -f 2`; \
    echo $$f $$fid $(f1) ;\
done

谢谢@MadScientist的解释。谢谢@MadScientist的解释。