有人可以帮我理解下面的makefile的行为吗?为了给出一些上下文,我试图从一组.proto文件中生成一系列c#类。 proto文件包含在我想要在输出中镜像的目录结构中。因此,假设我的源文件位于名为“Source”的文件夹中,并且我输出到名为“Generated”的文件夹中,如果文件位于:
'源/富/酒吧/ myfile.protoc'
然后输出应该是:
'生成/富/酒吧/ MyFile.cs'。
这看起来很简单,但是当我在make文件中使用dir / notdir时,我看到了一些奇怪的行为。这是一个例子:
# Makefile to build message definitions within this repo
PROTOS:= SourceFiles/Module_1/BasicMessage.proto SourceFiles/Module_2/BasicMessage.proto
withVariables:
for proto in $(PROTOS) ; do \
echo $(dir $$proto) ; \
echo $(notdir $$proto) ; \
done;
hardCoded:
echo $(dir ./SourceFiles/Module_1/BasicMessage.proto)
echo $(notdir ./SourceFiles/Module_1/BasicMessage.proto)
echo $(dir ./SourceFiles/Module_2/BasicMessage.proto)
echo $(notdir ./SourceFiles/Module_2/BasicMessage.proto)
基本上,当我在变量中收集文件名并尝试迭代它们时,dir / notdir似乎无法识别路径中的分隔符。在这里运行Make hardCoded给出:
./SourceFiles/Module_1/
BasicMessage.proto
./SourceFiles/Module_2/
BasicMessage.proto
这是我所期待的。但是,运行withVariables会给出:
./
SourceFiles/Module_1/BasicMessage.proto
./
SourceFiles/Module_2/BasicMessage.proto
我仍然是制作文件的新手,所以我可能遗漏了一些简单的东西,但是如果有人能够解释为什么这两个例子表现不同,那将非常感激。
答案 0 :(得分:1)
配方在传递给shell之前通过make扩展。因此,在withVariables
的方法中,$(dir $$proto)
和$(notdir $$proto)
分别扩展为./
和$proto
。食谱变为:
for proto in SourceFiles/Module_1/BasicMessage.proto SourceFiles/Module_2/BasicMessage.proto; do \
echo ./ ; \
echo $proto ; \
done;
逻辑上产生您看到的输出。您不能在配方中使用make函数,并期望它们由shell执行。相反,您可以从您的食谱中调用标准的dirname
和basename
外部程序:
withVariables:
for proto in $(PROTOS); do \
echo $$(dirname $$proto); \
echo $$(basename $$proto); \
done
通过make as:
扩展配方for proto in SourceFiles/Module_1/BasicMessage.proto SourceFiles/Module_2/BasicMessage.proto; do \
echo $(dirname $proto); \
echo $(basename $proto); \
done
,当由shell执行时,输出:
host> make withVariables
SourceFiles/Module_1
BasicMessage.proto
SourceFiles/Module_2
BasicMessage.proto