Reputation: 1336
I have a C++ desktop app that uses several folders of resources, some of which are generated at buildtime like this:
<ItemDefinitionGroup>
<PreBuildEvent>
<Command>generate stuff</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>xcopy stuff to $(OutDir)
xcopy otherstuff to $(OutDir)</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
('otherstuff' represents pre-existing, not generated resources. I have good reasons why I cannot enumerate the contents of those folders file by file inside the vcxproj.)
However, when packaging the application for the Windows Store via a Windows Application Packaging Project (.wapproj), the generated stuff is not included in the .msix, because the wapproj, understandably, only knows about those resources that are referenced with a <Content Include="" />
.
Since the resources are generated at buildtime, they don't exist when the .vcxproj is evaluated, so adding this to the vcxproj doesn't work:
<Content Include="stuff\**"
Link="%(RecursiveDir)%(Filename)%(Extension)"
CopyToOutputDirectory="PreserveNewest"/>
<Content Include="otherstuff\**"
Link="%(RecursiveDir)%(Filename)%(Extension)"
CopyToOutputDirectory="PreserveNewest"/>
According to the docs, wildcards are not supported in .vcxproj anyway, however with VS 16.11.24 / MSBuild 16.11.2, they seem to work for 'otherstuff', that is as long as the files are already present at evaluation time. Using a suggestion from the same docs, I tried to move the wildcards to a Target:
<Target Name="CopyStuff" AfterTargets="PreBuildEvent">
<ItemGroup>
<Content Include="stuff\**"
Link="%(RecursiveDir)%(Filename)%(Extension)"
CopyToOutputDirectory="PreserveNewest" />
<Content Include="otherstuff\**"
Link="%(RecursiveDir)%(Filename)%(Extension)"
CopyToOutputDirectory="PreserveNewest"/>
</ItemGroup>
</Target>
This results in the weirdest behaviour ever, since the files from the two wildcards start overwriting one another, as if MSBuild accidentally performed a cross product of the two sets of files. Example from the buildlog:
Copying file from "otherstuff\vk_swiftshader_icd.json" to "stuff\assets\help_active.svg".
Here are some alternative approaches I've tried, none of which were successful:
<Target>
<CreateItem ...>
<Target>
<ItemGroup>
<ContentFilesProjectOutputGroupOutput Include="stuff/**" />
</ItemGroup>
</Target>
I'm also looking at the last part of the vcxproj of WindowsTerminal because they seem to somehow override the task that wapproj uses to query the original project for packaging outputs, but I haven't made sense of that yet or whether it would work with buildtime generated files.
How can I achieve this?
Upvotes: 0
Views: 313
Reputation: 1336
Looks like this is the magic incantation I needed:
<Target Name="CopyStuff" AfterTargets="PreBuildEvent">
<ItemGroup>
<Stuff Include="stuff\**" />
</ItemGroup>
<CreateItem Include="@(Stuff)"
AdditionalMetadata="CopyToOutputDirectory=PreserveNewest;TargetPath=%(Stuff.RecursiveDir)%(Filename)%(Extension)">
<Output TaskParameter="Include" ItemName="Content" />
</CreateItem>
</Target>
Upvotes: 0