Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple authored runtime components #922

Merged
merged 9 commits into from
Aug 6, 2021
54 changes: 25 additions & 29 deletions nuget/Microsoft.Windows.CsWinRT.Authoring.Transitive.targets
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,40 @@
</PropertyGroup>

<PropertyGroup>
<!-- Local variables -->
<HostingSupport-Net5Dir>$(MSBuildThisFileDirectory)..\lib\net5.0*</HostingSupport-Net5Dir>
<HostingSupport-MetadataDir>$(HostingSupport-Net5Dir)\winmd</HostingSupport-MetadataDir>
<HostingSupport-RuntimesDir>$(MSBuildThisFileDirectory)..\runtimes</HostingSupport-RuntimesDir>
<HostingSupport-DependenciesDir>$(MSBuildThisFileDirectory)..\build\native</HostingSupport-DependenciesDir>
<HostingSupport-IsNative Condition="'$(TargetFramework)' == 'native' OR '$(TargetFramework)' == ''">true</HostingSupport-IsNative>
<HostingSupport-IsArmArch Condition="'$(Platform)' == 'arm' OR '$(Platform)' == 'arm64'">true</HostingSupport-IsArmArch>
</PropertyGroup>

<Target Name="CsWinRTAddAuthoredWinMDReference" Condition="'$(HostingSupport-IsNative)' == 'true'" Outputs="@(Reference)">
<!-- Add the WinMD file as a reference of the native app, so a projection can be made -->
<_NormalizedPlatform Condition="'$(Platform)' == 'Win32'">x86</_NormalizedPlatform>
<_NormalizedPlatform Condition="'$(_NormalizedPlatform)' == ''">$(Platform)</_NormalizedPlatform>
</PropertyGroup>

<ItemGroup>
<!-- Managed, WinRT and SDK.NET dlls -->
<HostingAssets Include="$(MSBuildThisFileDirectory)..\lib\net5.0*\*.dll"/>
<!-- Managed DLLs from packages the component depends on -->
<HostingAssets Include="$(MSBuildThisFileDirectory)..\build\native\*.dll"/>
<!-- Add the runtimeconfig.json -->
<HostingAssets Include="$(MSBuildThisFileDirectory)..\build\native\WinRT.Host.runtimeconfig.json"/>
<!-- Get the proper WinRT.Host.dll -->
<HostingAssets Include="$(MSBuildThisFileDirectory)..\runtimes\win-$(_NormalizedPlatform)\native\WinRT.Host.dll" />
</ItemGroup>

<!-- Add the WinMD file as a reference of the native app so a projection gets made -->
<Target Name="CsWinRTAddAuthoredWinMDReference" Condition="'$(TargetFramework)' == 'native' OR '$(TargetFramework)' == ''" Outputs="@(Reference)">

<ItemGroup>
<Reference Include="$(HostingSupport-MetadataDir)\*.winmd">
<Reference Include="$(MSBuildThisFileDirectory)..\lib\net5.0*\winmd\*.winmd">
<IsWinMDFile>true</IsWinMDFile>
<Implementation>WinRT.Host.dll</Implementation>
</Reference>
</ItemGroup>

</Target>

<Target Name="CsWinRTCopyAuthoringDlls" Condition="'$(HostingSupport-IsNative)' == 'true'" Outputs="@(ReferenceCopyLocalPaths)">
<!-- Make sure the runtime assets are available to the app -->
<Target Name="CsWinRTCopyAuthoringDlls" Condition="'$(TargetFramework)' == 'native' OR '$(TargetFramework)' == ''" Outputs="@(ReferenceCopyLocalPaths)">

<ItemGroup>
<!-- Managed, WinRT and SDK.NET dlls -->
<ReferenceCopyLocalPaths Include="$(HostingSupport-Net5Dir)\*.dll" />

<!-- Managed DLLs from packages the component depends on -->
<ReferenceCopyLocalPaths Include="$(HostingSupport-DependenciesDir)\*.dll" />

<!-- Add the runtimeconfig.json -->
<ReferenceCopyLocalPaths Include="$(HostingSupport-DependenciesDir)\WinRT.Host.runtimeconfig.json" />

