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

net5.0 warnings, errors, and auto-translation of aliases #3678

Merged
merged 2 commits into from
Sep 24, 2020
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
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