1 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
4 <CrossGenDuringPublish Condition=" '$(CrossGenDuringPublish)' == '' And '$(RuntimeIdentifier)' != '' And '$(LinkDuringPublish)' == 'true' ">true</CrossGenDuringPublish>
8 <IntermediateOptimizedDirName Condition=" '$(IntermediateOptimizedDirName)' == '' ">optimized</IntermediateOptimizedDirName>
9 <IntermediateOptimizedDir Condition=" '$(IntermediateOptimizedDir)' == '' ">$(IntermediateOutputPath)$(IntermediateOptimizedDirName)</IntermediateOptimizedDir>
10 <IntermediateCrossGenDirName Condition=" '$(IntermediateCrossGenDirName)' == '' ">crossgen</IntermediateCrossGenDirName>
11 <IntermediateCrossGenDir Condition=" '$(IntermediateCrossGenDir)' == '' ">$(IntermediateOutputPath)$(IntermediateCrossGenDirName)</IntermediateCrossGenDir>
15 <ComputeCrossGenFilesToPublishAfter Condition=" '$(LinkDuringPublish)' == 'true' ">ComputeLinkedFilesToPublish</ComputeCrossGenFilesToPublishAfter>
16 <ComputeCrossGenFilesToPublishBefore Condition=" '$(LinkDuringPublish)' != 'true' ">ComputeFilesToPublish</ComputeCrossGenFilesToPublishBefore>
19 <!-- Rewrite inputs to ComputeFilesToPublish, so that crossgen'd
20 files get published instead of the pre-crossgen assemblies. -->
21 <Target Name="ComputeCrossGenFilesToPublish"
22 BeforeTargets="$(ComputeCrossGenFilesToPublishBefore)"
23 AfterTargets="$(ComputeCrossGenFilesToPublishAfter)"
24 Condition=" '$(CrossGenDuringPublish)' == 'true' "
25 DependsOnTargets="_CrossGenForPublish">
27 <!-- Rewrite ResolvedAssembliesToPublish, preserving metadata. -->
29 <_CrossGenResolvedAssembliesToPublishCandidates Include="@(ResolvedAssembliesToPublish->'$(IntermediateOptimizedDir)/%(Filename)%(Extension)')" />
30 <_CrossGenResolvedAssembliesToPublish Include="@(_CrossGenResolvedAssembliesToPublishCandidates)" Condition="Exists('%(Identity)')" />
32 <ResolvedAssembliesToPublish Remove="@(FilesToCrossGen)" />
33 <ResolvedAssembliesToPublish Include="@(_CrossGenResolvedAssembliesToPublish)" />
36 <!-- Rewrite IntermediateAssembly, preserving metadata. -->
38 <_CrossGenIntermediateAssemblyCandidates Include="@(IntermediateAssembly->'$(IntermediateOptimizedDir)/%(Filename)%(Extension)')" />
39 <_CrossGenIntermediateAssembly Include="@(_CrossGenIntermediateAssemblyCandidates)" Condition="Exists('%(Identity)')" />
40 <IntermediateAssembly Remove="@(FilesToCrossGen)" />
41 <IntermediateAssembly Include="@(_CrossGenIntermediateAssembly)" />
46 <!-- The target that runs crossgen on all input assemblies. We could
47 probably also reuse _RunCrossgen, but this gets its inputs from
48 ResolvedFileToPublish, so we would need to run crossgen after
49 ComputeFilesToPublish. -->
50 <Target Name="_CrossGenForPublish"
51 DependsOnTargets="PrepOptimizer;_ComputeCrossGenInputs">
53 <MakeDir Directories="$(IntermediateOptimizedDir)" />
56 <_CrossGenPlatformAssemblies>@(_CrossGenPlatformAssemblies)</_CrossGenPlatformAssemblies>
60 <CrossGenInvocations Include="$(MSBuildProjectFullPath)">
62 CrossGenExe=$(Crossgen);
63 CrossGenInput=%(FilesToCrossGen.FullPath);
64 CrossGenOutput=$(IntermediateOptimizedDir)/%(Filename)%(Extension);
65 CrossGenPlatformAssemblies=$(_CrossGenPlatformAssemblies)
67 </CrossGenInvocations>
70 <MSBuild Projects="@(CrossGenInvocations)"
71 Targets="RunCrossGenForPublish" />
75 <!-- Workarounds for SDK issues around the interdependency between
76 ComposeStore targets and CrossGen targets. These let us reuse
77 PrepOptimizer from the SDK to obtain a crossgen executable for
80 <!-- _RestoreCrossgen (a dependency of PrepOptimizer) requires _TFM
81 to be set, but it is only set in an unrelated target called
82 during ComposeStore (PrepareForComposeStore). -->
83 <Target Name="_SetTFMForCrossGenRestore"
84 BeforeTargets="_RestoreCrossgen"
85 Condition=" '$(CrossGenDuringPublish)' == 'true' ">
87 <_TFM Condition=" '$(_TFM)' == '' ">$(TargetFramework)</_TFM>
91 <!-- _RestoreCrossgen also requires _CrossProjAssetsFile to be
92 set. This path is computed from ComposeWorkingDir in the target
93 _GetCrossgenProps, but ComposeWorkingDir is set only in
94 store-related targets. We hook into _GetCrossgenProps to
95 specify where to restore crossgen. -->
96 <Target Name="_SetComposeWorkingDirForCrossGenRestore"
97 AfterTargets="_GetCrossgenProps"
98 Condition=" '$(CrossGenDuringPublish)' == 'true' ">
100 <_CrossProjFileDir>$([System.IO.Path]::GetFullPath($(IntermediateCrossGenDir)))</_CrossProjFileDir>
101 <_NetCoreRefDir>$([System.IO.Path]::Combine($(_CrossProjFileDir), "netcoreapp"))</_NetCoreRefDir>
102 <_CrossProjAssetsFile>$([System.IO.Path]::Combine($(_CrossProjFileDir), project.assets.json))</_CrossProjAssetsFile>
104 <MakeDir Directories="$(_CrossProjFileDir)" />
107 <!-- PrepforRestoreForComposeStore (a dependency of
108 _RestoreCrossgen) sets BaseIntermediateOutputPath and
109 ProjectAssetsFile to the compose working directory. We don't
110 want this because we are not composing a package store, so we
111 save and restore these properties. -->
112 <Target Name="_SavePropsModifiedByPrepforRestoreForComposeStore"
113 BeforeTargets="PrepforRestoreForComposeStore"
114 Condition=" '$(CrossGenDuringPublish)' == 'true' ">
116 <_SavedBaseIntermediateOutputPath>$(BaseIntermediateOutputPath)</_SavedBaseIntermediateOutputPath>
117 <_SavedProjectAssetsFile>$(ProjectAssetsFile)</_SavedProjectAssetsFile>
120 <Target Name="_RestorePropsModifiedByPrepforRestoreForComposeStore"
121 AfterTargets="PrepforRestoreForComposeStore">
123 <BaseIntermediateOutputPath>$(_SavedBaseIntermediateOutputPath)</BaseIntermediateOutputPath>
124 <ProjectAssetsFile>$(_SavedProjectAssetsFile)</ProjectAssetsFile>
128 <!-- Run crossgen on a single input assembly. -->
129 <Target Name="RunCrossGenForPublish"
130 Inputs="$(CrossGenInput);$(CrossGenPlatformAssemblies)"
131 Outputs="$(CrossGenOutput)">
133 <!-- The property CrossGenPlatformAssemblies must be
134 semicolon-delimited for incremental build to work correctly,
135 but the directory paths have to be passed with
136 platform-specific path separators in the crossgen command.
139 <_CrossGenPlatformAssemblies Include="$(CrossGenPlatformAssemblies)" />
140 <__CrossGenPlatformAssembliesPaths Include="@(_CrossGenPlatformAssemblies->'%(RootDir)%(Directory)')" />
141 <_CrossGenPlatformAssembliesPaths Include="@(__CrossGenPlatformAssembliesPaths->Distinct())" />
145 <_PathSeparator>$([System.IO.Path]::PathSeparator)</_PathSeparator>
146 <_CrossGenPlatformAssembliesPaths>@(_CrossGenPlatformAssembliesPaths, '$(_PathSeparator)')</_CrossGenPlatformAssembliesPaths>
150 <CrossGenCommand>$(CrossGenExe) -readytorun -in $(CrossGenInput) -out $(CrossGenOutput) -platform_assemblies_paths $(_CrossGenPlatformAssembliesPaths)</CrossGenCommand>
153 <Message Text="$(CrossGenCommand)" />
154 <Exec Command="$(CrossGenCommand)" />
158 <Target Name="_ComputeCrossGenInputs"
159 DependsOnTargets="_ComputeCrossGenPlatformAssemblies;_ComputeFilesToCrossGen" />
161 <!-- Compute the platform assembly paths, a parameter to crossgen
162 that lets it find dependencies of the input file. This needs to
163 include the path to the input file and its dependency closure,
164 including System.Private.CoreLib. -->
165 <Target Name="_ComputeCrossGenPlatformAssemblies"
166 DependsOnTargets="_ComputeManagedResolvedAssembliesForCrossGen">
169 <_CrossGenPlatformAssemblies Include="@(_ManagedResolvedAssembliesForCrossGen)" />
170 <_CrossGenPlatformAssemblies Include="@(IntermediateAssembly)" />
175 <!-- _ManagedResolvedAssembliesForCrossGen includes the app's
176 managed dependency closure, including System.Private.CoreLib,
177 but not the app itself or resource assemblies. -->
178 <Target Name="_ComputeManagedResolvedAssembliesForCrossGen">
179 <ComputeManagedAssemblies Assemblies="@(ResolvedAssembliesToPublish)">
180 <Output TaskParameter="ManagedAssemblies" ItemName="_ManagedResolvedAssembliesForCrossGen" />
181 </ComputeManagedAssemblies>
184 <_ManagedResolvedAssembliesForCrossGen Remove="@(_ManagedResolvedAssembliesForCrossGen->WithMetadataValue('AssetType', 'resources'))" />
188 <UsingTask TaskName="FilterByMetadata" AssemblyFile="$(LinkTaskDllPath)" />
189 <!-- This computes the default set of files that we want to be
190 crossgen'd. Some of these may already be crossgen images, and
191 these will not be crossgen'd again. The default is to crossgen
192 the app and platform libraries. Defaults will be used only if
193 FilesToCrossGen hasn't been set elsewhere, allowing users and
194 other props/targets to select what will be crossgen'd. -->
195 <Target Name="_ComputeDefaultFilesToCrossGen"
196 DependsOnTargets="_ComputeManagedResolvedAssembliesForCrossGen;_ComputePlatformLibraries"
197 Condition=" '@(FilesToCrossGen->Count())' == '0' ">
199 <FilterByMetadata Items="@(_ManagedResolvedAssembliesForCrossGen)"
200 MetadataName="Filename"
201 MetadataValues="@(PlatformLibraries->'%(Filename)')">
202 <Output TaskParameter="FilteredItems" ItemName="_PlatformLibrariesForCrossGen" />
206 <FilesToCrossGen Include="@(IntermediateAssembly)" />
207 <FilesToCrossGen Include="@(_PlatformLibrariesForCrossGen)" />
212 <UsingTask TaskName="ComputeCrossgenedAssemblies" AssemblyFile="$(LinkTaskDllPath)" />
213 <Target Name="_ComputeFilesToCrossGen"
214 DependsOnTargets="_ComputeDefaultFilesToCrossGen">
216 <ComputeCrossgenedAssemblies Assemblies="@(FilesToCrossGen)">
217 <Output TaskParameter="CrossgenedAssemblies" ItemName="_CrossgenedFiles" />
218 </ComputeCrossgenedAssemblies>
220 <!-- Don't try to run crossgen on assemblies that are already
223 <FilesToCrossGen Remove="@(_CrossgenedFiles)" />
226 <Message Text="files to crossgen: @(FilesToCrossGen)" />