Skip to content
5 changes: 5 additions & 0 deletions src/Tasks/Common/FileUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using Microsoft.Build.Framework;

namespace Microsoft.NET.Build.Tasks
{
Expand All @@ -22,12 +23,16 @@ static partial class FileUtilities
return null;
}

public static Version? GetFileVersion(AbsolutePath sourcePath) => GetFileVersion(sourcePath.Value);

static readonly HashSet<string?> s_assemblyExtensions = new(new[] { ".dll", ".exe", ".winmd" }, StringComparer.OrdinalIgnoreCase);
public static Version? TryGetAssemblyVersion(string sourcePath)
{
var extension = Path.GetExtension(sourcePath);

return s_assemblyExtensions.Contains(extension) ? GetAssemblyVersion(sourcePath) : null;
}

public static Version? TryGetAssemblyVersion(AbsolutePath sourcePath) => TryGetAssemblyVersion(sourcePath.Value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public DependencyContextBuilder WithPackagesThatWereFiltered(Dictionary<PackageI
return this;
}

public DependencyContext Build((string Path, string DestinationSubPath)[] userRuntimeAssemblies = null)
public DependencyContext Build((AbsolutePath Path, string DestinationSubPath)[] userRuntimeAssemblies = null)
{
CalculateExcludedLibraries();

Expand Down Expand Up @@ -626,7 +626,7 @@ private IEnumerable<ModifiableRuntimeLibrary> GetRuntimePackLibraries()
});
}

