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

Include assembly and file versions in deps file for non self-contained publish #2118

Merged
2 changes: 1 addition & 1 deletion build/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<PropertyGroup>
<MicrosoftBuildFrameworkVersion>15.4.8</MicrosoftBuildFrameworkVersion>
<MicrosoftBuildUtilitiesCoreVersion>15.4.8</MicrosoftBuildUtilitiesCoreVersion>
<MicrosoftExtensionsDependencyModelVersion>2.0.0</MicrosoftExtensionsDependencyModelVersion>
<MicrosoftExtensionsDependencyModelVersion>2.1.0-preview2-26306-03</MicrosoftExtensionsDependencyModelVersion>
<NETStandardLibraryNETFrameworkVersion>2.0.1-servicing-26011-01</NETStandardLibraryNETFrameworkVersion>
<NewtonsoftJsonVersion>9.0.1</NewtonsoftJsonVersion>
<NuGetBuildTasksPackVersion>4.7.0-rtm.5081</NuGetBuildTasksPackVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void ItBuildsDependencyContextsFromProjectLockFiles(
Constants.DefaultPlatformLibrary,
isSelfContained: !string.IsNullOrEmpty(runtime));

DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext)
DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext, includeRuntimeFileVersions: false)
.WithDirectReferences(directReferences)
.WithCompilationOptions(compilationOptions)
.Build();
Expand Down Expand Up @@ -260,7 +260,7 @@ private DependencyContext BuildDependencyContextWithReferenceAssemblies(bool use
useCompilationOptions ? CreateCompilationOptions() :
null;

DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext)
DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext, includeRuntimeFileVersions: false)
.WithReferenceAssemblies(ReferenceInfo.CreateReferenceInfos(referencePaths))
.WithCompilationOptions(compilationOptions)
.Build();
Expand Down
43 changes: 37 additions & 6 deletions src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ internal class DependencyContextBuilder
private readonly VersionFolderPathResolver _versionFolderPathResolver;
private readonly SingleProjectInfo _mainProjectInfo;
private readonly ProjectContext _projectContext;
private readonly bool _includeRuntimeFileVersions;
private readonly NuGetPackageResolver _packageResolver;
private IEnumerable<ReferenceInfo> _referenceAssemblies;
private IEnumerable<ReferenceInfo> _directReferences;
private IEnumerable<ReferenceInfo> _dependencyReferences;
Expand All @@ -32,13 +34,21 @@ internal class DependencyContextBuilder
private HashSet<string> _usedLibraryNames;
private Dictionary<ReferenceInfo, string> _referenceLibraryNames;

public DependencyContextBuilder(SingleProjectInfo mainProjectInfo, ProjectContext projectContext)
public DependencyContextBuilder(SingleProjectInfo mainProjectInfo, ProjectContext projectContext, bool includeRuntimeFileVersions)
{
_mainProjectInfo = mainProjectInfo;
_projectContext = projectContext;
_includeRuntimeFileVersions = includeRuntimeFileVersions;

// This resolver is only used for building file names, so that base path is not required.
_versionFolderPathResolver = new VersionFolderPathResolver(rootPath: null);

if (_includeRuntimeFileVersions)
{
// This is used to look up the paths to package files on disk, which is only needed in this class if
// it needs to read the file versions
_packageResolver = NuGetPackageResolver.CreateResolver(projectContext.LockFile, mainProjectInfo.ProjectPath);
}
}

/// <summary>
Expand Down Expand Up @@ -436,6 +446,27 @@ private Library GetLibrary(
}
}

private RuntimeFile CreateRuntimeFile(LockFileTargetLibrary library, LockFileItem item)
{
// _packageResolver will be null if _includeRuntimeFileVersions is false, hence the "?."
var itemFullPath = _packageResolver?.ResolvePackageAssetPath(library, item.Path);
return CreateRuntimeFile(item.Path, itemFullPath);
}

private RuntimeFile CreateRuntimeFile(string path, string fullPath)
{
if (_includeRuntimeFileVersions)
{
string fileVersion = FileUtilities.GetFileVersion(fullPath).ToString();
string assemblyVersion = FileUtilities.TryGetAssemblyVersion(fullPath)?.ToString();
return new RuntimeFile(path, assemblyVersion, fileVersion);
}
else
{
return new RuntimeFile(path, null, null);
}
}

private IReadOnlyList<RuntimeAssetGroup> CreateRuntimeAssemblyGroups(LockFileTargetLibrary targetLibrary, SingleProjectInfo referenceProjectInfo)
{
if (targetLibrary.IsProject())
Expand All @@ -450,14 +481,14 @@ private IReadOnlyList<RuntimeAssetGroup> CreateRuntimeAssemblyGroups(LockFileTar
assemblyGroups.Add(
new RuntimeAssetGroup(
string.Empty,
targetLibrary.RuntimeAssemblies.FilterPlaceholderFiles().Select(a => a.Path)));
targetLibrary.RuntimeAssemblies.FilterPlaceholderFiles().Select(a => CreateRuntimeFile(targetLibrary, a))));

