<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>
--- /dev/null
+<?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>
--- /dev/null
+<?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)' > 0" Text="$(_WireUpCoreRuntimeMsg)" />
+ </Target>
+</Project>
--- /dev/null
+<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>
--- /dev/null
+<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>
--- /dev/null
+<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>
+++ /dev/null
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <UseAppLocalCoreCLR>true</UseAppLocalCoreCLR>
- </PropertyGroup>
-</Project>
\ No newline at end of file
+++ /dev/null
-<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)' <= '10.0.15063.0'" />
- </Target>
-</Project>
\ No newline at end of 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>
<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>
--- /dev/null
+// 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
+
+}
--- /dev/null
+// 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;
+ }
+ }
+ }
+}
--- /dev/null
+// 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));
+ }
+
+ }
+}
--- /dev/null
+<?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
--- /dev/null
+<?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>
--- /dev/null
+// 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;
+ }
+
+ }
+}
--- /dev/null
+//------------------------------------------------------------------------------
+// <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 "{0}".
+ /// </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 '{0}'.
+ /// </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 "{0}" 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 "{0}": {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 "{0}" doesn't exist: "{1}".
+ /// </summary>
+ internal static string Message_CachedReswNotExists {
+ get {
+ return ResourceManager.GetString("Message_CachedReswNotExists", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Cached ResW "{0}" 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 "{0}" 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: "{0}".
+ /// </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 "{0}". 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 "{0}" for "{1}".
+ /// </summary>
+ internal static string Message_UsingCachedResw {
+ get {
+ return ResourceManager.GetString("Message_UsingCachedResw", resourceCulture);
+ }
+ }
+ }
+}
--- /dev/null
+<?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
--- /dev/null
+// 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;
+ }
+
+ }
+}
+
<!-- Target that builds UWP Host for CoreCLR.
-->
- <Target Name="Build" DependsOnTargets="BuildUWPHost" />
+ <Target Name="Build" DependsOnTargets="BuildUWPHost;BuildMSBuildTask" />
<Target Name="BuildUWPHost" DependsOnTargets="GetLatestCommitHash">
<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>