private ModifiableRuntimeLibrary GetRuntimeLibrary(DependencyLibrary library, (string Path, string DestinationSubPath)[] userRuntimeAssemblies)
private ModifiableRuntimeLibrary GetRuntimeLibrary(DependencyLibrary library, (AbsolutePath Path, string DestinationSubPath)[] userRuntimeAssemblies)
{
GetCommonLibraryProperties(library,
out string hash,
Expand All @@ -649,11 +649,13 @@ private ModifiableRuntimeLibrary GetRuntimeLibrary(DependencyLibrary library, (s
if (library.Type == "project" && !(referenceProjectInfo is UnreferencedProjectInfo))
{
var fileName = Path.GetFileNameWithoutExtension(library.Path);
(string Path, string DestinationSubPath) assembly = userRuntimeAssemblies is not null
(AbsolutePath Path, string DestinationSubPath) assembly = userRuntimeAssemblies is not null
? userRuntimeAssemblies.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p.Path).Equals(fileName))
: default;
string mainProjectDirectory = Path.GetDirectoryName(_mainProjectInfo.ProjectPath);
string libraryPath = !string.IsNullOrWhiteSpace(library.Path) ? Path.Combine(mainProjectDirectory, library.Path) : null;
var runtimeFile = !string.IsNullOrWhiteSpace(assembly.Path) && File.Exists(assembly.Path) ? CreateRuntimeFile(referenceProjectInfo.OutputName, assembly.Path, assembly.DestinationSubPath) :
!string.IsNullOrWhiteSpace(library.Path) && File.Exists(library.Path) ? CreateRuntimeFile(referenceProjectInfo.OutputName, library.Path) :
libraryPath != null && File.Exists(libraryPath) ? CreateRuntimeFile(referenceProjectInfo.OutputName, libraryPath) :
new RuntimeFile(referenceProjectInfo.OutputName, string.Empty, string.Empty);
runtimeAssemblyGroups.Add(new RuntimeAssetGroup(string.Empty, [runtimeFile]));

Expand Down Expand Up @@ -836,6 +838,9 @@ private RuntimeFile CreateRuntimeFile(string path, string fullPath, string local
}
}

private RuntimeFile CreateRuntimeFile(string path, AbsolutePath fullPath, string localPath = null)
=> CreateRuntimeFile(path, fullPath.Value, localPath);

private static IEnumerable<ResourceAssembly> CreateResourceAssemblies(IEnumerable<ResourceAssemblyInfo> resourceAssemblyInfos)
{
return resourceAssemblyInfos
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,10 @@ internal class FrameworkReferenceResolver
{
private readonly Func<string, string> _getEnvironmentVariable;

/// <summary>
/// Creates an instance that reads environment variables from the process environment.
/// </summary>
public FrameworkReferenceResolver()
: this(Environment.GetEnvironmentVariable)
{
}

/// <summary>
/// Creates an instance that reads environment variables via the supplied delegate.
/// Use this from MSBuild tasks to route reads through TaskEnvironment.
/// Use this from MSBuild tasks to route reads through TaskEnvironment so that
/// per-task isolated environment state (multithreaded mode) is honored.
/// </summary>
public FrameworkReferenceResolver(Func<string, string> getEnvironmentVariable)
{
Expand Down
42 changes: 26 additions & 16 deletions src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ namespace Microsoft.NET.Build.Tasks
/// <summary>
/// Generates the $(project).deps.json file.
/// </summary>
public class GenerateDepsFile : TaskBase
[MSBuildMultiThreadableTask]
public class GenerateDepsFile : TaskBase, IMultiThreadableTask
{
public TaskEnvironment TaskEnvironment { get; set; } = TaskEnvironment.Fallback;

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

Expand Down Expand Up @@ -133,13 +136,14 @@ private Dictionary<PackageIdentity, string> GetFilteredPackages()
return filteredPackages;
}

private void WriteDepsFile(string depsFilePath)
private void WriteDepsFile(AbsolutePath projectPath, AbsolutePath depsFilePath)
{
ProjectContext projectContext = null;
LockFileLookup lockFileLookup = null;
if (AssetsFilePath != null)
{
LockFile lockFile = new LockFileCache(this).GetLockFile(AssetsFilePath);
LockFile lockFile = new LockFileCache(this).GetLockFile(
string.IsNullOrEmpty(AssetsFilePath) ? AssetsFilePath : TaskEnvironment.GetAbsolutePath(AssetsFilePath));
projectContext = lockFile.CreateProjectContext(
TargetFramework,
EffectiveRuntimeIdentifier,
Expand All @@ -153,7 +157,7 @@ private void WriteDepsFile(string depsFilePath)
CompilationOptions compilationOptions = CompilationOptionsConverter.ConvertFrom(CompilerOptions);

SingleProjectInfo mainProject = SingleProjectInfo.Create(
Comment thread
jankratochvilcz marked this conversation as resolved.
Resolved
ProjectPath,
projectPath,
AssemblyName,
AssemblyExtension,
AssemblyVersion,
Expand Down Expand Up @@ -218,8 +222,12 @@ bool ShouldIncludeRuntimeAsset(ITaskItem item)
// If a RID-graph is provided to the DependencyContextBuilder, it generates a RID-fallback
// graph with respect to the target RuntimeIdentifier.

RuntimeGraph runtimeGraph =
IsSelfContained ? new RuntimeGraphCache(this).GetRuntimeGraph(RuntimeGraphPath) : null;
RuntimeGraph runtimeGraph = null;
if (IsSelfContained)
{
runtimeGraph = new RuntimeGraphCache(this).GetRuntimeGraph(
string.IsNullOrEmpty(RuntimeGraphPath) ? RuntimeGraphPath : TaskEnvironment.GetAbsolutePath(RuntimeGraphPath));
}

builder = new DependencyContextBuilder(mainProject, IncludeRuntimeFileVersions, runtimeGraph, projectContext, lockFileLookup);
}
Expand All @@ -229,10 +237,10 @@ bool ShouldIncludeRuntimeAsset(ITaskItem item)
mainProject,
IncludeRuntimeFileVersions,
RuntimeFrameworks,
isSelfContained: IsSelfContained,
platformLibraryName: PlatformLibraryName,
runtimeIdentifier: EffectiveRuntimeIdentifier,
targetFramework: TargetFramework);
EffectiveRuntimeIdentifier,
IsSelfContained,
PlatformLibraryName,
TargetFramework);
}

builder = builder
Expand All @@ -244,23 +252,23 @@ bool ShouldIncludeRuntimeAsset(ITaskItem item)
.WithReferenceProjectInfos(referenceProjects)
.WithRuntimePackAssets(runtimePackAssets)
.WithCompilationOptions(compilationOptions)
.WithReferenceAssembliesPath(new FrameworkReferenceResolver().GetDefaultReferenceAssembliesPath())
.WithReferenceAssembliesPath(new FrameworkReferenceResolver(TaskEnvironment.GetEnvironmentVariable).GetDefaultReferenceAssembliesPath())
.WithPackagesThatWereFiltered(GetFilteredPackages());

if (CompileReferences.Length > 0)
{
builder = builder.WithCompileReferences(ReferenceInfo.CreateReferenceInfos(CompileReferences));
}

var resolvedNuGetFiles = ResolvedNuGetFiles.Select(f => new ResolvedFile(f, false))
var resolvedNuGetFileInfos = ResolvedNuGetFiles.Select(f => new ResolvedFile(f, false))
.Concat(ResolvedRuntimeTargetsFiles.Select(f => new ResolvedFile(f, true)));
builder = builder.WithResolvedNuGetFiles(resolvedNuGetFiles);
builder = builder.WithResolvedNuGetFiles(resolvedNuGetFileInfos);

var userRuntimeAssemblies = UserRuntimeAssemblies.Select(i =>
{
string destinationSubDir = i.GetMetadata(MetadataKeys.DestinationSubDirectory);
string destinationSubPath = string.IsNullOrEmpty(destinationSubDir) ? null : Path.Combine(destinationSubDir, Path.GetFileName(i.ItemSpec));
return (i.ItemSpec, destinationSubPath);
return (TaskEnvironment.GetAbsolutePath(i.ItemSpec), destinationSubPath);
}).ToArray();
DependencyContext dependencyContext = builder.Build(userRuntimeAssemblies);
Comment thread
OvesN marked this conversation as resolved.
Resolved

Expand All @@ -269,7 +277,7 @@ bool ShouldIncludeRuntimeAsset(ITaskItem item)
{
writer.Write(dependencyContext, fileStream);
}
_filesWritten.Add(new TaskItem(depsFilePath));
_filesWritten.Add(new TaskItem(depsFilePath.OriginalValue));

if (ValidRuntimeIdentifierPlatformsForAssets != null)
{
Expand Down Expand Up @@ -310,7 +318,9 @@ private bool ShouldWarnOnRuntimeIdentifer(string runtimeIdentifier)

protected override void ExecuteCore()
{
WriteDepsFile(DepsFilePath);
AbsolutePath absoluteProjectPath = TaskEnvironment.GetAbsolutePath(ProjectPath);
Comment thread
jankratochvilcz marked this conversation as resolved.
Resolved
AbsolutePath absoluteDepsFilePath = TaskEnvironment.GetAbsolutePath(DepsFilePath);
WriteDepsFile(absoluteProjectPath, absoluteDepsFilePath);
}
}
}
4 changes: 4 additions & 0 deletions src/Tasks/Microsoft.NET.Build.Tasks/GetPackageDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ protected override void ExecuteCore()
return;
}

// The package folder paths (PackageFolders and those read from the assets file) are already
// absolute, as they originate from NuGet restore. Likewise, the package directory resolved
// below is an absolute on-disk path. These paths are intentionally not wrapped in AbsolutePath:
// doing so would not change behavior and would only complicate this code.
if (!string.IsNullOrEmpty(AssetsFileWithAdditionalPackageFolders))
{
var lockFileCache = new LockFileCache(this);
Expand Down
Loading
Loading