Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix pack targets to add tfm metadata to output lib files #1255

Merged
merged 1 commit into from
Mar 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public interface IPackTaskRequest<TItem>
string AssemblyName { get; }
TItem[] AssemblyReferences { get; }
string[] Authors { get; }
TItem[] BuildOutputInPackage { get; }
string BuildOutputFolder { get; }
string[] ContentTargetFolders { get; }
bool ContinuePackingAfterGeneratingNuspec { get; }
Expand Down Expand Up @@ -53,8 +54,7 @@ public interface IPackTaskRequest<TItem>
TItem[] SourceFiles { get; }
string[] Tags { get; }
string[] TargetFrameworks { get; }
string[] TargetPathsToAssemblies { get; }
string[] TargetPathsToSymbols { get; }
TItem[] TargetPathsToSymbols { get; }
string Title { get; }
}
}
64 changes: 54 additions & 10 deletions src/NuGet.Core/NuGet.Build.Tasks.Pack.Library/Pack.targets
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ Copyright (c) .NET Foundation. All rights reserved.
<_TargetFrameworks Condition="'$(TargetFramework)' == ''" Include="$(TargetFrameworks.Split(';'))"/>
<_TargetFrameworks Condition="'$(TargetFramework)' != ''" Include="$(TargetFramework)"/>
</ItemGroup>
<ItemDefinitionGroup>
<BuildOutputInPackage>
<TargetFramework>$(TargetFramework)</TargetFramework>
</BuildOutputInPackage>
<TfmSpecificPackageFile>
<BuildAction>None</BuildAction>
</TfmSpecificPackageFile>
</ItemDefinitionGroup>

<!--
============================================================
Expand Down Expand Up @@ -93,8 +101,8 @@ Copyright (c) .NET Foundation. All rights reserved.
<NuGetPackInput Include="$(MSBuildAllProjects)"/>
<NuGetPackInput Include="@(_PackageFiles)"/>
<NuGetPackInput Include="@(_PackageFilesToExclude)"/>
<NuGetPackInput Include="@(_TargetPathsToAssemblies->'%(FinalOutputPath)')"/>
<NuGetPackInput Include="@(_TargetPathsToSymbols)"/>
<NuGetPackInput Include="@(_BuildOutputInPackage->'%(FinalOutputPath)')"/>
<NuGetPackInput Include="@(_TargetPathsToSymbols->'%(FinalOutputPath)')"/>
<NuGetPackInput Include="@(_SourceFiles)"/>
<NuGetPackInput Include="@(_References)"/>
<NuGetPackOutput Include="$(RestoreOutputAbsolutePath)$(PackageId).$(PackageVersion).nuspec"/>
Expand Down Expand Up @@ -144,7 +152,7 @@ Copyright (c) .NET Foundation. All rights reserved.
IconUrl="$(PackageIconUrl)"
ReleaseNotes="$(PackageReleaseNotes)"
Tags="$(PackageTags)"
TargetPathsToAssemblies="@(_TargetPathsToAssemblies->'%(FinalOutputPath)')"
BuildOutputInPackage="@(_BuildOutputInPackage)"
TargetPathsToSymbols="@(_TargetPathsToSymbols)"
TargetFrameworks="@(_TargetFrameworks)"
AssemblyName="$(AssemblyName)"
Expand Down Expand Up @@ -193,21 +201,30 @@ Copyright (c) .NET Foundation. All rights reserved.
<MSBuild
Condition="'$(IncludeBuildOutput)' == 'true'"
Projects="$(MSBuildProjectFullPath)"
Targets="BuiltProjectOutputGroup;DocumentationProjectOutputGroup;_AddPriFileToPackBuildOutput"
Properties="TargetFramework=%(_TargetFrameworks.Identity);
BuildProjectReferences=false;">
Targets="_GetBuildOutputFilesWithTfm"
Properties="TargetFramework=%(_TargetFrameworks.Identity);">

<Output
TaskParameter="TargetOutputs"
ItemName="_TargetPathsToAssemblies" />
ItemName="_BuildOutputInPackage" />
</MSBuild>

<MSBuild
Condition="'$(TargetsForTfmSpecificContentInPackage)' != ''"
Projects="$(MSBuildProjectFullPath)"
Targets="_GetTfmSpecificContentForPackage"
Properties="TargetFramework=%(_TargetFrameworks.Identity);">

<Output
TaskParameter="TargetOutputs"
ItemName="_PackageFiles"/>
</MSBuild>