<!-- Get the proper WinRT.Host.dll -->
<ReferenceCopyLocalPaths Include="$(HostingSupport-RuntimesDir)\win-$(Platform)\native\WinRT.Host.dll"
Condition="'$(Platform)' == 'x64' OR '$(Platform)' == 'x86' OR '$(HostingSupport-IsArmArch)' == 'true'" />

<!-- Treat Win32 platform as win-x86 architecture -->
<ReferenceCopyLocalPaths Include="$(HostingSupport-RuntimesDir)\win-x86\native\WinRT.Host.dll"
Condition="'$(Platform)' == 'Win32'"/>
<ReferenceCopyLocalPaths Include="@(HostingAssets)"/>
</ItemGroup>

</Target>

</Project>
109 changes: 97 additions & 12 deletions nuget/Microsoft.Windows.CsWinRT.Authoring.targets
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,16 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<CsWinRTAuthoringWinMDs Include="@(CsWinRTInputs)" />
<CsWinRTAuthoringDistinctWinMDs Include="@(CsWinRTAuthoringWinMDs->Distinct())" />
</ItemGroup>

<PropertyGroup>
<CsWinRTAuthoringInputs>$(CsWinRTAuthoringInputs) @(CsWinRTAuthoringDistinctWinMDs->'"%(FullPath)"', ' ') </CsWinRTAuthoringInputs>
</PropertyGroup>

</Target>

<!-- For Project Reference consumers, copy the necessary WinRT DLLs to output directory -->
<ItemGroup>

<CsWinRTAuthoringDependencyDlls Condition="Exists('$(CsWinRTPath)lib\net5.0\WinRT.Host.Shim.dll')" Include="$(CsWinRTPath)lib\net5.0\WinRT.Host.Shim.dll" />
<CsWinRTAuthoringDependencyDlls Condition="Exists('$(CsWinRTPath)lib\net5.0\WinRT.Runtime.dll')" Include="$(CsWinRTPath)lib\net5.0\WinRT.Runtime.dll" />

Expand All @@ -69,13 +72,16 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<TargetPath>WinRT.Host.dll</TargetPath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

</ItemGroup>

<!-- Add the RuntimeConfig to output of project reference consumers -->
<Target Name="CsWinRTAuthoring_AddRuntimeDependenciesToContent"
AfterTargets="GenerateBuildRuntimeConfigurationFiles"
BeforeTargets="GetCopyToOutputDirectoryItems;_GetCopyToOutputDirectoryItemsFromThisProject">

<ItemGroup>

<AllItemsFullPathWithTargetPath Include="$(ProjectRuntimeConfigFilePath)">
<TargetPath>$([System.IO.Path]::GetFileName($(ProjectRuntimeConfigFilePath)))</TargetPath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Expand All @@ -85,20 +91,17 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<TargetPath>$([System.IO.Path]::GetFileName($(ProjectRuntimeConfigFilePath)))</TargetPath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</AllPublishItemsFullPathWithTargetPath>

</ItemGroup>

</Target>

<!-- Update the project's output to include the generated WinMD.

ResolveableAssembly metadata decides who we can support:
if it is not present, we support C++, but not C#
=> solution: sdk1130 error becomes a warning

if it is present (as 'false'), we support C#, but not C++
=> solution: C++/WinRT targets need to use _ResolvedNativeProjectReferencePaths
-->
<!-- MSBuild only sees WinRT component's .winmd as an output, the managed implementation
is handled by target CsWinRTAuthoring_AddRuntimeDependenciesToContent -->
<Target Name="GetTargetPath" Returns="@(TargetPathWithTargetPlatformMoniker)">

<ItemGroup>

<TargetPathWithTargetPlatformMoniker Include="$(TargetDir)$(AssemblyName).winmd">
<BuildReference>true</BuildReference>
<WinMDFile>true</WinMDFile>
Expand All @@ -107,26 +110,34 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<FileType>winmd</FileType>
<Primary>true</Primary>
</TargetPathWithTargetPlatformMoniker>

</ItemGroup>

