Reputation: 440
I'm kinda studying MsBuild. As a practical work I prepared a *.proj file to build simple "hello, world" C++ application. Things were gone well but then it fail after I added one line to "Compile" target - I cannot find how to make it prepare list of *.obj files to be used by linker.
Note:* Microsoft (R) Build Engine version 4.7.2558.0 (that is just a MsBuild.exe from "C:\Windows\Microsoft.NET\Framework\v4.0.30319" dir).
Here is my *.proj file:
<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>
Note: is a simple MsBuild task developed by me. That is just a simple wrapper for .NET ProcessStartInfo and Process classes. It works fine.
Targets Clean, CopeFiles are working fine. Target Compile also was working fine before I added echo command with redirecting to *.link file.
The problem is - it begins to report an error in Compile target after I added echo to *.link file:
Error message:
D:\BuildProc\msbld06\build06.proj(73,9): error MSB4095: The item metadata %(Filename) is being referenced without an item name. Specify th e item name by using %(itemname.Filename).
And here is a line in my *.proj file which lead to mentioned error:
<Exec Command="echo %(Compile.Identity->'%(Filename).obj') >> $(OutputPath)\$(ExecutableName).link " />
So, I need somehow to output {filename}.obj into $(OutputPath)\$(ExecutableName).link file and then use that file as @-parameter for linker. I tried to use other forms but all fail. So, searching for a hint...
In this case for me it is much more important to understand - how to achieve this with transformation exactly from %(Compile.Identity) if that is possible at all. And only as a second step maybe you can recommend other way to do the same (my idea is not to use Microsoft.Cpp.targets or other include files, I want to do this with only empty/clean MsBuild setup).
Thanks.
Upvotes: 0
Views: 3163
Reputation: 100571
The easiest way to accomplish what you want to do ist to use the WriteLinesToFile task:
<WriteLinesToFile Lines="@(Compile->'%(Filename).obj')" File="$(OutputPath)$(ExecutableName).link" Overwrite="true" />
Upvotes: 1
Reputation: 7792
Compile is ItemGroup so you should refer it with @ and not %. Try following
<Exec Command="echo @(Compile)->%(Filename).obj >> $(OutputPath)$(ExecutableName).link" />
Upvotes: 1