<MSBuild
Condition="'$(IncludeSymbols)' == 'true' OR '$(IncludeSource)' == 'true'"
Projects="$(MSBuildProjectFullPath)"
Targets="DebugSymbolsProjectOutputGroup"
Properties="TargetFramework=%(_TargetFrameworks.Identity);
BuildProjectReferences=false;">
Targets="_GetDebugSymbolsWithTfm"
Properties="TargetFramework=%(_TargetFrameworks.Identity);">

<Output
TaskParameter="TargetOutputs"
Expand All @@ -227,6 +244,32 @@ Copyright (c) .NET Foundation. All rights reserved.
</MSBuild>
</Target>

<Target Name="_GetBuildOutputFilesWithTfm"
DependsOnTargets="BuiltProjectOutputGroup;DocumentationProjectOutputGroup;SatelliteDllsProjectOutputGroup;_AddPriFileToPackBuildOutput;$(TargetsForTfmSpecificBuildOutput)"
Returns="@(BuildOutputInPackage)">
<ItemGroup>
<BuildOutputInPackage Include="@(SatelliteDllsProjectOutputGroupOutput);
@(BuiltProjectOutputGroupOutput);
@(DocumentationProjectOutputGroupOutput);
@(_PathToPriFile)"/>
</ItemGroup>
</Target>

<Target Name="_GetTfmSpecificContentForPackage"
DependsOnTargets="$(TargetsForTfmSpecificContentInPackage)"
Returns="@(TfmSpecificPackageFile)">
</Target>

<Target Name="_GetDebugSymbolsWithTfm"
DependsOnTargets="DebugSymbolsProjectOutputGroup"
Returns="@(_TargetPathsToSymbolsWithTfm)">
<ItemGroup>
<_TargetPathsToSymbolsWithTfm Include="@(DebugSymbolsProjectOutputGroupOutput)">
<TargetFramework>$(TargetFramework)</TargetFramework>
</_TargetPathsToSymbolsWithTfm>
</ItemGroup>
</Target>

<!--Projects with target framework like UWP, Win8, wpa81 produce a Pri file
in their bin dir. This Pri file is not included in the BuiltProjectGroupOutput, and
has to be added manually here.-->
Expand All @@ -235,6 +278,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<ItemGroup Condition="'$(IncludeProjectPriFile)' == 'true'">
<_PathToPriFile Include="$(ProjectPriFullPath)">
<FinalOutputPath>$(ProjectPriFullPath)</FinalOutputPath>
<TargetPath>$(ProjectPriFileName)</TargetPath>
</_PathToPriFile>
</ItemGroup>
</Target>
Expand Down
8 changes: 4 additions & 4 deletions src/NuGet.Core/NuGet.Build.Tasks.Pack.Library/PackTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class PackTask : Microsoft.Build.Utilities.Task, IPackTaskRequest<ITaskIt
public ITaskItem[] PackageFilesToExclude { get; set; }
public string[] TargetFrameworks { get; set; }
public string[] PackageTypes { get; set; }
public ITaskItem[] BuildOutputInPackage { get; set; }
public string PackageId { get; set; }
public string PackageVersion { get; set; }
public string Title { get; set; }
Expand All @@ -30,8 +31,7 @@ public class PackTask : Microsoft.Build.Utilities.Task, IPackTaskRequest<ITaskIt
public string IconUrl { get; set; }
public string[] Tags { get; set; }
public string ReleaseNotes { get; set; }
public string[] TargetPathsToAssemblies { get; set; }
public string[] TargetPathsToSymbols { get; set; }
public ITaskItem[] TargetPathsToSymbols { get; set; }
public string AssemblyName { get; set; }
public string PackageOutputPath { get; set; }
public bool IsTool { get; set; }
Expand Down Expand Up @@ -110,6 +110,7 @@ private IPackTaskRequest<IMSBuildItem> GetRequest()
AssemblyName = MSBuildStringUtility.TrimAndGetNullForEmpty(AssemblyName),
AssemblyReferences = MSBuildUtility.WrapMSBuildItem(AssemblyReferences),
Authors = MSBuildStringUtility.TrimAndExcludeNullOrEmpty(Authors),
BuildOutputInPackage = MSBuildUtility.WrapMSBuildItem(BuildOutputInPackage),
BuildOutputFolder = MSBuildStringUtility.TrimAndGetNullForEmpty(BuildOutputFolder),
ContinuePackingAfterGeneratingNuspec = ContinuePackingAfterGeneratingNuspec,
ContentTargetFolders = MSBuildStringUtility.TrimAndExcludeNullOrEmpty(ContentTargetFolders),
Expand Down Expand Up @@ -145,8 +146,7 @@ private IPackTaskRequest<IMSBuildItem> GetRequest()
SourceFiles = MSBuildUtility.WrapMSBuildItem(SourceFiles),
Tags = MSBuildStringUtility.TrimAndExcludeNullOrEmpty(Tags),
TargetFrameworks = MSBuildStringUtility.TrimAndExcludeNullOrEmpty(TargetFrameworks),
TargetPathsToAssemblies = MSBuildStringUtility.TrimAndExcludeNullOrEmpty(TargetPathsToAssemblies),
TargetPathsToSymbols = MSBuildStringUtility.TrimAndExcludeNullOrEmpty(TargetPathsToSymbols),
TargetPathsToSymbols = MSBuildUtility.WrapMSBuildItem(TargetPathsToSymbols),
Title = MSBuildStringUtility.TrimAndGetNullForEmpty(Title),
};
}
Expand Down
61 changes: 45 additions & 16 deletions src/NuGet.Core/NuGet.Build.Tasks.Pack.Library/PackTaskLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ public PackArgs GetPackArgs(IPackTaskRequest<IMSBuildItem> request)
NoPackageAnalysis = request.NoPackageAnalysis,
PackTargetArgs = new MSBuildPackTargetArgs
{
TargetPathsToAssemblies = GetTargetPathsToAssemblies(request),
TargetPathsToSymbols = request.TargetPathsToSymbols,
TargetPathsToAssemblies = InitLibFiles(request.BuildOutputInPackage),
TargetPathsToSymbols = InitLibFiles(request.TargetPathsToSymbols),
AssemblyName = request.AssemblyName,
IncludeBuildOutput = request.IncludeBuildOutput,
BuildOutputFolder = request.BuildOutputFolder,
Expand Down Expand Up @@ -200,19 +200,48 @@ public void BuildPackage(PackCommandRunner runner)
runner.BuildPackage();
}

