Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MSBuild-如何将%(Compile.Identity)转换为具有其他扩展名的文件名?_Msbuild_Transformation - Fatal编程技术网

MSBuild-如何将%(Compile.Identity)转换为具有其他扩展名的文件名?

MSBuild-如何将%(Compile.Identity)转换为具有其他扩展名的文件名?,msbuild,transformation,Msbuild,Transformation,我在研究MsBuild。作为一个实际的工作,我编写了一个*.PRJ文件来构建简单的“hello,Word”C++应用程序。事情进展顺利,但在我为“编译”目标添加了一行之后失败了——我找不到如何让它准备链接器使用的*.obj文件列表 注意:Microsoft(R)生成引擎版本4.7.2558.0(这只是“C:\Windows\Microsoft.NET\Framework\v4.0.30319”目录中的MsBuild.exe) 这是我的*.proj文件: <Project Defau

我在研究MsBuild。作为一个实际的工作,我编写了一个*.PRJ文件来构建简单的“hello,Word”C++应用程序。事情进展顺利,但在我为“编译”目标添加了一行之后失败了——我找不到如何让它准备链接器使用的*.obj文件列表

注意:Microsoft(R)生成引擎版本4.7.2558.0(这只是“C:\Windows\Microsoft.NET\Framework\v4.0.30319”目录中的MsBuild.exe)

这是我的*.proj文件:

    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">

        <PropertyGroup>
            <SourceDir>D:\BuildProc\cpp1</SourceDir>

            <OutputPath>$(MSBuildProjectDirectory)\Bin\</OutputPath>
            <ExecutableName>MyCppSample</ExecutableName>
            [...]       
        </PropertyGroup>

        <ItemGroup>
            <Compile Include="hello.cpp"/>
            <Compile Include="main.cpp"/>
        </ItemGroup>

        <Target Name="Build" DependsOnTargets="CopyFiles;Compile;Link"
            Inputs="@(Compile)" 
            Outputs="$(OutputPath)$(ExecutableName).exe">

            <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
        </Target>

        <Target Name="CopyFiles" 
            Inputs="@(Compile->'$(SourceDir)\%(Filename)%(Extension)')" 
            Outputs="@(Compile->'$(OutputPath)\%(Filename)%(Extension)')">

            <Copy SourceFiles="@(Compile->'$(SourceDir)\%(Filename)%(Extension)')" DestinationFolder="$(OutputPath)" />
        </Target>

        <Target Name="Compile" 
            Inputs="@(Compile->'$(OutputPath)\%(Filename)%(Extension)')" 
            Outputs="@(Compile->'$(OutputPath)\%(Filename).obj')">

            <Exec Command="@echo === %(Compile.Identity)" />
            <ExecEx Filename="cl" Arguments="%(Compile.Identity) $(CLOptions) -I$(SourceDir)" WorkingDir="bin" />

            <!-- here it fail! :-( -->
            <Exec Command="echo %(Compile.Identity->'%(Filename).obj') >> $(OutputPath)\$(ExecutableName).link " />

        </Target>

        <Target Name="Link" 
            Inputs="@(Compile->'$(OutputPath)\%(Filename).obj')" 
            Outputs="$(OutputPath)\$(ExecutableName).exe">      

            <Exec Command="@echo === Linking..." />
            <ExecEx Filename="link" Arguments="$(LibPath) $(Libs) $(LinkOptions) @$(ExecutableName).link" WorkingDir="bin" />
        </Target>

    </Project>

D:\BuildProc\cpp1
$(MSBuildProjectDirectory)\Bin\
MyCppSample
[...]       
注意:是我开发的一个简单的MsBuild任务。这只是.NET ProcessStartInfo和Process类的简单包装。它很好用

目标干净,文件工作正常。在我添加echo命令并重定向到*.link文件之前,目标编译也运行良好

问题是-在我将echo添加到*.link文件后,它开始报告编译目标中的错误:

错误消息:

D:\BuildProc\msbld06\build06.proj(73,9):错误MSB4095:引用的项元数据%(文件名)没有项名称。指定th 使用%(itemname.Filename)编辑项目名称

我的*.proj文件中有一行导致上述错误:

<Exec Command="echo %(Compile.Identity->'%(Filename).obj') >> $(OutputPath)\$(ExecutableName).link " />

因此,我需要以某种方式将{filename}.obj输出到$(OutputPath)\$(ExecutableName).link文件中,然后将该文件用作链接器的@参数。我尝试使用其他形式,但都失败了。所以,寻找一个提示

在这种情况下,对我来说,更重要的是要理解——如果可能的话,如何通过从%(Compile.Identity)转换来实现这一点。 仅作为第二步,您可以推荐其他方法来执行相同的操作(我的想法是不要使用Microsoft.Cpp.targets或其他include文件,我只希望使用空/干净的MsBuild设置来执行此操作)


谢谢。

Compile是ItemGroup,所以你应该用@而不是%来引用它。 试着跟随

<Exec Command="echo @(Compile)->%(Filename).obj >> $(OutputPath)$(ExecutableName).link" />

Compile是ItemGroup,因此您应该使用@而不是%来引用它。 试着跟随

<Exec Command="echo @(Compile)->%(Filename).obj >> $(OutputPath)$(ExecutableName).link" />

完成您想做的事情的最简单方法是使用任务:


完成您想做的事情的最简单方法是使用任务:



对不起,它不工作!首先,它不应该是“@(Compile)->%(Filename).obj”,而是“@(Compile->'%(Filename.obj')”。其次,这两种变体都不起作用。下面是它正在生成的输出示例:
hello.obj;main.obj;你好,obj;main.obj
。链接器输入文件应每1行包含1个*.obj文件。很抱歉,它不起作用!首先,它不应该是“@(Compile)->%(Filename).obj”,而是“@(Compile->'%(Filename.obj')”。其次,这两种变体都不起作用。下面是它正在生成的输出示例:
hello.obj;main.obj;你好,obj;main.obj
。链接器输入文件应每1行包含1*.obj文件。谢谢。它起作用了。但是我想知道-为什么同样的语句
@(Compile->'%(Filename).obj')
不起作用?!嗯,我可以猜,在Microsoft.Build.Tasks.dll上使用Reflector——因为任务的Lines属性是一个数组。但是从微软团队看来,这有点愚蠢实际上,这意味着对于不同的任务,相同参数语句的扩展是非常不同的!我认为这很糟糕。所以
@()
将返回一个
-默认情况下,如果传递给某个最终将作为字符串参数的对象,则使用分隔字符串<代码>@(项->'%(元数据)''-')
将使用“-”分隔。您也可以在那里传递编码的换行符(
%0A
)。使用
%(Compile.Filename)
将导致对元数据进行批处理-对于每个唯一值,将多次调用exec任务。啊,好的。非常感谢,谢谢。它起作用了。但是我想知道-为什么同样的语句
@(Compile->'%(Filename).obj')
不起作用?!嗯,我可以猜,在Microsoft.Build.Tasks.dll上使用Reflector——因为任务的Lines属性是一个数组。但是从微软团队看来,这有点愚蠢实际上,这意味着对于不同的任务,相同参数语句的扩展是非常不同的!我认为这很糟糕。所以
@()
将返回一个
-默认情况下,如果传递给某个最终将作为字符串参数的对象,则使用分隔字符串<代码>@(项->'%(元数据)''-')
将使用“-”分隔。您也可以在那里传递编码的换行符(
%0A
)。使用
%(Compile.Filename)
将导致对元数据进行批处理-对于每个唯一值,将多次调用exec任务。啊,好的。非常感谢你。