foreach (var runtimeTargetsGroup in targetLibrary.GetRuntimeTargetsGroups("runtime"))
{
assemblyGroups.Add(
new RuntimeAssetGroup(
runtimeTargetsGroup.Key,
runtimeTargetsGroup.Select(t => t.Path)));
runtimeTargetsGroup.Select(t => CreateRuntimeFile(targetLibrary, t))));
}

return assemblyGroups;
Expand All @@ -471,14 +502,14 @@ private IReadOnlyList<RuntimeAssetGroup> CreateNativeLibraryGroups(LockFileTarge
nativeGroups.Add(
new RuntimeAssetGroup(
string.Empty,
export.NativeLibraries.FilterPlaceholderFiles().Select(a => a.Path)));
export.NativeLibraries.FilterPlaceholderFiles().Select(a => CreateRuntimeFile(export, a))));

foreach (var runtimeTargetsGroup in export.GetRuntimeTargetsGroups("native"))
{
nativeGroups.Add(
new RuntimeAssetGroup(
runtimeTargetsGroup.Key,
runtimeTargetsGroup.Select(t => t.Path)));
runtimeTargetsGroup.Select(t => CreateRuntimeFile(export, t))));
}

return nativeGroups;
Expand Down Expand Up @@ -560,7 +591,7 @@ private IEnumerable<RuntimeLibrary> GetReferenceRuntimeLibraries(IEnumerable<Ref
name: GetReferenceLibraryName(r),
version: r.Version,
hash: string.Empty,
runtimeAssemblyGroups: new[] { new RuntimeAssetGroup(string.Empty, r.FileName) },
runtimeAssemblyGroups: new[] { new RuntimeAssetGroup(string.Empty, new[] { CreateRuntimeFile(r.FileName, r.FullPath) }) },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note - when @tannergooding's change #2090 goes in, we will need to merge this with that, so the new references get CreateRuntimeFile called on them as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#2090 was merged, was this handled?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tannergooding @eerhardt It looks like this is handled correctly, as the new code from #2090 ends up calling through GetReferenceRuntimeLibraries for the indirect references, the same as how the direct references are handled.

nativeLibraryGroups: new RuntimeAssetGroup[] { },
resourceAssemblies: CreateResourceAssemblies(r.ResourceAssemblies),
dependencies: Enumerable.Empty<Dependency>(),
Expand Down
18 changes: 16 additions & 2 deletions src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ public class GenerateDepsFile : TaskBase

public bool IsSelfContained { get; set; }

public bool IncludeRuntimeFileVersions { get; set; }

List<ITaskItem> _filesWritten = new List<ITaskItem>();

[Output]
Expand Down Expand Up @@ -138,7 +140,7 @@ protected override void ExecuteCore()
PlatformLibraryName,
IsSelfContained);

DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext)
DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext, IncludeRuntimeFileVersions)
.WithMainProjectInDepsFile(IncludeMainProject)
.WithReferenceAssemblies(referenceAssemblyInfos)
.WithDirectReferences(directReferences)
Expand Down Expand Up @@ -229,7 +231,7 @@ private IEnumerable<RuntimeAssetGroup> TrimAssetGroups(IEnumerable<RuntimeAssetG
{
foreach (var assetGroup in assetGroups)
{
yield return new RuntimeAssetGroup(assetGroup.Runtime, TrimAssemblies(assetGroup.AssetPaths, filesToTrim));
yield return new RuntimeAssetGroup(assetGroup.Runtime, TrimRuntimeFiles(assetGroup.RuntimeFiles, filesToTrim));
}
}

Expand Down Expand Up @@ -278,5 +280,17 @@ private IEnumerable<string> TrimAssemblies(IEnumerable<string> assemblies, ISet<
}
}
}


private IEnumerable<RuntimeFile> TrimRuntimeFiles(IEnumerable<RuntimeFile> assemblies, ISet<string> filesToTrim)
{
foreach (var assembly in assemblies)
{
if (!filesToTrim.Contains(assembly.Path))
{
yield return assembly;
}
}
}
}
}
9 changes: 9 additions & 0 deletions src/Tasks/Microsoft.NET.Build.Tasks/NuGetPackageResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ public string GetPackageDirectory(string packageId, NuGetVersion version, out st
return _packagePathResolver.GetPackageDirectory(packageId, version);
}

public string ResolvePackageAssetPath(LockFileTargetLibrary package, string relativePath)
{
string packagePath = GetPackageDirectory(package.Name, package.Version);
return Path.Combine(packagePath, NormalizeRelativePath(relativePath));
}

public static string NormalizeRelativePath(string relativePath)
=> relativePath.Replace('/', Path.DirectorySeparatorChar);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation looks non-standard here.


