dmitry_bond
dmitry_bond

Reputation: 440

MSBuild - how to transform %(Compile.Identity) into filename with other extension?

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

Answers (2)

Martin Ullrich
Martin Ullrich

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

Pankaj Kapare
Pankaj Kapare

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

Related Questions