在Makefile中提取目录/文件名

时间:2018-06-15 12:53:43

标签: c# makefile protocol-buffers

有人可以帮我理解下面的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

我仍然是制作文件的新手,所以我可能遗漏了一些简单的东西,但是如果有人能够解释为什么这两个例子表现不同,那将非常感激。

1 个答案:

答案 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执行。相反,您可以从您的食谱中调用标准的dirnamebasename外部程序:

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