public static NuGetPackageResolver CreateResolver(LockFile lockFile, string projectPath)
{
NuGetPackageResolver packageResolver;
Expand Down
15 changes: 3 additions & 12 deletions src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ private void WriteAnalyzers()

if (targetLibraries.TryGetValue(library.Name, out var targetLibrary))
{
WriteItem(ResolvePackageAssetPath(targetLibrary, file), targetLibrary);
WriteItem(_packageResolver.ResolvePackageAssetPath(targetLibrary, file), targetLibrary);
}
}
}
Expand Down Expand Up @@ -925,7 +925,7 @@ private void WriteItems<T>(
continue;
}

string itemSpec = ResolvePackageAssetPath(library, asset.Path);
string itemSpec = _packageResolver.ResolvePackageAssetPath(library, asset.Path);
WriteItem(itemSpec, library);
writeMetadata?.Invoke(asset);
}
Expand Down Expand Up @@ -968,12 +968,6 @@ private int GetMetadataIndex(string value)
return index;
}

private string ResolvePackageAssetPath(LockFileTargetLibrary package, string relativePath)
{
string packagePath = _packageResolver.GetPackageDirectory(package.Name, package.Version);
return Path.Combine(packagePath, NormalizeRelativePath(relativePath));
}

private static Dictionary<string, string> GetProjectReferencePaths(LockFile lockFile)
{
Dictionary<string, string> paths = new Dictionary<string, string>();
Expand All @@ -982,15 +976,12 @@ private static Dictionary<string, string> GetProjectReferencePaths(LockFile lock
{
if (library.IsProject())
{
paths[library.Name] = NormalizeRelativePath(library.MSBuildProject);
paths[library.Name] = NuGetPackageResolver.NormalizeRelativePath(library.MSBuildProject);
}
}

return paths;
}

private static string NormalizeRelativePath(string relativePath)
=> relativePath.Replace('/', Path.DirectorySeparatorChar);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,8 @@ Copyright (c) .NET Foundation. All rights reserved.
CompilerOptions="@(DependencyFileCompilerOptions)"
ExcludeFromPublishPackageReferences="@(_ExcludeFromPublishPackageReference)"
RuntimeStorePackages="@(RuntimeStorePackages)"
IsSelfContained="$(SelfContained)" />
IsSelfContained="$(SelfContained)"
IncludeRuntimeFileVersions="$(IncludeFileVersionsInDependencyFile)" />

</Target>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ Copyright (c) .NET Foundation. All rights reserved.
<!-- Default settings for .NET Core and .NET Standard build logic -->
<PropertyGroup Condition="'$(_IsNETCoreOrNETStandard)' == 'true'">
<GenerateDependencyFile Condition=" '$(GenerateDependencyFile)' == '' ">true</GenerateDependencyFile>

<!-- Assembly and file versions of runtime assets should be written to the deps.json by default, to support
runtime minor version roll-forward: https://github.com/dotnet/core-setup/issues/3546 -->
<IncludeFileVersionsInDependencyFile Condition="'$(IncludeFileVersionsInDependencyFile)' == ''">true</IncludeFileVersionsInDependencyFile>

<!-- Force .dll extension for .NETCoreApp and .NETStandard projects even if output type is exe. -->
<TargetExt Condition="'$(TargetExt)' == ''">.dll</TargetExt>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ Copyright (c) .NET Foundation. All rights reserved.
_ComputeReferenceAssemblies"
BeforeTargets="CopyFilesToOutputDirectory"
Condition=" '$(GenerateDependencyFile)' == 'true'"
Inputs="$(ProjectAssetsFile)"
Inputs="$(ProjectAssetsFile);$(MSBuildAllProjects)"
Outputs="$(ProjectDepsFilePath)">

<!--
Expand All @@ -142,7 +142,8 @@ Copyright (c) .NET Foundation. All rights reserved.
PlatformLibraryName="$(MicrosoftNETPlatformLibrary)"
FilesToSkip="@(_ConflictPackageFiles)"
CompilerOptions="@(DependencyFileCompilerOptions)"
IsSelfContained="$(SelfContained)">
IsSelfContained="$(SelfContained)"
IncludeRuntimeFileVersions="$(IncludeFileVersionsInDependencyFile)">
</GenerateDepsFile>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
<PackageReference Include="NuGet.Packaging" Version="$(NuGetProjectModelVersion)" />
<PackageReference Include="NuGet.Frameworks" Version="$(NuGetProjectModelVersion)" />
<PackageReference Include="NuGet.Common" Version="$(NuGetProjectModelVersion)" />

<!-- Referenced explicitly here because Microsoft.DotNet.Cli.Utils references a lower version at the moment, which causes
RAR conflicts (though ideally I would think NuGet would resolve this) -->
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftExtensionsDependencyModelVersion)" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading