Merge pull request #3962 from eerhardt/msbuild-GenerateDepsFile

Implement GenerateDepsFile MSBuild Task
This commit is contained in:
Eric Erhardt 2016-08-01 20:17:05 -05:00 committed by GitHub
commit df3fea3736
23 changed files with 14021 additions and 149 deletions

View file

@ -142,13 +142,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "compile", "compile", "{8E33
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{FF498306-2DE2-47F6-8C35-3CF0589CF2B8}"
ProjectSection(SolutionItems) = preProject
build\test\TestPackageProjects.props = build\test\TestPackageProjects.props
build\test\TestAssetProjects.targets = build\test\TestAssetProjects.targets
build\test\TestPackageProjects.targets = build\test\TestPackageProjects.targets
build\test\TestProjects.targets = build\test\TestProjects.targets
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Core.Build.Tasks", "src\Microsoft.DotNet.Core.Build.Tasks\Microsoft.DotNet.Core.Build.Tasks.xproj", "{E8E7D24B-4830-4662-80A8-255D6FE3B0BE}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Tools.Tests.Utilities", "test\Microsoft.DotNet.Tools.Tests.Utilities\Microsoft.DotNet.Tools.Tests.Utilities.xproj", "{E4F46EAB-B5A5-4E60-9B9D-40A1FADBF45C}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Core.Build.Tasks.Tests", "test\Microsoft.DotNet.Core.Build.Tasks.Tests\Microsoft.DotNet.Core.Build.Tasks.Tests.xproj", "{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -913,6 +917,22 @@ Global
{E4F46EAB-B5A5-4E60-9B9D-40A1FADBF45C}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{E4F46EAB-B5A5-4E60-9B9D-40A1FADBF45C}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{E4F46EAB-B5A5-4E60-9B9D-40A1FADBF45C}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.Debug|x64.ActiveCfg = Debug|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.Debug|x64.Build.0 = Debug|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.Release|Any CPU.Build.0 = Release|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.Release|x64.ActiveCfg = Release|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.Release|x64.Build.0 = Release|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -973,5 +993,6 @@ Global
{FF498306-2DE2-47F6-8C35-3CF0589CF2B8} = {89905EC4-BC0F-443B-8ADF-691321F10108}
{E8E7D24B-4830-4662-80A8-255D6FE3B0BE} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{E4F46EAB-B5A5-4E60-9B9D-40A1FADBF45C} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{EDD6C92D-0A58-4FCB-A0E9-9D0FFC045177} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
EndGlobalSection
EndGlobal

View file

@ -56,12 +56,12 @@ namespace Microsoft.DotNet.Tools.Common
return path + trailingCharacter;
}
public static string EnsureNoTrailingSlash(string path)
public static string EnsureNoTrailingDirectorySeparator(string path)
{
if (!string.IsNullOrEmpty(path))
{
char lastChar = path[path.Length - 1];
if (lastChar == Path.DirectorySeparatorChar || lastChar == '/')
if (lastChar == Path.DirectorySeparatorChar)
{
path = path.Substring(0, path.Length - 1);
}

View file

@ -50,10 +50,10 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
_compilerOptions = _context.ProjectFile.GetCompilerOptions(_context.TargetFramework, configuration);
}
public void MakeCompilationOutputRunnable(bool skipRuntimeConfig = false)
public void MakeCompilationOutputRunnable()
{
CopyContentFiles();
ExportRuntimeAssets(skipRuntimeConfig);
ExportRuntimeAssets();
}
private void VerifyCoreClrPresenceInPackageGraph()
@ -73,7 +73,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
}
}
private void ExportRuntimeAssets(bool skipRuntimeConfig)
private void ExportRuntimeAssets()
{
if (_context.TargetFramework.IsDesktop())
{
@ -81,7 +81,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
}
else
{
MakeCompilationOutputRunnableForCoreCLR(skipRuntimeConfig);
MakeCompilationOutputRunnableForCoreCLR();
}
}
@ -93,11 +93,11 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
GenerateBindingRedirects(_exporter);
}
private void MakeCompilationOutputRunnableForCoreCLR(bool skipRuntimeConfig)
private void MakeCompilationOutputRunnableForCoreCLR()
{
WriteDepsFileAndCopyProjectDependencies(_exporter, skipRuntimeConfig);
WriteDepsFileAndCopyProjectDependencies(_exporter);
var isRunnable = _compilerOptions.EmitEntryPoint ?? _context.ProjectFile.OverrideIsRunnable;
var isRunnable = _compilerOptions.EmitEntryPoint ?? false;
if (isRunnable && !_context.IsPortable)
{
@ -155,14 +155,14 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
}
}
private void WriteDepsFileAndCopyProjectDependencies(LibraryExporter exporter, bool skipRuntimeConfig)
private void WriteDepsFileAndCopyProjectDependencies(LibraryExporter exporter)
{
var exports = exporter.GetAllExports().ToList();
var exportsLookup = exports.ToDictionary(e => e.Library.Identity.Name, StringComparer.OrdinalIgnoreCase);
var platformExclusionList = _context.GetPlatformExclusionList(exportsLookup);
var filteredExports = exports.FilterExports(platformExclusionList);
WriteConfigurationFiles(exports, filteredExports, exports, includeDevConfig: true, skipRuntimeConfig: skipRuntimeConfig);
WriteConfigurationFiles(exports, filteredExports, exports, includeDevConfig: true);
var projectExports = exporter.GetAllProjectTypeDependencies();
CopyAssemblies(projectExports);
@ -176,11 +176,10 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
IEnumerable<LibraryExport> allExports,
IEnumerable<LibraryExport> depsRuntimeExports,
IEnumerable<LibraryExport> depsCompilationExports,
bool includeDevConfig,
bool skipRuntimeConfig = false)
bool includeDevConfig)
{
WriteDeps(depsRuntimeExports, depsCompilationExports);
if (_context.ProjectFile.HasRuntimeOutput(_configuration) && !skipRuntimeConfig)
if (_context.ProjectFile.HasRuntimeOutput(_configuration))
{
WriteRuntimeConfig(allExports);
if (includeDevConfig)
@ -282,14 +281,14 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
foreach (var packageFolder in _context.LockFile.PackageFolders)
{
// DotNetHost doesn't handle additional probing paths with a trailing slash
additionalProbingPaths.Add(PathUtility.EnsureNoTrailingSlash(packageFolder.Path));
additionalProbingPaths.Add(PathUtility.EnsureNoTrailingDirectorySeparator(packageFolder.Path));
}
runtimeOptions.Add("additionalProbingPaths", additionalProbingPaths);
}
}
public void WriteDeps(IEnumerable<LibraryExport> runtimeExports, IEnumerable<LibraryExport> compilationExports)
private void WriteDeps(IEnumerable<LibraryExport> runtimeExports, IEnumerable<LibraryExport> compilationExports)
{
Directory.CreateDirectory(_runtimeOutputPath);
@ -311,7 +310,7 @@ namespace Microsoft.DotNet.Cli.Compiler.Common
}
}
public void GenerateBindingRedirects(LibraryExporter exporter)
private void GenerateBindingRedirects(LibraryExporter exporter)
{
var outputName = _outputPaths.RuntimeFiles.Assembly;
var configFile = outputName + Constants.ConfigSuffix;

View file

@ -0,0 +1,270 @@
// 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.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.DependencyModel;
using NuGet.Frameworks;
using NuGet.Packaging.Core;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Core.Build.Tasks
{
public class DependencyContextBuilder
{
public DependencyContextBuilder()
{
}
public DependencyContext Build(
string projectName,
string projectVersion,
CompilationOptions compilerOptions,
LockFile lockFile,
NuGetFramework framework,
string runtime)
{
LockFileTarget lockFileTarget = lockFile.GetTarget(framework, runtime);
IEnumerable<LockFileTargetLibrary> runtimeExports = lockFileTarget.Libraries;
// TODO: get this from the lock file once https://github.com/NuGet/Home/issues/2695 is fixed.
var platformPackageName = "Microsoft.NETCore.App";
var platformExport = lockFileTarget
.Libraries
.FirstOrDefault(e => e.Name.Equals(platformPackageName, StringComparison.OrdinalIgnoreCase));
bool portable = platformExport != null;
if (portable)
{
runtimeExports = FilterPlatformDependencies(runtimeExports, platformExport);
}
var dependencyLookup = runtimeExports
.Select(identity => new Dependency(identity.Name, identity.Version.ToString()))
.ToDictionary(dependency => dependency.Name, StringComparer.OrdinalIgnoreCase);
var libraryLookup = lockFile.Libraries.ToDictionary(l => l.Name, StringComparer.OrdinalIgnoreCase);
var runtimeSignature = GenerateRuntimeSignature(runtimeExports);
IEnumerable<RuntimeLibrary> runtimeLibraries =
new[] { GetProjectLibrary(projectName, projectVersion, lockFile, lockFileTarget, dependencyLookup) }
.Concat(GetLibraries(runtimeExports, libraryLookup, dependencyLookup, runtime: true).Cast<RuntimeLibrary>());
return new DependencyContext(
new TargetInfo(framework.DotNetFrameworkName, runtime, runtimeSignature, portable),
compilerOptions ?? CompilationOptions.Default,
Enumerable.Empty<CompilationLibrary>(), //GetLibraries(compilationExports, dependencyLookup, runtime: false).Cast<CompilationLibrary>(),
runtimeLibraries,
new RuntimeFallbacks[] { });
}
private static IEnumerable<LockFileTargetLibrary> FilterPlatformDependencies(
IEnumerable<LockFileTargetLibrary> runtimeExports,
LockFileTargetLibrary platformExport)
{
var exportsLookup = runtimeExports.ToDictionary(e => e.Name, StringComparer.OrdinalIgnoreCase);
HashSet<string> exclusionList = GetPlatformExclusionList(platformExport, exportsLookup);
return runtimeExports.Where(e => !exclusionList.Contains(e.Name));
}
private static HashSet<string> GetPlatformExclusionList(
LockFileTargetLibrary platformExport,
IDictionary<string, LockFileTargetLibrary> exportsLookup)
{
var exclusionList = new HashSet<string>();
exclusionList.Add(platformExport.Name);
CollectDependencies(exportsLookup, platformExport.Dependencies, exclusionList);
return exclusionList;
}
private static void CollectDependencies(
IDictionary<string, LockFileTargetLibrary> exportsLookup,
IEnumerable<PackageDependency> dependencies,
HashSet<string> exclusionList)
{
foreach (PackageDependency dependency in dependencies)
{
LockFileTargetLibrary export = exportsLookup[dependency.Id];
if (export.Version.Equals(dependency.VersionRange.MinVersion))
{
exclusionList.Add(export.Name);
CollectDependencies(exportsLookup, export.Dependencies, exclusionList);
}
}
}
private static string GenerateRuntimeSignature(IEnumerable<LockFileTargetLibrary> runtimeExports)
{
var sha1 = SHA1.Create();
var builder = new StringBuilder();
var packages = runtimeExports
.Where(libraryExport => libraryExport.Type == "package");
var separator = "|";
foreach (var libraryExport in packages)
{
builder.Append(libraryExport.Name);
builder.Append(separator);
builder.Append(libraryExport.Version.ToString());
builder.Append(separator);
}
var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(builder.ToString()));
builder.Clear();
foreach (var hashByte in hash)
{
builder.AppendFormat("{0:x2}", hashByte);
}
return builder.ToString();
}
private RuntimeLibrary GetProjectLibrary(
string projectName,
string projectVersion,
LockFile lockFile,
LockFileTarget lockFileTarget,
Dictionary<string, Dependency> dependencyLookup)
{
RuntimeAssetGroup[] runtimeAssemblyGroups = new[] { new RuntimeAssetGroup(string.Empty, $"{projectName}.dll") };
List<Dependency> dependencies = new List<Dependency>();
IEnumerable<ProjectFileDependencyGroup> projectFileDependencies = lockFile
.ProjectFileDependencyGroups
.Where(dg => dg.FrameworkName == string.Empty ||
dg.FrameworkName == lockFileTarget.TargetFramework.DotNetFrameworkName);
foreach (string projectFileDependency in projectFileDependencies.SelectMany(dg => dg.Dependencies))
{
int separatorIndex = projectFileDependency.IndexOf(' ');
string dependencyName = separatorIndex > 0 ?
projectFileDependency.Substring(0, separatorIndex) :
projectFileDependency;
Dependency dependency;
if (dependencyLookup.TryGetValue(dependencyName, out dependency))
{
dependencies.Add(dependency);
}
}
return new RuntimeLibrary(
type: "project",
name: projectName,
version: projectVersion,
hash: string.Empty,
runtimeAssemblyGroups: runtimeAssemblyGroups,
nativeLibraryGroups: new RuntimeAssetGroup[] { },
resourceAssemblies: new ResourceAssembly[] { },
dependencies: dependencies.ToArray(),
serviceable: false);
}
private IEnumerable<Library> GetLibraries(
IEnumerable<LockFileTargetLibrary> exports,
IDictionary<string, LockFileLibrary> libraryLookup,
IDictionary<string, Dependency> dependencyLookup,
bool runtime)
{
return exports.Select(export => GetLibrary(export, libraryLookup, dependencyLookup, runtime));
}
private Library GetLibrary(
LockFileTargetLibrary export,
IDictionary<string, LockFileLibrary> libraryLookup,
IDictionary<string, Dependency> dependencyLookup,
bool runtime)
{
var type = export.Type;
// TEMPORARY: All packages are serviceable in RC2
// See https://github.com/dotnet/cli/issues/2569
var serviceable = export.Type == "package";
var libraryDependencies = new HashSet<Dependency>();
foreach (PackageDependency libraryDependency in export.Dependencies)
{
Dependency dependency;
if (dependencyLookup.TryGetValue(libraryDependency.Id, out dependency))
{
libraryDependencies.Add(dependency);
}
}
string hash = string.Empty;
LockFileLibrary library;
if (libraryLookup.TryGetValue(export.Name, out library))
{
hash = "sha512-" + library.Sha512;
}
if (runtime)
{
return new RuntimeLibrary(
type.ToLowerInvariant(),
export.Name,
export.Version.ToString(),
hash,
CreateRuntimeAssemblyGroups(export),
CreateNativeLibraryGroups(export),
export.ResourceAssemblies.Select(CreateResourceAssembly),
libraryDependencies,
serviceable
);
}
//else
//{
// IEnumerable<string> assemblies = export
// .CompilationAssemblies
// .Select(libraryAsset => libraryAsset.RelativePath);
// return new CompilationLibrary(
// type.ToString().ToLowerInvariant(),
// export.Library.Identity.Name,
// export.Library.Identity.Version.ToString(),
// export.Library.Hash,
// assemblies,
// libraryDependencies,
// serviceable);
//}
return null;
}
private IReadOnlyList<RuntimeAssetGroup> CreateRuntimeAssemblyGroups(LockFileTargetLibrary export)
{
List<RuntimeAssetGroup> assemblyGroups = new List<RuntimeAssetGroup>();
assemblyGroups.Add(
new RuntimeAssetGroup(string.Empty, export.RuntimeAssemblies.Select(a => a.Path)));
// TODO RuntimeTargets
//export.RuntimeTargets.GroupBy(l => l.)
return assemblyGroups;
}
private IReadOnlyList<RuntimeAssetGroup> CreateNativeLibraryGroups(LockFileTargetLibrary export)
{
return new[] { new RuntimeAssetGroup(string.Empty, export.NativeLibraries.Select(a => a.Path)) };
}
private ResourceAssembly CreateResourceAssembly(LockFileItem resourceAssembly)
{
// TODO: implement
return null;
//return new ResourceAssembly(
// path: resourceAssembly.Path,
// locale: resourceAssembly.Locale
// );
}
}
}

