Deliver Microsoft.Net.CoreRuntime.targets in the UwpCoreRuntimeSdk package (dotnet...
authorZach Montoya <zamont@microsoft.com>
Wed, 5 Jul 2017 22:07:42 +0000 (15:07 -0700)
committerGitHub <noreply@github.com>
Wed, 5 Jul 2017 22:07:42 +0000 (15:07 -0700)
* Update Microsoft.Net.CoreRuntime.targets to those shipped in latest VS

* Generate Microsoft.Net.CoreRuntime.settings.targets from template during build

* Successfully build and sign Microsoft.Net.CoreRuntimeTask.dll

* Copy Microsoft.Cci to the output of Microsoft.Build.Net.CoreRuntimeTask.dll and include Microsoft.Cci.dll in identity package for Microsoft.Net.UWPCoreRuntimeSdk

* Correctly generate .props/.targets files for each RID-specific package of Microsoft.Net.UWPCoreRuntimeSdk to provide information about the Appx packages. Change Microsoft.Net.CoreRuntime.targets and WireUpCoreRuntime appropriately.

* Make Microsoft.Net.CoreRuntime.targets consume x86 CopyWin32Resources.exe from the native x86 runtime package

* Rearrange source of Microsoft.Net.UWPCoreRuntimeSdk. Add Microsoft.Net.UWPCoreRuntimeSdk.props to point to Microsoft.Net.CoreRuntime targets files in NuGet package

* Make fixes to complete VS integration

* Address PR feedback. Change uap moniker to use property $(UAPvNextTFM)

Commit migrated from https://github.com/dotnet/core-setup/commit/b814c63a7834a58d892feef2376521856c5cd4d2

22 files changed:
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/Microsoft.Net.UWPCoreRuntimeSdk.pkgproj
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/identity/Microsoft.Net.CoreRuntime.settings.targets.template [new file with mode: 0644]
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/identity/Microsoft.Net.CoreRuntime.targets [new file with mode: 0644]
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/identity/Microsoft.Net.UWPCoreRuntimeSdk.props [new file with mode: 0644]
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/rid-templates/Microsoft.Net.UWPCoreRuntimeSdk.props.template [new file with mode: 0644]
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/rid-templates/Microsoft.Net.UWPCoreRuntimeSdk.targets.template [new file with mode: 0644]
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/build/Microsoft.Net.UWPCoreRuntimeSdk.props [deleted file]
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/build/Microsoft.Net.UWPCoreRuntimeSdk.targets [deleted file]
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/tools/CoreRuntime/Microsoft.Net.CoreRuntime.settings.targets [deleted file]
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/tools/CoreRuntime/Microsoft.Net.CoreRuntime.targets [deleted file]
src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/src/Microsoft.Net.UWPCoreRuntimeSdk.depproj
src/installer/signing/sign.proj
src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/ErrorCodes.cs [new file with mode: 0644]
src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/MergePriConfigTask.cs [new file with mode: 0644]
src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/MergeResWFilesTask.cs [new file with mode: 0644]
src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Microsoft.Build.Net.CoreRuntimeTask.builds [new file with mode: 0644]
src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Microsoft.Build.Net.CoreRuntimeTask.csproj [new file with mode: 0644]
src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/ResourceHandlingTask.cs [new file with mode: 0644]
src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Resources.Designer.cs [new file with mode: 0644]
src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Resources.resx [new file with mode: 0644]
src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/WireUpCoreRuntime.cs [new file with mode: 0644]
src/installer/uwp/build.proj

index a5bfa8e..54f00bb 100644 (file)
@@ -4,6 +4,12 @@
 
   <PropertyGroup>
     <Version>$(ProductVersion)</Version>
+    <OmitDependencies>true</OmitDependencies>
+
+  <!-- Reference runtime packages directly so that MSBuild .props / .targets get imported correctly in VS" -->
+    <IsLineupPackage>false</IsLineupPackage>
+    <IncludeRuntimeJson>false</IncludeRuntimeJson>
+    <ExcludeLineupReference>true</ExcludeLineupReference>
   </PropertyGroup>
 
   <!-- Redistributed package content from other nuget packages-->
 
   <!-- Identity / Reference package content -->
   <ItemGroup Condition="'$(PackageTargetRuntime)' == ''">
-    <File Include="files\build\*">
+    <File Include="contents\identity\Microsoft.Net.UWPCoreRuntimeSdk.props">
       <TargetPath>build</TargetPath>
     </File>
-    <File Include="files\tools\CoreRuntime\*">
+    <File Include="contents\identity\Microsoft.Net.CoreRuntime.targets">
       <TargetPath>tools/CoreRuntime</TargetPath>
     </File>
   </ItemGroup>
 
+  <!-- Reference runtime packages directly so that MSBuild .props / .targets get imported correctly in VS" -->
+  <Target Name="InjectNuGetDependencyOnRuntimePackages"
+          BeforeTargets="GenerateNuSpec"
+          DependsOnTargets="DetermineRuntimeDependencies"
+          Condition="'$(PackageTargetRuntime)' == ''">
+    <ItemGroup>
+      <Dependency Include="@(RuntimeDependency)">
+        <TargetFramework>$(UAPvNextTFM)</TargetFramework>
+      </Dependency>
+    </ItemGroup>
+  </Target>
+
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
 </Project>
diff --git a/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/identity/Microsoft.Net.CoreRuntime.settings.targets.template b/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/identity/Microsoft.Net.CoreRuntime.settings.targets.template
new file mode 100644 (file)
index 0000000..71ab408
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+***********************************************************************************************
+Microsoft.Net.CoreRuntime.Settings.targets
+
+WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
+          created a backup copy.  Incorrect changes to this file will make it
+          impossible to load or build your projects from the command-line or the IDE.
+
+Copyright (C) Microsoft Corporation. All rights reserved.
+***********************************************************************************************
+-->
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <_CoreRuntimeVersion>[AppxVersion]</_CoreRuntimeVersion>
+  </PropertyGroup>
+</Project>
diff --git a/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/identity/Microsoft.Net.CoreRuntime.targets b/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/identity/Microsoft.Net.CoreRuntime.targets
new file mode 100644 (file)
index 0000000..a0126ef
--- /dev/null
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+***********************************************************************************************
+Microsoft.Net.CoreRuntime.targets
+
+WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
+          created a backup copy.  Incorrect changes to this file will make it
+          impossible to load or build your projects from the command-line or the IDE.
+
+Copyright (C) Microsoft Corporation. All rights reserved.
+***********************************************************************************************
+-->
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <!-- Provides a default target platform for finding the ilc.exe version when
+       the project is configured to AnyCPU -->
+  <PropertyGroup>
+    <_PlatformTargetForCoreRuntime Condition="'$(PlatformTarget)'!='AnyCPU'">$(PlatformTarget)</_PlatformTargetForCoreRuntime>
+    <_PlatformTargetForCoreRuntime Condition="'$(PlatformTarget)'=='AnyCPU'">x86</_PlatformTargetForCoreRuntime>
+  </PropertyGroup>
+
+
+  <!--
+       _TargetsCoreRuntime is one of the main flags that decides whether the toolchain needs to kick-in. It implies:
+       - This is a UAP app (including those that are pure C++ or JS)
+       - .NetNativeToolchain is not going to be used (i.e.: the default debug configuration)
+
+       The second flag will narrow the condition further to UAP apps that has some managed code in their dependency closure.
+       (See _AppContainsManagedCodeInItsClosure)
+
+       This flag (_TargetsCoreRuntime) is also being consumed by project system to decide which debugger guid needs to be used,
+       hence if you intend to rename this flag make sure that project system is also updated
+  -->
+
+  <PropertyGroup Condition="'$(AppxPackage)' == 'true' and '$(TargetPlatformIdentifier)' == 'UAP' and '$(UseDotNetNativeToolchain)' != 'true'">
+    <_TargetsCoreRuntime>true</_TargetsCoreRuntime>
+  </PropertyGroup>
+
+  <PropertyGroup>
+    <BeforeRunGatekeeperTargets>ComputeWireUpCoreRuntimeGates</BeforeRunGatekeeperTargets>
+  </PropertyGroup>
+
+  <PropertyGroup>
+    <_CoreRuntimeMSBuildTaskAssembly>$(MSBuildThisFileDirectory)\Microsoft.Build.Net.CoreRuntimeTask.dll</_CoreRuntimeMSBuildTaskAssembly>
+    <_AppxMSBuildToolsPath Condition="'$(_AppxMSBuildToolsPath)' == ''">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\AppxPackage\</_AppxMSBuildToolsPath>
+    <_AppxMSBuildTaskAssembly Condition="'$(_AppxMSBuildTaskAssembly)' == ''">$(_AppxMSBuildToolsPath)Microsoft.Build.AppxPackage.dll</_AppxMSBuildTaskAssembly>
+    <CoreRuntimeSDKName>Microsoft.NET.CoreRuntime, Version=$(_CoreRuntimeVersion)</CoreRuntimeSDKName>
+    <VCLibs14SDKName>Microsoft.VCLibs, Version=14.0</VCLibs14SDKName>
+  </PropertyGroup>
+
+  <UsingTask AssemblyFile="$(_CoreRuntimeMSBuildTaskAssembly)" TaskName="Microsoft.Build.Net.CoreRuntimeTask.WireUpCoreRuntime" />
+  <UsingTask AssemblyFile="$(_CoreRuntimeMSBuildTaskAssembly)" TaskName="Microsoft.Build.Net.CoreRuntimeTask.MergePriConfigTask" />
+  <UsingTask AssemblyFile="$(_CoreRuntimeMSBuildTaskAssembly)" TaskName="Microsoft.Build.Net.CoreRuntimeTask.MergeResWFilesTask" />
+  <UsingTask AssemblyFile="$(_CoreRuntimeMSBuildTaskAssembly)" TaskName="Microsoft.Build.Net.CoreRuntimeTask.ResourceHandlingTask" />
+  <UsingTask AssemblyFile="$(_AppxMSBuildTaskAssembly)" TaskName="Microsoft.Build.AppxPackage.GetFrameworkSdkPackages" />
+
+
+  <!-- Adds a <build:Item> tag for OptimizingToolset and TargetRuntime properties
+       WireUpCoreRuntime needs these metadata -->
+
+  <ItemGroup Condition="'$(_TargetsCoreRuntime)'=='true'">
+    <AppxManifestMetadata Include="OptimizingToolset">
+      <Value>None</Value>
+    </AppxManifestMetadata>
+    <AppxManifestMetadata Include="TargetRuntime" Condition="'$(TargetRuntime)'!=''">
+        <Value>$(TargetRuntime)</Value>
+    </AppxManifestMetadata>
+  </ItemGroup>
+
+  <Target Name="ComputeWireUpCoreRuntimeGates"
+          AfterTargets="AfterGenerateAppxManifest">
+    <!--
+         _AppContainsManagedCodeInItsClosure is going to be used as a gate to invoking the toolchain. As name suggests,
+         it implies that the app or one of the dependencies in its closure has managed code in it.
+
+         ASSUMPTION: In deciding whether an unmanaged app has a managed dependency we'll defer to the computation of
+         whether UnionWinMD needs to be included in the PackagingOutputs or not.
+         (See the target _AddUnionWinmd in Microsoft.AppxPackage.Targets)
+         Briefly, UnionWinMD is going to be included if any of the winmds that the app is referencing is managed.
+         So existance of UnionWinMD is being used as an indicator to existance of managed code.
+         This way the cost of computing managed dependency is avoided.
+    -->
+    <ItemGroup>
+      <_UnionMetadataWinMD Include="@(PackagingOutputs)" Condition="'%(Identity)' == '$(_TargetPlatformSdkDir)UnionMetadata\Windows.winmd'" />
+      <_UnionMetadataWinMD Include="@(PackagingOutputs)" Condition="'%(Identity)' == '$(WindowsSDK_UnionMetadataPath)\Windows.winmd'" />
+    </ItemGroup>
+
+    <PropertyGroup Condition="'$(TargetRuntime)' == 'Managed' or '@(_UnionMetadataWinMD)' != ''">
+      <_AppContainsManagedCodeInItsClosure>true</_AppContainsManagedCodeInItsClosure>
+    </PropertyGroup>
+
+    <!--
+         WireUpCoreRuntimeGates is the property that ultimately controls triggering the toolchain. It implies:
+         - This is a UAP app that has some managed code in its dependency closure
+         - .NetNativeToolchain is not going to be used (i.e.: the default debug configuration)
+    -->
+    <PropertyGroup Condition="'$(_TargetsCoreRuntime)' == 'true' and '$(_AppContainsManagedCodeInItsClosure)' == 'true'">
+      <WireUpCoreRuntimeGates>Satisfied</WireUpCoreRuntimeGates>
+    </PropertyGroup>
+  </Target>
+
+  <Target Name="ComputeWireUpCoreRuntimeParameters"
+          DependsOnTargets="ComputeWireUpCoreRuntimeGates"
+          Condition="'$(WireUpCoreRuntimeGates)'=='Satisfied'">
+
+    <!-- Compute the input/output location of the WireUpCoreRuntime-->
+    <PropertyGroup Condition="'$(WireUpCoreRuntimeOutputPath)'==''">
+      <WireUpCoreRuntimeOutputPath>$(OutputPath.TrimEnd('\'))\Core\</WireUpCoreRuntimeOutputPath>
+    </PropertyGroup>
+    <ConvertToAbsolutePath Paths="$(WireUpCoreRuntimeOutputPath)">
+      <Output TaskParameter="AbsolutePaths" PropertyName="_WireUpCoreRuntimeOutputPath"/>
+    </ConvertToAbsolutePath>
+
+    <PropertyGroup>
+      <_WireUpCoreRuntimeExitCode>0</_WireUpCoreRuntimeExitCode>
+      <_WireUpCoreRuntimeTaskExecuted>false</_WireUpCoreRuntimeTaskExecuted>
+    </PropertyGroup>
+
+    <GetInstalledSDKLocations
+           SDKDirectoryRoots="$(SDKReferenceDirectoryRoot)"
+           SDKExtensionDirectoryRoots="$(SDKExtensionDirectoryRoot)"
+           SDKRegistryRoot="$(SDKReferenceRegistryRoot)"
+           TargetPlatformVersion="$(TargetPlatformVersion)"
+           TargetPlatformIdentifier="$(TargetPlatformIdentifier)"
+           Condition="'@(InstalledSDKLocations)' == ''"
+           >
+      <Output TaskParameter="InstalledSDKs" ItemName="InstalledSDKLocations"/>
+    </GetInstalledSDKLocations>
+
+
+    <ItemGroup>
+      <DependencySDKs Include="$(VCLibs14SDKName)" />  <!--UWPShim is built against dev14 CRT-->
+    </ItemGroup>
+
+    <ResolveSDKReference
+      SDKReferences="@(DependencySDKs)"
+      TargetPlatformVersion="$(TargetPlatformVersion)"
+      TargetPlatformIdentifier="$(TargetPlatformIdentifier)"
+      TargetedSDKConfiguration="$(TargetedSDKConfiguration)"
+      TargetedSDKArchitecture="$(TargetedSDKArchitecture)"
+      ProjectName="$(ProjectName)"
+      InstalledSDKs ="@(InstalledSDKLocations)"
+    >
+      <Output TaskParameter="ResolvedSDKReferences" ItemName="ResolvedDependencySDKs"/>
+    </ResolveSDKReference>
+
+    <ItemGroup>
+      <CoreRuntimeSDK Include="@(ResolvedDependencySDKs)" Condition="'%(ResolvedDependencySDKs.SDKName)' == '$(CoreRuntimeSDKName)'" />
+    </ItemGroup>
+
+    <GetFrameworkSdkPackages FrameworkSdkReferences="@(ResolvedDependencySDKs)"
+        TargetPlatformIdentifier="$(TargetPlatformIdentifier)">
+      <Output TaskParameter="FrameworkSdkPackages" ItemName="FrameworkPackageDependencies" />
+    </GetFrameworkSdkPackages>
+
+
+    <ItemGroup>
+      <FrameworkPackagesForTargetArchitecture Include="@(FrameworkPackageDependencies)" Condition="'%(Architecture)' == '$(_PlatformTargetForCoreRuntime)'" />
+    </ItemGroup>
+
+    <PropertyGroup>
+      <!-- Name of manifest file is predefined -->
+      <_AppxManifestXmlFileName>AppxManifest.xml</_AppxManifestXmlFileName>
+      <!-- Expected location of result manifest file where it supposed to be dropped by WireUpCoreRuntime -->
+      <_TransformedAppxManifestXmlFile>$(_WireUpCoreRuntimeOutputPath)$(_AppxManifestXmlFileName)</_TransformedAppxManifestXmlFile>
+
+      <CoreRuntimeSDKLocation Condition="'$(PlatformTarget)' == 'x86'">$(CoreRuntimeSDKRootX86)</CoreRuntimeSDKLocation>
+      <CoreRuntimeSDKLocation Condition="'$(PlatformTarget)' == 'x64'">$(CoreRuntimeSDKRootX64)</CoreRuntimeSDKLocation>
+      <CoreRuntimeSDKLocation Condition="'$(PlatformTarget)' == 'arm'">$(CoreRuntimeSDKRootArm)</CoreRuntimeSDKLocation>
+    </PropertyGroup>
+  </Target>
+
+  <Target Name="_GetLibrariesToGeneratePrisForUWPApps"
+          BeforeTargets="_GeneratePrisForPortableLibraries"
+          Condition="'$(TargetPlatformIdentifier)'=='UAP'">
+
+        <ItemGroup>
+          <_FullAppLibrariesUnfiltered Include="@(PackagingOutputs)" Condition="'%(Extension)' == '.dll'" />
+        </ItemGroup>
+
+        <ConvertToAbsolutePath Paths="$(IntermediateOutputPath)">
+          <Output TaskParameter="AbsolutePaths" PropertyName="ResWOutputFullPath"/>
+        </ConvertToAbsolutePath>
+
+        <PropertyGroup Condition="'$(SkipMergingFrameworkResources)' == ''">
+          <!--
+            When building ProjectN apps in retail mode we need to skip including the framework resources in the app because we optimize the exception stack
+            and we use the resource keys instead of the exception messages.
+          -->
+          <SkipMergingFrameworkResources Condition="'$(_ProjectNToolchainEnabled)'=='true' And '$(Optimize)'=='true' And '$(EnableNetNativeDeveloperExperienceMode)'!='true'">true</SkipMergingFrameworkResources>
+          <SkipMergingFrameworkResources Condition="'$(SkipMergingFrameworkResources)' == ''">false</SkipMergingFrameworkResources>
+        </PropertyGroup>
+
+        <ResourceHandlingTask
+          AssemblyList="@(_FullAppLibrariesUnfiltered)"
+          OutResWPath="$(ResWOutputFullPath)"
+          SkipFrameworkResources="$(SkipMergingFrameworkResources)"
+          StateFile="$(ResWOutputFullPath.TrimEnd('\'))\ResourceHandlingTask.state">
+
+          <!--
+              Explicitly using CreatedResWFiles and _LibrariesUnfiltered item group
+              names because we are feeding them into the existing item groups that are
+              used as part of _GeneratePrisForPortableLibraries.
+          -->
+          <Output TaskParameter="ReswFileList" ItemName="CreatedResWFiles"/>
+          <Output TaskParameter="UnprocessedAssemblyList" ItemName="_LibrariesUnfiltered"/>
+        </ResourceHandlingTask>
+        <ItemGroup>
+          <FileWrites Include="$(ResWOutputFullPath.TrimEnd('\'))\ResourceHandlingTask.state" />
+          <FileWrites Include="@(CreatedResWFiles)" />
+        </ItemGroup>
+  </Target>
+
+  <!-- We will always inject the CLR from the framework SDK, so remove it if it was contributed through NuGet -->
+  <Target Name="FilterCoreRuntimePayloadFromNuGet" AfterTargets="ResolveReferences" DependsOnTargets="ResolveNuGetPackageAssets" Condition="'$(ResolveNuGetPackages)' == 'true' AND '$(_TargetsCoreRuntime)' == 'true'">
+    <PropertyGroup>
+      <_CoreRuntimePackageId Condition="'%(ReferenceCopyLocalPaths.FileName)%(ReferenceCopyLocalPaths.Extension)' == 'mscorlib.dll' OR '%(ReferenceCopyLocalPaths.FileName)%(ReferenceCopyLocalPaths.Extension)' == 'mscorlib.ni.dll'">%(ReferenceCopyLocalPaths.NuGetPackageId)</_CoreRuntimePackageId>
+    </PropertyGroup>
+    <ItemGroup>
+      <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" Condition="'$(UseAppLocalCoreCLR)' != 'true' AND '%(ReferenceCopyLocalPaths.NuGetPackageId)' == '$(_CoreRuntimePackageId)' AND '$(_CoreRuntimePackageId)' != ''"/>
+    </ItemGroup>
+  </Target>
+
+  <!-- Wire up the CoreRuntime -->
+  <Target Name="_WireUpCoreRuntime"
+          Inputs="@(AppxPackagePayload);@(FinalAppxManifest);@(MSBuildAllProjects)"
+          Outputs="$(_TransformedAppxManifestXmlFile)"
+          DependsOnTargets="ComputeWireUpCoreRuntimeParameters"
+          AfterTargets="ComputeWireUpCoreRuntimeGates"
+          Condition="'$(WireUpCoreRuntimeGates)'=='Satisfied'">
+
+
+    <CreateProperty Value="true">
+      <Output PropertyName="_WireUpCoreRuntimeTaskExecuted" TaskParameter="ValueSetByTask"/>
+    </CreateProperty>
+
+    <WireUpCoreRuntime
+        AppxManifest="@(FinalAppxManifest)"
+        AppxPackagePayload="@(AppxPackagePayload)"
+        OutputPath="$(_WireUpCoreRuntimeOutputPath.TrimEnd('\'))"
+        TargetRuntime="$(TargetRuntime)"
+        TargetArch="$(_PlatformTargetForCoreRuntime)"
+        FrameworkPackages="@(FrameworkPackagesForTargetArchitecture)"
+        CoreRuntimeSDKLocation="$(CoreRuntimeSDKLocation)"
+        CopyWin32ResourcesLocation="$(CopyWin32ResourcesX86Path)"
+    >
+      <Output TaskParameter="ErrorCode" PropertyName="_WireUpCoreRuntimeExitCode"/>
+      <Output TaskParameter="FrameworkPackagesNeedsToBeDeployed" PropertyName="FrameworkPackagesNeedsToBeDeployed" />
+      <Output TaskParameter="TransformedAppxPackagePayload" ItemName="_TransformedAppxPackagePayload" />
+    </WireUpCoreRuntime>
+
+    <!-- Record output files as file writes -->
+    <ItemGroup>
+      <FileWrites Include="$(_WireUpCoreRuntimeOutputPath)**\*"/>
+    </ItemGroup>
+
+    <ItemGroup Condition="'$(_WireUpCoreRuntimeTaskExecuted)' == 'true'">
+      <FrameworkSdkPackage Include="@(FrameworkPackageDependencies)" Condition="'$(FrameworkPackagesNeedsToBeDeployed)'=='true'" />
+    </ItemGroup>
+
+    <ItemGroup Condition="'$(_WireUpCoreRuntimeTaskExecuted)' == 'true'">
+      <AppxPackagePayload Remove="@(AppxPackagePayload)" />
+      <AppxPackagePayload Include="@(_TransformedAppxPackagePayload)" />
+    </ItemGroup>
+
+    <ItemGroup Condition="'$(_WireUpCoreRuntimeTaskExecuted)' == 'true' and Exists('$(_TransformedAppxManifestXmlFile)')">
+      <FinalAppxManifest Remove="@(FinalAppxManifest)"/>
+      <FinalAppxManifest Include="$(_TransformedAppxManifestXmlFile)" />
+    </ItemGroup>
+
+    <PropertyGroup>
+      <_WireUpCoreRuntimeMsg>WireUpCoreRuntime has encountered an error</_WireUpCoreRuntimeMsg>
+    </PropertyGroup>
+
+    <Error Condition="'$(_WireUpCoreRuntimeExitCode)' &gt; 0" Text="$(_WireUpCoreRuntimeMsg)" />
+  </Target>
+</Project>
diff --git a/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/identity/Microsoft.Net.UWPCoreRuntimeSdk.props b/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/identity/Microsoft.Net.UWPCoreRuntimeSdk.props
new file mode 100644 (file)
index 0000000..c5db11a
--- /dev/null
@@ -0,0 +1,6 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <NetfxCoreRuntimeTargets>$(MSBuildThisFileDirectory)..\tools\CoreRuntime\Microsoft.Net.CoreRuntime.targets</NetfxCoreRuntimeTargets>
+    <NetfxCoreRuntimeSettingsTargets>$(MSBuildThisFileDirectory)..\tools\CoreRuntime\Microsoft.Net.CoreRuntime.settings.targets</NetfxCoreRuntimeSettingsTargets>
+  </PropertyGroup>
+</Project>
diff --git a/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/rid-templates/Microsoft.Net.UWPCoreRuntimeSdk.props.template b/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/rid-templates/Microsoft.Net.UWPCoreRuntimeSdk.props.template
new file mode 100644 (file)
index 0000000..22b0d4f
--- /dev/null
@@ -0,0 +1,6 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <CoreRuntimeSDKRoot[AppxBuildArch]>$(MSBuildThisFileDirectory)..\tools</CoreRuntimeSDKRoot[AppxBuildArch]>
+    <CopyWin32Resources[AppxBuildArch]Path>$(MSBuildThisFileDirectory)..\tools\CoreRuntime\copywin32resources.exe</CopyWin32Resources[AppxBuildArch]Path>
+  </PropertyGroup>
+</Project>
diff --git a/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/rid-templates/Microsoft.Net.UWPCoreRuntimeSdk.targets.template b/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/contents/rid-templates/Microsoft.Net.UWPCoreRuntimeSdk.targets.template
new file mode 100644 (file)
index 0000000..9d3137c
--- /dev/null
@@ -0,0 +1,11 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <AppxPackageRegistration
+        Include="$(MSBuildThisFileDirectory)..\tools\Appx\[AppxDisplayName].appx"
+        Condition="'$(_TargetsCoreRuntime)' == 'true'">
+        <Architecture>[AppxBuildArch]</Architecture>
+        <Version>[AppxVersion]</Version>
+        <Publisher>'CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US'</Publisher>
+    </AppxPackageRegistration>
+  </ItemGroup>
+</Project>
diff --git a/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/build/Microsoft.Net.UWPCoreRuntimeSdk.props b/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/build/Microsoft.Net.UWPCoreRuntimeSdk.props
deleted file mode 100644 (file)
index 9f72ff2..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <UseAppLocalCoreCLR>true</UseAppLocalCoreCLR>
-  </PropertyGroup>
-</Project>
\ No newline at end of file
diff --git a/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/build/Microsoft.Net.UWPCoreRuntimeSdk.targets b/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/build/Microsoft.Net.UWPCoreRuntimeSdk.targets
deleted file mode 100644 (file)
index 91f2ae8..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <BuildDependsOn>
-      CheckCoreRuntimeCompatibility;
-      $(BuildDependsOn);
-    </BuildDependsOn>
-  </PropertyGroup>
-
-  <Target Name="CheckCoreRuntimeCompatibility">
-    <Error
-      Text="The Microsoft.Net.UWPCoreRuntimeSdk package, included in Microsoft.NETCore.UniversalWindowsPlatform 5.4 and later, is only supported for TargetPlatformVersion's higher than '10.0.15063.0'. You can downgrade the version of the Microsoft.NETCore.UniversalWindowsPlatorm NuGet package to 5.3.* or earlier for earlier TargetPlatformVersion's."
-      Condition="'$(TargetPlatformVersion)' &lt;= '10.0.15063.0'" />
-  </Target>
-</Project>
\ No newline at end of file
diff --git a/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/tools/CoreRuntime/Microsoft.Net.CoreRuntime.settings.targets b/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/tools/CoreRuntime/Microsoft.Net.CoreRuntime.settings.targets
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/tools/CoreRuntime/Microsoft.Net.CoreRuntime.targets b/src/installer/pkg/projects/Microsoft.Net.UWPCoreRuntimeSdk/files/tools/CoreRuntime/Microsoft.Net.CoreRuntime.targets
deleted file mode 100644 (file)
index e69de29..0000000
index f2863d5..5535fac 100644 (file)
     <RidSpecificAssets Condition="'$(NuGetRuntimeIdentifier)' != ''">true</RidSpecificAssets>
     <IntermediateOutputPath>$(IntermediateOutputPath)$(NuGetRuntimeIdentifier)</IntermediateOutputPath>
     <RestoreOutputPath>$(IntermediateOutputPath)</RestoreOutputPath>
+    <CoreRuntimeSettingsTemplate>$(MSBuildProjectDirectory)\..\contents\identity\Microsoft.Net.CoreRuntime.settings.targets.template</CoreRuntimeSettingsTemplate>
+    <CoreRuntimeSettings>$(IntermediateOutputPath)Microsoft.Net.CoreRuntime.settings.targets</CoreRuntimeSettings>
+
+    <AppxDisplayName>Microsoft.NET.CoreRuntime.$(MajorVersion).$(MinorVersion)</AppxDisplayName>
+    <BuildVersionAppX>$([System.Int32]::Parse($(BuildNumberMajor)))</BuildVersionAppX>
+    <RevisionVersionAppX>$([System.Int32]::Parse($(BuildNumberMinor)))</RevisionVersionAppX>
   </PropertyGroup>
 
   <ItemGroup>
+    <RidPackageTransformations Include="$(MSBuildProjectDirectory)\..\contents\rid-templates\Microsoft.Net.UWPCoreRuntimeSdk.props.template">
+      <OutputPath>$(IntermediateOutputPath)runtime.$(NuGetRuntimeIdentifier).Microsoft.Net.UWPCoreRuntimeSdk.props</OutputPath>
+    </RidPackageTransformations>
+    <RidPackageTransformations Include="$(MSBuildProjectDirectory)\..\contents\rid-templates\Microsoft.Net.UWPCoreRuntimeSdk.targets.template">
+      <OutputPath>$(IntermediateOutputPath)runtime.$(NuGetRuntimeIdentifier).Microsoft.Net.UWPCoreRuntimeSdk.targets</OutputPath>
+    </RidPackageTransformations>
+
     <ProjectReference Include="..\..\Microsoft.Net.CoreRuntime\Microsoft.Net.CoreRuntime.depproj" />
   </ItemGroup>
 
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
 
+  <Target Name="GenerateCoreRuntimeSettingsFromTemplate"
+          BeforeTargets="GetFilesToPackage"
+          Inputs="$(CoreRuntimeSettingsTemplate)"
+          Outputs="$(CoreRuntimeSettings)"
+          Condition="'$(PackageTargetRuntime)' == ''">
+    <MakeDir Directories="$(IntermediateOutputPath)" />
+    <WriteLinesToFile File="$(CoreRuntimeSettings)"
+                      Lines="$([System.IO.File]::ReadAllText($(CoreRuntimeSettingsTemplate)).Replace('[AppxVersion]',$(MajorVersion).$(MinorVersion)))"
+                      Overwrite="true" />
+    <ItemGroup>
+      <FileWrites Include="$(CoreRuntimeSettings)" />
+    </ItemGroup>
+  </Target>
+
+  <Target Name="GenerateRidPackageTargetsFromTemplate"
+          BeforeTargets="GetFilesToPackage"
+          Inputs="@(RidPackageTransformations)"
+          Outputs="@(RidPackageTransformations -> %(OutputPath)')"
+          Condition="'$(PackageTargetRuntime)' != ''">
+    <MakeDir Directories="$(IntermediateOutputPath)" />
+    <WriteLinesToFile File="%(RidPackageTransformations.OutputPath)"
+                      Lines="$([System.IO.File]::ReadAllText(%(RidPackageTransformations.FullPath)).Replace('[AppxBuildArch]',$(Platform)).Replace('[AppxVersion]',$(MajorVersion).$(MinorVersion).$(BuildVersionAppX).$(RevisionVersionAppX)).Replace('[AppxDisplayName]',$(AppxDisplayName)))"
+                      Overwrite="true" />
+    <ItemGroup>
+      <FileWrites Include="@(RidPackageTransformations -> %(OutputPath)')" />
+    </ItemGroup>
+  </Target>
+
   <Target Name="GetFilesToPackage" AfterTargets="Build" Returns="@(FilesToPackage)">
+    <ItemGroup Condition="'$(NuGetRuntimeIdentifier)' == ''">
+      <FilesToPackage Include="$(CoreRuntimeSettings)">
+        <TargetPath>tools/CoreRuntime</TargetPath>
+      </FilesToPackage>
+      <FilesToPackage Include="$(CoreRuntimeTaskDir)\*.dll">
+        <TargetPath>tools/CoreRuntime</TargetPath>
+      </FilesToPackage>
+    </ItemGroup>
     <ItemGroup Condition="'$(NuGetRuntimeIdentifier)' != ''">
+      <!-- RID-specific: include targets files generated per runtime package -->
+      <FilesToPackage Include="$(IntermediateOutputPath)\*.props">
+        <TargetPath>build</TargetPath>
+      </FilesToPackage>
+      <FilesToPackage Include="$(IntermediateOutputPath)\*.targets">
+        <TargetPath>build</TargetPath>
+      </FilesToPackage>
       <!-- RID-specific: include all runtime files -->
       <FilesToPackage Include="$(UWPOutputDir)\copywin32resources.exe">
         <TargetPath>tools/CoreRuntime</TargetPath>
index 4d7d4d5..aa2a5b0 100644 (file)
@@ -36,6 +36,9 @@
       <FilesToSign Include="$(OutDir)corehost/**/dotnet.exe">
         <Authenticode>$(CertificateId)</Authenticode>
       </FilesToSign>
+      <FilesToSign Include="$(OutDir)Microsoft.Build.Net.CoreRuntimeTask/**/Microsoft.Build.Net.CoreRuntimeTask.dll">
+        <Authenticode>$(CertificateId)</Authenticode>
+      </FilesToSign>
     </ItemGroup>
 
     <ItemGroup>
diff --git a/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/ErrorCodes.cs b/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/ErrorCodes.cs
new file mode 100644 (file)
index 0000000..4bdea57
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/// <summary>
+/// Errors codes the application may return.
+/// The codes are divided up into buckets at the Phone team's behest so that they can easily
+/// triage errors.
+/// </summary>
+enum ErrorCodes
+{
+    Success = 0,
+
+    //
+    // Bucket 1: Deployment / Usage
+    //           Errors that the Marketplace team should address in their deployment
+    //
+
+    // 1000+: tool usage errors
+    EmptyFileList = 1000,
+    IncorrectInputFolder = 1001,
+    IncorrectOutputFolder = 1002,
+    IncorrectConfigFile = 1003,
+    InvalidArgument = 1004,
+    CrossGenNotOnPath = 1005,
+    InvalidAppManifest = 1006,
+    IncorrectPlatformFolder = 1007,
+    IncorrectFrameworkFolder = 1008,
+    IncorrectMakePriPath = 1009,
+    IncorrectRcPath = 1009, 
+
+    // 1200+: Errors getting crossgen off the ground and running
+    UnknownCrossgenError = 1200,
+    CLRInitError = 1201,
+    InvalidCrossgenArguments = 1202,
+    AssemblyNotFound = 1203,
+
+    // 1300+: Errors that occur while processing the app
+    InputFileReadError = 1300,
+    InputPackageFolderStructureTooComplex = 1301,
+    SecurityException = 1302,
+    UnauthorizedAccessException = 1303,
+    PathTooLongException = 1304,
+    NotSupported = 1305,
+    CoreRuntimeLinkageError = 1306,
+    InternalWireUpCoreRuntimeError = 1307,
+
+    // 1400+: Errors from the OS that were unexpected (ie, not specifically caused by user input or config)
+    FailedCreatingJobObject = 1400,
+
+    //
+    // Bucket 2: Invalid IL
+    //           Expected errors that occur because the user's application was malformed
+    //
+
+    CompilationFailedBadInputIL = 2001,
+    ExceededMaximumMethodSize =   2002,
+
+    //
+    // Bucket 3: Transient Errors
+    //           Errors most likely caused by machine state that could pass given a second chance
+    //
+    CrossgenTimeout = 3000,
+    InsufficientMemory = 3001,
+    InsufficientDiskSpace = 3003,
+    SharingViolation = 3004,
+    
+    //
+    // Bucket 4: Unexpected Errors
+    //           Errors that most likely indicate a bug in the runtime and need investigation by the CLR team
+    //
+    CorEExecutionEngine = 4000,
+    CorESecurity = 4001,
+    CldbEInternalError = 4002,
+    AccessViolation = 4004,
+    AppCompileInternalFailure = 4005
+
+}
diff --git a/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/MergePriConfigTask.cs b/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/MergePriConfigTask.cs
new file mode 100644 (file)
index 0000000..f7afa0c
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using System.IO;
+using System.Xml.Linq;
+
+namespace Microsoft.Build.Net.CoreRuntimeTask
+{
+    public sealed class MergePriConfigTask : Task
+    {
+        [Required]
+        public string AppPriConfig { get; set; }
+
+        [Required]
+        public string CustomPriConfig { get; set; }
+
+        [Required]
+        public string MergedPriConfig { get; set; }
+
+        public override bool Execute()
+        {
+            return (0 == InternalExecute());
+        }
+
+        private int InternalExecute()
+        {
+            XElement appConfig = XElement.Load(AppPriConfig);
+            if (appConfig == null)
+            {
+                Log.LogErrorFromResources(Resources.Error_FailedToLoadResourceConfig, AppPriConfig);
+                return -1;
+            }
+
+            XElement customConfig = XElement.Load(CustomPriConfig);
+            if (customConfig == null)
+            {
+                Log.LogError(Resources.Error_FailedToLoadResourceConfig, CustomPriConfig);
+                return -1;
+            }
+
+
+            IEnumerable<XElement> customIndexRoot = customConfig.Descendants("index").Where(x => x.Descendants("indexer-config").Any(y => y.Attribute("type").Value == "RESW")).Select(x => x);
+            if (customIndexRoot.Count() > 0)
+            {
+                appConfig.Add(customIndexRoot);
+                appConfig.Save(MergedPriConfig);
+                return 0;
+            }
+            else
+            {
+                Log.LogError(Resources.Error_InvalidResourceConfig, CustomPriConfig);
+                return -1;
+            }
+        }
+    }
+}
diff --git a/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/MergeResWFilesTask.cs b/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/MergeResWFilesTask.cs
new file mode 100644 (file)
index 0000000..29afe10
--- /dev/null
@@ -0,0 +1,111 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using System.IO;
+using System.Xml;
+using System.Xml.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Microsoft.Build.Net.CoreRuntimeTask
+{
+    public sealed class MergeResWFilesTask : Task
+    {
+        private List<ITaskItem> mergedResources = new List<ITaskItem>();
+
+        /// <summary>
+        /// The list of merged resource files
+        /// </summary>
+        [Output]
+        public ITaskItem[] MergedResources { get; set; }
+
+        /// <summary>
+        /// OutputLocation is where the merged resw files are going to be stored.
+        /// The merged resw files are going to be overwriting the existing files
+        /// in OutputLocation
+        /// </summary>
+        [Required]
+        public string OutputLocation { get; set; }
+        /// <summary>
+        /// The *.resw files to merge for
+        /// </summary>
+        [Required]
+        public ITaskItem[] ResourceFiles { get; set; }
+        /// <summary>
+        /// Implementation of Microsoft.Build.Utilities.Task.Execute
+        /// </summary>
+        /// <returns></returns>
+        public override bool Execute()
+        {
+            bool succeeded = (0 == InternalExecute());
+            MergedResources = mergedResources.ToArray();
+            return succeeded;
+
+        }
+
+        /// <summary>
+        /// The actual implementation of the Execute
+        /// </summary>
+        /// <returns>Returns 0 on success</returns>
+        private int InternalExecute()
+        {
+
+            // Loop through the ResourceFiles in groups of ResourceIndexName
+            foreach (var resourceIndex in GetResourceIndexes())
+            {
+                var resourceFiles = GetResourceFilesOfResourceIndex(resourceIndex);
+                var firstResourceFile = resourceFiles.FirstOrDefault();
+                if (firstResourceFile != null)
+                {
+                    XDocument doc = XDocument.Load(firstResourceFile.ItemSpec);
+                    HashSet<string> mergedResourceKeys = new HashSet<string>();
+                    foreach (var key in doc.Descendants("data").Select(x => x.Attribute("name").Value))
+                        mergedResourceKeys.Add(key);
+                    foreach (var resourceFile in resourceFiles.Skip(1))
+                    {
+                        XDocument mergee = XDocument.Load(resourceFile.ItemSpec);
+                        
+                        foreach (var dataNode in mergee.Descendants("data"))
+                        {
+                            if (mergedResourceKeys.Add(dataNode.Attribute("name").Value))
+                                doc.Root.Add(dataNode);
+                        }
+
+                    }
+                    Directory.CreateDirectory(Path.GetFullPath(OutputLocation));
+                    var mergedFilePath = Path.Combine(Path.GetFullPath(OutputLocation), Path.GetFileName(firstResourceFile.ItemSpec));
+                    doc.Save(mergedFilePath);
+                    TaskItem newItem = new TaskItem(firstResourceFile);
+                    newItem.ItemSpec = mergedFilePath;
+                    mergedResources.Add(newItem);
+                }
+                    
+            }
+            return 0;
+        }
+
+        /// <summary>
+        /// Returns the unique resource indexes from the list of resource files
+        /// </summary>
+        /// <returns>Unique list of resource</returns>
+        private IEnumerable<string> GetResourceIndexes()
+        {
+            return ResourceFiles.Select(x => x.GetMetadata("ResourceIndexName")).Distinct();
+        }
+        /// <summary>
+        /// Filters the resources according to the index
+        /// </summary>
+        /// <param name="resourceIndex">Item metadata value (of ResourceIndex) to filter the ResourceFiles</param>
+        /// <returns>Filtered list of ResourceFiles</returns>
+        private IEnumerable<ITaskItem> GetResourceFilesOfResourceIndex(string resourceIndex)
+        {
+            return ResourceFiles.Where(x => x.GetMetadata("ResourceIndexname").Equals(resourceIndex, StringComparison.OrdinalIgnoreCase));
+        }
+
+    }
+}
diff --git a/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Microsoft.Build.Net.CoreRuntimeTask.builds b/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Microsoft.Build.Net.CoreRuntimeTask.builds
new file mode 100644 (file)
index 0000000..c320fdd
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <ItemGroup>
+    <Project Include="$(MSBuildThisFileDirectory)$(MSBuildProjectName).csproj" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
+</Project>
\ No newline at end of file
diff --git a/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Microsoft.Build.Net.CoreRuntimeTask.csproj b/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Microsoft.Build.Net.CoreRuntimeTask.csproj
new file mode 100644 (file)
index 0000000..1e2c7b5
--- /dev/null
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <AllowCrossTargeting>true</AllowCrossTargeting>
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+  </PropertyGroup>
+  
+  <PropertyGroup>
+    <ProjectGuid>{49082C55-62B7-4DEC-BC9E-3F57945AC37E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Microsoft.Build.Net.CoreRuntimeTask</RootNamespace>
+    <AssemblyName>Microsoft.Build.Net.CoreRuntimeTask</AssemblyName>
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+    
+    <!-- turn off CLS compliant check to make it work with CCI code -->
+    <AssemblyAttributeClsCompliant>false</AssemblyAttributeClsCompliant>
+
+    <AssemblyVersion>$(MajorVersion).$(MinorVersion).$(PatchVersion).0</AssemblyVersion>
+    <AssemblyComVisible>false</AssemblyComVisible>
+    <OutputType>Library</OutputType>
+    <NuGetTargetMoniker>.NETFramework,Version=v4.6</NuGetTargetMoniker>
+    <NuGetTargetMonikerShort>net46</NuGetTargetMonikerShort>
+    <CLSCompliant>false</CLSCompliant>
+    <ProjectGuid>{49082C55-62B7-4DEC-BC9E-3F57945AC37E}</ProjectGuid>
+    <PackageTargetFallback>dnxcore50;portable-net45+win8+wpa81</PackageTargetFallback>
+    <ContainsPackageReferences>true</ContainsPackageReferences>
+    <TargetFrameworkIdentifier>.NETStandard</TargetFrameworkIdentifier>
+    <RestoreOutputPath>obj</RestoreOutputPath>
+    <SkipSigning>true</SkipSigning>
+    <RestorePackages>true</RestorePackages>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the options -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|amd64' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|amd64' ">
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Compile Include="ErrorCodes.cs" />
+    <Compile Include="Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="WireUpCoreRuntime.cs" />
+    <Compile Include="MergePriConfigTask.cs" />
+    <Compile Include="MergeResWFilesTask.cs" />
+    <Compile Include="ResourceHandlingTask.cs" />
+  </ItemGroup>  
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.Cci">
+      <Version>4.0.0-rc4-24217-00</Version>
+    </PackageReference>
+    <PackageReference Include="Microsoft.TargetingPack.NETFramework.v4.6">
+      <Version>1.0.1</Version>
+    </PackageReference>
+    <TargetingPackReference Include="System" />
+    <TargetingPackReference Include="System.Core" />
+    <TargetingPackReference Include="System.Xml" />
+    <TargetingPackReference Include="System.Xml.Linq" />
+    <TargetingPackReference Include="System.Runtime" />
+    <TargetingPackReference Include="System.Runtime.Serialization" />
+    <TargetingPackReference Include="System.Windows.Forms" />
+    <TargetingPackReference Include="Microsoft.Build" />
+    <TargetingPackReference Include="Microsoft.Build.Framework" />
+    <TargetingPackReference Include="Microsoft.Build.Utilities.v4.0" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+
+  <Target Name="CopyLocalMicrosoftCci" BeforeTargets="ResolveAssemblyReferences">
+    <ItemGroup>
+      <ModifiedCci Include="@(Reference)" Condition="'%(NuGetPackageId)' == 'Microsoft.Cci'">
+        <Private>true</Private>
+      </ModifiedCci>
+      <Reference Remove="@(Reference)" Condition="'%(NuGetPackageId)' == 'Microsoft.Cci'" />
+      <Reference Include="@(ModifiedCci)" />
+    </ItemGroup>
+  </Target>
+
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/ResourceHandlingTask.cs b/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/ResourceHandlingTask.cs
new file mode 100644 (file)
index 0000000..0fe93bd
--- /dev/null
@@ -0,0 +1,355 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using System.IO;
+using System.Xml.Linq;
+using System.Collections;
+using System.Resources;
+using Microsoft.Cci;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+
+namespace Microsoft.Build.Net.CoreRuntimeTask
+{
+
+    public sealed class ResourceHandlingTask : Task
+    {
+        [Serializable()]
+        public sealed class PortableLibraryResourceStateInfo
+        {
+            public DateTime PLibTimeUtc;
+            public DateTime ResWTimeUtc;
+            public string   ResWPath;
+        }
+
+        [Serializable()]
+        public sealed class ResourceHandlingState
+        {
+            [NonSerialized]
+            private TaskLoggingHelper _logger;
+            public Dictionary<string, PortableLibraryResourceStateInfo> PortableLibraryStatesLookup = new Dictionary<string, PortableLibraryResourceStateInfo>();
+
+            public void SetLogger(TaskLoggingHelper logger) { _logger = logger; } 
+
+            public bool IsUpToDate(string assemblyPath, out string reswFilePath)
+            {
+                reswFilePath = null;
+                if (PortableLibraryStatesLookup == null)
+                {
+                    PortableLibraryStatesLookup = new Dictionary<string, PortableLibraryResourceStateInfo>();
+                    return false;
+                }
+                if (PortableLibraryStatesLookup.Count == 0)
+                {
+                    return false;
+                }
+
+                try
+                {
+                    if (assemblyPath == null || !File.Exists(assemblyPath))
+                    {
+                        return false;
+                    }
+                    PortableLibraryResourceStateInfo info; 
+                    if (!PortableLibraryStatesLookup.TryGetValue(assemblyPath, out info))
+                    {
+                        return false;
+                    }
+                    FileInfo fiPlib = new FileInfo(assemblyPath);
+                    if (!fiPlib.LastWriteTimeUtc.Equals(info.PLibTimeUtc))
+                    {
+                        _logger.LogMessage(MessageImportance.Low, Resources.Message_CachedReswNotUpToDateAssemblyNewer, assemblyPath); 
+                        return false;
+                    }
+                    if (info.ResWPath == null || !File.Exists(info.ResWPath))
+                    {
+                        _logger.LogMessage(MessageImportance.Low, Resources.Message_CachedReswNotExists, assemblyPath, info.ResWPath); 
+                        return false;
+                    }
+    
+                    FileInfo fiResW = new FileInfo(info.ResWPath);
+                    if (!fiResW.LastWriteTimeUtc.Equals(info.ResWTimeUtc))
+                    {
+                        _logger.LogMessage(MessageImportance.Low, Resources.Message_CachedReswNotUpToDate, info.ResWPath); 
+                        return false;
+                    }
+
+                    _logger.LogMessage(MessageImportance.Low, Resources.Message_UsingCachedResw, info.ResWPath, assemblyPath); 
+                    reswFilePath = info.ResWPath;
+                    return true;
+                }
+                catch (Exception e)
+                {
+                    _logger.LogMessage(MessageImportance.Low, Resources.Error_UnspecifiedCheckUpToDate, assemblyPath, e.Message);
+                    return false;
+                }
+            }
+
+            public void Save(string assemblyPath, string reswPath, DateTime plibTimeUtc, DateTime reswTimeUtc)
+            {
+                try
+                {
+                    PortableLibraryStatesLookup[assemblyPath] = new PortableLibraryResourceStateInfo() { PLibTimeUtc = plibTimeUtc, ResWTimeUtc = reswTimeUtc, ResWPath = reswPath};
+                }
+                catch (Exception e) 
+                {
+                    _logger.LogMessage(MessageImportance.Low, Resources.Error_UnspecifiedSaveState, assemblyPath, e.Message);
+                }
+            }
+
+        }
+
+        [Required]
+        public ITaskItem[] AssemblyList { get; set; }
+
+        [Required]
+        public string OutResWPath { get; set; }
+
+        [Required]
+        public string StateFile { get; set; }
+
+        public bool SkipFrameworkResources { get; set; }
+
+        [Output]
+        public ITaskItem[] ReswFileList { get; set; }
+
+        [Output]
+        public ITaskItem[] UnprocessedAssemblyList { get; set; }
+
+        private MetadataReaderHost _host; 
+
+        private ResourceHandlingState _state = null;
+
+        public override bool Execute()
+        {
+            ReswFileList            = null;
+            UnprocessedAssemblyList = null;
+
+            List<ITaskItem> unprocessedAssemblyList = new List<ITaskItem>();
+            List<ITaskItem> reswList = new List<ITaskItem>();
+
+            _state = ReadStateFile(StateFile);
+            if (_state == null)
+            {
+                _state = new ResourceHandlingState();
+            }
+            _state.SetLogger(Log);
+
+            using (_host = new PeReader.DefaultHost())
+            {
+                try
+                {
+                    ITaskItem firstNonFrameworkAssembly = null;
+                    foreach (ITaskItem assemblyFilePath in AssemblyList)
+                    {
+                        string reswPath = null;
+                        bool containsResources = false;
+                        if (!_state.IsUpToDate(assemblyFilePath.ItemSpec, out reswPath) || 
+                            !IsAtOutputFolder(reswPath) )
+                        {
+                            reswPath = ExtractFrameworkAssemblyResW(assemblyFilePath.ItemSpec, out containsResources);
+                            if (reswPath != null)
+                            {
+                                FileInfo fiAssembly = new FileInfo(assemblyFilePath.ItemSpec);
+                                FileInfo fiResW = new FileInfo(reswPath);
+                                _state.Save(assemblyFilePath.ItemSpec, reswPath, fiAssembly.LastWriteTimeUtc, fiResW.LastWriteTimeUtc);
+                            }
+                        }
+
+                        if (reswPath == null)
+                        {
+                            if (containsResources)
+                                unprocessedAssemblyList.Add(assemblyFilePath);
+                            
+                            if (unprocessedAssemblyList.Count == 0)
+                                firstNonFrameworkAssembly = assemblyFilePath;
+                        }
+                        else
+                        {
+                            TaskItem newTaskItem = new TaskItem(reswPath);
+                            newTaskItem.SetMetadata("NeutralResourceLanguage","en-US");
+                            newTaskItem.SetMetadata("ResourceIndexName",Path.GetFileNameWithoutExtension(reswPath));
+                            reswList.Add(newTaskItem);
+                        }
+
+                    }
+
+                    UnprocessedAssemblyList = unprocessedAssemblyList.ToArray();
+                    
+                    if (!SkipFrameworkResources)
+                    {
+                        ReswFileList = reswList.ToArray();
+                    }
+
+                    // we make sure unprocessedAssemblyList has at least one item if ReswFileList is empty to avoid having _GeneratePrisForPortableLibraries
+                    // repopulate the assembly list and reprocess them
+                    if ((ReswFileList == null || ReswFileList.Length == 0) && 
+                        UnprocessedAssemblyList.Length == 0 && 
+                        firstNonFrameworkAssembly != null)
+                    {
+                        UnprocessedAssemblyList = new ITaskItem[1] { firstNonFrameworkAssembly };
+                    }
+
+                    WriteStateFile(StateFile, _state);
+                } 
+                catch (Exception e)
+                {
+                    Log.LogError(Resources.Error_ResourceExtractionFailed, e.Message);
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        private ResourceHandlingState ReadStateFile(string stateFile)
+        {
+            try 
+            {
+                if (!String.IsNullOrEmpty(stateFile) && File.Exists(stateFile))
+                {
+                    using (FileStream fs = new FileStream(stateFile, FileMode.Open))
+                    {
+                        BinaryFormatter formatter = new BinaryFormatter();
+                        object deserializedObject = formatter.Deserialize(fs);
+                        ResourceHandlingState state = deserializedObject as ResourceHandlingState;
+                        if (state == null && deserializedObject != null)
+                        {
+                            Log.LogMessage(MessageImportance.Normal, Resources.Message_UnspecifiedStateFileCorrupted, stateFile);
+                        }
+                        return state;
+                    }
+                }
+                else
+                    return null;
+            }
+            catch (Exception e)
+            {
+                Log.LogMessage(MessageImportance.Low, Resources.Message_UnspecifiedReadStateFile, e.Message);
+                return null;
+            }
+        }
+
+        private bool IsAtOutputFolder(string path)
+        {
+            try
+            {
+                return (Path.GetDirectoryName(path).Equals(OutResWPath.TrimEnd(new char[] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar}), StringComparison.OrdinalIgnoreCase));
+            }
+            catch
+            {
+                return false;
+            }
+        }
+
+        private void WriteStateFile(string stateFile, ResourceHandlingState state)
+        {
+            try
+            {
+                if (stateFile != null && stateFile.Length > 0 )
+                {
+                    using (FileStream fs = new FileStream(stateFile, FileMode.Create))
+                    {
+                        BinaryFormatter formatter = new BinaryFormatter();
+                        formatter.Serialize(fs, state);
+                    }
+                }
+
+            }
+            catch (Exception e) 
+            {
+                Log.LogMessage(MessageImportance.Low, Resources.Message_UnspecifiedSaveStateFile, e.Message);
+            }
+        }
+
+        private string ExtractFrameworkAssemblyResW(string assemblyFilePath, out bool containsResources)
+        {
+            string assemblyName;
+            using (Stream stream = ExtractFromAssembly(assemblyFilePath, out assemblyName, out containsResources))
+            {
+                if (stream == null)
+                    return null;
+
+                string reswFilePath = OutResWPath + Path.AltDirectorySeparatorChar + "FxResources." + assemblyName + ".SR.resw";
+                WriteResW(stream, reswFilePath);
+                return reswFilePath;
+            }
+        }
+
+        private void WriteResW(Stream stream, string reswFilePath)
+        {
+            using (ResourceReader rr = new ResourceReader(stream))
+            {
+                using (ResXResourceWriter rw = new ResXResourceWriter(reswFilePath))
+                {
+                    foreach (DictionaryEntry dict in rr)
+                    {
+                        rw.AddResource((string)dict.Key, (string)dict.Value);
+                    }
+                }
+            }
+        }
+
+        private Stream ExtractFromAssembly(string assemblyFilePath, out string assemblyName, out bool containsResources)
+        {
+            assemblyName = null;
+            containsResources = true;
+
+            IAssembly assembly = _host.LoadUnitFrom(assemblyFilePath) as IAssembly;
+            if (assembly == null || assembly == Dummy.Assembly)
+            {
+                containsResources = false;
+                return null;
+            }
+
+            if (assembly.Resources == null)
+            {
+                containsResources = false;
+                return null;
+            }
+
+            assemblyName = assembly.Name.Value;
+            string resourcesName = "FxResources." + assemblyName + ".SR.resources";
+            int resourceCount = 0;
+
+            foreach (IResourceReference resourceReference in assembly.Resources)
+            {
+                resourceCount++;
+                if (!resourceReference.Resource.IsInExternalFile && resourceReference.Name.Value.Equals(resourcesName, StringComparison.OrdinalIgnoreCase))
+                {
+                    const int BUFFERSIZE = 4096;
+                    byte[] buffer = new byte[BUFFERSIZE];
+                    int index = 0;
+
+                    MemoryStream ms = new MemoryStream(BUFFERSIZE);
+
+                    foreach (byte b in resourceReference.Resource.Data)
+                    {
+                        if (index == BUFFERSIZE)
+                        {
+                            ms.Write(buffer, 0, BUFFERSIZE);
+                            index = 0;
+                        }
+                        buffer[index++] = b;
+                    }
+                    ms.Write(buffer, 0, index);
+                    ms.Seek(0, SeekOrigin.Begin);
+                    return ms;
+                }
+            }
+
+            if (resourceCount == 0) // no resources
+            {
+                containsResources = false;
+            }
+
+            return null;
+        }
+
+    }
+}
diff --git a/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Resources.Designer.cs b/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Resources.Designer.cs
new file mode 100644 (file)
index 0000000..0a35eab
--- /dev/null
@@ -0,0 +1,252 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Build.Net.CoreRuntimeTask {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Build.Net.CoreRuntimeTask.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to CopyWin32Resources failed with exit code {0}.
+        /// </summary>
+        internal static string Error_CopyWin32ResourcesFailed {
+            get {
+                return ResourceManager.GetString("Error_CopyWin32ResourcesFailed", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Applications with custom entry point executables are not supported. Check Executable attribute of the Application element in the package manifest.
+        /// </summary>
+        internal static string Error_CustomEntryPointNotSupported {
+            get {
+                return ResourceManager.GetString("Error_CustomEntryPointNotSupported", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Failed to load resource config file &quot;{0}&quot;.
+        /// </summary>
+        internal static string Error_FailedToLoadResourceConfig {
+            get {
+                return ResourceManager.GetString("Error_FailedToLoadResourceConfig", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to WireUpCoreRuntime encountered an error: {0}.
+        /// </summary>
+        internal static string Error_InternalWireUpCoreRuntimeError {
+            get {
+                return ResourceManager.GetString("Error_InternalWireUpCoreRuntimeError", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Invalid resource config file &apos;{0}&apos;.
+        /// </summary>
+        internal static string Error_InvalidResourceConfig {
+            get {
+                return ResourceManager.GetString("Error_InvalidResourceConfig", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to IO exception while copying file {0}.  {1}.
+        /// </summary>
+        internal static string Error_IOExceptionCopyFile {
+            get {
+                return ResourceManager.GetString("Error_IOExceptionCopyFile", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to IO exception while creating output folder. {0}.
+        /// </summary>
+        internal static string Error_IOExceptionOutputFolder {
+            get {
+                return ResourceManager.GetString("Error_IOExceptionOutputFolder", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to PathTooLongException while copying file {0}.
+        /// </summary>
+        internal static string Error_PathTooLongExceptionCopyFile {
+            get {
+                return ResourceManager.GetString("Error_PathTooLongExceptionCopyFile", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to PathTooLongException while creating output folder.
+        /// </summary>
+        internal static string Error_PathTooLongExceptionOutputFolder {
+            get {
+                return ResourceManager.GetString("Error_PathTooLongExceptionOutputFolder", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Framework resource extraction failed. {0}.
+        /// </summary>
+        internal static string Error_ResourceExtractionFailed {
+            get {
+                return ResourceManager.GetString("Error_ResourceExtractionFailed", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Encountered an error while checking if the resource cache of &quot;{0}&quot; is up to date: {1}.
+        /// </summary>
+        internal static string Error_UnspecifiedCheckUpToDate {
+            get {
+                return ResourceManager.GetString("Error_UnspecifiedCheckUpToDate", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Exception while creating entry point shim for hybrid apps: {0}.
+        /// </summary>
+        internal static string Error_UnspecifiedCreatingUWPShimForHybrid {
+            get {
+                return ResourceManager.GetString("Error_UnspecifiedCreatingUWPShimForHybrid", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Encountered an error while saving the resource state for &quot;{0}&quot;: {1}.
+        /// </summary>
+        internal static string Error_UnspecifiedSaveState {
+            get {
+                return ResourceManager.GetString("Error_UnspecifiedSaveState", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Cached ResW of assembly &quot;{0}&quot; doesn&apos;t exist: &quot;{1}&quot;.
+        /// </summary>
+        internal static string Message_CachedReswNotExists {
+            get {
+                return ResourceManager.GetString("Message_CachedReswNotExists", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Cached ResW &quot;{0}&quot; is not up to date.
+        /// </summary>
+        internal static string Message_CachedReswNotUpToDate {
+            get {
+                return ResourceManager.GetString("Message_CachedReswNotUpToDate", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Cached ResW of assembly &quot;{0}&quot; is not up to date, assembly itself is newer.
+        /// </summary>
+        internal static string Message_CachedReswNotUpToDateAssemblyNewer {
+            get {
+                return ResourceManager.GetString("Message_CachedReswNotUpToDateAssemblyNewer", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Processing file: &quot;{0}&quot;.
+        /// </summary>
+        internal static string Message_ProcessingFile {
+            get {
+                return ResourceManager.GetString("Message_ProcessingFile", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to An error occured while reading the state file: {0}.
+        /// </summary>
+        internal static string Message_UnspecifiedReadStateFile {
+            get {
+                return ResourceManager.GetString("Message_UnspecifiedReadStateFile", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to An error occured while writing the state file: {0}.
+        /// </summary>
+        internal static string Message_UnspecifiedSaveStateFile {
+            get {
+                return ResourceManager.GetString("Message_UnspecifiedSaveStateFile", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Encountered an error while reading the  state file &quot;{0}&quot;. The state file may be corrupt. Disregarding the state file..
+        /// </summary>
+        internal static string Message_UnspecifiedStateFileCorrupted {
+            get {
+                return ResourceManager.GetString("Message_UnspecifiedStateFileCorrupted", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Using cached ResW &quot;{0}&quot; for &quot;{1}&quot;.
+        /// </summary>
+        internal static string Message_UsingCachedResw {
+            get {
+                return ResourceManager.GetString("Message_UsingCachedResw", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Resources.resx b/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/Resources.resx
new file mode 100644 (file)
index 0000000..8e86564
--- /dev/null
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="Error_CopyWin32ResourcesFailed" xml:space="preserve">
+    <value>CopyWin32Resources failed with exit code {0}</value>
+  </data>
+  <data name="Error_CustomEntryPointNotSupported" xml:space="preserve">
+    <value>Applications with custom entry point executables are not supported. Check Executable attribute of the Application element in the package manifest</value>
+  </data>
+  <data name="Error_FailedToLoadResourceConfig" xml:space="preserve">
+    <value>Failed to load resource config file "{0}"</value>
+  </data>
+  <data name="Error_InternalWireUpCoreRuntimeError" xml:space="preserve">
+    <value>WireUpCoreRuntime encountered an error: {0}</value>
+  </data>
+  <data name="Error_InvalidResourceConfig" xml:space="preserve">
+    <value>Invalid resource config file '{0}'</value>
+  </data>
+  <data name="Error_IOExceptionCopyFile" xml:space="preserve">
+    <value>IO exception while copying file {0}.  {1}</value>
+  </data>
+  <data name="Error_IOExceptionOutputFolder" xml:space="preserve">
+    <value>IO exception while creating output folder. {0}</value>
+  </data>
+  <data name="Error_PathTooLongExceptionCopyFile" xml:space="preserve">
+    <value>PathTooLongException while copying file {0}</value>
+  </data>
+  <data name="Error_PathTooLongExceptionOutputFolder" xml:space="preserve">
+    <value>PathTooLongException while creating output folder</value>
+  </data>
+  <data name="Error_ResourceExtractionFailed" xml:space="preserve">
+    <value>Framework resource extraction failed. {0}</value>
+  </data>
+  <data name="Error_UnspecifiedCheckUpToDate" xml:space="preserve">
+    <value>Encountered an error while checking if the resource cache of "{0}" is up to date: {1}</value>
+  </data>
+  <data name="Error_UnspecifiedCreatingUWPShimForHybrid" xml:space="preserve">
+    <value>Exception while creating entry point shim for hybrid apps: {0}</value>
+  </data>
+  <data name="Error_UnspecifiedSaveState" xml:space="preserve">
+    <value>Encountered an error while saving the resource state for "{0}": {1}</value>
+  </data>
+  <data name="Message_CachedReswNotExists" xml:space="preserve">
+    <value>Cached ResW of assembly "{0}" doesn't exist: "{1}"</value>
+  </data>
+  <data name="Message_CachedReswNotUpToDate" xml:space="preserve">
+    <value>Cached ResW "{0}" is not up to date</value>
+  </data>
+  <data name="Message_CachedReswNotUpToDateAssemblyNewer" xml:space="preserve">
+    <value>Cached ResW of assembly "{0}" is not up to date, assembly itself is newer</value>
+  </data>
+  <data name="Message_ProcessingFile" xml:space="preserve">
+    <value>Processing file: "{0}"</value>
+  </data>
+  <data name="Message_UnspecifiedReadStateFile" xml:space="preserve">
+    <value>An error occured while reading the state file: {0}</value>
+  </data>
+  <data name="Message_UnspecifiedSaveStateFile" xml:space="preserve">
+    <value>An error occured while writing the state file: {0}</value>
+  </data>
+  <data name="Message_UnspecifiedStateFileCorrupted" xml:space="preserve">
+    <value>Encountered an error while reading the  state file "{0}". The state file may be corrupt. Disregarding the state file.</value>
+  </data>
+  <data name="Message_UsingCachedResw" xml:space="preserve">
+    <value>Using cached ResW "{0}" for "{1}"</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/WireUpCoreRuntime.cs b/src/installer/uwp/Microsoft.Build.Net.CoreRuntimeTask/WireUpCoreRuntime.cs
new file mode 100644 (file)
index 0000000..6897a49
--- /dev/null
@@ -0,0 +1,301 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace Microsoft.Build.Net.CoreRuntimeTask
+{
+    using System;
+    using System.Collections.Generic;
+    using System.ComponentModel;
+    using System.Diagnostics;
+    using System.IO;
+    using System.Linq;
+    using System.Reflection;
+    using System.Runtime.Serialization;
+    using System.Text;
+    using System.Xml;
+    using System.Xml.Linq;
+    using System.Xml.Serialization;
+    using Microsoft.Build.Framework;
+    using Microsoft.Build.Utilities;
+    using System.Runtime.InteropServices;
+
+    /// <summary> Task for wiring up CoreRuntime to appx payload </summary>
+    public class WireUpCoreRuntime : Task
+    {
+        private static int timeoutDuration = 360000; // 6 minutes
+
+        // HRESULT exit codes from Crossgen that indicate the input file is not a managed assembly
+        private const int ErrorNotAnAssembly = -2146230517; // 0x80131f0b
+        
+        private const string PackageDependencyElementName = "PackageDependency";
+
+        private const string AppEntryPointDir = "entrypoint";
+
+        private const string UWPShimEXE = "UWPShim.exe";
+
+        /// <summary> Gets or sets the path to the input AppxManifest file </summary>
+        [Required]
+        public string AppxManifest { get; set; }
+
+        /// <summary> Gets or sets the appx package payload that will be processed </summary>
+        [Required]
+        public ITaskItem[] AppxPackagePayload { get; set; }
+
+        /// <summary> Gets or sets the output directory that will contain the output appx manifest and any output executables </summary>
+        [Required]
+        public string OutputPath { get; set; }
+
+        /// <summary> Gets ot sets the target runtime of the application </summary>
+        [Required]
+        public string TargetRuntime { get; set; }
+
+        /// <summary> Gets or sets the target architecture </summary>
+        [Required]
+        public string TargetArch { get; set; } 
+
+        /// <summary> Gets or sets the framework packages to be added as PackageDependencies </summary>
+        [Required]
+        public ITaskItem[] FrameworkPackages { get; set; }
+
+        /// <summary> Gets or sets the CoreRuntime Extension SDK location. This is used to locate the UWPShim.exe </summary>
+        [Required]
+        public string CoreRuntimeSDKLocation { get; set; }
+
+        /// <summary> Location of CopyWin32Resources.exe </summary>
+        [Required]
+        public string CopyWin32ResourcesLocation { get; set; }
+
+        /// <summary> Gets ot sets the timeout duration in which the call to CopyWin32Resources is expected to return </summary>
+        public int TimeoutDuration 
+        { 
+            get 
+            { 
+                return timeoutDuration; 
+            }  
+            set
+            {
+                timeoutDuration = value;
+            }
+        }
+
+        /// <summary> Output parameter indicating the error code of executing this task </summary>
+        [Output]
+        public int ErrorCode { get; private set; }
+
+        /// <summary> 
+        /// Output parameter indicating whether the CoreRuntime framework package needs to be deployed before
+        /// deploying the application
+        /// </summary>
+        [Output]
+        public bool FrameworkPackagesNeedsToBeDeployed { get; private set; }
+
+        /// <summary> Gets or sets the appx package payload that has been processed </summary>
+        [Output]
+        public ITaskItem[] TransformedAppxPackagePayload { get; set; }
+
+
+        /// <summary> Execute the task. </summary>
+        /// <returns> True if succeeeds </returns>
+        public override bool Execute()
+        {
+            ErrorCode = InternalExecute();
+            return (ErrorCode == (int)ErrorCodes.Success);
+        }
+
+        /// <summary> The internal implementation of the execute task </summary>
+        /// <returns> ErrorCodes.Success if succeeds, one of the other ErrorCodes otherwise </returns>
+        internal int InternalExecute()
+        {
+            bool isTargetRuntimeManaged = TargetRuntime.Equals("Managed", StringComparison.OrdinalIgnoreCase);
+            List<ITaskItem> currentAppxPackagePayload = AppxPackagePayload.ToList();
+            string transformedAppxManifest = Path.Combine(OutputPath, "AppxManifest.xml");
+
+            // Perform setup:
+            //   - Create output directory if it does not already exist
+            //   - Delete existing AppxManifest.xml if it exists
+            try
+            {
+                Directory.CreateDirectory(OutputPath);
+                File.Delete(transformedAppxManifest);
+            }
+            catch (PathTooLongException)
+            {
+                Log.LogError(Resources.Error_PathTooLongExceptionOutputFolder);
+                return (int)ErrorCodes.PathTooLongException;
+            }
+            catch (IOException ioException)
+            {
+                Log.LogError(Resources.Error_IOExceptionOutputFolder, ioException.Message);
+                return (int)ErrorCodes.InputFileReadError;
+            }
+            catch (Exception e)
+            {
+                Log.LogError(Resources.Error_InternalWireUpCoreRuntimeError, e.Message);
+                return (int)ErrorCodes.InternalWireUpCoreRuntimeError;
+            }
+
+            // Apply transformations required to hook up the Core Runtime
+            // 1. For Managed apps, move <app.exe> to [AppEntryPointDir]\<app.exe> and copy UWPShim.exe to package root as <app.exe>
+            // 2. Replace all ClrHost.dll with either UWPShim.exe (for hybrid apps) or <app.exe> (for managed apps)
+            // 3. If #2 above is performed, inject UWPShim.exe into the output directory for unmanaged apps
+            //    which contain managed winmd and for managed background tasks (which do not contain entrypoint exe)
+            // 4. If #1 or #2 above is performed, add a package dependency to CoreRuntime framework package.
+
+            using (StreamReader sr = new StreamReader(AppxManifest))
+            {
+                XDocument doc = XDocument.Load(sr, LoadOptions.None);
+                XNamespace ns = @"http://schemas.microsoft.com/appx/manifest/foundation/windows10";
+                string inprocServer = UWPShimEXE;
+                var uwpShimLocation = Path.Combine(new [] { 
+                            CoreRuntimeSDKLocation,
+                            "AppLocal",
+                            UWPShimEXE} );
+
+                IEnumerable<XAttribute> entryPointExecutables = Enumerable.Empty<XAttribute>();
+                if (isTargetRuntimeManaged)
+                {
+                    // 1. For Managed apps, move <app.exe> to [AppEntryPointDir]\<app.exe> and copy UWPShim.exe to package root as <app.exe>
+                    entryPointExecutables = doc.Descendants(ns + "Applications").Descendants(ns + "Application").Where(x => x.Attribute("Executable") != null).Select(x => x.Attribute("Executable"));
+
+                    if (entryPointExecutables.Any())
+                    {
+                        // Set the inprocServer to the <app.exe>. From this point on that's our UWPShim.exe
+                        // and since we will be copying uwpShim possibly several times with different names, yet they are all 
+                        // uwpshim.exe, it's OK to grab the first one and use it as inprocserver entry
+                        inprocServer = entryPointExecutables.First().Value;
+                        if (entryPointExecutables.Any(x => x.Value.Contains(Path.DirectorySeparatorChar)))
+                        {
+                            Log.LogError(Resources.Error_CustomEntryPointNotSupported);
+                            return (int)ErrorCodes.NotSupported;
+                        }
+
+                        foreach (var entryPointExecutable in entryPointExecutables)
+                        {
+                            // Do not copy <app.exe> from original location, just modify TargetPath to [AppEntryPointDir]\<app.exe>
+                            ITaskItem currentManagedEntryPointExecutableTaskItem = AppxPackagePayload.Where(x => x.GetMetadata("TargetPath") == entryPointExecutable.Value).Single();
+                            currentManagedEntryPointExecutableTaskItem.SetMetadata("TargetPath", AppEntryPointDir + "\\" + entryPointExecutable.Value);
+
+                            // Copy UWPShim
+                            var entryPointExecutableShim = Path.Combine(OutputPath, entryPointExecutable.Value);
+                            File.Copy(uwpShimLocation, entryPointExecutableShim, true);
+                            var copyResourcesReturncode = CopyWin32Resources(currentManagedEntryPointExecutableTaskItem.ItemSpec, entryPointExecutableShim);
+                            if (copyResourcesReturncode != 0)
+                            {
+                                Log.LogError(Resources.Error_CopyWin32ResourcesFailed, copyResourcesReturncode);
+                                return (int)ErrorCodes.CoreRuntimeLinkageError;
+                            }
+
+                            // Add UWPShim to appx package payload
+                            ITaskItem entryPointExecutableShimTaskItem = new TaskItem(entryPointExecutableShim);
+                            entryPointExecutableShimTaskItem.SetMetadata("TargetPath", entryPointExecutable.Value);
+                            currentManagedEntryPointExecutableTaskItem.CopyMetadataTo(entryPointExecutableShimTaskItem);
+                            currentAppxPackagePayload.Add(entryPointExecutableShimTaskItem);
+                        }
+                    }
+                }
+                
+                // 
+                // 2. Replace all ClrHost.dll with either UWPShim.exe (for hybrid apps) or <app.exe> (for managed apps)
+                var inprocServerNodes = doc.DescendantNodes().OfType<XText>()
+                                           .Where(x => x.Value.Equals("ClrHost.dll", StringComparison.OrdinalIgnoreCase))
+                                           .Select(x => x);
+
+                bool bHasManagedWinMD = false;
+                foreach (var node in inprocServerNodes)
+                {
+                    node.Value = inprocServer;
+                    bHasManagedWinMD = true;
+                }
+
+                //
+                // 3. If #2 above is performed, inject UWPShim.exe into the output directory for unmanaged apps
+                //    which contain managed winmd and for managed background tasks (which do not contain entrypoint exe)
+                if (bHasManagedWinMD && inprocServer.Equals(UWPShimEXE))
+                {
+                    try 
+                    {
+                        // Copy UWPShim
+                        string uwpDestination = Path.Combine(OutputPath, inprocServer);
+                        File.Copy(uwpShimLocation, uwpDestination, true);
+
+                        // Add UWPShim to appx package payload
+                        TaskItem uwpShimTaskItem = new TaskItem(uwpDestination);
+                        uwpShimTaskItem.SetMetadata("TargetPath", inprocServer);
+                        currentAppxPackagePayload.Add(uwpShimTaskItem);
+                    }
+                    catch (Exception exception)
+                    {
+                        Log.LogError(Resources.Error_UnspecifiedCreatingUWPShimForHybrid, exception.Message);
+                        return (int)ErrorCodes.CoreRuntimeLinkageError;
+                    }
+
+                }
+
+                //
+                // 4. If #1 or #2 above is performed, add a package dependency to CoreRuntime framework package.
+                if (isTargetRuntimeManaged || bHasManagedWinMD)
+                {
+                    foreach (var FrameworkPackage in FrameworkPackages) 
+                    {
+                        string FrameworkPackageName = FrameworkPackage.GetMetadata("Name");
+                        string FrameworkPackageMinVersion = FrameworkPackage.GetMetadata("Version");
+                        string FrameworkPackagePublisher = FrameworkPackage.GetMetadata("Publisher");
+                        if (!doc.Descendants(ns + "PackageDependency").Any(x => x.Attributes("Name").SingleOrDefault().Value == FrameworkPackageName))
+                        {
+                            // There aren't any such PackageDependency. Add it now.
+                            XElement packageDependency = new XElement(
+                                                            ns + "PackageDependency",
+                                                            new XAttribute("Name",          FrameworkPackageName),
+                                                            new XAttribute("MinVersion",    FrameworkPackageMinVersion),
+                                                            new XAttribute("Publisher",     FrameworkPackagePublisher)
+                                                        );
+                            doc.Descendants(ns + "Dependencies").SingleOrDefault().Add(packageDependency);
+                            FrameworkPackagesNeedsToBeDeployed = true;
+
+                        }
+                    }
+                }
+
+                doc.Save(transformedAppxManifest);
+            }
+
+            TransformedAppxPackagePayload = currentAppxPackagePayload.ToArray();
+            return (int)ErrorCodes.Success;
+
+        }
+
+        int CopyWin32Resources(string lpPEFileToReadResourcesFrom, string lpPEFileToInsertResourcesInto)
+        {
+
+            Process process = new Process();
+            process.StartInfo.FileName = CopyWin32ResourcesLocation ;
+            process.StartInfo.CreateNoWindow = true;
+            process.StartInfo.UseShellExecute = false;
+
+            string args = "/input:\"" + lpPEFileToReadResourcesFrom + "\" ";
+            args += "/output:\"" + lpPEFileToInsertResourcesInto + "\"";
+
+            process.StartInfo.Arguments = args;
+            string output = String.Empty;
+
+            process.Start();
+
+            bool timeOut = !process.WaitForExit(TimeoutDuration);
+
+            if (timeOut)
+            {
+                try 
+                {
+                    process.Kill();
+                }
+                catch {}
+                
+                return -1;
+            }
+
+            return process.ExitCode;
+        }
+        
+    }
+}
+
index d14f8e6..d6c9206 100644 (file)
@@ -6,7 +6,7 @@
 
   <!-- Target that builds UWP Host for CoreCLR.
   -->
-  <Target Name="Build" DependsOnTargets="BuildUWPHost" /> 
+  <Target Name="Build" DependsOnTargets="BuildUWPHost;BuildMSBuildTask" />
 
   <Target Name="BuildUWPHost" DependsOnTargets="GetLatestCommitHash">
 
@@ -34,4 +34,8 @@
     <Copy SourceFiles="@(CMakeOutput)"
           DestinationFolder="$(UWPOutputDir)"/>
   </Target>
+
+  <Target Name="BuildMSBuildTask" DependsOnTargets="GetLatestCommitHash">
+    <MSBuild Projects="$(MSBuildThisFileDirectory)Microsoft.Build.Net.CoreRuntimeTask/Microsoft.Build.Net.CoreRuntimeTask.builds" />
+  </Target>
 </Project>