Skip to content

Commit

Permalink
Enable "portable" RID graph when targeting .NET 8 and higher (#34279)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsplaisted authored Aug 4, 2023
2 parents 9077980 + 177651f commit e626b7f
Show file tree
Hide file tree
Showing 15 changed files with 648 additions and 25 deletions.
464 changes: 464 additions & 0 deletions src/Layout/redist/PortableRuntimeIdentifierGraph.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/Layout/redist/targets/BuildToolsetTasks.targets
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@
<UsingTask TaskName="ZipFileCreateFromDirectory" AssemblyFile="$(ToolsetTaskDll)"/>
<UsingTask TaskName="OverrideAndCreateBundledNETCoreAppPackageVersion" AssemblyFile="$(ToolsetTaskDll)"/>
<UsingTask TaskName="OverrideWasmRuntimePackVersions" AssemblyFile="$(ToolsetTaskDll)"/>
<UsingTask TaskName="UpdatePortableRuntimeIdentifierGraph" AssemblyFile="$(ToolsetTaskDll)"/>

</Project>
12 changes: 12 additions & 0 deletions src/Layout/redist/targets/GenerateLayout.targets
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
<Project>

<Target Name="PublishPortableRuntimeIdentifierGraph"
BeforeTargets="Build">

<UpdatePortableRuntimeIdentifierGraph
InputFile="PortableRuntimeIdentifierGraph.json"
OutputFile="$(OutputPath)/PortableRuntimeIdentifierGraph.json"
AdditionalRuntimeIdentifiers="@(AdditionalRuntimeIdentifier)"
/>

</Target>

<Target Name="PublishVersionFile"
BeforeTargets="Build">

Expand Down
60 changes: 60 additions & 0 deletions src/Layout/toolset-tasks/UpdatePortableRuntimeIdentifierGraph.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Microsoft.DotNet.Cli.Build
{
public class UpdatePortableRuntimeIdentifierGraph : Task
{
[Required]
public string InputFile { get; set; }

[Required]
public string OutputFile { get; set; }


// ItemSpec should be a RID, and "Imports" metadata should be a semicolon-separated list of RIDs that the ItemSpec RID imports
public ITaskItem[] AdditionalRuntimeIdentifiers { get; set; }

public override bool Execute()
{
JToken json;

using (var file = File.OpenText(InputFile))
using (JsonTextReader reader = new JsonTextReader(file))
{
json = JObject.ReadFrom(reader);
}

JObject runtimes = (JObject) json["runtimes"];

if (AdditionalRuntimeIdentifiers != null)
{
foreach (var rid in AdditionalRuntimeIdentifiers)
{
var importedRids = rid.GetMetadata("Imports").Split(';');
runtimes.Add(rid.ItemSpec, new JObject(new JProperty("#import", new JArray(importedRids))));
}
}

using (var file = File.CreateText(OutputFile))
using (var writer = new JsonTextWriter(file) { Formatting = Formatting.Indented })
{
json.WriteTo(writer);
}

return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<ResolveReadyToRunCompilers RuntimePacks="@(ResolvedRuntimePack)"
Crossgen2Packs="@(ResolvedCrossgen2Pack)"
TargetingPacks="@(ResolvedTargetingPack)"
RuntimeGraphPath="$(BundledRuntimeIdentifierGraphFile)"
RuntimeGraphPath="$(RuntimeIdentifierGraphPath)"
NETCoreSdkRuntimeIdentifier="$(NETCoreSdkRuntimeIdentifier)"
EmitSymbols="$(PublishReadyToRunEmitSymbols)"
ReadyToRunUseCrossgen2="$(PublishReadyToRunUseCrossgen2)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Copyright (c) .NET Foundation. All rights reserved.
ResolvedNuGetFiles="@(NativeCopyLocalItems);@(ResourceCopyLocalItems);@(RuntimeCopyLocalItems)"
ResolvedRuntimeTargetsFiles="@(RuntimeTargetsCopyLocalItems)"
TargetFramework="$(TargetFramework)"
RuntimeGraphPath="$(BundledRuntimeIdentifierGraphFile)"
RuntimeGraphPath="$(RuntimeIdentifierGraphPath)"
IncludeProjectsNotInAssetsFile="$(IncludeProjectsNotInAssetsFileInDepsFile)"
/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<ResolveReadyToRunCompilers RuntimePacks="@(ResolvedRuntimePack)"
Crossgen2Packs="@(ResolvedCrossgen2Pack)"
TargetingPacks="@(ResolvedTargetingPack)"
RuntimeGraphPath="$(BundledRuntimeIdentifierGraphFile)"
RuntimeGraphPath="$(RuntimeIdentifierGraphPath)"
NETCoreSdkRuntimeIdentifier="$(NETCoreSdkRuntimeIdentifier)"
EmitSymbols="$(PublishReadyToRunEmitSymbols)"
ReadyToRunUseCrossgen2="$(PublishReadyToRunUseCrossgen2)"
Expand Down Expand Up @@ -1013,7 +1013,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(MicrosoftNETPlatformLibrary)" />
<_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(SelfContained)" />
<_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(IncludeFileVersionsInDependencyFile)" />
<_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(BundledRuntimeIdentifierGraphFile)" />
<_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(RuntimeIdentifierGraphPath)" />
<_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(IncludeProjectsNotInAssetsFileInDepsFile)" />
</ItemGroup>

Expand Down Expand Up @@ -1099,7 +1099,7 @@ Copyright (c) .NET Foundation. All rights reserved.
IsSelfContained="$(SelfContained)"
IsSingleFile="$(_IsSingleFilePublish)"
IncludeRuntimeFileVersions="$(IncludeFileVersionsInDependencyFile)"
RuntimeGraphPath="$(BundledRuntimeIdentifierGraphFile)"
RuntimeGraphPath="$(RuntimeIdentifierGraphPath)"
IncludeProjectsNotInAssetsFile="$(IncludeProjectsNotInAssetsFileInDepsFile)"/>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ Copyright (c) .NET Foundation. All rights reserved.

<Import Project="$(NETCoreSdkBundledVersionsProps)" Condition="Exists('$(NETCoreSdkBundledVersionsProps)')" />

<PropertyGroup>
<!-- Set RuntimeIdentifier graph for NuGet (this needs to be after NETCoreSdkBundledVersionsProps is imported, as that's where
BundledRuntimeIdentifierGraphFile is set. -->
<RuntimeIdentifierGraphPath Condition="'$(RuntimeIdentifierGraphPath)' == ''">$(BundledRuntimeIdentifierGraphFile)</RuntimeIdentifierGraphPath>
</PropertyGroup>

<PropertyGroup>
<!-- Disable web SDK implicit package versions for ASP.NET packages, since the .NET SDK now handles that -->
<EnableWebSdkImplicitPackageVersions>false</EnableWebSdkImplicitPackageVersions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Copyright (c) .NET Foundation. All rights reserved.
TargetPlatformIdentifier="$(TargetPlatformIdentifier)"
TargetPlatformVersion="$(TargetPlatformVersion)"
TargetingPackRoot="$(NetCoreTargetingPackRoot)"
RuntimeGraphPath="$(BundledRuntimeIdentifierGraphFile)"
RuntimeGraphPath="$(RuntimeIdentifierGraphPath)"
SelfContained="$(SelfContained)"
ReadyToRunEnabled="$(PublishReadyToRun)"
ReadyToRunUseCrossgen2="$(PublishReadyToRunUseCrossgen2)"
Expand Down Expand Up @@ -155,7 +155,7 @@ Copyright (c) .NET Foundation. All rights reserved.
DotNetSingleFileHostExecutableNameWithoutExtension="$(_DotNetSingleFileHostExecutableNameWithoutExtension)"
DotNetComHostLibraryNameWithoutExtension="$(_DotNetComHostLibraryNameWithoutExtension)"
DotNetIjwHostLibraryNameWithoutExtension="$(_DotNetIjwHostLibraryNameWithoutExtension)"
RuntimeGraphPath="$(BundledRuntimeIdentifierGraphFile)"
RuntimeGraphPath="$(RuntimeIdentifierGraphPath)"
KnownAppHostPacks="@(KnownAppHostPack)"
NuGetRestoreSupported="$(_NuGetRestoreSupported)"
EnableAppHostPackDownload="$(EnableAppHostPackDownload)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ Copyright (c) .NET Foundation. All rights reserved.
<_GenerateSingleFileBundlePropertyInputsCache>$([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(_GenerateSingleFileBundlePropertyInputsCache)))</_GenerateSingleFileBundlePropertyInputsCache>
</PropertyGroup>

<!-- For .NET 8 and higher, we will by default use a simplified "portable" RID graph -->
<PropertyGroup Condition="'$(UseRidGraph)' == ''">
<UseRidGraph Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0'))">false</UseRidGraph>
<UseRidGraph Condition="'$(UseRidGraph)' == ''">true</UseRidGraph>
</PropertyGroup>

<PropertyGroup Condition="'$(RuntimeIdentifierGraphPath)' == ''">
<RuntimeIdentifierGraphPath Condition="'$(UseRidGraph)' == 'true'">$(BundledRuntimeIdentifierGraphFile)</RuntimeIdentifierGraphPath>

<!-- The portable RID graph should be in the same directory as the full RID graph -->
<RuntimeIdentifierGraphPath Condition="'$(UseRidGraph)' != 'true'">$([System.IO.Path]::GetDirectoryName($(BundledRuntimeIdentifierGraphFile)))/PortableRuntimeIdentifierGraph.json</RuntimeIdentifierGraphPath>
</PropertyGroup>

<ItemGroup>
<GenerateRuntimeConfigurationFilesInputs Include="$(ProjectAssetsFile)" />
<GenerateRuntimeConfigurationFilesInputs Include="$(ProjectAssetsCacheFile)" />
Expand Down Expand Up @@ -288,7 +301,7 @@ Copyright (c) .NET Foundation. All rights reserved.
ResolvedRuntimeTargetsFiles="@(RuntimeTargetsCopyLocalItems)"
IsSelfContained="$(SelfContained)"
IncludeRuntimeFileVersions="$(IncludeFileVersionsInDependencyFile)"
RuntimeGraphPath="$(BundledRuntimeIdentifierGraphFile)"
RuntimeGraphPath="$(RuntimeIdentifierGraphPath)"
IncludeProjectsNotInAssetsFile="$(IncludeProjectsNotInAssetsFileInDepsFile)"
ValidRuntimeIdentifierPlatformsForAssets="@(_ValidRuntimeIdentifierPlatformsForAssets)"/>
<ItemGroup>
Expand Down
66 changes: 66 additions & 0 deletions src/Tests/Microsoft.NET.Build.Tests/RuntimeIdentifierGraphTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.NET.TestFramework;
using Microsoft.NET.TestFramework.Assertions;
using Microsoft.NET.TestFramework.Commands;
using Microsoft.NET.TestFramework.ProjectConstruction;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.NET.Build.Tests
{
public class RuntimeIdentifierGraphTests : SdkTest
{
public RuntimeIdentifierGraphTests(ITestOutputHelper log) : base(log)
{
}

[Theory]
[InlineData("net7.0", null, true)]
[InlineData("net8.0", null, false)]
[InlineData("net7.0", "false", false)]
[InlineData("net8.0", "true", true)]
public void ItUsesCorrectRuntimeIdentifierGraph(string targetFramework, string useRidGraphValue, bool shouldUseFullRidGraph)
{
var testProject = new TestProject()
{
TargetFrameworks = targetFramework,
IsExe = true
};

if (useRidGraphValue != null)
{
testProject.AdditionalProperties["UseRidGraph"] = useRidGraphValue;
}

testProject.RecordProperties("RuntimeIdentifierGraphPath");

var testAsset = _testAssetsManager.CreateTestProject(testProject, identifier: targetFramework + "_" + (useRidGraphValue ?? "null"));

var buildCommand = new BuildCommand(testAsset);

buildCommand.Execute()
.Should()
.Pass();

var runtimeIdentifierGraphPath = testProject.GetPropertyValues(testAsset.TestRoot)["RuntimeIdentifierGraphPath"];

if (shouldUseFullRidGraph)
{
Path.GetFileName(runtimeIdentifierGraphPath).Should().Be("RuntimeIdentifierGraph.json");
}
else
{
Path.GetFileName(runtimeIdentifierGraphPath).Should().Be("PortableRuntimeIdentifierGraph.json");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void There_should_be_no_unresolved_conflicts()
Name = "CrossPublish",
TargetFrameworks = ToolsetInfo.CurrentTargetFramework,
IsExe = true,
RuntimeIdentifier = "centos.8-x64"
RuntimeIdentifier = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "linux-x64" : "win-x64"
};

testProject.PackageReferences.Add(new TestPackageReference("System.Threading", "4.3.0"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,6 @@ public static void Main()
}

[Theory]
[InlineData("win-arm")]
[InlineData("win8-arm")]
[InlineData("win81-arm")]
[InlineData($"{ToolsetInfo.LatestWinRuntimeIdentifier}-arm")]
[InlineData($"{ToolsetInfo.LatestWinRuntimeIdentifier}-arm64")]
public void Publish_standalone_post_netcoreapp2_arm_app(string runtimeIdentifier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,17 @@ public GivenThatWeWantToPublishASingleFileApp(ITestOutputHelper log) : base(log)
{
}

private PublishCommand GetPublishCommand(string identifier = null, [CallerMemberName] string callingMethod = "")
private PublishCommand GetPublishCommand(string identifier = null, [CallerMemberName] string callingMethod = "", Action<XDocument> projectChanges = null)
{
if (projectChanges == null)
{
projectChanges = d => { };
}

var testAsset = _testAssetsManager
.CopyTestAsset(TestProjectName, callingMethod, identifier)
.WithSource();
.WithSource()
.WithProjectChanges(projectChanges);

// Create the following content:
// <TestRoot>/SmallNameDir/This is a directory with a really long name for one that only contains a small file/.word
Expand Down Expand Up @@ -127,7 +133,17 @@ public void It_errors_when_publishing_single_file_without_apphost()
public void It_generates_publishing_single_file_with_win7()
{
const string rid = "win7-x86";
GetPublishCommand()

// Retarget project to net7.0, as net8.0 and up by default use portable runtime graph which doesn't have win7-* RIDs
var projectChanges = (XDocument doc) =>
{
var ns = doc.Root.Name.Namespace;
doc.Root.Element(ns + "PropertyGroup")
.Element(ns + "TargetFramework")
.Value = "net7.0";
};

GetPublishCommand(projectChanges: projectChanges)
.Execute($"/p:RuntimeIdentifier={rid}", PublishSingleFile)
.Should()
.Pass();
Expand Down
8 changes: 4 additions & 4 deletions src/Tests/Microsoft.NET.TestFramework/ToolsetInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ public class ToolsetInfo
public const string NextTargetFramework = "net9.0";
public const string NextTargetFrameworkVersion = "9.0";

public const string LatestWinRuntimeIdentifier = "win10";
public const string LatestLinuxRuntimeIdentifier = "ubuntu.22.04";
public const string LatestMacRuntimeIdentifier = "osx.13";
public const string LatestRuntimeIdentifiers = $"{LatestWinRuntimeIdentifier}-x64;{LatestWinRuntimeIdentifier}-x86;osx.10.10-x64;osx.10.11-x64;osx.10.12-x64;osx.10.14-x64;{LatestMacRuntimeIdentifier}-x64;ubuntu.14.04-x64;ubuntu.16.04-x64;ubuntu.16.10-x64;ubuntu.18.04-x64;ubuntu.20.04-x64;{LatestLinuxRuntimeIdentifier}-x64;centos.9-x64;rhel.9-x64;debian.9-x64;fedora.37-x64;opensuse.42.3-x64;linux-musl-x64";
public const string LatestWinRuntimeIdentifier = "win";
public const string LatestLinuxRuntimeIdentifier = "linux";
public const string LatestMacRuntimeIdentifier = "osx";
public const string LatestRuntimeIdentifiers = $"{LatestWinRuntimeIdentifier}-x64;{LatestWinRuntimeIdentifier}-x86;osx-x64;{LatestMacRuntimeIdentifier}-x64;{LatestLinuxRuntimeIdentifier}-x64;linux-musl-x64";

public string DotNetRoot { get; }
public string DotNetHostPath { get; }
Expand Down

0 comments on commit e626b7f

Please sign in to comment.