</Target>

<!-- Prevent C++ apps from thinking there is a framework mismatch by setting our target framework to blank.
Note, this does prevent C#/WinRT apps from cross-platform targeting, but a netcore3.1 app wouldn't use C#/WinRT anyway -->
<Target Name="GetTargetFrameworks" Returns="@(_ThisProjectBuildMetadata)">

<ItemGroup>

<_ThisProjectBuildMetadata Include="$(MSBuildProjectFullPath)">
<TargetFrameworks></TargetFrameworks>
<TargetFrameworkMonikers></TargetFrameworkMonikers>
<TargetPlatformMonikers></TargetPlatformMonikers>
<HasSingleTargetFramework>true</HasSingleTargetFramework>
<IsRidAgnostic>true</IsRidAgnostic>
</_ThisProjectBuildMetadata>

</ItemGroup>

</Target>

<!-- For project references, we need to copy the SDK.NET.dll to the output directory -->
<Target Name="CsWinRTCopySDKRefDllToOutDir" AfterTargets="ResolveRuntimePackAssets">

<ItemGroup>

<!-- Local item group to store the SDK.NET.dll -->
<CsWinRTSDKRefDll Include="@(RuntimePackAsset)" Condition="'%(RuntimePackAsset.DestinationSubPath)' == 'Microsoft.Windows.SDK.NET.dll'" />
<!-- Use the below item group to package up managed DLLs from one source -->
Expand All @@ -137,13 +148,84 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>Microsoft.Windows.SDK.NET.dll</TargetPath>
</_ThisProjectItemstoCopyToOutputDirectory>

</ItemGroup>

</Target>

<!-- Make the target take an input targets file and just write on that -->
<Target Name="CsWinRTGenerateTransitiveTargets" BeforeTargets="CsWinRTIncludeHostDlls">

<Copy SourceFiles="$(MSBuildThisFileDirectory)Microsoft.Windows.CsWinRT.Authoring.Transitive.targets" DestinationFolder="$(CsWinRTGeneratedFilesDir)" UseHardlinksIfPossible="false" SkipUnchangedFiles="true" />

<PropertyGroup>

<AuthoringTransitiveTargets>$(CsWinRTGeneratedFilesDir)\Microsoft.Windows.CsWinRT.Authoring.Transitive.targets</AuthoringTransitiveTargets>

<PeekQuery_Depends1>Project/PropertyGroup/ResolveReferencesDependsOn/text()</PeekQuery_Depends1>
<PokeQuery_Depends1>Project/PropertyGroup/ResolveReferencesDependsOn</PokeQuery_Depends1>

<PeekQuery_Depends2>Project/PropertyGroup/BuildDependsOn/text()</PeekQuery_Depends2>
<PokeQuery_Depends2>Project/PropertyGroup/BuildDependsOn</PokeQuery_Depends2>

<PeekQuery_Target1>Project/Target[@Name='CsWinRTAddAuthoredWinMDReference']/@Name</PeekQuery_Target1>
<PokeQuery_Target1>Project/Target[@Name='CsWinRTAddAuthoredWinMDReference']/@Name</PokeQuery_Target1>

<PeekQuery_Target2>Project/Target[@Name='CsWinRTCopyAuthoringDlls']/@Name</PeekQuery_Target2>
<PokeQuery_Target2>Project/Target[@Name='CsWinRTCopyAuthoringDlls']/@Name</PokeQuery_Target2>

</PropertyGroup>

<!-- Peeks -->

<XmlPeek XmlInputPath="$(AuthoringTransitiveTargets)" Query="$(PeekQuery_Depends1)">
<Output TaskParameter="Result" ItemName="Peeked_Depends1" />
</XmlPeek>

<XmlPeek XmlInputPath="$(AuthoringTransitiveTargets)" Query="$(PeekQuery_Depends2)">
<Output TaskParameter="Result" ItemName="Peeked_Depends2" />
</XmlPeek>

<XmlPeek XmlInputPath="$(AuthoringTransitiveTargets)" Query="$(PeekQuery_Target1)">
<Output TaskParameter="Result" ItemName="Peeked_Target1" />
</XmlPeek>

