3

I'm trying to make a .targets file for my NuGet package, which will link to a proper .lib file depending on the C++ runtime library of a project. This answer recommends to use %(ClCompile.RuntimeLibrary) metadata for this. But it seems like metadata cannot be accessed outside the <Target> node! And library dependencies are added in <ItemDefinitionGroup> node just under the root <Project> node.

Here is the SSCCE:

<?xml version="1.0" encoding="us-ascii"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <ClCompile Include="main.cpp">
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
    </ClCompile>
  </ItemGroup>
  <PropertyGroup>
    <RuntimeLibrary>%(ClCompile.RuntimeLibrary)</RuntimeLibrary>
  </PropertyGroup>
  <Target Name="Build">
    <Message Text="Property = $(RuntimeLibrary)" Importance="high" />
    <Message Text="Metadata = %(ClCompile.RuntimeLibrary)" Importance="high" />
  </Target>
</Project>

Running it with MsBuild yields:

Property = %(ClCompile.RuntimeLibrary)
Metadata = MultiThreadedDebugDLL

The same statement %(ClCompile.RuntimeLibrary) is expanded to the value when used inside <Target> node, but not when used in <PropertyGroup> node outside <Target> node.

So how can I access runtime library metadata value to add reference the proper library?

Update: The suggested, but not satisfying fix is to define RuntimeLibrary like the following:

<RuntimeLibrary>@(ClCompile->'%(RuntimeLibrary)')</RuntimeLibrary>

Output of the initial script is proper in this case, but my task is still not solved, since I want to use this property in a condition. So if I add the following:

<PropertyGroup Condition="'$(RuntimeLibrary)'=='MultiThreadedDebugDLL'">
  <TestProp>defined</TestProp>
</PropertyGroup>
...
<Message Text="TestProp = $(TestProp)" Importance="high" />

TestProp is undefined. How do I make this work for conditions?

Community
  • 1
  • 1
Mikhail
  • 20,685
  • 7
  • 70
  • 146
  • 1
    re: your edit: that will work if you put that PropertyGroup in the Target iteself - or if you use `Condition="'@(ClCompile->'%(RuntimeLibrary)')'`. I'm not 100% sure but I think the way you wrote it won't work due to the eveluation order msbuild uses. – stijn Dec 22 '14 at 09:04
  • @stijn I cannot put this property in a ``, since I need to use it in a condition for ``, which cannot be placed in a `` :( – Mikhail Dec 22 '14 at 09:21
  • Well then the condition with `@` seems the only solution? – stijn Dec 22 '14 at 09:24
  • @stijn Yes, but it is not working too. Besides, `@(ClCompile->'%(RuntimeLibrary)')` is expanded to a string like `MultiThreadedDebugDLL;MultiThreadedDebugDLL;MultiThreadedDebugDLL` in case there are several files in a project (which is almost always true), and requires split before usage. Not sure whether it is possible to make this split in the condition itself. – Mikhail Dec 22 '14 at 09:30

1 Answers1

3

Try the following instead:

  <PropertyGroup>
    <RuntimeLibrary>@(ClCompile->'%(RuntimeLibrary)')</RuntimeLibrary>
  </PropertyGroup>

Using the @ symbol allows you to reference item lists.

There is also an example on StackOverflow.

Community
  • 1
  • 1
Matt Ward
  • 47,057
  • 5
  • 93
  • 94