private string[] GetTargetPathsToAssemblies(IPackTaskRequest<IMSBuildItem> request)
private IEnumerable<OutputLibFile> InitLibFiles(IMSBuildItem[] libFiles)
{
if (request.TargetPathsToAssemblies == null)
var assemblies = new List<OutputLibFile>();
if (libFiles == null)
{
return new string[0];
return assemblies;
}

return request.TargetPathsToAssemblies
.Where(path => path != null)
.Select(path => path.Trim())
.Where(path => path != string.Empty)
.Distinct()
.ToArray();

foreach (var assembly in libFiles)
{
var finalOutputPath = assembly.GetProperty("FinalOutputPath");
var targetPath = assembly.GetProperty("TargetPath");
var targetFramework = assembly.GetProperty("TargetFramework");

if (!File.Exists(finalOutputPath))
{
throw new FileNotFoundException(string.Format(CultureInfo.CurrentCulture, Strings.Error_FileNotFound, finalOutputPath));
}

// If target path is not set, default it to the file name. Only satellite DLLs have a special target path
// where culture is part of the target path. This condition holds true for files like runtimeconfig.json file
// in netcore projects.
if (targetPath == null)
{
targetPath = Path.GetFileName(finalOutputPath);
}

if (string.IsNullOrEmpty(targetFramework) || NuGetFramework.Parse(targetFramework).IsSpecificFramework == false)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings.InvalidTargetFramework, finalOutputPath));
}

assemblies.Add(new OutputLibFile()
{
FinalOutputPath = finalOutputPath,
TargetPath = targetPath,
TargetFramework = targetFramework
});
}

return assemblies;
}

private ISet<NuGetFramework> ParseFrameworks(IPackTaskRequest<IMSBuildItem> request)
Expand Down Expand Up @@ -285,12 +314,12 @@ private void InitNuspecOutputPath(IPackTaskRequest<IMSBuildItem> request, PackAr
}
}

