Memory usage improvements in build (#2626)
* Use a WorkspaceContext in dotnet-build to cache project data across multiple compilations in a single build action * Dramatically reduce string and object duplication by introducing a "Symbol Table" that shares instances of NuGetVersion, NuGetFramework, VersionRange and string across multiple lock-file parses Test Results: * Testing was done by compiling Microsoft.AspNetCore.Mvc (and it's dependencies) and taking memory snapshots after each compilation in dotMemory * We used to allocate ~3MB and deallocate ~2.5MB on EACH compilation in a single build action. This has been reduced to ~120KB allocated/deallocated * After introducing WorkspaceContext, total memory usage spiked from 6MB across the whole build action to about 13MB, introducing the symbol table dropped it back to about 5-6MB.
This commit is contained in:
parent
80df3688b1
commit
ef0ca39da1
42 changed files with 496 additions and 268 deletions
|
@ -1,8 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "1.0.0-*",
|
"version": "1.0.0-*",
|
||||||
"compilationOptions": {
|
|
||||||
"emitEntryPoint": true
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"NETStandard.Library": "1.5.0-rc2-24022",
|
"NETStandard.Library": "1.5.0-rc2-24022",
|
||||||
"System.Runtime.Analyzers": {
|
"System.Runtime.Analyzers": {
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"projects": [ "src", "test", "tools" ]
|
"projects": [ "src", "test", "tools" ]
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,7 +280,7 @@ namespace Microsoft.DotNet.Cli.Build
|
||||||
return rid;
|
return rid;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Target]
|
[Target(nameof(PrepareTargets.Init))]
|
||||||
public static BuildTargetResult CompileStage1(BuildTargetContext c)
|
public static BuildTargetResult CompileStage1(BuildTargetContext c)
|
||||||
{
|
{
|
||||||
CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "src"));
|
CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "src"));
|
||||||
|
@ -305,7 +305,7 @@ namespace Microsoft.DotNet.Cli.Build
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Target]
|
[Target(nameof(PrepareTargets.Init))]
|
||||||
public static BuildTargetResult CompileStage2(BuildTargetContext c)
|
public static BuildTargetResult CompileStage2(BuildTargetContext c)
|
||||||
{
|
{
|
||||||
var configuration = c.BuildContext.Get<string>("Configuration");
|
var configuration = c.BuildContext.Get<string>("Configuration");
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.Utils
|
namespace Microsoft.DotNet.Cli.Utils
|
||||||
{
|
{
|
||||||
|
@ -51,17 +52,16 @@ namespace Microsoft.DotNet.Cli.Utils
|
||||||
// Reset the Reporters to the new Console Out and Error.
|
// Reset the Reporters to the new Console Out and Error.
|
||||||
Reporter.Reset();
|
Reporter.Reset();
|
||||||
|
|
||||||
Thread threadOut = _stdOut.BeginRead(new StreamReader(outStream));
|
var taskOut = _stdOut.BeginRead(new StreamReader(outStream));
|
||||||
Thread threadErr = _stdErr.BeginRead(new StreamReader(errorStream));
|
var taskErr = _stdErr.BeginRead(new StreamReader(errorStream));
|
||||||
|
|
||||||
int exitCode = _builtInCommand(_commandArgs.ToArray());
|
int exitCode = _builtInCommand(_commandArgs.ToArray());
|
||||||
|
|
||||||
outStream.DoneWriting();
|
outStream.DoneWriting();
|
||||||
errorStream.DoneWriting();
|
errorStream.DoneWriting();
|
||||||
|
|
||||||
threadOut.Join();
|
Task.WaitAll(taskOut, taskErr);
|
||||||
threadErr.Join();
|
|
||||||
|
|
||||||
// fake out a ProcessStartInfo using the Muxer command name, since this is a built-in command
|
// fake out a ProcessStartInfo using the Muxer command name, since this is a built-in command
|
||||||
ProcessStartInfo startInfo = new ProcessStartInfo(new Muxer().MuxerPath, $"{CommandName} {CommandArgs}");
|
ProcessStartInfo startInfo = new ProcessStartInfo(new Muxer().MuxerPath, $"{CommandName} {CommandArgs}");
|
||||||
return new CommandResult(startInfo, exitCode, null, null);
|
return new CommandResult(startInfo, exitCode, null, null);
|
||||||
|
|
|
@ -7,8 +7,9 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using NuGet.Frameworks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.DotNet.ProjectModel;
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.Utils
|
namespace Microsoft.DotNet.Cli.Utils
|
||||||
{
|
{
|
||||||
|
@ -131,12 +132,11 @@ namespace Microsoft.DotNet.Cli.Utils
|
||||||
|
|
||||||
Reporter.Verbose.WriteLine($"Process ID: {_process.Id}");
|
Reporter.Verbose.WriteLine($"Process ID: {_process.Id}");
|
||||||
|
|
||||||
var threadOut = _stdOut.BeginRead(_process.StandardOutput);
|
var taskOut = _stdOut.BeginRead(_process.StandardOutput);
|
||||||
var threadErr = _stdErr.BeginRead(_process.StandardError);
|
var taskErr = _stdErr.BeginRead(_process.StandardError);
|
||||||
|
|
||||||
_process.WaitForExit();
|
_process.WaitForExit();
|
||||||
threadOut.Join();
|
|
||||||
threadErr.Join();
|
Task.WaitAll(taskOut, taskErr);
|
||||||
|
|
||||||
var exitCode = _process.ExitCode;
|
var exitCode = _process.ExitCode;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.Utils
|
namespace Microsoft.DotNet.Cli.Utils
|
||||||
{
|
{
|
||||||
|
@ -17,7 +20,7 @@ namespace Microsoft.DotNet.Cli.Utils
|
||||||
|
|
||||||
public string CapturedOutput
|
public string CapturedOutput
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _capture?.GetStringBuilder()?.ToString();
|
return _capture?.GetStringBuilder()?.ToString();
|
||||||
}
|
}
|
||||||
|
@ -43,18 +46,16 @@ namespace Microsoft.DotNet.Cli.Utils
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Thread BeginRead(TextReader reader)
|
public Task BeginRead(TextReader reader)
|
||||||
{
|
{
|
||||||
var thread = new Thread(() => Read(reader)) { IsBackground = true };
|
return Task.Run(() => Read(reader));
|
||||||
thread.Start();
|
|
||||||
return thread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Read(TextReader reader)
|
public void Read(TextReader reader)
|
||||||
{
|
{
|
||||||
var bufferSize = 1;
|
var bufferSize = 1;
|
||||||
|
|
||||||
int readCharacterCount;
|
int readCharacterCount;
|
||||||
char currentCharacter;
|
char currentCharacter;
|
||||||
|
|
||||||
var buffer = new char[bufferSize];
|
var buffer = new char[bufferSize];
|
||||||
|
@ -93,7 +94,7 @@ namespace Microsoft.DotNet.Cli.Utils
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteLine(string str)
|
private void WriteLine(string str)
|
||||||
{
|
{
|
||||||
if (_capture != null)
|
if (_capture != null)
|
||||||
{
|
{
|
||||||
_capture.WriteLine(str);
|
_capture.WriteLine(str);
|
||||||
|
|
|
@ -13,10 +13,12 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
{
|
{
|
||||||
private readonly LockFile _lockFile;
|
private readonly LockFile _lockFile;
|
||||||
private Dictionary<string, IList<LockFileTargetLibrary>> _msbuildTargetLibraries;
|
private Dictionary<string, IList<LockFileTargetLibrary>> _msbuildTargetLibraries;
|
||||||
|
private readonly LockFileReader _reader;
|
||||||
|
|
||||||
public LockFilePatcher(LockFile lockFile)
|
public LockFilePatcher(LockFile lockFile, LockFileReader reader)
|
||||||
{
|
{
|
||||||
_lockFile = lockFile;
|
_lockFile = lockFile;
|
||||||
|
_reader = reader;
|
||||||
|
|
||||||
var msbuildProjectLibraries = lockFile.ProjectLibraries.Where(MSBuildDependencyProvider.IsMSBuildProjectLibrary);
|
var msbuildProjectLibraries = lockFile.ProjectLibraries.Where(MSBuildDependencyProvider.IsMSBuildProjectLibrary);
|
||||||
_msbuildTargetLibraries = msbuildProjectLibraries.ToDictionary(GetProjectLibraryKey, l => GetTargetsForLibrary(_lockFile, l));
|
_msbuildTargetLibraries = msbuildProjectLibraries.ToDictionary(GetProjectLibraryKey, l => GetTargetsForLibrary(_lockFile, l));
|
||||||
|
@ -27,8 +29,8 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
var exportFilePath = GetExportFilePath(_lockFile.LockFilePath);
|
var exportFilePath = GetExportFilePath(_lockFile.LockFilePath);
|
||||||
if (File.Exists(exportFilePath) && _msbuildTargetLibraries.Any())
|
if (File.Exists(exportFilePath) && _msbuildTargetLibraries.Any())
|
||||||
{
|
{
|
||||||
var exportFile = LockFileReader.ReadExportFile(exportFilePath);
|
var exportFile = _reader.ReadExportFile(exportFilePath);
|
||||||
PatchLockWithExport(exportFile);
|
PatchLockWithExport(exportFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,15 +13,24 @@ using NuGet.Versioning;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.ProjectModel.Graph
|
namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
{
|
{
|
||||||
public static class LockFileReader
|
public class LockFileReader
|
||||||
{
|
{
|
||||||
|
private readonly LockFileSymbolTable _symbols;
|
||||||
|
|
||||||
|
public LockFileReader() : this(new LockFileSymbolTable()) { }
|
||||||
|
|
||||||
|
public LockFileReader(LockFileSymbolTable symbols)
|
||||||
|
{
|
||||||
|
_symbols = symbols;
|
||||||
|
}
|
||||||
|
|
||||||
public static LockFile Read(string lockFilePath, bool designTime)
|
public static LockFile Read(string lockFilePath, bool designTime)
|
||||||
{
|
{
|
||||||
using (var stream = ResilientFileStreamOpener.OpenFile(lockFilePath))
|
using (var stream = ResilientFileStreamOpener.OpenFile(lockFilePath))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return Read(lockFilePath, stream, designTime);
|
return new LockFileReader().ReadLockFile(lockFilePath, stream, designTime);
|
||||||
}
|
}
|
||||||
catch (FileFormatException ex)
|
catch (FileFormatException ex)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +43,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LockFile Read(string lockFilePath, Stream stream, bool designTime)
|
public LockFile ReadLockFile(string lockFilePath, Stream stream, bool designTime)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -47,10 +56,10 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
}
|
}
|
||||||
|
|
||||||
var lockFile = ReadLockFile(lockFilePath, jobject);
|
var lockFile = ReadLockFile(lockFilePath, jobject);
|
||||||
|
|
||||||
if (!designTime)
|
if (!designTime)
|
||||||
{
|
{
|
||||||
var patcher = new LockFilePatcher(lockFile);
|
var patcher = new LockFilePatcher(lockFile, this);
|
||||||
patcher.Patch();
|
patcher.Patch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +79,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExportFile ReadExportFile(string fragmentLockFilePath)
|
public ExportFile ReadExportFile(string fragmentLockFilePath)
|
||||||
{
|
{
|
||||||
using (var stream = ResilientFileStreamOpener.OpenFile(fragmentLockFilePath))
|
using (var stream = ResilientFileStreamOpener.OpenFile(fragmentLockFilePath))
|
||||||
{
|
{
|
||||||
|
@ -100,7 +109,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LockFile ReadLockFile(string lockFilePath, JsonObject cursor)
|
private LockFile ReadLockFile(string lockFilePath, JsonObject cursor)
|
||||||
{
|
{
|
||||||
var lockFile = new LockFile(lockFilePath);
|
var lockFile = new LockFile(lockFilePath);
|
||||||
lockFile.Version = ReadInt(cursor, "version", defaultValue: int.MinValue);
|
lockFile.Version = ReadInt(cursor, "version", defaultValue: int.MinValue);
|
||||||
|
@ -111,7 +120,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
return lockFile;
|
return lockFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReadLibrary(JsonObject json, LockFile lockFile)
|
private void ReadLibrary(JsonObject json, LockFile lockFile)
|
||||||
{
|
{
|
||||||
if (json == null)
|
if (json == null)
|
||||||
{
|
{
|
||||||
|
@ -128,9 +137,9 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
|
|
||||||
var parts = key.Split(new[] { '/' }, 2);
|
var parts = key.Split(new[] { '/' }, 2);
|
||||||
var name = parts[0];
|
var name = parts[0];
|
||||||
var version = parts.Length == 2 ? NuGetVersion.Parse(parts[1]) : null;
|
var version = parts.Length == 2 ? _symbols.GetVersion(parts[1]) : null;
|
||||||
|
|
||||||
var type = value.ValueAsString("type")?.Value;
|
var type = _symbols.GetString(value.ValueAsString("type")?.Value);
|
||||||
|
|
||||||
if (type == null || string.Equals(type, "package", StringComparison.OrdinalIgnoreCase))
|
if (type == null || string.Equals(type, "package", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
@ -162,7 +171,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LockFileTarget ReadTarget(string property, JsonValue json)
|
private LockFileTarget ReadTarget(string property, JsonValue json)
|
||||||
{
|
{
|
||||||
var jobject = json as JsonObject;
|
var jobject = json as JsonObject;
|
||||||
if (jobject == null)
|
if (jobject == null)
|
||||||
|
@ -172,10 +181,10 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
|
|
||||||
var target = new LockFileTarget();
|
var target = new LockFileTarget();
|
||||||
var parts = property.Split(new[] { '/' }, 2);
|
var parts = property.Split(new[] { '/' }, 2);
|
||||||
target.TargetFramework = NuGetFramework.Parse(parts[0]);
|
target.TargetFramework = _symbols.GetFramework(parts[0]);
|
||||||
if (parts.Length == 2)
|
if (parts.Length == 2)
|
||||||
{
|
{
|
||||||
target.RuntimeIdentifier = parts[1];
|
target.RuntimeIdentifier = _symbols.GetString(parts[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
target.Libraries = ReadObject(jobject, ReadTargetLibrary);
|
target.Libraries = ReadObject(jobject, ReadTargetLibrary);
|
||||||
|
@ -183,7 +192,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LockFileTargetLibrary ReadTargetLibrary(string property, JsonValue json)
|
private LockFileTargetLibrary ReadTargetLibrary(string property, JsonValue json)
|
||||||
{
|
{
|
||||||
var jobject = json as JsonObject;
|
var jobject = json as JsonObject;
|
||||||
if (jobject == null)
|
if (jobject == null)
|
||||||
|
@ -194,17 +203,17 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
var library = new LockFileTargetLibrary();
|
var library = new LockFileTargetLibrary();
|
||||||
|
|
||||||
var parts = property.Split(new[] { '/' }, 2);
|
var parts = property.Split(new[] { '/' }, 2);
|
||||||
library.Name = parts[0];
|
library.Name = _symbols.GetString(parts[0]);
|
||||||
if (parts.Length == 2)
|
if (parts.Length == 2)
|
||||||
{
|
{
|
||||||
library.Version = NuGetVersion.Parse(parts[1]);
|
library.Version = _symbols.GetVersion(parts[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
library.Type = jobject.ValueAsString("type");
|
library.Type = _symbols.GetString(jobject.ValueAsString("type"));
|
||||||
var framework = jobject.ValueAsString("framework");
|
var framework = jobject.ValueAsString("framework");
|
||||||
if (framework != null)
|
if (framework != null)
|
||||||
{
|
{
|
||||||
library.TargetFramework = NuGetFramework.Parse(framework);
|
library.TargetFramework = _symbols.GetFramework(framework);
|
||||||
}
|
}
|
||||||
|
|
||||||
library.Dependencies = ReadObject(jobject.ValueAsJsonObject("dependencies"), ReadPackageDependency);
|
library.Dependencies = ReadObject(jobject.ValueAsJsonObject("dependencies"), ReadPackageDependency);
|
||||||
|
@ -215,10 +224,11 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
library.NativeLibraries = ReadObject(jobject.ValueAsJsonObject("native"), ReadFileItem);
|
library.NativeLibraries = ReadObject(jobject.ValueAsJsonObject("native"), ReadFileItem);
|
||||||
library.ContentFiles = ReadObject(jobject.ValueAsJsonObject("contentFiles"), ReadContentFile);
|
library.ContentFiles = ReadObject(jobject.ValueAsJsonObject("contentFiles"), ReadContentFile);
|
||||||
library.RuntimeTargets = ReadObject(jobject.ValueAsJsonObject("runtimeTargets"), ReadRuntimeTarget);
|
library.RuntimeTargets = ReadObject(jobject.ValueAsJsonObject("runtimeTargets"), ReadRuntimeTarget);
|
||||||
|
|
||||||
return library;
|
return library;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LockFileRuntimeTarget ReadRuntimeTarget(string property, JsonValue json)
|
private LockFileRuntimeTarget ReadRuntimeTarget(string property, JsonValue json)
|
||||||
{
|
{
|
||||||
var jsonObject = json as JsonObject;
|
var jsonObject = json as JsonObject;
|
||||||
if (jsonObject == null)
|
if (jsonObject == null)
|
||||||
|
@ -227,13 +237,13 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LockFileRuntimeTarget(
|
return new LockFileRuntimeTarget(
|
||||||
path: property,
|
path: _symbols.GetString(property),
|
||||||
runtime: jsonObject.ValueAsString("rid"),
|
runtime: _symbols.GetString(jsonObject.ValueAsString("rid")),
|
||||||
assetType: jsonObject.ValueAsString("assetType")
|
assetType: _symbols.GetString(jsonObject.ValueAsString("assetType"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LockFileContentFile ReadContentFile(string property, JsonValue json)
|
private LockFileContentFile ReadContentFile(string property, JsonValue json)
|
||||||
{
|
{
|
||||||
var contentFile = new LockFileContentFile()
|
var contentFile = new LockFileContentFile()
|
||||||
{
|
{
|
||||||
|
@ -248,7 +258,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
BuildAction.TryParse(jsonObject.ValueAsString("buildAction"), out action);
|
BuildAction.TryParse(jsonObject.ValueAsString("buildAction"), out action);
|
||||||
|
|
||||||
contentFile.BuildAction = action;
|
contentFile.BuildAction = action;
|
||||||
var codeLanguage = jsonObject.ValueAsString("codeLanguage");
|
var codeLanguage = _symbols.GetString(jsonObject.ValueAsString("codeLanguage"));
|
||||||
if (codeLanguage == "any")
|
if (codeLanguage == "any")
|
||||||
{
|
{
|
||||||
codeLanguage = null;
|
codeLanguage = null;
|
||||||
|
@ -262,37 +272,37 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
return contentFile;
|
return contentFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ProjectFileDependencyGroup ReadProjectFileDependencyGroup(string property, JsonValue json)
|
private ProjectFileDependencyGroup ReadProjectFileDependencyGroup(string property, JsonValue json)
|
||||||
{
|
{
|
||||||
return new ProjectFileDependencyGroup(
|
return new ProjectFileDependencyGroup(
|
||||||
string.IsNullOrEmpty(property) ? null : NuGetFramework.Parse(property),
|
string.IsNullOrEmpty(property) ? null : NuGetFramework.Parse(property),
|
||||||
ReadArray(json, ReadString));
|
ReadArray(json, ReadString));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PackageDependency ReadPackageDependency(string property, JsonValue json)
|
private PackageDependency ReadPackageDependency(string property, JsonValue json)
|
||||||
{
|
{
|
||||||
var versionStr = ReadString(json);
|
var versionStr = ReadString(json);
|
||||||
return new PackageDependency(
|
return new PackageDependency(
|
||||||
property,
|
_symbols.GetString(property),
|
||||||
versionStr == null ? null : VersionRange.Parse(versionStr));
|
versionStr == null ? null : _symbols.GetVersionRange(versionStr));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LockFileItem ReadFileItem(string property, JsonValue json)
|
private LockFileItem ReadFileItem(string property, JsonValue json)
|
||||||
{
|
{
|
||||||
var item = new LockFileItem { Path = PathUtility.GetPathWithDirectorySeparator(property) };
|
var item = new LockFileItem { Path = _symbols.GetString(PathUtility.GetPathWithDirectorySeparator(property)) };
|
||||||
var jobject = json as JsonObject;
|
var jobject = json as JsonObject;
|
||||||
|
|
||||||
if (jobject != null)
|
if (jobject != null)
|
||||||
{
|
{
|
||||||
foreach (var subProperty in jobject.Keys)
|
foreach (var subProperty in jobject.Keys)
|
||||||
{
|
{
|
||||||
item.Properties[subProperty] = jobject.ValueAsString(subProperty);
|
item.Properties[_symbols.GetString(subProperty)] = jobject.ValueAsString(subProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ReadFrameworkAssemblyReference(JsonValue json)
|
private string ReadFrameworkAssemblyReference(JsonValue json)
|
||||||
{
|
{
|
||||||
return ReadString(json);
|
return ReadString(json);
|
||||||
}
|
}
|
||||||
|
@ -318,9 +328,9 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IList<string> ReadPathArray(JsonValue json, Func<JsonValue, string> readItem)
|
private IList<string> ReadPathArray(JsonValue json, Func<JsonValue, string> readItem)
|
||||||
{
|
{
|
||||||
return ReadArray(json, readItem).Select(f => PathUtility.GetPathWithDirectorySeparator(f)).ToList();
|
return ReadArray(json, readItem).Select(f => _symbols.GetString(PathUtility.GetPathWithDirectorySeparator(f))).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IList<TItem> ReadObject<TItem>(JsonObject json, Func<string, JsonValue, TItem> readItem)
|
private static IList<TItem> ReadObject<TItem>(JsonObject json, Func<string, JsonValue, TItem> readItem)
|
||||||
|
@ -368,11 +378,11 @@ namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ReadString(JsonValue json)
|
private string ReadString(JsonValue json)
|
||||||
{
|
{
|
||||||
if (json is JsonString)
|
if (json is JsonString)
|
||||||
{
|
{
|
||||||
return (json as JsonString).Value;
|
return _symbols.GetString((json as JsonString).Value);
|
||||||
}
|
}
|
||||||
else if (json is JsonNull)
|
else if (json is JsonNull)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.ProjectModel.Graph
|
||||||
|
{
|
||||||
|
public class LockFileSymbolTable
|
||||||
|
{
|
||||||
|
private ConcurrentDictionary<string, NuGetVersion> _versionTable = new ConcurrentDictionary<string, NuGetVersion>(Environment.ProcessorCount * 4, 1000, StringComparer.Ordinal);
|
||||||
|
private ConcurrentDictionary<string, VersionRange> _versionRangeTable = new ConcurrentDictionary<string, VersionRange>(Environment.ProcessorCount * 4, 1000, StringComparer.Ordinal);
|
||||||
|
private ConcurrentDictionary<string, NuGetFramework> _frameworksTable = new ConcurrentDictionary<string, NuGetFramework>(Environment.ProcessorCount * 4, 1000, StringComparer.Ordinal);
|
||||||
|
private ConcurrentDictionary<string, string> _stringsTable = new ConcurrentDictionary<string, string>(Environment.ProcessorCount * 4, 1000, StringComparer.Ordinal);
|
||||||
|
|
||||||
|
public NuGetVersion GetVersion(string versionString) => _versionTable.GetOrAdd(versionString, (s) => NuGetVersion.Parse(s));
|
||||||
|
public VersionRange GetVersionRange(string versionRangeString) => _versionRangeTable.GetOrAdd(versionRangeString, (s) => VersionRange.Parse(s));
|
||||||
|
public NuGetFramework GetFramework(string frameworkString) => _frameworksTable.GetOrAdd(frameworkString, (s) => NuGetFramework.Parse(s));
|
||||||
|
public string GetString(string frameworkString) => _stringsTable.GetOrAdd(frameworkString, frameworkString);
|
||||||
|
}
|
||||||
|
}
|
|
@ -154,39 +154,6 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
.BuildAllTargets();
|
.BuildAllTargets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a project context based on existing context but using runtime target
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context"></param>
|
|
||||||
/// <param name="runtimeIdentifiers"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
|
|
||||||
public ProjectContext CreateRuntimeContext(IEnumerable<string> runtimeIdentifiers)
|
|
||||||
{
|
|
||||||
// Temporary until we have removed RID inference from NuGet
|
|
||||||
if(TargetFramework.IsCompileOnly)
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
var context = CreateBuilder(ProjectFile.ProjectFilePath, TargetFramework)
|
|
||||||
.WithRuntimeIdentifiers(runtimeIdentifiers)
|
|
||||||
.WithLockFile(LockFile)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
if (!context.IsPortable && context.RuntimeIdentifier == null)
|
|
||||||
{
|
|
||||||
// We are standalone, but don't support this runtime
|
|
||||||
var rids = string.Join(", ", runtimeIdentifiers);
|
|
||||||
throw new InvalidOperationException($"Can not find runtime target for framework '{TargetFramework}' compatible with one of the target runtimes: '{rids}'. " +
|
|
||||||
"Possible causes:" + Environment.NewLine +
|
|
||||||
"1. The project has not been restored or restore failed - run `dotnet restore`" + Environment.NewLine +
|
|
||||||
$"2. The project does not list one of '{rids}' in the 'runtimes' section.");
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OutputPaths GetOutputPaths(string configuration, string buidBasePath = null, string outputPath = null)
|
public OutputPaths GetOutputPaths(string configuration, string buidBasePath = null, string outputPath = null)
|
||||||
{
|
{
|
||||||
return OutputPathsCalculator.GetOutputPaths(ProjectFile,
|
return OutputPathsCalculator.GetOutputPaths(ProjectFile,
|
||||||
|
|
|
@ -132,16 +132,42 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
EnsureProjectLoaded();
|
EnsureProjectLoaded();
|
||||||
LockFile = LockFile ?? LockFileResolver(ProjectDirectory);
|
LockFile = LockFile ?? LockFileResolver(ProjectDirectory);
|
||||||
|
|
||||||
if (LockFile != null)
|
if (LockFile != null && LockFile.Targets.Any())
|
||||||
{
|
{
|
||||||
|
var deduper = new HashSet<string>();
|
||||||
foreach (var target in LockFile.Targets)
|
foreach (var target in LockFile.Targets)
|
||||||
{
|
{
|
||||||
yield return new ProjectContextBuilder()
|
var id = $"{target.TargetFramework}/{target.RuntimeIdentifier}";
|
||||||
.WithProject(Project)
|
if (deduper.Add(id))
|
||||||
.WithLockFile(LockFile)
|
{
|
||||||
.WithTargetFramework(target.TargetFramework)
|
var builder = new ProjectContextBuilder()
|
||||||
.WithRuntimeIdentifiers(new[] { target.RuntimeIdentifier })
|
.WithProject(Project)
|
||||||
.Build();
|
.WithLockFile(LockFile)
|
||||||
|
.WithTargetFramework(target.TargetFramework)
|
||||||
|
.WithRuntimeIdentifiers(new[] { target.RuntimeIdentifier });
|
||||||
|
if (IsDesignTime)
|
||||||
|
{
|
||||||
|
builder.AsDesignTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return builder.Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Build a context for each framework. It won't be fully valid, since it won't have resolved data or runtime data, but the diagnostics will show that
|
||||||
|
// (Project Model Server needs this)
|
||||||
|
foreach (var framework in Project.GetTargetFrameworks())
|
||||||
|
{
|
||||||
|
var builder = new ProjectContextBuilder()
|
||||||
|
.WithProject(Project)
|
||||||
|
.WithTargetFramework(framework.FrameworkName);
|
||||||
|
if (IsDesignTime)
|
||||||
|
{
|
||||||
|
builder.AsDesignTime();
|
||||||
|
}
|
||||||
|
yield return builder.Build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,8 +191,17 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
|
|
||||||
RootDirectory = GlobalSettings?.DirectoryPath ?? RootDirectory;
|
RootDirectory = GlobalSettings?.DirectoryPath ?? RootDirectory;
|
||||||
PackagesDirectory = PackagesDirectory ?? PackageDependencyProvider.ResolvePackagesPath(RootDirectory, GlobalSettings);
|
PackagesDirectory = PackagesDirectory ?? PackageDependencyProvider.ResolvePackagesPath(RootDirectory, GlobalSettings);
|
||||||
ReferenceAssembliesPath = ReferenceAssembliesPath ?? FrameworkReferenceResolver.GetDefaultReferenceAssembliesPath();
|
|
||||||
var frameworkReferenceResolver = new FrameworkReferenceResolver(ReferenceAssembliesPath);
|
FrameworkReferenceResolver frameworkReferenceResolver;
|
||||||
|
if (string.IsNullOrEmpty(ReferenceAssembliesPath))
|
||||||
|
{
|
||||||
|
// Use the default static resolver
|
||||||
|
frameworkReferenceResolver = FrameworkReferenceResolver.Default;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frameworkReferenceResolver = new FrameworkReferenceResolver(ReferenceAssembliesPath);
|
||||||
|
}
|
||||||
|
|
||||||
LockFileLookup lockFileLookup = null;
|
LockFileLookup lockFileLookup = null;
|
||||||
EnsureProjectLoaded();
|
EnsureProjectLoaded();
|
||||||
|
@ -202,7 +237,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
if (mainProject != null)
|
if (mainProject != null)
|
||||||
{
|
{
|
||||||
platformDependency = mainProject.Dependencies
|
platformDependency = mainProject.Dependencies
|
||||||
.Where(d => d.Type.Equals(LibraryDependencyType.Platform))
|
.Where(d => d.Type.Equals(LibraryDependencyType.Platform))
|
||||||
.Cast<LibraryRange?>()
|
.Cast<LibraryRange?>()
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
@ -274,7 +309,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
var frameworkInfo = Project.GetTargetFramework(TargetFramework);
|
var frameworkInfo = Project.GetTargetFramework(TargetFramework);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(ReferenceAssembliesPath))
|
if (frameworkReferenceResolver == null || string.IsNullOrEmpty(frameworkReferenceResolver.ReferenceAssembliesPath))
|
||||||
{
|
{
|
||||||
// If there was an attempt to use reference assemblies but they were not installed
|
// If there was an attempt to use reference assemblies but they were not installed
|
||||||
// report an error
|
// report an error
|
||||||
|
@ -373,13 +408,13 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
var library = pair.Value;
|
var library = pair.Value;
|
||||||
|
|
||||||
// The System.* packages provide placeholders on any non netstandard platform
|
// The System.* packages provide placeholders on any non netstandard platform
|
||||||
// To make them work seamlessly on those platforms, we fill the gap with a reference
|
// To make them work seamlessly on those platforms, we fill the gap with a reference
|
||||||
// assembly (if available)
|
// assembly (if available)
|
||||||
var package = library as PackageDescription;
|
var package = library as PackageDescription;
|
||||||
if (package != null &&
|
if (package != null &&
|
||||||
package.Resolved &&
|
package.Resolved &&
|
||||||
package.HasCompileTimePlaceholder &&
|
package.HasCompileTimePlaceholder &&
|
||||||
!TargetFramework.IsPackageBased())
|
!TargetFramework.IsPackageBased())
|
||||||
{
|
{
|
||||||
var newKey = new LibraryKey(library.Identity.Name, LibraryType.ReferenceAssembly);
|
var newKey = new LibraryKey(library.Identity.Name, LibraryType.ReferenceAssembly);
|
||||||
|
@ -583,7 +618,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
|
|
||||||
return combiner.CombinedHash;
|
return combiner.CombinedHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Name + " " + LibraryType;
|
return Name + " " + LibraryType;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.ProjectModel
|
namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
|
@ -13,6 +15,8 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
|
|
||||||
public List<ProjectContext> ProjectContexts { get; } = new List<ProjectContext>();
|
public List<ProjectContext> ProjectContexts { get; } = new List<ProjectContext>();
|
||||||
|
|
||||||
|
public IEnumerable<ProjectContext> FrameworkOnlyContexts => ProjectContexts.Where(c => string.IsNullOrEmpty(c.RuntimeIdentifier));
|
||||||
|
|
||||||
public List<DiagnosticMessage> ProjectDiagnostics { get; } = new List<DiagnosticMessage>();
|
public List<DiagnosticMessage> ProjectDiagnostics { get; } = new List<DiagnosticMessage>();
|
||||||
|
|
||||||
public string LockFilePath { get; set; }
|
public string LockFilePath { get; set; }
|
||||||
|
@ -51,6 +55,16 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProjectContext GetTarget(NuGetFramework targetFramework) => GetTarget(targetFramework, string.Empty);
|
||||||
|
|
||||||
|
public ProjectContext GetTarget(NuGetFramework targetFramework, string runtimeIdentifier)
|
||||||
|
{
|
||||||
|
return ProjectContexts
|
||||||
|
.FirstOrDefault(c =>
|
||||||
|
Equals(c.TargetFramework, targetFramework) &&
|
||||||
|
string.Equals(c.RuntimeIdentifier ?? string.Empty, runtimeIdentifier ?? string.Empty));
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
Project = null;
|
Project = null;
|
||||||
|
|
|
@ -85,8 +85,16 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
var project = new Project();
|
var project = new Project();
|
||||||
|
|
||||||
var reader = new StreamReader(stream);
|
var reader = new StreamReader(stream);
|
||||||
|
JObject rawProject;
|
||||||
|
using (var jsonReader = new JsonTextReader(reader))
|
||||||
|
{
|
||||||
|
rawProject = JObject.Load(jsonReader);
|
||||||
|
|
||||||
|
// Try to read another token to ensure we're at the end of the document.
|
||||||
|
// This will no-op if we are, and throw a JsonReaderException if there is additional content (which is what we want)
|
||||||
|
jsonReader.Read();
|
||||||
|
}
|
||||||
|
|
||||||
var rawProject = JObject.Parse(reader.ReadToEnd());
|
|
||||||
if (rawProject == null)
|
if (rawProject == null)
|
||||||
{
|
{
|
||||||
throw FileFormatException.Create(
|
throw FileFormatException.Create(
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Microsoft.DotNet.ProjectModel.Utilities;
|
using Microsoft.DotNet.ProjectModel.Utilities;
|
||||||
using Microsoft.Extensions.DependencyModel.Resolution;
|
using Microsoft.Extensions.DependencyModel.Resolution;
|
||||||
|
@ -23,7 +25,7 @@ namespace Microsoft.DotNet.ProjectModel.Resolution
|
||||||
|
|
||||||
private static FrameworkReferenceResolver _default;
|
private static FrameworkReferenceResolver _default;
|
||||||
|
|
||||||
private readonly IDictionary<NuGetFramework, FrameworkInformation> _cache = new Dictionary<NuGetFramework, FrameworkInformation>();
|
private readonly ConcurrentDictionary<NuGetFramework, FrameworkInformation> _cache = new ConcurrentDictionary<NuGetFramework, FrameworkInformation>();
|
||||||
|
|
||||||
private static readonly IDictionary<NuGetFramework, NuGetFramework[]> _aliases = new Dictionary<NuGetFramework, NuGetFramework[]>
|
private static readonly IDictionary<NuGetFramework, NuGetFramework[]> _aliases = new Dictionary<NuGetFramework, NuGetFramework[]>
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace Microsoft.DotNet.ProjectModel.Resolution
|
||||||
LibraryDependencyType.Default));
|
LibraryDependencyType.Default));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!targetFramework.IsPackageBased)
|
if (!targetFramework.IsPackageBased())
|
||||||
{
|
{
|
||||||
// Only add framework assemblies for non-package based frameworks.
|
// Only add framework assemblies for non-package based frameworks.
|
||||||
foreach (var frameworkAssembly in targetLibrary.FrameworkAssemblies)
|
foreach (var frameworkAssembly in targetLibrary.FrameworkAssemblies)
|
||||||
|
|
|
@ -138,7 +138,7 @@ namespace Microsoft.DotNet.ProjectModel.Resolution
|
||||||
LibraryDependencyType.Default));
|
LibraryDependencyType.Default));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!targetFramework.IsPackageBased)
|
if (!targetFramework.IsPackageBased())
|
||||||
{
|
{
|
||||||
// Only add framework assemblies for non-package based frameworks.
|
// Only add framework assemblies for non-package based frameworks.
|
||||||
foreach (var frameworkAssembly in targetLibrary.FrameworkAssemblies)
|
foreach (var frameworkAssembly in targetLibrary.FrameworkAssemblies)
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace NuGet.Frameworks
|
||||||
}
|
}
|
||||||
return name + "-" + frameworkName.Profile;
|
return name + "-" + frameworkName.Profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool IsPackageBased(this NuGetFramework self)
|
internal static bool IsPackageBased(this NuGetFramework self)
|
||||||
{
|
{
|
||||||
return self.IsPackageBased ||
|
return self.IsPackageBased ||
|
||||||
|
|
|
@ -13,18 +13,18 @@ namespace Microsoft.DotNet.ProjectModel.Utilities
|
||||||
{
|
{
|
||||||
return OpenFile(filepath, 0);
|
return OpenFile(filepath, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileStream OpenFile(string filepath, int retry)
|
public static FileStream OpenFile(string filepath, int retry)
|
||||||
{
|
{
|
||||||
if (retry < 0)
|
if (retry < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Retry can't be fewer than 0", nameof(retry));
|
throw new ArgumentException("Retry can't be fewer than 0", nameof(retry));
|
||||||
}
|
}
|
||||||
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
return new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.DotNet.ProjectModel.Graph;
|
using Microsoft.DotNet.ProjectModel.Graph;
|
||||||
using Microsoft.DotNet.ProjectModel.Utilities;
|
using Microsoft.DotNet.ProjectModel.Utilities;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.ProjectModel
|
namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
|
@ -28,9 +29,16 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
private readonly HashSet<string> _projects = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
private readonly HashSet<string> _projects = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
private bool _needRefresh;
|
private bool _needRefresh;
|
||||||
|
private readonly ProjectReaderSettings _settings;
|
||||||
|
private readonly bool _designTime;
|
||||||
|
private readonly LockFileReader _lockFileReader;
|
||||||
|
|
||||||
private WorkspaceContext(IEnumerable<string> projectPaths)
|
private WorkspaceContext(IEnumerable<string> projectPaths, ProjectReaderSettings settings, bool designTime)
|
||||||
{
|
{
|
||||||
|
_settings = settings;
|
||||||
|
_designTime = designTime;
|
||||||
|
_lockFileReader = new LockFileReader();
|
||||||
|
|
||||||
foreach (var path in projectPaths)
|
foreach (var path in projectPaths)
|
||||||
{
|
{
|
||||||
AddProject(path);
|
AddProject(path);
|
||||||
|
@ -41,31 +49,60 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a WorkspaceContext from a given path.
|
/// Create a WorkspaceContext from a given path.
|
||||||
///
|
///
|
||||||
/// There must be either a global.json or project.json at under the given path. Otherwise
|
|
||||||
/// null is returned.
|
|
||||||
///
|
|
||||||
/// If the given path points to a global.json, all the projects found under the search paths
|
/// If the given path points to a global.json, all the projects found under the search paths
|
||||||
/// are added to the WorkspaceContext.
|
/// are added to the WorkspaceContext.
|
||||||
///
|
///
|
||||||
/// If the given path points to a project.json, all the projects it referenced as well as itself
|
/// If the given path points to a project.json, all the projects it referenced as well as itself
|
||||||
/// are added to the WorkspaceContext.
|
/// are added to the WorkspaceContext.
|
||||||
|
///
|
||||||
|
/// If no path is provided, the workspace context is created empty and projects must be manually added
|
||||||
|
/// to it using <see cref="AddProject(string)"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static WorkspaceContext CreateFrom(string projectPath)
|
public static WorkspaceContext CreateFrom(string projectPath, bool designTime)
|
||||||
{
|
{
|
||||||
var projectPaths = ResolveProjectPath(projectPath);
|
var projectPaths = ResolveProjectPath(projectPath);
|
||||||
if (projectPaths == null || !projectPaths.Any())
|
if (projectPaths == null || !projectPaths.Any())
|
||||||
{
|
{
|
||||||
return null;
|
return new WorkspaceContext(Enumerable.Empty<string>(), ProjectReaderSettings.ReadFromEnvironment(), designTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
var context = new WorkspaceContext(projectPaths);
|
var context = new WorkspaceContext(projectPaths, ProjectReaderSettings.ReadFromEnvironment(), designTime);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WorkspaceContext Create()
|
/// <summary>
|
||||||
|
/// Create an empty <see cref="WorkspaceContext" /> using the default <see cref="ProjectReaderSettings" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="designTime">A boolean indicating if the workspace should be created in Design-Time mode</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static WorkspaceContext Create(bool designTime) => Create(ProjectReaderSettings.ReadFromEnvironment(), designTime);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create an empty <see cref="WorkspaceContext" /> using the default <see cref="ProjectReaderSettings" />, with the specified Version Suffix
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="versionSuffix">The suffix to use to replace any '-*' snapshot tokens in Project versions.</param>
|
||||||
|
/// <param name="designTime">A boolean indicating if the workspace should be created in Design-Time mode</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static WorkspaceContext Create(string versionSuffix, bool designTime)
|
||||||
{
|
{
|
||||||
return new WorkspaceContext(Enumerable.Empty<string>());
|
var settings = ProjectReaderSettings.ReadFromEnvironment();
|
||||||
|
if (!string.IsNullOrEmpty(versionSuffix))
|
||||||
|
{
|
||||||
|
settings.VersionSuffix = versionSuffix;
|
||||||
|
}
|
||||||
|
return Create(settings, designTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create an empty <see cref="WorkspaceContext" /> using the provided <see cref="ProjectReaderSettings" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="settings">The settings to use when reading projects</param>
|
||||||
|
/// <param name="designTime">A boolean indicating if the workspace should be created in Design-Time mode</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static WorkspaceContext Create(ProjectReaderSettings settings, bool designTime)
|
||||||
|
{
|
||||||
|
return new WorkspaceContext(Enumerable.Empty<string>(), settings, designTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddProject(string path)
|
public void AddProject(string path)
|
||||||
|
@ -104,7 +141,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
|
|
||||||
foreach (var projectDirectory in basePaths)
|
foreach (var projectDirectory in basePaths)
|
||||||
{
|
{
|
||||||
var project = GetProject(projectDirectory).Model;
|
var project = GetProjectCore(projectDirectory).Model;
|
||||||
if (project == null)
|
if (project == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -116,7 +153,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
foreach (var reference in GetProjectReferences(projectContext))
|
foreach (var reference in GetProjectReferences(projectContext))
|
||||||
{
|
{
|
||||||
var referencedProject = GetProject(reference.Path).Model;
|
var referencedProject = GetProjectCore(reference.Path).Model;
|
||||||
if (referencedProject != null)
|
if (referencedProject != null)
|
||||||
{
|
{
|
||||||
_projects.Add(referencedProject.ProjectDirectory);
|
_projects.Add(referencedProject.ProjectDirectory);
|
||||||
|
@ -130,29 +167,100 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
|
|
||||||
public IReadOnlyList<ProjectContext> GetProjectContexts(string projectPath)
|
public IReadOnlyList<ProjectContext> GetProjectContexts(string projectPath)
|
||||||
{
|
{
|
||||||
return GetProjectContextCollection(projectPath).ProjectContexts;
|
return (IReadOnlyList<ProjectContext>)GetProjectContextCollection(projectPath)?.ProjectContexts.AsReadOnly() ??
|
||||||
|
EmptyArray<ProjectContext>.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProjectContext GetProjectContext(string projectPath, NuGetFramework framework) => GetProjectContext(projectPath, framework, EmptyArray<string>.Value);
|
||||||
|
|
||||||
|
public ProjectContext GetProjectContext(string projectPath, NuGetFramework framework, IEnumerable<string> runtimeIdentifier)
|
||||||
|
{
|
||||||
|
var contexts = GetProjectContextCollection(projectPath);
|
||||||
|
if (contexts == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return contexts
|
||||||
|
.ProjectContexts
|
||||||
|
.FirstOrDefault(c => Equals(c.TargetFramework, framework) && RidsMatch(c.RuntimeIdentifier, runtimeIdentifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProjectContext GetRuntimeContext(ProjectContext context, IEnumerable<string> runtimeIdentifiers)
|
||||||
|
{
|
||||||
|
var contexts = GetProjectContextCollection(context.ProjectDirectory);
|
||||||
|
if (contexts == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var runtimeContext = runtimeIdentifiers
|
||||||
|
.Select(r => contexts.GetTarget(context.TargetFramework, r))
|
||||||
|
.FirstOrDefault(c => c != null);
|
||||||
|
|
||||||
|
if (runtimeContext == null)
|
||||||
|
{
|
||||||
|
if (context.IsPortable)
|
||||||
|
{
|
||||||
|
// We're specializing a portable target, so synthesize a runtime target manually
|
||||||
|
// We don't cache this project context, but we'll still use the cached Project and LockFile
|
||||||
|
return InitializeProjectContextBuilder(context.ProjectFile)
|
||||||
|
.WithTargetFramework(context.TargetFramework)
|
||||||
|
.WithRuntimeIdentifiers(runtimeIdentifiers)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are standalone, but don't support this runtime
|
||||||
|
var rids = string.Join(", ", runtimeIdentifiers);
|
||||||
|
throw new InvalidOperationException($"Can not find runtime target for framework '{context.TargetFramework}' compatible with one of the target runtimes: '{rids}'. " +
|
||||||
|
"Possible causes:" + Environment.NewLine +
|
||||||
|
"1. The project has not been restored or restore failed - run `dotnet restore`" + Environment.NewLine +
|
||||||
|
$"2. The project does not list one of '{rids}' in the 'runtimes' section.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return runtimeContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Project GetProject(string projectDirectory) => GetProjectCore(projectDirectory)?.Model;
|
||||||
|
|
||||||
public ProjectContextCollection GetProjectContextCollection(string projectPath)
|
public ProjectContextCollection GetProjectContextCollection(string projectPath)
|
||||||
{
|
{
|
||||||
|
var normalizedPath = NormalizeProjectPath(projectPath);
|
||||||
|
if (normalizedPath == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return _projectContextsCache.AddOrUpdate(
|
return _projectContextsCache.AddOrUpdate(
|
||||||
projectPath,
|
normalizedPath,
|
||||||
key => AddProjectContextEntry(key, null),
|
key => AddProjectContextEntry(key, null),
|
||||||
(key, oldEntry) => AddProjectContextEntry(key, oldEntry));
|
(key, oldEntry) => AddProjectContextEntry(key, oldEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileModelEntry<Project> GetProject(string projectDirectory)
|
private FileModelEntry<Project> GetProjectCore(string projectDirectory)
|
||||||
{
|
{
|
||||||
|
var normalizedPath = NormalizeProjectPath(projectDirectory);
|
||||||
|
if (normalizedPath == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return _projectsCache.AddOrUpdate(
|
return _projectsCache.AddOrUpdate(
|
||||||
projectDirectory,
|
normalizedPath,
|
||||||
key => AddProjectEntry(key, null),
|
key => AddProjectEntry(key, null),
|
||||||
(key, oldEntry) => AddProjectEntry(key, oldEntry));
|
(key, oldEntry) => AddProjectEntry(key, oldEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
private LockFile GetLockFile(string projectDirectory)
|
private LockFile GetLockFile(string projectDirectory)
|
||||||
{
|
{
|
||||||
|
var normalizedPath = NormalizeProjectPath(projectDirectory);
|
||||||
|
if (normalizedPath == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return _lockFileCache.AddOrUpdate(
|
return _lockFileCache.AddOrUpdate(
|
||||||
projectDirectory,
|
normalizedPath,
|
||||||
key => AddLockFileEntry(key, null),
|
key => AddLockFileEntry(key, null),
|
||||||
(key, oldEntry) => AddLockFileEntry(key, oldEntry)).Model;
|
(key, oldEntry) => AddLockFileEntry(key, oldEntry)).Model;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +281,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
if (currentEntry.IsInvalid)
|
if (currentEntry.IsInvalid)
|
||||||
{
|
{
|
||||||
Project project;
|
Project project;
|
||||||
if (!ProjectReader.TryGetProject(projectDirectory, out project, currentEntry.Diagnostics))
|
if (!ProjectReader.TryGetProject(projectDirectory, out project, currentEntry.Diagnostics, _settings))
|
||||||
{
|
{
|
||||||
currentEntry.Reset();
|
currentEntry.Reset();
|
||||||
}
|
}
|
||||||
|
@ -211,7 +319,7 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
currentEntry.Model = LockFileReader.Read(currentEntry.FilePath, fs, designTime: true);
|
currentEntry.Model = _lockFileReader.ReadLockFile(currentEntry.FilePath, fs, designTime: true);
|
||||||
currentEntry.UpdateLastWriteTimeUtc();
|
currentEntry.UpdateLastWriteTimeUtc();
|
||||||
}
|
}
|
||||||
catch (FileFormatException ex)
|
catch (FileFormatException ex)
|
||||||
|
@ -238,8 +346,9 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
currentEntry = new ProjectContextCollection();
|
currentEntry = new ProjectContextCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectEntry = GetProject(projectDirectory);
|
var projectEntry = GetProjectCore(projectDirectory);
|
||||||
if (projectEntry.Model == null)
|
|
||||||
|
if (projectEntry?.Model == null)
|
||||||
{
|
{
|
||||||
// project doesn't exist anymore
|
// project doesn't exist anymore
|
||||||
currentEntry.Reset();
|
currentEntry.Reset();
|
||||||
|
@ -251,17 +360,9 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
{
|
{
|
||||||
currentEntry.Reset();
|
currentEntry.Reset();
|
||||||
|
|
||||||
foreach (var framework in project.GetTargetFrameworks())
|
var builder = InitializeProjectContextBuilder(project);
|
||||||
{
|
|
||||||
var builder = new ProjectContextBuilder()
|
|
||||||
.WithProjectResolver(path => GetProject(path).Model)
|
|
||||||
.WithLockFileResolver(path => GetLockFile(path))
|
|
||||||
.WithProject(project)
|
|
||||||
.WithTargetFramework(framework.FrameworkName)
|
|
||||||
.AsDesignTime();
|
|
||||||
|
|
||||||
currentEntry.ProjectContexts.Add(builder.Build());
|
currentEntry.ProjectContexts.AddRange(builder.BuildAllTargets());
|
||||||
}
|
|
||||||
|
|
||||||
currentEntry.Project = project;
|
currentEntry.Project = project;
|
||||||
currentEntry.ProjectFilePath = project.ProjectFilePath;
|
currentEntry.ProjectFilePath = project.ProjectFilePath;
|
||||||
|
@ -280,6 +381,20 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
return currentEntry;
|
return currentEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ProjectContextBuilder InitializeProjectContextBuilder(Project project)
|
||||||
|
{
|
||||||
|
var builder = new ProjectContextBuilder()
|
||||||
|
.WithProjectResolver(path => GetProjectCore(path)?.Model)
|
||||||
|
.WithLockFileResolver(path => GetLockFile(path))
|
||||||
|
.WithProject(project);
|
||||||
|
if (_designTime)
|
||||||
|
{
|
||||||
|
builder.AsDesignTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
private class FileModelEntry<TModel> where TModel : class
|
private class FileModelEntry<TModel> where TModel : class
|
||||||
{
|
{
|
||||||
private DateTime _lastWriteTimeUtc;
|
private DateTime _lastWriteTimeUtc;
|
||||||
|
@ -400,5 +515,11 @@ namespace Microsoft.DotNet.ProjectModel
|
||||||
yield return description;
|
yield return description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool RidsMatch(string rid, IEnumerable<string> compatibleRids)
|
||||||
|
{
|
||||||
|
return (string.IsNullOrEmpty(rid) && !compatibleRids.Any()) ||
|
||||||
|
(compatibleRids.Contains(rid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Microsoft.Extensions.DependencyModel.Resolution
|
||||||
public class DotNetReferenceAssembliesPathResolver
|
public class DotNetReferenceAssembliesPathResolver
|
||||||
{
|
{
|
||||||
public static readonly string DotNetReferenceAssembliesPathEnv = "DOTNET_REFERENCE_ASSEMBLIES_PATH";
|
public static readonly string DotNetReferenceAssembliesPathEnv = "DOTNET_REFERENCE_ASSEMBLIES_PATH";
|
||||||
|
|
||||||
internal static string Resolve(IEnvironment envirnment, IFileSystem fileSystem, IRuntimeEnvironment runtimeEnvironment)
|
internal static string Resolve(IEnvironment envirnment, IFileSystem fileSystem, IRuntimeEnvironment runtimeEnvironment)
|
||||||
{
|
{
|
||||||
var path = envirnment.GetEnvironmentVariable(DotNetReferenceAssembliesPathEnv);
|
var path = envirnment.GetEnvironmentVariable(DotNetReferenceAssembliesPathEnv);
|
||||||
|
@ -19,40 +19,40 @@ namespace Microsoft.Extensions.DependencyModel.Resolution
|
||||||
{
|
{
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetDefaultDotNetReferenceAssembliesPath(fileSystem, runtimeEnvironment);
|
return GetDefaultDotNetReferenceAssembliesPath(fileSystem, runtimeEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string Resolve()
|
public static string Resolve()
|
||||||
{
|
{
|
||||||
return Resolve(EnvironmentWrapper.Default, FileSystemWrapper.Default, PlatformServices.Default.Runtime);
|
return Resolve(EnvironmentWrapper.Default, FileSystemWrapper.Default, PlatformServices.Default.Runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetDefaultDotNetReferenceAssembliesPath(IFileSystem fileSystem, IRuntimeEnvironment runtimeEnvironment)
|
private static string GetDefaultDotNetReferenceAssembliesPath(IFileSystem fileSystem, IRuntimeEnvironment runtimeEnvironment)
|
||||||
{
|
{
|
||||||
var os = runtimeEnvironment.OperatingSystemPlatform;
|
var os = runtimeEnvironment.OperatingSystemPlatform;
|
||||||
|
|
||||||
if (os == Platform.Windows)
|
if (os == Platform.Windows)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os == Platform.Darwin &&
|
if (os == Platform.Darwin &&
|
||||||
fileSystem.Directory.Exists("/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/xbuild-frameworks"))
|
fileSystem.Directory.Exists("/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/xbuild-frameworks"))
|
||||||
{
|
{
|
||||||
return "/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/xbuild-frameworks";
|
return "/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/xbuild-frameworks";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileSystem.Directory.Exists("/usr/local/lib/mono/xbuild-frameworks"))
|
if (fileSystem.Directory.Exists("/usr/local/lib/mono/xbuild-frameworks"))
|
||||||
{
|
{
|
||||||
return "/usr/local/lib/mono/xbuild-frameworks";
|
return "/usr/local/lib/mono/xbuild-frameworks";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileSystem.Directory.Exists("/usr/lib/mono/xbuild-frameworks"))
|
if (fileSystem.Directory.Exists("/usr/lib/mono/xbuild-frameworks"))
|
||||||
{
|
{
|
||||||
return "/usr/lib/mono/xbuild-frameworks";
|
return "/usr/lib/mono/xbuild-frameworks";
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ namespace Microsoft.DotNet.Cli
|
||||||
command = "help";
|
command = "help";
|
||||||
}
|
}
|
||||||
|
|
||||||
int exitCode;
|
int exitCode;
|
||||||
Func<string[], int> builtIn;
|
Func<string[], int> builtIn;
|
||||||
if (s_builtIns.TryGetValue(command, out builtIn))
|
if (s_builtIns.TryGetValue(command, out builtIn))
|
||||||
{
|
{
|
||||||
|
@ -175,16 +175,16 @@ namespace Microsoft.DotNet.Cli
|
||||||
{
|
{
|
||||||
return (shortName != null && candidate.Equals("-" + shortName)) || (longName != null && candidate.Equals("--" + longName));
|
return (shortName != null && candidate.Equals("-" + shortName)) || (longName != null && candidate.Equals("--" + longName));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetCommitSha()
|
private static string GetCommitSha()
|
||||||
{
|
{
|
||||||
var versionFile = DotnetFiles.VersionFile;
|
var versionFile = DotnetFiles.VersionFile;
|
||||||
|
|
||||||
if (File.Exists(versionFile))
|
if (File.Exists(versionFile))
|
||||||
{
|
{
|
||||||
return File.ReadLines(versionFile).FirstOrDefault()?.Substring(0, 10);
|
return File.ReadLines(versionFile).FirstOrDefault()?.Substring(0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,12 +52,17 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
yield return filePatternMatch.Path;
|
yield return filePatternMatch.Path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (value.Contains("*"))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Globbing pattern '{value}' did not match any files");
|
||||||
|
}
|
||||||
|
else if (value.EndsWith(Project.FileName))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Could not find project file '{value}'");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Could not resolve project path from '{value}':" +
|
throw new InvalidOperationException($"Couldn't find '{Project.FileName}' in '{value}'");
|
||||||
"1. It's not project file" +
|
|
||||||
"2. It's not directory containing project.json file" +
|
|
||||||
"3. Globbing returned no mathces");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.DotNet.Cli.CommandLine;
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
using Microsoft.DotNet.Cli.Utils;
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
using Microsoft.DotNet.ProjectModel;
|
||||||
using Microsoft.Extensions.PlatformAbstractions;
|
using Microsoft.Extensions.PlatformAbstractions;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
|
@ -44,11 +45,16 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
public bool ShouldNotUseIncrementality { get; set; }
|
public bool ShouldNotUseIncrementality { get; set; }
|
||||||
public bool ShouldSkipDependencies { get; set; }
|
public bool ShouldSkipDependencies { get; set; }
|
||||||
|
|
||||||
|
public WorkspaceContext Workspace { get; private set; }
|
||||||
|
|
||||||
// workaround: CommandLineApplication is internal therefore I cannot make _app protected so baseclasses can add their own params
|
// workaround: CommandLineApplication is internal therefore I cannot make _app protected so baseclasses can add their own params
|
||||||
private readonly Dictionary<string, CommandOption> baseClassOptions;
|
private readonly Dictionary<string, CommandOption> baseClassOptions;
|
||||||
|
|
||||||
public BuildCommandApp(string name, string fullName, string description)
|
public BuildCommandApp(string name, string fullName, string description) : this(name, fullName, description, workspace: null) { }
|
||||||
|
|
||||||
|
public BuildCommandApp(string name, string fullName, string description, WorkspaceContext workspace)
|
||||||
{
|
{
|
||||||
|
Workspace = workspace;
|
||||||
_app = new CommandLineApplication
|
_app = new CommandLineApplication
|
||||||
{
|
{
|
||||||
Name = name,
|
Name = name,
|
||||||
|
@ -99,6 +105,18 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
ShouldNotUseIncrementality = _shouldNotUseIncrementalityArgument.HasValue();
|
ShouldNotUseIncrementality = _shouldNotUseIncrementalityArgument.HasValue();
|
||||||
ShouldSkipDependencies = _shouldSkipDependenciesArgument.HasValue();
|
ShouldSkipDependencies = _shouldSkipDependenciesArgument.HasValue();
|
||||||
|
|
||||||
|
// Set defaults based on the environment
|
||||||
|
if (Workspace == null)
|
||||||
|
{
|
||||||
|
var settings = ProjectReaderSettings.ReadFromEnvironment();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(VersionSuffixValue))
|
||||||
|
{
|
||||||
|
settings.VersionSuffix = VersionSuffixValue;
|
||||||
|
}
|
||||||
|
Workspace = WorkspaceContext.Create(settings, designTime: false);
|
||||||
|
}
|
||||||
|
|
||||||
var files = new ProjectGlobbingResolver().Resolve(_projectArgument.Values);
|
var files = new ProjectGlobbingResolver().Resolve(_projectArgument.Values);
|
||||||
IEnumerable<NuGetFramework> frameworks = null;
|
IEnumerable<NuGetFramework> frameworks = null;
|
||||||
if (_frameworkOption.HasValue())
|
if (_frameworkOption.HasValue())
|
||||||
|
|
|
@ -18,16 +18,19 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
private readonly string _outputPath;
|
private readonly string _outputPath;
|
||||||
private readonly string _buildBasePath;
|
private readonly string _buildBasePath;
|
||||||
private readonly IList<string> _runtimes;
|
private readonly IList<string> _runtimes;
|
||||||
|
private readonly WorkspaceContext _workspace;
|
||||||
|
|
||||||
public CompilerIOManager(string configuration,
|
public CompilerIOManager(string configuration,
|
||||||
string outputPath,
|
string outputPath,
|
||||||
string buildBasePath,
|
string buildBasePath,
|
||||||
IEnumerable<string> runtimes)
|
IEnumerable<string> runtimes,
|
||||||
|
WorkspaceContext workspace)
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
_outputPath = outputPath;
|
_outputPath = outputPath;
|
||||||
_buildBasePath = buildBasePath;
|
_buildBasePath = buildBasePath;
|
||||||
_runtimes = runtimes.ToList();
|
_runtimes = runtimes.ToList();
|
||||||
|
_workspace = workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AnyMissingIO(ProjectContext project, IEnumerable<string> items, string itemsType)
|
public bool AnyMissingIO(ProjectContext project, IEnumerable<string> items, string itemsType)
|
||||||
|
@ -75,7 +78,7 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
var allOutputPath = new HashSet<string>(calculator.CompilationFiles.All());
|
var allOutputPath = new HashSet<string>(calculator.CompilationFiles.All());
|
||||||
if (isRootProject && project.ProjectFile.HasRuntimeOutput(_configuration))
|
if (isRootProject && project.ProjectFile.HasRuntimeOutput(_configuration))
|
||||||
{
|
{
|
||||||
var runtimeContext = project.CreateRuntimeContext(_runtimes);
|
var runtimeContext = _workspace.GetRuntimeContext(project, _runtimes);
|
||||||
foreach (var path in runtimeContext.GetOutputPaths(_configuration, _buildBasePath, _outputPath).RuntimeFiles.All())
|
foreach (var path in runtimeContext.GetOutputPaths(_configuration, _buildBasePath, _outputPath).RuntimeFiles.All())
|
||||||
{
|
{
|
||||||
allOutputPath.Add(path);
|
allOutputPath.Add(path);
|
||||||
|
|
|
@ -33,7 +33,8 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
args.ConfigValue,
|
args.ConfigValue,
|
||||||
args.OutputValue,
|
args.OutputValue,
|
||||||
args.BuildBasePathValue,
|
args.BuildBasePathValue,
|
||||||
args.GetRuntimes()
|
args.GetRuntimes(),
|
||||||
|
args.Workspace
|
||||||
);
|
);
|
||||||
_scriptRunner = new ScriptRunner();
|
_scriptRunner = new ScriptRunner();
|
||||||
_commandFactory = new DotNetCommandFactory();
|
_commandFactory = new DotNetCommandFactory();
|
||||||
|
@ -120,7 +121,7 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
private void MakeRunnable(ProjectGraphNode graphNode)
|
private void MakeRunnable(ProjectGraphNode graphNode)
|
||||||
{
|
{
|
||||||
var runtimeContext = graphNode.ProjectContext.ProjectFile.HasRuntimeOutput(_args.ConfigValue) ?
|
var runtimeContext = graphNode.ProjectContext.ProjectFile.HasRuntimeOutput(_args.ConfigValue) ?
|
||||||
graphNode.ProjectContext.CreateRuntimeContext(_args.GetRuntimes()) :
|
_args.Workspace.GetRuntimeContext(graphNode.ProjectContext, _args.GetRuntimes()) :
|
||||||
graphNode.ProjectContext;
|
graphNode.ProjectContext;
|
||||||
|
|
||||||
var outputPaths = runtimeContext.GetOutputPaths(_args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue);
|
var outputPaths = runtimeContext.GetOutputPaths(_args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue);
|
||||||
|
|
|
@ -15,13 +15,19 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
{
|
{
|
||||||
public class BuildCommand
|
public class BuildCommand
|
||||||
{
|
{
|
||||||
public static int Run(string[] args)
|
public static int Run(string[] args) => Run(args, null);
|
||||||
|
|
||||||
|
public static int Run(string[] args, WorkspaceContext workspace)
|
||||||
{
|
{
|
||||||
DebugHelper.HandleDebugSwitch(ref args);
|
DebugHelper.HandleDebugSwitch(ref args);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var app = new BuildCommandApp("dotnet build", ".NET Builder", "Builder for the .NET Platform. It performs incremental compilation if it's safe to do so. Otherwise it delegates to dotnet-compile which performs non-incremental compilation");
|
var app = new BuildCommandApp(
|
||||||
|
"dotnet build",
|
||||||
|
".NET Builder",
|
||||||
|
"Builder for the .NET Platform. It performs incremental compilation if it's safe to do so. Otherwise it delegates to dotnet-compile which performs non-incremental compilation",
|
||||||
|
workspace);
|
||||||
return app.Execute(OnExecute, args);
|
return app.Execute(OnExecute, args);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -40,7 +46,7 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
var builderCommandApp = args;
|
var builderCommandApp = args;
|
||||||
var graphCollector = new ProjectGraphCollector(
|
var graphCollector = new ProjectGraphCollector(
|
||||||
!builderCommandApp.ShouldSkipDependencies,
|
!builderCommandApp.ShouldSkipDependencies,
|
||||||
(project, target) => ProjectContext.Create(project, target));
|
(project, target) => args.Workspace.GetProjectContext(project, target));
|
||||||
|
|
||||||
var contexts = ResolveRootContexts(files, frameworks, args);
|
var contexts = ResolveRootContexts(files, frameworks, args);
|
||||||
var graph = graphCollector.Collect(contexts).ToArray();
|
var graph = graphCollector.Collect(contexts).ToArray();
|
||||||
|
@ -53,19 +59,11 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
IEnumerable<NuGetFramework> frameworks,
|
IEnumerable<NuGetFramework> frameworks,
|
||||||
BuildCommandApp args)
|
BuildCommandApp args)
|
||||||
{
|
{
|
||||||
|
|
||||||
List<Task<ProjectContext>> tasks = new List<Task<ProjectContext>>();
|
List<Task<ProjectContext>> tasks = new List<Task<ProjectContext>>();
|
||||||
// Set defaults based on the environment
|
|
||||||
var settings = ProjectReaderSettings.ReadFromEnvironment();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(args.VersionSuffixValue))
|
|
||||||
{
|
|
||||||
settings.VersionSuffix = args.VersionSuffixValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
var project = ProjectReader.GetProject(file);
|
var project = args.Workspace.GetProject(file);
|
||||||
var projectFrameworks = project.GetTargetFrameworks().Select(f => f.FrameworkName);
|
var projectFrameworks = project.GetTargetFrameworks().Select(f => f.FrameworkName);
|
||||||
if (!projectFrameworks.Any())
|
if (!projectFrameworks.Any())
|
||||||
{
|
{
|
||||||
|
@ -91,11 +89,7 @@ namespace Microsoft.DotNet.Tools.Build
|
||||||
|
|
||||||
foreach (var framework in selectedFrameworks)
|
foreach (var framework in selectedFrameworks)
|
||||||
{
|
{
|
||||||
tasks.Add(Task.Run(() => new ProjectContextBuilder()
|
tasks.Add(Task.Run(() => args.Workspace.GetProjectContext(file, framework)));
|
||||||
.WithProjectDirectory(Path.GetDirectoryName(file))
|
|
||||||
.WithTargetFramework(framework)
|
|
||||||
.WithReaderSettings(settings)
|
|
||||||
.Build()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Task.WhenAll(tasks).GetAwaiter().GetResult();
|
return Task.WhenAll(tasks).GetAwaiter().GetResult();
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
success &= _managedCompiler.Compile(context, args);
|
success &= _managedCompiler.Compile(context, args);
|
||||||
if (args.IsNativeValue && success)
|
if (args.IsNativeValue && success)
|
||||||
{
|
{
|
||||||
var runtimeContext = context.CreateRuntimeContext(args.GetRuntimes());
|
var runtimeContext = args.Workspace.GetRuntimeContext(context, args.GetRuntimes());
|
||||||
success &= _nativeCompiler.Compile(runtimeContext, args);
|
success &= _nativeCompiler.Compile(runtimeContext, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
|
|
||||||
if (context.ProjectFile.HasRuntimeOutput(args.ConfigValue))
|
if (context.ProjectFile.HasRuntimeOutput(args.ConfigValue))
|
||||||
{
|
{
|
||||||
var runtimeContext = context.CreateRuntimeContext(args.GetRuntimes());
|
var runtimeContext = args.Workspace.GetRuntimeContext(context, args.GetRuntimes());
|
||||||
var runtimeOutputPath = runtimeContext.GetOutputPaths(args.ConfigValue, args.BuildBasePathValue, args.OutputValue);
|
var runtimeOutputPath = runtimeContext.GetOutputPaths(args.ConfigValue, args.BuildBasePathValue, args.OutputValue);
|
||||||
|
|
||||||
contextVariables.Add(
|
contextVariables.Add(
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.DotNet.ProjectModel.Server.Helpers;
|
using Microsoft.DotNet.ProjectModel.Server.Helpers;
|
||||||
using Microsoft.DotNet.ProjectModel.Server.Models;
|
using Microsoft.DotNet.ProjectModel.Server.Models;
|
||||||
|
@ -35,12 +36,12 @@ namespace Microsoft.DotNet.ProjectModel.Server
|
||||||
snapshot.ProjectSearchPaths = currentSearchPaths.ToList();
|
snapshot.ProjectSearchPaths = currentSearchPaths.ToList();
|
||||||
snapshot.GlobalJsonPath = globalSettings?.FilePath;
|
snapshot.GlobalJsonPath = globalSettings?.FilePath;
|
||||||
|
|
||||||
foreach (var projectContext in projectContextsCollection.ProjectContexts)
|
foreach (var projectContext in projectContextsCollection.FrameworkOnlyContexts)
|
||||||
{
|
{
|
||||||
snapshot.ProjectContexts[projectContext.TargetFramework] =
|
snapshot.ProjectContexts[projectContext.TargetFramework] =
|
||||||
ProjectContextSnapshot.Create(projectContext, configuration, currentSearchPaths);
|
ProjectContextSnapshot.Create(projectContext, configuration, currentSearchPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
return snapshot;
|
return snapshot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
@ -26,7 +27,7 @@ namespace Microsoft.DotNet.ProjectModel.Server
|
||||||
_hostName = hostName;
|
_hostName = hostName;
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
_protocolManager = new ProtocolManager(maxVersion: 4, loggerFactory: _loggerFactory);
|
_protocolManager = new ProtocolManager(maxVersion: 4, loggerFactory: _loggerFactory);
|
||||||
_workspaceContext = WorkspaceContext.Create();
|
_workspaceContext = WorkspaceContext.Create(designTime: true);
|
||||||
_projects = new Dictionary<int, ProjectManager>();
|
_projects = new Dictionary<int, ProjectManager>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,26 +52,34 @@ namespace Microsoft.DotNet.ProjectModel.Server
|
||||||
|
|
||||||
var logger = loggerFactory.CreateLogger<ProjectModelServerCommand>();
|
var logger = loggerFactory.CreateLogger<ProjectModelServerCommand>();
|
||||||
|
|
||||||
if (!MonitorHostProcess(hostpid, logger))
|
try
|
||||||
{
|
{
|
||||||
return 1;
|
if (!MonitorHostProcess(hostpid, logger))
|
||||||
}
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
var intPort = CheckPort(port, logger);
|
var intPort = CheckPort(port, logger);
|
||||||
if (intPort == -1)
|
if (intPort == -1)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hostname.HasValue())
|
||||||
|
{
|
||||||
|
logger.LogError($"Option \"{hostname.LongName}\" is missing.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var program = new ProjectModelServerCommand(intPort, hostname.Value(), loggerFactory);
|
||||||
|
program.OpenChannel();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return 1;
|
logger.LogCritical($"Unhandled exception in server main: {ex}");
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hostname.HasValue())
|
|
||||||
{
|
|
||||||
logger.LogError($"Option \"{hostname.LongName}\" is missing.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var program = new ProjectModelServerCommand(intPort, hostname.Value(), loggerFactory);
|
|
||||||
program.OpenChannel();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ namespace Microsoft.DotNet.ProjectModel.Server
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_log.LogError("A unexpected exception occurred: {0}", ex.ToString());
|
_log.LogError("A unexpected exception occurred: {0}", ex.ToString());
|
||||||
|
|
||||||
var error = new ErrorMessage
|
var error = new ErrorMessage
|
||||||
{
|
{
|
||||||
Message = ex.Message
|
Message = ex.Message
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.DotNet.Cli.CommandLine;
|
using Microsoft.DotNet.Cli.CommandLine;
|
||||||
using Microsoft.DotNet.Cli.Utils;
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Tools.Publish
|
namespace Microsoft.DotNet.Tools.Publish
|
||||||
{
|
{
|
||||||
|
@ -44,6 +45,8 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
publish.VersionSuffix = versionSuffix.Value();
|
publish.VersionSuffix = versionSuffix.Value();
|
||||||
publish.ShouldBuild = !noBuild.HasValue();
|
publish.ShouldBuild = !noBuild.HasValue();
|
||||||
|
|
||||||
|
publish.Workspace = WorkspaceContext.Create(versionSuffix.Value(), designTime: false);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(publish.ProjectPath))
|
if (string.IsNullOrEmpty(publish.ProjectPath))
|
||||||
{
|
{
|
||||||
publish.ProjectPath = Directory.GetCurrentDirectory();
|
publish.ProjectPath = Directory.GetCurrentDirectory();
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
public string Runtime { get; set; }
|
public string Runtime { get; set; }
|
||||||
public bool NativeSubdirectories { get; set; }
|
public bool NativeSubdirectories { get; set; }
|
||||||
public NuGetFramework NugetFramework { get; set; }
|
public NuGetFramework NugetFramework { get; set; }
|
||||||
|
public WorkspaceContext Workspace { get; set; }
|
||||||
public IList<ProjectContext> ProjectContexts { get; set; }
|
public IList<ProjectContext> ProjectContexts { get; set; }
|
||||||
public string VersionSuffix { get; set; }
|
public string VersionSuffix { get; set; }
|
||||||
public int NumberOfProjects { get; private set; }
|
public int NumberOfProjects { get; private set; }
|
||||||
|
@ -432,14 +433,17 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
throw new InvalidProjectException($"'{projectPath}' does not contain a project.json file");
|
throw new InvalidProjectException($"'{projectPath}' does not contain a project.json file");
|
||||||
}
|
}
|
||||||
|
|
||||||
var allContexts = framework == null ?
|
var contexts = Workspace.GetProjectContextCollection(projectPath).FrameworkOnlyContexts;
|
||||||
ProjectContext.CreateContextForEachFramework(projectPath) :
|
|
||||||
new[] { ProjectContext.Create(projectPath, framework) };
|
|
||||||
|
|
||||||
var runtimes = !string.IsNullOrEmpty(runtime) ?
|
contexts = framework == null ?
|
||||||
new [] {runtime} :
|
contexts :
|
||||||
PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers();
|
contexts.Where(c => Equals(c.TargetFramework, framework));
|
||||||
return allContexts.Select(c => c.CreateRuntimeContext(runtimes));
|
|
||||||
|
var rids = string.IsNullOrEmpty(runtime) ?
|
||||||
|
PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers() :
|
||||||
|
new[] { runtime };
|
||||||
|
|
||||||
|
return contexts.Select(c => Workspace.GetRuntimeContext(c, rids));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CopyContents(ProjectContext context, string outputPath)
|
private static void CopyContents(ProjectContext context, string outputPath)
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace Microsoft.DotNet.Tools.Run
|
||||||
|
|
||||||
ProjectContext _context;
|
ProjectContext _context;
|
||||||
List<string> _args;
|
List<string> _args;
|
||||||
|
private WorkspaceContext _workspace;
|
||||||
|
|
||||||
public int Start()
|
public int Start()
|
||||||
{
|
{
|
||||||
|
@ -60,6 +61,8 @@ namespace Microsoft.DotNet.Tools.Run
|
||||||
Configuration = Constants.DefaultConfiguration;
|
Configuration = Constants.DefaultConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var frameworkContexts = _workspace.GetProjectContexts(Project).Where(c => string.IsNullOrEmpty(c.RuntimeIdentifier));
|
||||||
|
|
||||||
var rids = PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers();
|
var rids = PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers();
|
||||||
|
|
||||||
if (Framework == null)
|
if (Framework == null)
|
||||||
|
@ -70,16 +73,14 @@ namespace Microsoft.DotNet.Tools.Run
|
||||||
FrameworkConstants.FrameworkIdentifiers.NetStandardApp,
|
FrameworkConstants.FrameworkIdentifiers.NetStandardApp,
|
||||||
};
|
};
|
||||||
|
|
||||||
var contexts = ProjectContext.CreateContextForEachFramework(Project, null);
|
|
||||||
|
|
||||||
ProjectContext context;
|
ProjectContext context;
|
||||||
if (contexts.Count() == 1)
|
if (frameworkContexts.Count() == 1)
|
||||||
{
|
{
|
||||||
context = contexts.Single();
|
context = frameworkContexts.Single();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context = contexts.FirstOrDefault(c => defaultFrameworks.Contains(c.TargetFramework.Framework));
|
context = frameworkContexts.FirstOrDefault(c => defaultFrameworks.Contains(c.TargetFramework.Framework));
|
||||||
if (context == null)
|
if (context == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Couldn't find target to run. Possible causes:" + Environment.NewLine +
|
throw new InvalidOperationException($"Couldn't find target to run. Possible causes:" + Environment.NewLine +
|
||||||
|
@ -88,11 +89,11 @@ namespace Microsoft.DotNet.Tools.Run
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_context = context.CreateRuntimeContext(rids);
|
_context = _workspace.GetRuntimeContext(context, rids);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_context = ProjectContext.Create(Project, NuGetFramework.Parse(Framework), rids);
|
_context = _workspace.GetProjectContext(Project, NuGetFramework.Parse(Framework), rids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Args == null)
|
if (Args == null)
|
||||||
|
@ -107,6 +108,9 @@ namespace Microsoft.DotNet.Tools.Run
|
||||||
|
|
||||||
private int RunExecutable()
|
private int RunExecutable()
|
||||||
{
|
{
|
||||||
|
// Set up the workspace
|
||||||
|
_workspace = WorkspaceContext.Create(ProjectReaderSettings.ReadFromEnvironment(), designTime: false);
|
||||||
|
|
||||||
CalculateDefaultsForNonAssigned();
|
CalculateDefaultsForNonAssigned();
|
||||||
|
|
||||||
// Compile to that directory
|
// Compile to that directory
|
||||||
|
|
|
@ -42,7 +42,10 @@ namespace Microsoft.DotNet.Tools.Test
|
||||||
RegisterForParentProcessExit(dotnetTestParams.ParentProcessId.Value);
|
RegisterForParentProcessExit(dotnetTestParams.ParentProcessId.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectContexts = CreateProjectContexts(dotnetTestParams.ProjectPath, dotnetTestParams.Runtime);
|
// Create a workspace
|
||||||
|
var workspace = WorkspaceContext.Create(ProjectReaderSettings.ReadFromEnvironment(), designTime: false);
|
||||||
|
|
||||||
|
var projectContexts = CreateProjectContexts(workspace, dotnetTestParams.ProjectPath, dotnetTestParams.Runtime);
|
||||||
|
|
||||||
var projectContext = projectContexts.First();
|
var projectContext = projectContexts.First();
|
||||||
|
|
||||||
|
@ -98,7 +101,7 @@ namespace Microsoft.DotNet.Tools.Test
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<ProjectContext> CreateProjectContexts(string projectPath, string runtime)
|
private static IEnumerable<ProjectContext> CreateProjectContexts(WorkspaceContext workspace, string projectPath, string runtime)
|
||||||
{
|
{
|
||||||
projectPath = projectPath ?? Directory.GetCurrentDirectory();
|
projectPath = projectPath ?? Directory.GetCurrentDirectory();
|
||||||
|
|
||||||
|
@ -116,7 +119,8 @@ namespace Microsoft.DotNet.Tools.Test
|
||||||
new[] { runtime } :
|
new[] { runtime } :
|
||||||
PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers();
|
PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers();
|
||||||
|
|
||||||
return ProjectContext.CreateContextForEachFramework(projectPath).Select(context => context.CreateRuntimeContext(runtimeIdentifiers));
|
var contexts = workspace.GetProjectContextCollection(projectPath).FrameworkOnlyContexts;
|
||||||
|
return contexts.Select(c => workspace.GetRuntimeContext(c, runtimeIdentifiers));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -43,14 +43,14 @@ namespace Microsoft.DotNet.ProjectModel.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineDataAttribute("TestMscorlibReference", true)]
|
[InlineData("TestMscorlibReference", true)]
|
||||||
[InlineDataAttribute("TestMscorlibReference", false)]
|
[InlineData("TestMscorlibReference", false)]
|
||||||
[InlineDataAttribute("TestMicrosoftCSharpReference", true)]
|
[InlineData("TestMicrosoftCSharpReference", true)]
|
||||||
[InlineDataAttribute("TestMicrosoftCSharpReference", false)]
|
[InlineData("TestMicrosoftCSharpReference", false)]
|
||||||
[InlineDataAttribute("TestSystemReference", true)]
|
[InlineData("TestSystemReference", true)]
|
||||||
[InlineDataAttribute("TestSystemReference", false)]
|
[InlineData("TestSystemReference", false)]
|
||||||
[InlineDataAttribute("TestSystemCoreReference", true)]
|
[InlineData("TestSystemCoreReference", true)]
|
||||||
[InlineDataAttribute("TestSystemCoreReference", false)]
|
[InlineData("TestSystemCoreReference", false)]
|
||||||
public void TestDuplicateDefaultDesktopReferences(string sampleName, bool withLockFile)
|
public void TestDuplicateDefaultDesktopReferences(string sampleName, bool withLockFile)
|
||||||
{
|
{
|
||||||
var instance = TestAssetsManager.CreateTestInstance(sampleName);
|
var instance = TestAssetsManager.CreateTestInstance(sampleName);
|
||||||
|
@ -65,7 +65,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests
|
||||||
|
|
||||||
Assert.Equal(4, context.RootProject.Dependencies.Count());
|
Assert.Equal(4, context.RootProject.Dependencies.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void NoDuplicateReferencesWhenFrameworkMissing()
|
public void NoDuplicateReferencesWhenFrameworkMissing()
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,7 @@ namespace Microsoft.DotNet.ProjectModel.Tests
|
||||||
// Will fail with dupes if any
|
// Will fail with dupes if any
|
||||||
context.LibraryManager.GetLibraries().ToDictionary(l => l.Identity.Name);
|
context.LibraryManager.GetLibraries().ToDictionary(l => l.Identity.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void NetCore50ShouldNotResolveFrameworkAssemblies()
|
public void NetCore50ShouldNotResolveFrameworkAssemblies()
|
||||||
{
|
{
|
||||||
|
|
|
@ -109,12 +109,11 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
private CommandResult RunProcess(string executable, string args, StreamForwarder stdOut, StreamForwarder stdErr)
|
private CommandResult RunProcess(string executable, string args, StreamForwarder stdOut, StreamForwarder stdErr)
|
||||||
{
|
{
|
||||||
CurrentProcess = StartProcess(executable, args);
|
CurrentProcess = StartProcess(executable, args);
|
||||||
var threadOut = stdOut.BeginRead(CurrentProcess.StandardOutput);
|
var taskOut = stdOut.BeginRead(CurrentProcess.StandardOutput);
|
||||||
var threadErr = stdErr.BeginRead(CurrentProcess.StandardError);
|
var taskErr = stdErr.BeginRead(CurrentProcess.StandardError);
|
||||||
|
|
||||||
CurrentProcess.WaitForExit();
|
CurrentProcess.WaitForExit();
|
||||||
threadOut.Join();
|
Task.WaitAll(taskOut, taskErr);
|
||||||
threadErr.Join();
|
|
||||||
|
|
||||||
var result = new CommandResult(
|
var result = new CommandResult(
|
||||||
CurrentProcess.StartInfo,
|
CurrentProcess.StartInfo,
|
||||||
|
@ -128,14 +127,13 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
private Task<CommandResult> RunProcessAsync(string executable, string args, StreamForwarder stdOut, StreamForwarder stdErr)
|
private Task<CommandResult> RunProcessAsync(string executable, string args, StreamForwarder stdOut, StreamForwarder stdErr)
|
||||||
{
|
{
|
||||||
CurrentProcess = StartProcess(executable, args);
|
CurrentProcess = StartProcess(executable, args);
|
||||||
var threadOut = stdOut.BeginRead(CurrentProcess.StandardOutput);
|
var taskOut = stdOut.BeginRead(CurrentProcess.StandardOutput);
|
||||||
var threadErr = stdErr.BeginRead(CurrentProcess.StandardError);
|
var taskErr = stdErr.BeginRead(CurrentProcess.StandardError);
|
||||||
|
|
||||||
var tcs = new TaskCompletionSource<CommandResult>();
|
var tcs = new TaskCompletionSource<CommandResult>();
|
||||||
CurrentProcess.Exited += (sender, arg) =>
|
CurrentProcess.Exited += (sender, arg) =>
|
||||||
{
|
{
|
||||||
threadOut.Join();
|
Task.WaitAll(taskOut, taskErr);
|
||||||
threadErr.Join();
|
|
||||||
var result = new CommandResult(
|
var result = new CommandResult(
|
||||||
CurrentProcess.StartInfo,
|
CurrentProcess.StartInfo,
|
||||||
CurrentProcess.ExitCode,
|
CurrentProcess.ExitCode,
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests
|
||||||
private Mock<ICompiler> _nativeCompilerMock;
|
private Mock<ICompiler> _nativeCompilerMock;
|
||||||
private List<ProjectContext> _contexts;
|
private List<ProjectContext> _contexts;
|
||||||
private BuildCommandApp _args;
|
private BuildCommandApp _args;
|
||||||
|
private readonly WorkspaceContext _workspace;
|
||||||
|
|
||||||
public GivenACompilationDriverController()
|
public GivenACompilationDriverController()
|
||||||
{
|
{
|
||||||
|
@ -34,12 +35,13 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests
|
||||||
.Compile(It.IsAny<ProjectContext>(), It.IsAny<BuildCommandApp>()))
|
.Compile(It.IsAny<ProjectContext>(), It.IsAny<BuildCommandApp>()))
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
|
|
||||||
|
_workspace = WorkspaceContext.Create(ProjectReaderSettings.ReadFromEnvironment(), designTime: false);
|
||||||
_contexts = new List<ProjectContext>
|
_contexts = new List<ProjectContext>
|
||||||
{
|
{
|
||||||
ProjectContext.Create(_projectJson, NuGetFramework.Parse("netcoreapp1.0"))
|
_workspace.GetProjectContext(_projectJson, NuGetFramework.Parse("netcoreapp1.0"))
|
||||||
};
|
};
|
||||||
|
|
||||||
_args = new BuildCommandApp("dotnet compile", ".NET Compiler", "Compiler for the .NET Platform");
|
_args = new BuildCommandApp("dotnet compile", ".NET Compiler", "Compiler for the .NET Platform", WorkspaceContext.Create(designTime: false));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
@ -188,7 +188,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests
|
||||||
It.IsAny<string>()))
|
It.IsAny<string>()))
|
||||||
.Returns(command.Object);
|
.Returns(command.Object);
|
||||||
|
|
||||||
var _args = new BuildCommandApp("dotnet compile", ".NET Compiler", "Compiler for the .NET Platform");
|
var _args = new BuildCommandApp("dotnet compile", ".NET Compiler", "Compiler for the .NET Platform", WorkspaceContext.Create(designTime: false));
|
||||||
_args.ConfigValue = ConfigValue;
|
_args.ConfigValue = ConfigValue;
|
||||||
|
|
||||||
PreCompileScriptVariables = new Dictionary<string, string>();
|
PreCompileScriptVariables = new Dictionary<string, string>();
|
||||||
|
@ -219,7 +219,8 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests
|
||||||
rids.Add(rid);
|
rids.Add(rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
var context = ProjectContext.Create(projectJson, TestAssetFramework, rids);
|
var workspace = WorkspaceContext.Create(ProjectReaderSettings.ReadFromEnvironment(), designTime: false);
|
||||||
|
var context = workspace.GetProjectContext(projectJson, TestAssetFramework, rids);
|
||||||
managedCompiler.Compile(context, _args);
|
managedCompiler.Compile(context, _args);
|
||||||
|
|
||||||
RuntimeOutputDir = Path.Combine(OutputPath, rid);
|
RuntimeOutputDir = Path.Combine(OutputPath, rid);
|
||||||
|
|
|
@ -228,7 +228,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests
|
||||||
_writer.Dispose();
|
_writer.Dispose();
|
||||||
_networkStream.Dispose();
|
_networkStream.Dispose();
|
||||||
_readCancellationToken.Cancel();
|
_readCancellationToken.Cancel();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_socket.Shutdown(SocketShutdown.Both);
|
_socket.Shutdown(SocketShutdown.Both);
|
||||||
|
|
|
@ -506,13 +506,13 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests
|
||||||
var testProjectRoot = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "MSBuildReferencesProjects", "ValidCase01");
|
var testProjectRoot = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "MSBuildReferencesProjects", "ValidCase01");
|
||||||
foreach (var classLibrary in classLibraries)
|
foreach (var classLibrary in classLibraries)
|
||||||
{
|
{
|
||||||
dependencies.RetrieveDependency(classLibrary)
|
var dependency = dependencies.RetrieveDependency(classLibrary);
|
||||||
.AssertProperty("Type", LibraryType.MSBuildProject.ToString())
|
dependency.AssertProperty("Type", LibraryType.MSBuildProject.ToString());
|
||||||
.AssertProperty("Path", NormalizePathString(Path.Combine(testProjectRoot, classLibrary, $"{classLibrary}.csproj")))
|
dependency.AssertProperty("Path", NormalizePathString(Path.Combine(testProjectRoot, classLibrary, $"{classLibrary}.csproj")));
|
||||||
.AssertProperty<bool>("Resolved", true)
|
dependency.AssertProperty<bool>("Resolved", true);
|
||||||
.AssertProperty("Name", classLibrary)
|
dependency.AssertProperty("Name", classLibrary);
|
||||||
.AssertProperty<JArray>("Errors", array => array.Count == 0)
|
dependency.AssertProperty<JArray>("Errors", array => array.Count == 0);
|
||||||
.AssertProperty<JArray>("Warnings", array => array.Count == 0);
|
dependency.AssertProperty<JArray>("Warnings", array => array.Count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
var references = messages.RetrieveSingleMessage(MessageTypes.References)
|
var references = messages.RetrieveSingleMessage(MessageTypes.References)
|
||||||
|
@ -632,12 +632,12 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests
|
||||||
afterDependencies.RetrieveDependency("ClassLibrary3");
|
afterDependencies.RetrieveDependency("ClassLibrary3");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TestMscorlibLibraryDuplication()
|
public void TestMscorlibLibraryDuplication()
|
||||||
{
|
{
|
||||||
var projectPath = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "MscorlibLibraryDuplication");
|
var projectPath = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "MscorlibLibraryDuplication");
|
||||||
|
|
||||||
using (var server = new DthTestServer(_loggerFactory))
|
using (var server = new DthTestServer(_loggerFactory))
|
||||||
using (var client = new DthTestClient(server, _loggerFactory))
|
using (var client = new DthTestClient(server, _loggerFactory))
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"content": [
|
"content": [
|
||||||
"../../TestAssets/TestProjects/ProjectWithTests/project.json"
|
"../../TestAssets/TestProjects/ProjectWithTests/project.json",
|
||||||
|
"../../TestAssets/TestProjects/ProjectWithTests/project.lock.json"
|
||||||
],
|
],
|
||||||
"testRunner": "xunit"
|
"testRunner": "xunit"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue