Skip to content

Commit

Permalink
net5.0 warnings, errors, and auto-translation of aliases (#3678)
Browse files Browse the repository at this point in the history
* translate aliases for lib and contentFiles

Fixes: NuGet/Home#10020

* quick test for the lib part
  • Loading branch information
zkat committed Sep 24, 2020
1 parent 7f62522 commit 2582e3e
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 13 deletions.
63 changes: 53 additions & 10 deletions src/NuGet.Core/NuGet.Build.Tasks.Pack/PackTaskLogic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ public PackArgs GetPackArgs(IPackTaskRequest<IMSBuildItem> request)
packArgs.MinClientVersion = version;
}

LockFile assetsFile = GetAssetsFile(request);
var aliases = new Dictionary<string, string>();
foreach (var tfm in assetsFile.PackageSpec.TargetFrameworks)
{
aliases[tfm.TargetAlias] = tfm.FrameworkName.GetShortFolderName();
}

InitCurrentDirectoryAndFileName(request, packArgs);
InitNuspecOutputPath(request, packArgs);
Expand All @@ -76,12 +82,12 @@ public PackArgs GetPackArgs(IPackTaskRequest<IMSBuildItem> request)
// This only needs to happen when packing via csproj, not nuspec.
packArgs.PackTargetArgs.AllowedOutputExtensionsInPackageBuildOutputFolder = InitOutputExtensions(request.AllowedOutputExtensionsInPackageBuildOutputFolder);
packArgs.PackTargetArgs.AllowedOutputExtensionsInSymbolsPackageBuildOutputFolder = InitOutputExtensions(request.AllowedOutputExtensionsInSymbolsPackageBuildOutputFolder);
packArgs.PackTargetArgs.TargetPathsToAssemblies = InitLibFiles(request.BuildOutputInPackage);
packArgs.PackTargetArgs.TargetPathsToSymbols = InitLibFiles(request.TargetPathsToSymbols);
packArgs.PackTargetArgs.TargetPathsToAssemblies = InitLibFiles(request.BuildOutputInPackage, aliases);
packArgs.PackTargetArgs.TargetPathsToSymbols = InitLibFiles(request.TargetPathsToSymbols, aliases);
packArgs.PackTargetArgs.AssemblyName = request.AssemblyName;
packArgs.PackTargetArgs.IncludeBuildOutput = request.IncludeBuildOutput;
packArgs.PackTargetArgs.BuildOutputFolder = request.BuildOutputFolders;
packArgs.PackTargetArgs.TargetFrameworks = ParseFrameworks(request);
packArgs.PackTargetArgs.TargetFrameworks = ParseFrameworks(request, aliases);