View file

@ -0,0 +1,57 @@
// 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.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.Extensions.DependencyModel;
using Newtonsoft.Json;
using NuGet.Frameworks;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Core.Build.Tasks
{
/// <summary>
/// Generates the $(project).deps.json file.
/// </summary>
public class GenerateDepsFile : Task
{
[Required]
public string LockFilePath { get; set; }
[Required]
public string DepsFilePath { get; set; }
[Required]
public string TargetFramework { get; set; }
public string RuntimeIdentifier { get; set; }
[Required]
public string AssemblyName { get; set; }
[Required]
public string AssemblyVersion { get; set; }
public override bool Execute()
{
LockFile lockFile = LockFileCache.Instance.GetLockFile(LockFilePath);
DependencyContext dependencyContext = new DependencyContextBuilder().Build(
projectName: AssemblyName,
projectVersion: AssemblyVersion,
compilerOptions: null, // TODO: PreservceCompliationContext
lockFile: lockFile,
framework: TargetFramework == null ? null : NuGetFramework.Parse(TargetFramework),
runtime: RuntimeIdentifier);
var writer = new DependencyContextWriter();
using (var fileStream = File.Create(DepsFilePath))
{
writer.Write(dependencyContext, fileStream);
}
return true;
}
}
}

View file

@ -7,14 +7,12 @@ using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.Tasks
namespace Microsoft.DotNet.Core.Build.Tasks
{
/// <summary>
/// Generates the $(project).runtimeconfig.json and optionally $(project).runtimeconfig.dev.json files
@ -22,18 +20,15 @@ namespace Microsoft.DotNet.Cli.Tasks
/// </summary>
public class GenerateRuntimeConfigurationFiles : Task
{
[Required]
public string RuntimeOutputPath { get; set; }
[Required]
public string OutputName { get; set; }
[Required]
public string LockFilePath { get; set; }
public string RawRuntimeOptions { get; set; }
[Required]
public string RuntimeConfigPath { get; set; }
public bool IncludeDevConfig { get; set; }
public string RuntimeConfigDevPath { get; set; }
public string RawRuntimeOptions { get; set; }
private LockFile LockFile { get; set; }
@ -43,7 +38,7 @@ namespace Microsoft.DotNet.Cli.Tasks
WriteRuntimeConfig();
if (IncludeDevConfig)
if (!string.IsNullOrEmpty(RuntimeConfigDevPath))
{
WriteDevRuntimeConfig();
}
@ -59,10 +54,7 @@ namespace Microsoft.DotNet.Cli.Tasks
AddFramework(config.RuntimeOptions);
AddRuntimeOptions(config.RuntimeOptions);
var runtimeConfigJsonFile =
Path.Combine(RuntimeOutputPath, OutputName + FileNameSuffixes.RuntimeConfigJson);
WriteToJsonFile(runtimeConfigJsonFile, config);
WriteToJsonFile(RuntimeConfigPath, config);
}
private void AddFramework(RuntimeOptions runtimeOptions)
@ -105,10 +97,7 @@ namespace Microsoft.DotNet.Cli.Tasks
AddAdditionalProbingPaths(devConfig.RuntimeOptions);
var runtimeConfigDevJsonFile =
Path.Combine(RuntimeOutputPath, OutputName + FileNameSuffixes.RuntimeConfigDevJson);
WriteToJsonFile(runtimeConfigDevJsonFile, devConfig);
WriteToJsonFile(RuntimeConfigDevPath, devConfig);
}
private void AddAdditionalProbingPaths(RuntimeOptions runtimeOptions)
@ -121,10 +110,24 @@ namespace Microsoft.DotNet.Cli.Tasks
}
// DotNetHost doesn't handle additional probing paths with a trailing slash
runtimeOptions.AdditionalProbingPaths.Add(PathUtility.EnsureNoTrailingSlash(packageFolder.Path));
runtimeOptions.AdditionalProbingPaths.Add(EnsureNoTrailingDirectorySeparator(packageFolder.Path));
}
}
private static string EnsureNoTrailingDirectorySeparator(string path)
{
if (!string.IsNullOrEmpty(path))
{
char lastChar = path[path.Length - 1];
if (lastChar == Path.DirectorySeparatorChar)
{
path = path.Substring(0, path.Length - 1);
}
}
return path;
}
private static void WriteToJsonFile(string fileName, object value)
{
JsonSerializer serializer = new JsonSerializer();

View file

@ -5,7 +5,7 @@ using System.Collections.Concurrent;
using NuGet.Common;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.Tasks
namespace Microsoft.DotNet.Core.Build.Tasks
{
internal class LockFileCache
{

View file

@ -1,89 +0,0 @@
// 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.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.DotNet.Cli.Compiler.Common;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Compilation;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Cli.Tasks
{
public class MakeNetCoreRunnable : Task
{
[Required]
public string ProjectPath { get; set; }
[Required]
public string Configuration { get; set; }
[Required]
public string OutputPath { get; set; }
[Required]
public string OutputType { get; set; }
public string Runtime { get; set; }
private bool HasRuntimeOutput
{
get { return string.Equals("Exe", OutputType, StringComparison.OrdinalIgnoreCase); }
}
public override bool Execute()
{
BuildWorkspace workspace = BuildWorkspace.Create();
string framework = null; //TODO: should we take a NuGet framework ?
IEnumerable<ProjectContext> projectContexts = GetProjectContexts(workspace,
framework == null ? null : NuGetFramework.Parse(framework),
Runtime);
if (!projectContexts.Any())
{
Log.LogError($"'{ProjectPath}' cannot be made runnable for '{framework ?? "<no framework provided>"}' '{Runtime ?? "<no runtime provided>"}'");
return false;
}
foreach (ProjectContext projectContext in projectContexts)
{
string buildBasePath = null; // TODO: Is there an "Intermediate Directory" property we can take?
projectContext.ProjectFile.OverrideIsRunnable = HasRuntimeOutput;
OutputPaths outputPaths = projectContext.GetOutputPaths(Configuration, buildBasePath, OutputPath);
LibraryExporter libraryExporter = projectContext.CreateExporter(Configuration, buildBasePath);
Executable executable = new Executable(projectContext, outputPaths, libraryExporter, Configuration);
executable.MakeCompilationOutputRunnable(skipRuntimeConfig: true);
}
return true;
}
private IEnumerable<ProjectContext> GetProjectContexts(BuildWorkspace workspace, NuGetFramework framework, string runtime)
{
var contexts = workspace.GetProjectContextCollection(ProjectPath)
.EnsureValid(ProjectPath)
.FrameworkOnlyContexts;
contexts = framework == null ?
contexts :
contexts.Where(c => Equals(c.TargetFramework, framework));
var rids = string.IsNullOrEmpty(runtime) ?
RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers() :
new[] { runtime };
return contexts.Select(c => workspace.GetRuntimeContext(c, rids));
}
}
}

View file

@ -0,0 +1,3 @@
using System.Reflection;
[assembly: AssemblyMetadataAttribute("Serviceable", "True")]

View file

@ -1,7 +1,7 @@
// 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.
namespace Microsoft.DotNet.Cli.Tasks
namespace Microsoft.DotNet.Core.Build.Tasks
{
internal class RuntimeConfig
{

View file

@ -1,7 +1,7 @@
// 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.
namespace Microsoft.DotNet.Cli.Tasks
namespace Microsoft.DotNet.Core.Build.Tasks
{
internal class RuntimeConfigFramework
{

View file

@ -5,7 +5,7 @@ using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.Cli.Tasks
namespace Microsoft.DotNet.Core.Build.Tasks
{
internal class RuntimeOptions
{

View file

@ -5,9 +5,10 @@
"warningsAsErrors": true
},
"dependencies": {
"Microsoft.DotNet.Compiler.Common": {
"Microsoft.Extensions.DependencyModel": {
"target": "project"
}
},
"NuGet.ProjectModel": "3.5.0-rc1-1653"
},
"frameworks": {
"net451": {

View file

@ -84,8 +84,6 @@ namespace Microsoft.DotNet.ProjectModel
public bool IsTestProject => !string.IsNullOrEmpty(TestRunner);
public bool OverrideIsRunnable { get; set; }
public IEnumerable<TargetFrameworkInformation> GetTargetFrameworks()
{
return _targetFrameworks.Values;
@ -130,7 +128,7 @@ namespace Microsoft.DotNet.ProjectModel
var compilerOptions = GetCompilerOptions(targetFramework: null, configurationName: configuration);
// TODO: Make this opt in via another mechanism
return compilerOptions.EmitEntryPoint.GetValueOrDefault() || IsTestProject || OverrideIsRunnable;
return compilerOptions.EmitEntryPoint.GetValueOrDefault() || IsTestProject;
}
private CommonCompilerOptions GetCompilerOptions()

View file

@ -20,10 +20,14 @@
<PropertyGroup>
<GenerateRuntimeConfigurationFiles Condition=" '$(GenerateRuntimeConfigurationFiles)' == '' and '$(OutputType)' == 'exe' ">true</GenerateRuntimeConfigurationFiles>
<VersionPrefix Condition=" '$(VersionPrefix)' == '' ">1.0.0</VersionPrefix>
<VersionSuffix Condition=" '$(VersionSuffix)' == '' "></VersionSuffix>
<Version Condition=" '$(Version)' == '' and '$(VersionSuffix)' != '' ">$(VersionPrefix)-$(VersionSuffix)</Version>
<Version Condition=" '$(Version)' == '' ">$(VersionPrefix)</Version>
</PropertyGroup>
<UsingTask TaskName="GenerateDepsFile" AssemblyFile="$(MicrosoftDotNetCoreBuildTasksDirectory)Microsoft.DotNet.Core.Build.Tasks.dll" />
<UsingTask TaskName="GenerateRuntimeConfigurationFiles" AssemblyFile="$(MicrosoftDotNetCoreBuildTasksDirectory)Microsoft.DotNet.Core.Build.Tasks.dll" />
<UsingTask TaskName="MakeNetCoreRunnable" AssemblyFile="$(MicrosoftDotNetCoreBuildTasksDirectory)Microsoft.DotNet.Core.Build.Tasks.dll" />
<PropertyGroup>
<CoreBuildDependsOn>
@ -41,12 +45,19 @@
<Move SourceFiles="$(TargetPath)" DestinationFiles="$(TargetDir)/$(AssemblyName).dll" />
<!--
TODO: need to remove ProjectPath (to load up the project.json) and instead pass @(PackageDependency)
TODO: Get RuntimeIdentifier
-->
<GenerateDepsFile LockFilePath="$(MSBuildProjectDirectory)/project.lock.json"
DepsFilePath="$(TargetDir)$(AssemblyName).deps.json"
TargetFramework="$(TargetFrameworkIdentifier),Version=$(TargetFrameworkVersion)"
AssemblyName="$(AssemblyName)"
AssemblyVersion="$(Version)"
RuntimeIdentifier="" />
<!--
TODO: When OutputType == 'exe' and !IsPortable, we need to verify CoreClr is present in the deps graph, and copy in a host to the output
See https://github.com/dotnet/cli/blob/6b54ae0bcc5c63e7c989ac19d851f234f9172bea/src/Microsoft.DotNet.Compiler.Common/Executable.cs#L102-L107
-->
<MakeNetCoreRunnable ProjectPath="$(MSBuildProjectDirectory)"
Configuration="$(Configuration)"
OutputPath="$(OutDir)"
OutputType="$(OutputType)" />
</Target>
<Target Name="GenerateRuntimeConfigurationFiles"
@ -56,10 +67,9 @@
TODO: Get RawRuntimeOptions from where it lives in the MSBuild world
-->
<GenerateRuntimeConfigurationFiles LockFilePath="$(MSBuildProjectDirectory)/project.lock.json"
RuntimeOutputPath="$(TargetDir)"
OutputName="$(AssemblyName)"
RawRuntimeOptions=""
IncludeDevConfig="true" />
RuntimeConfigPath="$(TargetDir)/$(AssemblyName).runtimeconfig.json"
RuntimeConfigDevPath="$(TargetDir)/$(AssemblyName).runtimeconfig.dev.json"
RawRuntimeOptions="" />
</Target>

View file

@ -154,7 +154,7 @@ namespace Microsoft.DotNet.Tools.Run
foreach (var packageFolder in _context.LockFile.PackageFolders)
{
// DotNetHost doesn't handle additional probing paths with a trailing slash
hostArgs.Insert(0, PathUtility.EnsureNoTrailingSlash(packageFolder.Path));
hostArgs.Insert(0, PathUtility.EnsureNoTrailingDirectorySeparator(packageFolder.Path));
hostArgs.Insert(0, probingPathArg);
}
}

View file

@ -0,0 +1,71 @@
// 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.IO;
using FluentAssertions.Json;
using Microsoft.Extensions.DependencyModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NuGet.Common;
using NuGet.Frameworks;
using NuGet.ProjectModel;
using Xunit;
namespace Microsoft.DotNet.Core.Build.Tasks.Tests
{
public class GivenADependencyContextBuilder
{
/// <summary>
/// Tests that DependencyContextBuilder generates DependencyContexts correctly.
/// </summary>
[Theory]
[InlineData("dotnet.new", "1.0.0")]
[InlineData("simple.dependencies", "1.0.0")]
public void ItBuildsDependencyContextsFromProjectLockFiles(string mainProjectName, string mainProjectVersion)
{
LockFile lockFile = LockFileUtilities.GetLockFile($"{mainProjectName}.project.lock.json", NullLogger.Instance);
DependencyContext dependencyContext = new DependencyContextBuilder().Build(
mainProjectName,
mainProjectVersion,
compilerOptions: null,
lockFile: lockFile,
framework: FrameworkConstants.CommonFrameworks.NetCoreApp10,
runtime: null);
JObject result = Save(dependencyContext);
JObject baseline = ReadJson($"{mainProjectName}.deps.json");
baseline
.Should()
.BeEquivalentTo(result);
}
private static JObject ReadJson(string path)
{
using (JsonTextReader jsonReader = new JsonTextReader(File.OpenText(path)))
{
JsonSerializer serializer = new JsonSerializer();
return serializer.Deserialize<JObject>(jsonReader);
}
}
private JObject Save(DependencyContext dependencyContext)
{
using (var memoryStream = new MemoryStream())
{
new DependencyContextWriter().Write(dependencyContext, memoryStream);
using (var readStream = new MemoryStream(memoryStream.ToArray()))
{
using (var textReader = new StreamReader(readStream))
{
using (var reader = new JsonTextReader(textReader))
{
return JObject.Load(reader);
}
}
}
}
}
}
}

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>edd6c92d-0a58-4fcb-a0e9-9d0ffc045177</ProjectGuid>
<RootNamespace>Microsoft.DotNet.Core.Build.Tasks.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View file

@ -0,0 +1,23 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v1.0",
"signature": "da39a3ee5e6b4b0d3255bfef95601890afd80709"
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v1.0": {
"dotnet.new/1.0.0": {
"runtime": {
"dotnet.new.dll": {}
}
}
}
},
"libraries": {
"dotnet.new/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
{
"version": "1.0.0-*",
"buildOptions": {
"keyFile": "../../tools/Key.snk"
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.DotNet.Core.Build.Tasks": {
"target": "project"
},
"xunit": "2.1.0",
"FluentAssertions.Json": "4.12.0",
"dotnet-test-xunit": "1.0.0-rc2-192208-24"
},
"testRunner": "xunit",
"frameworks": {
"netcoreapp1.0": {
"imports": [
"netstandardapp1.5",
"dotnet5.4",
"portable-net451+win8"
]
}
}
}

View file

@ -0,0 +1,60 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v1.0",
"signature": "a813617eb7d3bb5d69fa51d48f64bc6455d8ca5f"
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v1.0": {
"simple.dependencies/1.0.0": {
"dependencies": {
"System.Collections.NonGeneric": "4.0.1",
"Newtonsoft.Json": "9.0.1"
},
"runtime": {
"simple.dependencies.dll": {}
}
},
"newtonsoft.json/9.0.1": {
"dependencies": {
"System.Runtime.Serialization.Primitives": "4.1.1"
},
"runtime": {
"lib/netstandard1.0/Newtonsoft.Json.dll": {}
}
},
"system.collections.nongeneric/4.0.1": {
"runtime": {
"lib/netstandard1.3/System.Collections.NonGeneric.dll": {}
}
},
"system.runtime.serialization.primitives/4.1.1": {
"runtime": {
"lib/netstandard1.3/System.Runtime.Serialization.Primitives.dll": {}
}
}
}
},
"libraries": {
"simple.dependencies/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"newtonsoft.json/9.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-U82mHQSKaIk+lpSVCbWYKNavmNH1i5xrExDEquU1i6I5pV6UMOqRnJRSlKO3cMPfcpp0RgDY+8jUXHdQ4IfXvw=="
},
"system.collections.nongeneric/4.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-hMxFT2RhhlffyCdKLDXjx8WEC5JfCvNozAZxCablAuFRH74SCV4AgzE8yJCh/73bFnEoZgJ9MJmkjQ0dJmnKqA=="
},
"system.runtime.serialization.primitives/4.1.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg=="
}
}
}