-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathNuGetProj.targets
505 lines (463 loc) · 28.6 KB
/
NuGetProj.targets
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
<!--
****************************************************************************************************
Project global nuget targets.
Relevant parameters:
* NuSpecFile property:
The name of the project's nuspec file, relative to the project or with full path.
* NuSpecCreateOnMissing property:
When true and the NuSpecFile does not exists, one can be created from params defined by the project.
* NuGetContent, NuSpecMetadata, NuSpecDependency and NuSpecFrameworkAssembly item groups:
Represent the nuspec schema. See item definitions.
* NuGetContentProject: Item containing the project path and used to add Compile (source) items into
the NuGetContent collection for symbol packages.
* SourceRootFullPath: Default value for the NuGetFromProject corresponding item metadata.
* NuSpec[metadataName] property: Following this property name pattern NuSpec metadata items can be
defined in the project, a nuspec file could be fully generated this way.
* NuSpecProperties property:
NuGet supports property replacement in the nuspec file using the '$value$' token notation.
* Note: If NuSpecFile is provided and the project defines some nuspec parameters, values from both are
merged, with precedense taken by the provided parameters. This allows for parameterization of the file.
* NuGetPackOptions property:
Represents the options passed to the NuGet.exe tool in the command line.
* NuGetPackSymbols property:
Determines whether symbols package is built. Ignored if NuGetPackOptions is defined.
* NuGetOutputPath property:
Represents the directory where the package is to be created.
* NuSpecSchemaVersion: represents the nuspec file xml schema version.
****************************************************************************************************-->
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(CustomBeforeNuGetProjTargets)" Condition="Exists('$(CustomBeforeNuGetProjTargets)')"/>
<PropertyGroup>
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
<OutputPath Condition="'$(OutputPath)' == ''">bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath Condition="'$(IntermediateOutputPath)' == ''">obj\$(Configuration)\</IntermediateOutputPath>
<IntermediateOutputPath Condition="'$(NuGetPackageLanguage)' != ''">$(IntermediateOutputPath)$(NuGetPackageLanguage)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup>
<!-- The NuGet package name inlcudes the nusepc id and version which are ultimately taken from the NuSpec file. -->
<!-- The nuspec metadata is usually specified in the nuspec file (if provided). When NuSpec<metaName> props are specified they overwrite the nuspec items. -->
<!-- NuGetPackageID and NuSpecID should have the same value, the former is kept for legacy reasons (same for version properties). -->
<NuSpecId Condition="'$(NuSpecId)' == ''">$(MSBuildProjectName)</NuSpecId>
<NuGetPackageId Condition="'$(NuGetPackageId)' == ''">$(NuSpecId)</NuGetPackageId>
<NuGetPackageVersion Condition="'$(NuGetPackageVersion)' == ''">$(NuSpecVersion)</NuGetPackageVersion>
<NuSpecVersion Condition="'$(NuSpecVersion)' == ''">$(NuGetPackageVersion)</NuSpecVersion>
</PropertyGroup>
<PropertyGroup>
<NuSpecSchemaVersion Condition="'$(NuSpecSchemaVersion)' == ''">2</NuSpecSchemaVersion>
<NuGetPackSymbols Condition="'$(NuGetPackOptions.ToLower().Contains(symbols))'">true</NuGetPackSymbols>
<NuGetPackSymbols Condition="'$(NuGetPackSymbols)' == ''">false</NuGetPackSymbols>
<NuSpecFile Condition="'$(NuSpecFile)' == ''">$(MSBuildProjectDirectory)\$(NuGetPackageId).nuspec</NuSpecFile>
<NuSpecFileName>$([System.IO.Path]::GetFileName('$(NuSpecFile)'))</NuSpecFileName>
<NuSpecCreateOnMissing Condition="'$(NuSpecCreateOnMissing)' == ''">true</NuSpecCreateOnMissing>
<NuGetProjectOutputsFile>$(IntermediateOutputPath)$(NuGetPackageId).outputs</NuGetProjectOutputsFile>
</PropertyGroup>
<PropertyGroup Label="NuGet.targets inputs">
<NuGetExePath Condition="!Exists('$(NuGetExePath)')">$([MSBuild]::GetDirectoryNameOfFileAbove('$(MSBuildThisFileFullPath)', '.nuget\nuget.targets'))\.nuget\NuGet.exe</NuGetExePath>
<NuGetInstallPath>$([System.IO.Path]::GetDirectoryName('$(NuGetExePath)'))</NuGetInstallPath>
<PackageOutputDir Condition="'$(NuGetOutputPath)' != ''">$(NuGetOutputPath)</PackageOutputDir>
<PackageOutputDir Condition="'$(PackageOutputDir)' == ''">$(OutputPath)NuGet</PackageOutputDir>
<PackageOutputDir>$(PackageOutputDir.TrimEnd('\'))</PackageOutputDir>
<NuGetOutputPath Condition="'$(NuGetOutputPath)' == ''">$(PackageOutputDir)</NuGetOutputPath>
<ProjectPath>$(IntermediateOutputPath)$(NuSpecFileName)</ProjectPath>
</PropertyGroup>
<PropertyGroup>
<CodeTaskFactoryAssemblyFile Condition=" '$(CodeTaskFactoryAssemblyFile)' == '' And '$(MSBuildToolsVersion)' == '12.0' ">$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll</CodeTaskFactoryAssemblyFile>
<CodeTaskFactoryAssemblyFile Condition=" '$(CodeTaskFactoryAssemblyFile)' == '' ">$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll</CodeTaskFactoryAssemblyFile>
</PropertyGroup>
<PropertyGroup>
<!--Force a rebuild if this file is changed -->
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath);$(MSBuildProjectFullPath)</MSBuildAllProjects>
</PropertyGroup>
<!--
NuGet package layout conventions http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package#Package_Conventions
NuSpec metadata schema https://nuget.codeplex.com/wikipage?title=.nuspec%20v1.2%20Format
-->
<ItemDefinitionGroup>
<!-- NuGetContent represents the files to be packed (dll, exe, pdb, .cs, content, etc). -->
<NuGetContent>
<Source>$(NuGetContentSource)</Source>
<Destination>$(NuGetContentDestination)</Destination>
</NuGetContent>
<!-- NuSpecMetadata represents the simple items under the 'metadata' schema element (title, version, etc.) -->
<NuSpecMetadata>
<Value/>
</NuSpecMetadata>
<!-- NuSpecDependency represents the child element of the complex 'metadata/dependencies' schema element. -->
<NuSpecDependency>
<Version/>
<TargetFramework/>
</NuSpecDependency>
<!-- NuSpecFrameworkAssembly represents the child element of the complex 'metadata/frameworkAssemblies' schema element. -->
<NuSpecFrameworkAssembly>
<TargetFramework/>
</NuSpecFrameworkAssembly>
</ItemDefinitionGroup>
<!--
NuGetContentFromProject: Defines content from the Compile item collection (source files) from projects into the NuGetContent item.
-->
<ItemDefinitionGroup>
<NuGetContentProject>
<SourceRootFullPath>$(SourceRootFullPath)</SourceRootFullPath>
<Destination>src</Destination>
</NuGetContentProject>
</ItemDefinitionGroup>
<ItemGroup>
<!-- NuSpec file added by default. -->
<NuGetContent Include="$(ProjectPath)" />
</ItemGroup>
<!-- Optional NuSpec file metadata items. When provided, items are used for generating the final nuspec file. -->
<!-- http://docs.nuget.org/docs/reference/nuspec-reference -->
<ItemGroup>
<NuSpecMetadata Include="id" Condition="'$(NuSpecId)' != ''">
<Value>$(NuSpecId)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="version" Condition="'$(NuSpecVersion)' != ''">
<Value>$(NuSpecVersion)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="title" Condition="'$(NuSpecTitle)' != ''">
<Value>$(NuSpecTitle)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="authors" Condition="'$(NuSpecAuthors)' != ''">
<Value>$(NuSpecAuthors)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="owners" Condition="'$(NuSpecOwners)' != ''">
<Value>$(NuSpecOwners)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="description" Condition="'$(NuSpecDescription)' != ''">
<Value>$(NuSpecDescription)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="tags" Condition="'$(NuSpecTags)' != ''">
<Value>$(NuSpecTags)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="iconUrl" Condition="'$(NuSpecIconUrl)' != ''">
<Value>$(NuSpecIconUrl)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="projectUrl" Condition="'$(NuSpecProjectUrl)' != ''">
<Value>$(NuSpecProjectUrl)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="licenseUrl" Condition="'$(NuSpecLicenseUrl)' != ''">
<Value>$(NuSpecLicenseUrl)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="copyright" Condition="'$(NuSpecCopyright)' != ''">
<Value>$(NuSpecCopyright)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="requireLicenseAcceptance" Condition="'$(NuSpecRequireLicenseAcceptance)' != ''">
<Value>$(NuSpecRequireLicenseAcceptance)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="releaseNotes" Condition="'$(NuSpecReleaseNotes)' != ''">
<Value>$(NuSpecReleaseNotes)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="summary" Condition="'$(NuSpecSummary)' != ''">
<Value>$(NuSpecSummary)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="developmentDependency" Condition="'$(NuSpecDevelopmentDependency)' != ''">
<Value>$(NuSpecDevelopmentDependency)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="language" Condition="'$(NuSpecLanguage)' != ''">
<Value>$(NuSpecLanguage)</Value>
</NuSpecMetadata>
</ItemGroup>
<ItemGroup>
<Clean Include="$(NuGetProjectOutputsFile)" />
</ItemGroup>
<!--
****************************************************************************************************
Common build targets overwrites.
**************************************************************************************************** -->
<PropertyGroup>
<BuildDependsOn>BeforeBuild;GetNuGetContentFromProject;ValidateNuGetParams;ReadNuGetCleanOutputs;GetNuGetProjectInputs;GetNuGetProjectOutputs;ValidateOutputs;NuGetPack;WriteNuGetProjectOutputs;AfterBuild</BuildDependsOn>
<CleanDependsOn>BeforeClean;ReadNuGetCleanOutputs;CoreClean;AfterClean</CleanDependsOn>
<RebuildDependsOn>Clean;Build</RebuildDependsOn>
</PropertyGroup>
<Target Name="BeforeBuild">
<ItemGroup>
<NuGetContent Remove="@(NuGetContent)"/>
</ItemGroup>
</Target>
<Target Name="Build" DependsOnTargets="$(BuildDependsOn)" />
<Target Name="AfterBuild" />
<Target Name="BeforeClean" />
<Target Name="Clean" DependsOnTargets="$(CleanDependsOn)"/>
<Target Name="AfterClean" />
<Target Name="CoreClean">
<Delete Files="@(Clean)" />
<ItemGroup>
<Clean Remove="@(Clean)" />
</ItemGroup>
</Target>
<Target Name="Rebuild" DependsOnTargets="$(RebuildDependsOn)" />
<!--
****************************************************************************************************
GetNuGetContentFromProject: Gets Compile item collection (source files) from projects into the NuGetContent item.
Input: NuGetContentProject and SourceRootFullPath
**************************************************************************************************** -->
<Target Name="GetNuGetContentFromProject" Condition="'@(NuGetContentProject)' != ''">
<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="GetNuGetContentFromProjectCore"
Properties="NuGetContentProject=%(NuGetContentProject.FullPath);SourceRootFullPath=%(SourceRootFullPath);Destination=%(Destination)" >
<Output TaskParameter="TargetOutputs" ItemName="NuGetContent" />
</MSBuild>
</Target>
<Target Name="GetNuGetContentFromProjectCore" Outputs="@(NuGetContent)">
<Error Condition="'$(SourceRootFullPath)' == ''" Text="NuGetContentProject item does not define 'SourceRootFullPath' metadata: $(NuGetContentProject)" />
<PropertyGroup>
<!-- Normalize path (remove extra back-slashes and trim) -->
<SourceRootFullPath>$([System.IO.Path]::GetFullPath($(SourceRootFullPath)))</SourceRootFullPath>
</PropertyGroup>
<MSBuild Projects="$(NuGetContentProject)" Targets="GetCompile" RebaseOutputs="true">
<Output TaskParameter="TargetOutputs" ItemName="Compile" />
</MSBuild>
<ItemGroup>
<NugetContent Include="%(Compile.FullPath)" Condition="$([System.String]::Concat(%(FullPath)).ToLower().Contains($(SourceRootFullPath.ToLower())))">
<Destination>$([System.IO.Path]::Combine($(Destination), $([MSBuild]::MakeRelative($([System.IO.Path]::GetFullPath($(SourceRootFullPath))), %(Compile.RootDir)%(Directory)))))</Destination>
</NugetContent>
</ItemGroup>
</Target>
<!--
****************************************************************************************************
ValidateNuGetParams: validate input params.
****************************************************************************************************-->
<Target Name="ValidateNuGetParams">
<ItemGroup>
<PropMismatch Include="NuSpecID=$(NuSpecID) and NuGetPackageID=$(NuGetPackageID)"
Condition="'$(NuSpecId)' != '' AND '$(NuGetPackageID)' != '' AND '$(NuSpecId)' != '$(NuGetPackageID)'" />
<PropMismatch Include="NuSpecVersion=$(NuSpecVersion) and NuGetPackageVersion=$(NuGetPackageVersion)"
Condition="'$(NuSpecVersion)' != '' AND '$(NuGetPackageVersion)' != '' AND '$(NuSpecVersion)' != '$(NuGetPackageVersion)'" />
</ItemGroup>
<Warning Text="No content was specified " Condition="'@(NuGetContent)' == '' AND '$(DisableNoNuGetContentWarning)' != 'true'" />
<Error Text="@(PropMismatch -> '%(Identity) are different, this is an indication of an authoring error!', '%0A')" Condition="'@(PropMismatch)' != ''" />
<Error Text="Could not find nuspec file: $(NuSpecFile)" Condition="!Exists('$(NuSpecFile)') AND '$(NuSpecCreateOnMissing)' == 'false'" />
</Target>
<!--
****************************************************************************************************
ValidateOutputs: checks whether outputs are up-to-date with respect to the inputs to avoid rebuilding
if not needed and play nicely when building incrementally.
**************************************************************************************************** -->
<Target Name="ValidateOutputs" Inputs="@(NuGetProjectInput);$(MSBuildAllProjects)" Outputs="@(NuGetProjectOutput)">
<CreateProperty Value="true">
<Output TaskParameter="ValueSetByTask" PropertyName="OutputsOutdated"/>
</CreateProperty>
</Target>
<!--
****************************************************************************************************
NuGetPack: Creates a nuget package.
**************************************************************************************************** -->
<Target Name="NuGetPack" DependsOnTargets="GenerateNuSpecFile" Condition="'$(OutputsOutdated)' == 'true'">
<ItemGroup>
<!-- Normalize comman-separated property string (removes new lines and trims string)-->
<NuSpecProperties Include="$(NuSpecProperties)" />
</ItemGroup>
<PropertyGroup>
<NuSpecProperties>@(NuSpecProperties)</NuSpecProperties>
<NuGetPackOptions Condition="'$(NuGetPackOptions)' == '' AND '$(NuGetPackSymbols)' != 'true'">-NoPackageAnalysis</NuGetPackOptions>
<NuGetPackOptions Condition="'$(NuGetPackOptions)' == '' AND '$(NuGetPackSymbols)' == 'true'">-NoPackageAnalysis -Symbols -SymbolPackageFormat snupkg</NuGetPackOptions>
<!-- BuildCommand is defined in nuget.targets file -->
<BuildCommand>$(BuildCommand.Replace('-symbols', ''))</BuildCommand>
<BuildCommand>$(BuildCommand.Replace('/symbols', ''))</BuildCommand>
<BuildCommand Condition="'$(NuSpecProperties)' != ''">$(BuildCommand) -Properties "$(NuSpecProperties)"</BuildCommand>
<BuildCommand Condition="'$(NuGetPackOptions)' != ''">$(BuildCommand) $(NuGetPackOptions)</BuildCommand>
</PropertyGroup>
<!-- Invalidate outputs to force a full build in case of failure -->
<Delete Files="$(NuGetPackTargetFile)" />
<MakeDir Directories="$(PackageOutputDir)" />
<Exec Command="$(BuildCommand)" StandardOutputImportance="high" StandardErrorImportance="high" WorkingDirectory="$(MSBuildProjectDirectory)" CustomErrorRegularExpression="invalid"/>
<ItemGroup>
<Clean Include="$(PackageOutputDir)\$(NuGetPackageId).$(NuGetPackageVersion)*.nupkg" />
</ItemGroup>
<!-- This target can fail preventing outputs file from being updated, neet to account for that. -->
<OnError ExecuteTargets="WriteNuGetProjectOutputs" />
</Target>
<!--
****************************************************************************************************
GetNuGetProjectInputs: get the project inputs.
**************************************************************************************************** -->
<Target Name="GetNuGetProjectInputs">
<NormalizeNuGetContent NuGetContent="@(NuGetContent)">
<Output TaskParameter="NuGetContentNormalized" ItemName="NuGetProjectInput" />
</NormalizeNuGetContent>
</Target>
<!--
****************************************************************************************************
GetNuGetProjectOutputs: Reads build-generated files from outputs file.
**************************************************************************************************** -->
<Target Name="GetNuGetProjectOutputs">
<PropertyGroup>
<NuGetPackTargetFile>$(PackageOutputDir)\$(NuGetPackageId).$(NuGetPackageVersion).nupkg</NuGetPackTargetFile>
<NuGetSymbolPackTargetFile Condition="'$(NuGetPackSymbols)' == 'true'">$(PackageOutputDir)\$(NuGetPackageId).$(NuGetPackageVersion).symbols.nupkg</NuGetSymbolPackTargetFile>
</PropertyGroup>
<ItemGroup>
<NuGetProjectOutput Include="$(NuGetPackTargetFile)" />
<NuGetProjectOutput Include="$(NuGetSymbolPackTargetFile)" Condition="'$(NuGetSymbolPackTargetFile)' != ''" />
<NuGetProjectOutput Include="$(NuGetProjectOutputsFile)" />
</ItemGroup>
</Target>
<!--
****************************************************************************************************
ReadNuGetCleanOutputs: Reads build-generated files from outputs file into Clean item collection to
get them re-written into outputs file so they can be cleaned up later.
**************************************************************************************************** -->
<Target Name="ReadNuGetCleanOutputs">
<ReadLinesFromFile File="$(NuGetProjectOutputsFile)">
<Output TaskParameter="Lines" ItemName="Clean" />
</ReadLinesFromFile>
</Target>
<!--
****************************************************************************************************
WriteNuGetProjectOutputs: write the list of build-generated files into outputs file which is used for
cleaning and incremental build.
**************************************************************************************************** -->
<Target Name="WriteNuGetProjectOutputs" Condition="'$(OutputsOutdated)' == 'true'">
<ItemGroup>
<NuGetProjectOutput Include="@(Clean->Distinct())" />
</ItemGroup>
<WriteLinesToFile File="$(NuGetProjectOutputsFile)" Lines="@(NuGetProjectOutput->Distinct())" Overwrite="true" Condition="'@(NuGetProjectOutput)' != ''" />
</Target>
<!--
****************************************************************************************************
GenerateNuSpecFile: generates the final nuspec file for the package.
**************************************************************************************************** -->
<Target Name="GenerateNuSpecFile" DependsOnTargets="GetNuGetProjectInputs" Condition="'$(OutputsOutdated)' == 'true'">
<GenerateNuSpecFile NuSpecFile="$(NuSpecFile)" OutputDir="$(IntermediateOutputPath)" CreateNuSpec="$(NuSpecCreateOnMissing)" MetadataItems="@(NuSpecMetadata)"
Files="@(NuGetProjectInput);@(NuGetContentFromPdb)" FrameworkAssemblies="@(NuSpecFrameworkAssembly)" Dependencies="@(NuSpecDependency)" SchemaVersion="$(NuSpecSchemaVersion)">
<Output TaskParameter="GeneratedNuSpec" PropertyName="GeneratedNuSpec" />
</GenerateNuSpecFile>
<ItemGroup>
<Clean Include="$(GeneratedNuSpec)" />
</ItemGroup>
<Message Text="Generated NuSpec file: $(GeneratedNuSpec)" />
</Target>
<!--
==================================================================================================
Generates final nuspec file combining/replacing values from project nuspec file if provided.
==================================================================================================-->
<UsingTask TaskName="GenerateNuSpecFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(CodeTaskFactoryAssemblyFile)">
<ParameterGroup>
<NuSpecFile Required="true" ParameterType="System.String" />
<MetadataItems Required="false" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
<Files Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
<FrameworkAssemblies Required="false" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
<Dependencies Required="false" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
<OutputDir Required="true" ParameterType="System.String" />
<CreateNuSpec Required="false" ParameterType="System.Boolean" />
<SchemaVersion Required="true" ParameterType="System.Int32" />
<GeneratedNuSpec Output="true" ParameterType="System.String" />
</ParameterGroup>
<Task>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Using Namespace="System.Linq" />
<Using Namespace="System.IO" />
<Using Namespace="System.Xml.Linq" />
<Code Type="Fragment" Language="cs">
<![CDATA[
XElement packageNode = null;
if (File.Exists(NuSpecFile)) {
packageNode = XElement.Load(NuSpecFile);
} else {
if (!CreateNuSpec) { Log.LogError("NuSpec file does not exist: {0}", NuSpecFile); return false; }
if(SchemaVersion > 1) {
XNamespace pkgNs = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd";
packageNode = new XElement(pkgNs + "package", new XElement("metadata", new XAttribute("schemaVersion", SchemaVersion)));
} else {
packageNode = new XElement("package", new XElement("metadata"));
}
}
GeneratedNuSpec = Path.GetFullPath(Path.Combine(OutputDir, Path.GetFileName(NuSpecFile)));
if (File.Exists(GeneratedNuSpec)) File.Delete(GeneratedNuSpec);
XNamespace ns = packageNode.Name.Namespace;
if(packageNode.Name.LocalName != "package") { Log.LogError("NuSpec file missing 'package' schema element. Found:'{0}'", packageNode.Name.LocalName); return false; };
if (Files == null) Files = new TaskItem[] { };
if (Dependencies == null) Dependencies = new TaskItem[] { };
if (MetadataItems == null) MetadataItems = new TaskItem[] { };
if (FrameworkAssemblies == null) FrameworkAssemblies = new TaskItem[] { };
// replace/add simple metadata.
XElement metadataNode = packageNode.FirstNode as XElement;
if(metadataNode == null) { Log.LogError("NuSpec file missing 'metadata' schema element"); return false; };
foreach (var metaItem in MetadataItems) {
string name = metaItem.GetMetadata("Identity");
string value = metaItem.GetMetadata("Value");
XElement xnode = metadataNode.Descendants(ns + name).FirstOrDefault<XElement>();
if (xnode == null) { xnode = new XElement(name); metadataNode.Add(xnode); }
xnode.Value = value;
}
// replaceable values for dependencies and frameworkassemblies - just replace the whole node.
var removeQ1 = from dependencyNode in packageNode.Descendants(ns + "dependency").Attributes("id")
from dependencyItem in Dependencies
where dependencyItem.GetMetadata("Identity").ToLower().Equals(dependencyNode.Value.ToLower())
select dependencyNode.Parent;
var removeQ2 = from assemblyNode in packageNode.Descendants(ns + "frameworkAssembly").Attributes("assemblyName")
from assemblyItem in FrameworkAssemblies
where assemblyItem.GetMetadata("Identity").ToLower().Equals(assemblyNode.Value.ToLower())
select assemblyNode.Parent;
foreach (var node in removeQ1.ToArray<XElement>()) node.Remove();
foreach (var node in removeQ2.ToArray<XElement>()) node.Remove();
XElement filesNode = packageNode.Descendants(ns + "files").FirstOrDefault<XElement>();
if (filesNode == null) {
filesNode = new XElement("files");
packageNode.Add(filesNode);
}
filesNode.Add(from fi in Files select new XElement("file", new XAttribute("src", fi.GetMetadata("FullPath")), new XAttribute("target", fi.GetMetadata("Destination"))));
XElement frameworkAssembliesNode = packageNode.Descendants(ns + "frameworkAssemblies").FirstOrDefault<XElement>();
if (frameworkAssembliesNode == null) {
frameworkAssembliesNode = new XElement("frameworkAssemblies");
metadataNode.Add(frameworkAssembliesNode);
}
frameworkAssembliesNode.Add(from assembly in FrameworkAssemblies select new XElement("frameworkAssembly",
new XAttribute("assemblyName", assembly.GetMetadata("Identity")), new XAttribute("targetFramework", assembly.GetMetadata("TargetFramework"))));
XElement dependenciesNode = packageNode.Descendants(ns + "dependencies").FirstOrDefault<XElement>();
if (dependenciesNode == null) {
dependenciesNode = new XElement("dependencies");
metadataNode.Add(dependenciesNode);
}
if(SchemaVersion > 1) {
var depGroupsQ = from dp in Dependencies group dp by dp.GetMetadata("TargetFramework");
foreach (var dpGroup in depGroupsQ) {
XElement depGroupNode = new XElement("group");
string targetFx = dpGroup.First().GetMetadata("TargetFramework");
if(!string.IsNullOrEmpty(targetFx)) depGroupNode.Add(new XAttribute("targetFramework", dpGroup.First().GetMetadata("TargetFramework")));
foreach(var depItem in dpGroup) {
XElement dependencyNode = new XElement("dependency", new XAttribute("id", depItem.GetMetadata("Identity")), new XAttribute("version", depItem.GetMetadata("Version")));
depGroupNode.Add(dependencyNode);
}
dependenciesNode.Add(depGroupNode);
}
} else {
dependenciesNode.Add(from dp in Dependencies select new XElement("dependency", new XAttribute("id", dp.GetMetadata("Identity")), new XAttribute("version", dp.GetMetadata("Version"))));
}
if (!Directory.Exists(OutputDir)) Directory.CreateDirectory(OutputDir);
packageNode.Save(GeneratedNuSpec);
]]>
</Code>
</Task>
</UsingTask>
<!--
****************************************************************************************************
NormalizeNuGetContent: Normalize NuGetContent items full path and destination for packing.
****************************************************************************************************-->
<UsingTask TaskName="NormalizeNuGetContent" TaskFactory="CodeTaskFactory" AssemblyFile="$(CodeTaskFactoryAssemblyFile)">
<ParameterGroup>
<NuGetContent Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
<NuGetContentNormalized Output="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
</ParameterGroup>
<Task>
<Using Namespace="System.IO" />
<Code Type="Fragment" Language="cs">
<![CDATA[
NuGetContentNormalized = new TaskItem[NuGetContent.Length];
for (int idx = 0; idx < NuGetContent.Length; idx++) {
string src = NuGetContent[idx].GetMetadata("Source");
string id = NuGetContent[idx].GetMetadata("Identity");
if (!string.IsNullOrEmpty(src) && !Path.IsPathRooted(id)) {
NuGetContentNormalized[idx] = new TaskItem(Path.Combine(src, id));
}
else {
NuGetContentNormalized[idx] = new TaskItem(NuGetContent[idx].GetMetadata("FullPath"));
}
NuGetContentNormalized[idx].SetMetadata("Destination", NuGetContent[idx].GetMetadata("Destination"));
}
]]>
</Code>
</Task>
</UsingTask>
<Import Project="$(NuGetInstallPath)\nuget.targets" />
<Import Project="$(CustomAfterNuGetProjTargets)" Condition="Exists('$(CustomAfterNuGetProjTargets)')"/>
</Project>