if (request.IncludeSource)
{
Expand Down Expand Up @@ -322,6 +328,28 @@ private static Version GetLicenseExpressionVersion(IPackTaskRequest<IMSBuildItem
return version;
}


private LockFile GetAssetsFile(IPackTaskRequest<IMSBuildItem> request)
{
if (request.PackItem == null)
{
throw new PackagingException(NuGetLogCode.NU5028, Strings.NoPackItemProvided);
}

string assetsFilePath = Path.Combine(request.RestoreOutputPath, LockFileFormat.AssetsFileName);

if (!File.Exists(assetsFilePath))
{
throw new InvalidOperationException(string.Format(
CultureInfo.CurrentCulture,
Strings.AssetsFileNotFound,
assetsFilePath));
}
// The assets file is necessary for project and package references. Pack should not do any traversal,
// so we leave that work up to restore (which produces the assets file).
var lockFileFormat = new LockFileFormat();
return lockFileFormat.Read(assetsFilePath);
}
private void PopulateFrameworkAssemblyReferences(PackageBuilder builder, IPackTaskRequest<IMSBuildItem> request)
{
// First add all the assembly references which are not specific to a certain TFM.
Expand Down Expand Up @@ -396,7 +424,7 @@ public bool BuildPackage(PackCommandRunner runner)
return runner.RunPackageBuild();
}

private IEnumerable<OutputLibFile> InitLibFiles(IMSBuildItem[] libFiles)
private IEnumerable<OutputLibFile> InitLibFiles(IMSBuildItem[] libFiles, IDictionary<string, string> aliases)
{
var assemblies = new List<OutputLibFile>();
if (libFiles == null)
Expand All @@ -410,7 +438,7 @@ private IEnumerable<OutputLibFile> InitLibFiles(IMSBuildItem[] libFiles)
var finalOutputPath = assembly.GetProperty("FinalOutputPath");

// Fallback to using Identity if FinalOutputPath is not set.
// See bug https://github.com/NuGet/Home/issues/5408
// See bug https://github.com/NuGet/Home/issues/5408
if (string.IsNullOrEmpty(finalOutputPath))
{
finalOutputPath = assembly.GetProperty(IdentityProperty);
Expand All @@ -424,6 +452,13 @@ private IEnumerable<OutputLibFile> InitLibFiles(IMSBuildItem[] libFiles)
throw new PackagingException(NuGetLogCode.NU5026, string.Format(CultureInfo.CurrentCulture, Strings.Error_FileNotFound, finalOutputPath));
}

string translated = null;
var succeeded = aliases.TryGetValue(targetFramework, out translated);
if (succeeded)
{
targetFramework = translated;
}

// 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.
Expand All @@ -448,12 +483,20 @@ private IEnumerable<OutputLibFile> InitLibFiles(IMSBuildItem[] libFiles)
return assemblies;
}

private ISet<NuGetFramework> ParseFrameworks(IPackTaskRequest<IMSBuildItem> request)
private ISet<NuGetFramework> ParseFrameworks(IPackTaskRequest<IMSBuildItem> request, IDictionary<string, string> aliases)
{
var nugetFrameworks = new HashSet<NuGetFramework>();
if (request.TargetFrameworks != null)
{
nugetFrameworks = new HashSet<NuGetFramework>(request.TargetFrameworks.Select(t => NuGetFramework.Parse(t)));
nugetFrameworks = new HashSet<NuGetFramework>(request.TargetFrameworks.Select(targetFramework => {
string translated = null;
var succeeded = aliases.TryGetValue(targetFramework, out translated);
if (succeeded)
{
targetFramework = translated;
}
return NuGetFramework.Parse(targetFramework);
}));
}

return nugetFrameworks;
Expand Down Expand Up @@ -655,7 +698,7 @@ private IEnumerable<ContentMetadata> GetContentMetadata(IMSBuildItem packageFile
var newTargetPath = Path.Combine(targetPath, identity);
// We need to do this because evaluated identity in the above line of code can be an empty string
// in the case when the original identity string was the absolute path to a file in project directory, and is in
// the same directory as the csproj file.
// the same directory as the csproj file.
newTargetPath = PathUtility.EnsureTrailingSlash(newTargetPath);
newTargetPaths.Add(newTargetPath);
}
Expand Down Expand Up @@ -813,7 +856,7 @@ private static void InitializeProjectDependencies(

var versionToUse = new VersionRange(targetLibrary.Version);

// Use the project reference version obtained at build time if it exists, otherwise fallback to the one in assets file.
// Use the project reference version obtained at build time if it exists, otherwise fallback to the one in assets file.
if (projectRefToVersionMap.TryGetValue(projectReference.ProjectPath, out var projectRefVersion))
{
versionToUse = VersionRange.Parse(projectRefVersion, allowFloating: false);
Expand Down Expand Up @@ -872,7 +915,7 @@ private static void InitializePackageDependencies(
// Add each package dependency.
foreach (var packageDependency in packageDependencies)
{
// If we have a floating package dependency like 1.2.3-xyz-*, we
// If we have a floating package dependency like 1.2.3-xyz-*, we
// use the version of the package that restore resolved it to.
if (packageDependency.LibraryRange.VersionRange.IsFloating)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,121 @@ public void PackTaskLogic_SupportsContentFiles_WithPackageCopyToOutput()
}
}

[Fact]
public void PackTaskLogic_InfersFrameworkPlatformVersionFromAlias()
{
// Arrange
using (var testDir = TestDirectory.Create())
{
var tc = new TestContext(testDir, "net5.0-windows");

var assetsJson = @"{
""version"": 3,
""targets"": {
""net5.0"": {},
""net5.0-windows7.0"": {}
},
""libraries"": {},
""projectFileDependencyGroups"": {
""net5.0"": [],
""net5.0-windows7.0"": []
},
""project"": {
""version"": ""0.0.0"",
""restore"": {
""projectName"": ""bar"",
""projectStyle"": ""PackageReference"",
""crossTargeting"": true,
""fallbackFolders"": [
""C:\\Microsoft\\Xamarin\\NuGet\\""
],
""originalTargetFrameworks"": [
""net5.0"",
""net5.0-windows""
],
""sources"": {
""https://api.nuget.org/v3/index.json"": {},
},
""frameworks"": {
""net5.0"": {
""targetAlias"": ""net5.0"",
""projectReferences"": {}
},
""net5.0-windows7.0"": {
""targetAlias"": ""net5.0-windows"",
""projectReferences"": {}
}
},
""warningProperties"": {
""warnAsError"": [
""NU1605""
]
}
},
""frameworks"": {
""net5.0"": {
""targetAlias"": ""net5.0"",
""imports"": [
""net461"",
""net462"",
""net47"",
""net471"",
""net472"",
""net48""
],
""assetTargetFallback"": true,
""warn"": true,
""frameworkReferences"": {
""Microsoft.NETCore.App"": {
""privateAssets"": ""all""
}
},
},
""net5.0-windows7.0"": {
""targetAlias"": ""net5.0-windows"",
""imports"": [
""net461"",
""net462"",
""net47"",
""net471"",
""net472"",
""net48""
],
""assetTargetFallback"": true,
""warn"": true,
""frameworkReferences"": {
""Microsoft.NETCore.App"": {
""privateAssets"": ""all""
}
},
}
}
}
}";
File.WriteAllText(Path.Combine(testDir, "obj", "project.assets.json"), assetsJson);

// var msbuildItem = tc.AddContentToProject("", "abc.txt", "hello world");
// tc.Request.PackageFiles = new MSBuildItem[] { msbuildItem };
// tc.Request.ContentTargetFolders = new string[] { "content" };

// Act
tc.BuildPackage();

// Assert
using (var nupkgReader = new PackageArchiveReader(tc.NupkgPath))
{
var nuspecReader = nupkgReader.NuspecReader;

// Validate the assets.
var libItems = nupkgReader.GetLibItems().ToList();
Assert.Equal(1, libItems.Count);
Assert.Equal(NuGetFramework.Parse("net5.0-windows7.0"), libItems[0].TargetFramework);
Assert.Equal(new[] { "lib/net5.0-windows7.0/a.dll" }, libItems[0].Items);
}
}
}


[PlatformTheory(Platform.Windows)]
[InlineData(true)]
[InlineData(false)]
Expand Down Expand Up @@ -625,11 +740,18 @@ public void PackTaskLogic_EmbedInteropAssembly()

private class TestContext
{

public TestContext(TestDirectory testDir)
: this(testDir, "net45")
{

}

public TestContext(TestDirectory testDir, string tfm)
{
var fullPath = Path.Combine(testDir, "project.csproj");
var rootDir = Path.GetPathRoot(testDir);
var dllDir = Path.Combine(testDir, "bin", "Debug", "net45");
var dllDir = Path.Combine(testDir, "bin", "Debug", tfm);
var dllPath = Path.Combine(dllDir, "a.dll");

Directory.CreateDirectory(dllDir);
Expand Down Expand Up @@ -664,11 +786,11 @@ public TestContext(TestDirectory testDir)
IncludeBuildOutput = true,
RestoreOutputPath = Path.Combine(testDir, "obj"),
ContinuePackingAfterGeneratingNuspec = true,
TargetFrameworks = new[] { "net45" },
TargetFrameworks = new[] { tfm },
BuildOutputInPackage = new[] { new MSBuildItem(dllPath, new Dictionary<string, string>
{
{"FinalOutputPath", dllPath },
{"TargetFramework", "net45" }
{"TargetFramework", tfm }
})},
Logger = new TestLogger(),
SymbolPackageFormat = "symbols.nupkg",
Expand Down

0 comments on commit 2582e3e

Please sign in to comment.