private Dictionary<string, HashSet<ContentMetadata>> ProcessContentToIncludeInPackage(
private Dictionary<string, IEnumerable<ContentMetadata>> ProcessContentToIncludeInPackage(
IPackTaskRequest<IMSBuildItem> request,
PackArgs packArgs)
{
// This maps from source path on disk to target path inside the nupkg.
var fileModel = new Dictionary<string, HashSet<ContentMetadata>>();
var fileModel = new Dictionary<string, IEnumerable<ContentMetadata>>();
if (request.PackageFiles != null)
{
var excludeFiles = CalculateFilesToExcludeInPack(request);
Expand All @@ -307,11 +336,11 @@ private Dictionary<string, HashSet<ContentMetadata>> ProcessContentToIncludeInPa
if (fileModel.ContainsKey(sourcePath))
{
var existingContentMetadata = fileModel[sourcePath];
existingContentMetadata.AddRange(totalContentMetadata);
fileModel[sourcePath] = existingContentMetadata.Concat(totalContentMetadata);
}
else
{
var existingContentMetadata = new HashSet<ContentMetadata>();
var existingContentMetadata = new List<ContentMetadata>();
existingContentMetadata.AddRange(totalContentMetadata);
fileModel.Add(sourcePath, existingContentMetadata);
}
Expand Down Expand Up @@ -437,7 +466,7 @@ private IEnumerable<ContentMetadata> GetContentMetadata(IMSBuildItem packageFile
// we take the final set of evaluated target paths and append the file name to it if not
// already done. we check whether the extension of the target path is the same as the extension
// of the source path and add the filename accordingly.
var totalSetOfTargetPaths = new HashSet<string>(StringComparer.Ordinal);
var totalSetOfTargetPaths = new List<string>();
foreach (var targetPath in setOfTargetPaths)
{
var currentPath = targetPath;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class PackTaskRequest : IPackTaskRequest<IMSBuildItem>
public string AssemblyName { get; set; }
public IMSBuildItem[] AssemblyReferences { get; set; }
public string[] Authors { get; set; }
public IMSBuildItem[] BuildOutputInPackage { get; set; }
public string BuildOutputFolder { get; set; }
public string[] ContentTargetFolders { get; set; }
public bool ContinuePackingAfterGeneratingNuspec { get; set; }
Expand Down Expand Up @@ -46,8 +47,7 @@ public class PackTaskRequest : IPackTaskRequest<IMSBuildItem>
public IMSBuildItem[] SourceFiles { get; set; }
public string[] Tags { get; set; }
public string[] TargetFrameworks { get; set; }
public string[] TargetPathsToAssemblies { get; set; }
public string[] TargetPathsToSymbols { get; set; }
public IMSBuildItem[] TargetPathsToSymbols { get; set; }
public string Title { get; set; }
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions src/NuGet.Core/NuGet.Build.Tasks.Pack.Library/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@
<value>The assets file produced by restore does not exist. Try restoring the project again. The expected location of the assets file is {0}.</value>
<comment>{0} is the path to the assets file.</comment>
</data>
<data name="Error_FileNotFound" xml:space="preserve">
<value>The file '{0}' to be packed was not found on disk.</value>
<comment>{0} is the file being packed.</comment>
</data>
<data name="InvalidMinClientVersion" xml:space="preserve">
<value>MinClientVersion string specified '{0}' is invalid.</value>
<comment>{0} is the version.</comment>
Expand All @@ -140,6 +144,9 @@
<value>PackageVersion string specified '{0}' is invalid.</value>
<comment>{0} is the version.</comment>
</data>
<data name="InvalidTargetFramework" xml:space="preserve">
<value>Invalid target framework for the file '{0}'.</value>
</data>
<data name="NoPackItemProvided" xml:space="preserve">
<value>No project was provided to the PackTask.</value>
</data>
Expand Down
27 changes: 20 additions & 7 deletions src/NuGet.Core/NuGet.Commands/MSBuildPackTargetArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ namespace NuGet.Commands
{
public class MSBuildPackTargetArgs
{
public string[] TargetPathsToSymbols { get; set; }
public string[] TargetPathsToAssemblies { get; set; }
public IEnumerable<OutputLibFile> TargetPathsToSymbols { get; set; }
public IEnumerable<OutputLibFile> TargetPathsToAssemblies { get; set; }
public string AssemblyName { get; set; }
public string NuspecOutputPath { get; set; }
public IEnumerable<ProjectToProjectReference> ProjectReferences { get; set; }
public Dictionary<string, HashSet<ContentMetadata>> ContentFiles { get; set; }
public Dictionary<string, IEnumerable<ContentMetadata>> ContentFiles { get; set; }
public ISet<NuGetFramework> TargetFrameworks { get; set; }
public IDictionary<string, string> SourceFiles { get; set; }
public bool IncludeBuildOutput { get; set; }
Expand All @@ -23,14 +22,28 @@ public class MSBuildPackTargetArgs

public MSBuildPackTargetArgs()
{
ProjectReferences = new List<ProjectToProjectReference>();
SourceFiles = new Dictionary<string, string>();
TargetPathsToAssemblies = new List<OutputLibFile>();
TargetPathsToSymbols = new List<OutputLibFile>();
}
}

public struct ProjectToProjectReference
public struct OutputLibFile
{
public string AssemblyName { get; set; }
/// <summary>
/// This is the final output path of the assembly on disk as set by msbuild.
/// </summary>
public string FinalOutputPath { get; set; }

/// <summary>
/// This denotes the TargetPath as set by msbuild. Usually this is just the file name, but for satellite DLLs,
/// this is Culture\filename.
/// </summary>
public string TargetPath { get; set; }

/// <summary>
/// This is the target framework for which this assembly was built.
/// </summary>
public string TargetFramework { get; set; }
}
}
Loading