<XmlPeek XmlInputPath="$(AuthoringTransitiveTargets)" Query="$(PeekQuery_Target2)">
<Output TaskParameter="Result" ItemName="Peeked_Target2" />
</XmlPeek>

<!-- Flatten the outputs might be able to skip this by just inligning -->

<PropertyGroup>
<Flat_Peeked_Depends1>@(Peeked_Depends1)</Flat_Peeked_Depends1>
<Flat_Peeked_Depends2>@(Peeked_Depends2)</Flat_Peeked_Depends2>
<Flat_Peeked_Target1>@(Peeked_Target1)</Flat_Peeked_Target1>
<Flat_Peeked_Target2>@(Peeked_Target2)</Flat_Peeked_Target2>
</PropertyGroup>

<!-- Transform the fetched xml nodes -->

<PropertyGroup>
<Transformed1>$([System.String]::Copy('$(Flat_Peeked_Depends1)').Replace('CsWinRT','$(AssemblyName)'))</Transformed1>
<Transformed2>$([System.String]::Copy('$(Flat_Peeked_Depends2)').Replace('CsWinRT','$(AssemblyName)'))</Transformed2>
<Transformed3>$([System.String]::Copy('$(Flat_Peeked_Target1)').Replace('CsWinRT','$(AssemblyName)'))</Transformed3>
<Transformed4>$([System.String]::Copy('$(Flat_Peeked_Target2)').Replace('CsWinRT','$(AssemblyName)'))</Transformed4>
</PropertyGroup>

<!-- Change the target names -->
<XmlPoke XmlInputPath="$(AuthoringTransitiveTargets)" Query="$(PokeQuery_Depends1)" Value="$(Transformed1)"/>
<XmlPoke XmlInputPath="$(AuthoringTransitiveTargets)" Query="$(PokeQuery_Depends2)" Value="$(Transformed2)"/>
<XmlPoke XmlInputPath="$(AuthoringTransitiveTargets)" Query="$(PokeQuery_Target1)" Value="$(Transformed3)"/>
<XmlPoke XmlInputPath="$(AuthoringTransitiveTargets)" Query="$(PokeQuery_Target2)" Value="$(Transformed4)"/>

</Target>

<!-- When an authored component makes a nupkg, add the necessary hosting assets to the package -->
<Target Name="CsWinRTIncludeHostDlls" BeforeTargets="AfterBuild" Outputs="@(Content)">
<Target Name="CsWinRTIncludeHostDlls" DependsOnTargets="CsWinRTGenerateTransitiveTargets" BeforeTargets="AfterBuild" Outputs="@(Content)">

<!-- When packing, include all necessary DLLs and the targets file for DLL copying on the native side -->
<ItemGroup>

<!-- We must pack any managed DLLs the component depends on, because a native consumer won't restore them -->
<Content Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.AssetType)' == 'runtime'">
<Pack>true</Pack>
Expand All @@ -168,8 +250,8 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<PackagePath>lib\$(TargetFramework)\winmd</PackagePath>
</Content>

<!-- Custom targets that copy DLLs for consumers of the authored component. -->
<Content Include="$(CsWinRTPath)build\Microsoft.Windows.CsWinRT.Authoring.Transitive.targets">
<!-- Use a targets file generated for the component -->
<Content Include="$(AuthoringTransitiveTargets)">
<Pack>true</Pack>
<PackagePath>buildTransitive\$(AssemblyName).targets;build\$(AssemblyName).targets</PackagePath>
</Content>
Expand All @@ -196,11 +278,14 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<PackagePath>runtimes\win-arm64\native</PackagePath>
</Content>
</ItemGroup>

</Target>

<!-- Copy Authored winmd to output folder -->
<Target Name="CsWinRTPlaceWinMDInOutputFolder" BeforeTargets="AfterBuild">

<Copy SourceFiles="$(CsWinRTGeneratedFilesDir)\$(AssemblyName).winmd" DestinationFolder="$(TargetDir)" UseHardlinksIfPossible="false" SkipUnchangedFiles="true" />

</Target>

</Project>