Added support for relocating reference assemblies

- This enables building for mono by setting the DOTNET_REFERENCE_ASSEMBLIES_PATH env variable. We could add some smart defaults for mono later.
- Added a new diagnostic for reference assemblies when the framework itself isn't installed.
- Added new error codes for dotnet.
This commit is contained in:
David Fowler 2015-10-28 02:21:00 -07:00
parent 3b9cfb086c
commit 80beccdbdc
6 changed files with 99 additions and 41 deletions

View file

@ -0,0 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Extensions.ProjectModel
{
public static partial class ErrorCodes
{
// Target framework not installed
public static readonly string DOTNET1011 = nameof(DOTNET1011);
}
}

View file

@ -3,7 +3,7 @@
namespace Microsoft.Extensions.ProjectModel namespace Microsoft.Extensions.ProjectModel
{ {
public static class ErrorCodes public static partial class ErrorCodes
{ {
// The dependency A could not be resolved. // The dependency A could not be resolved.
public static readonly string NU1001 = nameof(NU1001); public static readonly string NU1001 = nameof(NU1001);

View file

@ -1,7 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
using Microsoft.Extensions.ProjectModel.Graph; using Microsoft.Extensions.ProjectModel.Graph;
using Microsoft.Extensions.ProjectModel.Resolution; using Microsoft.Extensions.ProjectModel.Resolution;
@ -26,6 +27,8 @@ namespace Microsoft.Extensions.ProjectModel
public string ProjectDirectory { get; set; } public string ProjectDirectory { get; set; }
public string PackagesDirectory { get; set; } public string PackagesDirectory { get; set; }
public string ReferenceAssembliesPath { get; set; }
public ProjectContext Build() public ProjectContext Build()
{ {
@ -44,6 +47,7 @@ namespace Microsoft.Extensions.ProjectModel
RootDirectory = GlobalSettings?.DirectoryPath ?? RootDirectory; RootDirectory = GlobalSettings?.DirectoryPath ?? RootDirectory;
PackagesDirectory = PackagesDirectory ?? PackageDependencyProvider.ResolveRepositoryPath(RootDirectory, GlobalSettings); PackagesDirectory = PackagesDirectory ?? PackageDependencyProvider.ResolveRepositoryPath(RootDirectory, GlobalSettings);
ReferenceAssembliesPath = ReferenceAssembliesPath ?? GetDefaultReferenceAssembliesPath();
LockFileLookup lockFileLookup = null; LockFileLookup lockFileLookup = null;
@ -85,11 +89,12 @@ namespace Microsoft.Extensions.ProjectModel
} }
} }
var frameworkReferenceResolver = new FrameworkReferenceResolver(); var frameworkReferenceResolver = new FrameworkReferenceResolver(ReferenceAssembliesPath);
var referenceAssemblyDependencyResolver = new ReferenceAssemblyDependencyResolver(frameworkReferenceResolver); var referenceAssemblyDependencyResolver = new ReferenceAssemblyDependencyResolver(frameworkReferenceResolver);
bool requiresFrameworkAssemblies;
// Resolve the dependencies // Resolve the dependencies
ResolveDependencies(libraries, referenceAssemblyDependencyResolver); ResolveDependencies(libraries, referenceAssemblyDependencyResolver, out requiresFrameworkAssemblies);
var diagnostics = new List<DiagnosticMessage>(); var diagnostics = new List<DiagnosticMessage>();
@ -112,6 +117,22 @@ namespace Microsoft.Extensions.ProjectModel
DiagnosticMessageSeverity.Warning)); DiagnosticMessageSeverity.Warning));
} }
if (requiresFrameworkAssemblies && !frameworkReferenceResolver.IsInstalled(TargetFramework))
{
var frameworkInfo = Project.GetTargetFramework(TargetFramework);
// If there was an attempt to use reference assemblies but they were not installed
// report an error
diagnostics.Add(new DiagnosticMessage(
ErrorCodes.DOTNET1011,
$"Framework not installed: {TargetFramework.DotNetFrameworkName}",
filePath: Project.ProjectFilePath,
severity: DiagnosticMessageSeverity.Error,
startLine: frameworkInfo.Line,
startColumn: frameworkInfo.Column
));
}
// Create a library manager // Create a library manager
var libraryManager = new LibraryManager(libraries.Values.ToList(), diagnostics); var libraryManager = new LibraryManager(libraries.Values.ToList(), diagnostics);
@ -124,8 +145,12 @@ namespace Microsoft.Extensions.ProjectModel
libraryManager); libraryManager);
} }
private void ResolveDependencies(Dictionary<LibraryKey, LibraryDescription> libraries, ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver) private void ResolveDependencies(Dictionary<LibraryKey, LibraryDescription> libraries,
ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver,
out bool requiresFrameworkAssemblies)
{ {
requiresFrameworkAssemblies = false;
foreach (var library in libraries.Values.ToList()) foreach (var library in libraries.Values.ToList())
{ {
if (Equals(library.Identity.Type, LibraryType.Package) && if (Equals(library.Identity.Type, LibraryType.Package) &&
@ -146,6 +171,8 @@ namespace Microsoft.Extensions.ProjectModel
{ {
if (Equals(LibraryType.ReferenceAssembly, dependency.Target)) if (Equals(LibraryType.ReferenceAssembly, dependency.Target))
{ {
requiresFrameworkAssemblies = true;
dep = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ?? dep = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ??
UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework);
@ -203,6 +230,44 @@ namespace Microsoft.Extensions.ProjectModel
} }
} }
public static string GetDefaultReferenceAssembliesPath()
{
// Allow setting the reference assemblies path via an environment variable
var referenceAssembliesPath = Environment.GetEnvironmentVariable("DOTNET_REFERENCE_ASSEMBLIES_PATH");
if (!string.IsNullOrEmpty(referenceAssembliesPath))
{
return referenceAssembliesPath;
}
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// There is no reference assemblies path outside of windows
// The enviorment variable can be used to specify one
return null;
}
// References assemblies are in %ProgramFiles(x86)% on
// 64 bit machines
var programFiles = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
if (string.IsNullOrEmpty(programFiles))
{
// On 32 bit machines they are in %ProgramFiles%
programFiles = Environment.GetEnvironmentVariable("ProgramFiles");
}
if (string.IsNullOrEmpty(programFiles))
{
// Reference assemblies aren't installed
return null;
}
return Path.Combine(
programFiles,
"Reference Assemblies", "Microsoft", "Framework");
}
private void EnsureProjectLoaded() private void EnsureProjectLoaded()
{ {
if (Project == null) if (Project == null)

View file

@ -465,7 +465,9 @@ namespace Microsoft.Extensions.ProjectModel
{ {
FrameworkName = frameworkName, FrameworkName = frameworkName,
Dependencies = new List<LibraryRange>(), Dependencies = new List<LibraryRange>(),
CompilerOptions = compilerOptions CompilerOptions = compilerOptions,
Line = frameworkValue.Line,
Column = frameworkValue.Column
}; };
var frameworkDependencies = new List<LibraryRange>(); var frameworkDependencies = new List<LibraryRange>();

View file

@ -14,8 +14,6 @@ namespace Microsoft.Extensions.ProjectModel.Resolution
{ {
public class FrameworkReferenceResolver public class FrameworkReferenceResolver
{ {
// TODO(anurse): Move the Mono stuff back in.
// FrameworkConstants doesn't have dnx46 yet // FrameworkConstants doesn't have dnx46 yet
private static readonly NuGetFramework Dnx46 = new NuGetFramework( private static readonly NuGetFramework Dnx46 = new NuGetFramework(
FrameworkConstants.FrameworkIdentifiers.Dnx, FrameworkConstants.FrameworkIdentifiers.Dnx,
@ -28,6 +26,13 @@ namespace Microsoft.Extensions.ProjectModel.Resolution
{ FrameworkConstants.CommonFrameworks.Dnx451, new [] { FrameworkConstants.CommonFrameworks.Net451 } }, { FrameworkConstants.CommonFrameworks.Dnx451, new [] { FrameworkConstants.CommonFrameworks.Net451 } },
{ Dnx46, new [] { FrameworkConstants.CommonFrameworks.Net46 } } { Dnx46, new [] { FrameworkConstants.CommonFrameworks.Net46 } }
}; };
public FrameworkReferenceResolver(string referenceAssembliesPath)
{
ReferenceAssembliesPath = referenceAssembliesPath;
}
public string ReferenceAssembliesPath { get; }
public bool TryGetAssembly(string name, NuGetFramework targetFramework, out string path, out Version version) public bool TryGetAssembly(string name, NuGetFramework targetFramework, out string path, out Version version)
{ {
@ -65,15 +70,11 @@ namespace Microsoft.Extensions.ProjectModel.Resolution
return !string.IsNullOrEmpty(path); return !string.IsNullOrEmpty(path);
} }
public IEnumerable<string> GetAttemptedPaths(NuGetFramework targetFramework) public bool IsInstalled(NuGetFramework targetFramework)
{ {
var information = _cache.GetOrAdd(targetFramework, GetFrameworkInformation); var information = _cache.GetOrAdd(targetFramework, GetFrameworkInformation);
if (information == null || !information.Exists) return information?.Exists == true;
{
return null;
}
return information.SearchPaths.Select(s => Path.Combine(s, "{name}.dll"));
} }
public string GetFrameworkRedistListPath(NuGetFramework targetFramework) public string GetFrameworkRedistListPath(NuGetFramework targetFramework)
@ -87,40 +88,15 @@ namespace Microsoft.Extensions.ProjectModel.Resolution
return information.RedistListPath; return information.RedistListPath;
} }
private FrameworkInformation GetFrameworkInformation(NuGetFramework targetFramework)
public static string GetReferenceAssembliesPath()
{ {
// References assemblies are in %ProgramFiles(x86)% on string referenceAssembliesPath = ReferenceAssembliesPath;
// 64 bit machines
var programFiles = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
if (string.IsNullOrEmpty(programFiles))
{
// On 32 bit machines they are in %ProgramFiles%
programFiles = Environment.GetEnvironmentVariable("ProgramFiles");
}
if (string.IsNullOrEmpty(programFiles))
{
// Reference assemblies aren't installed
return null;
}
return Path.Combine(
programFiles,
"Reference Assemblies", "Microsoft", "Framework");
}
private static FrameworkInformation GetFrameworkInformation(NuGetFramework targetFramework)
{
string referenceAssembliesPath = GetReferenceAssembliesPath();
if (string.IsNullOrEmpty(referenceAssembliesPath)) if (string.IsNullOrEmpty(referenceAssembliesPath))
{ {
return null; return null;
} }
NuGetFramework[] candidates; NuGetFramework[] candidates;
if (_aliases.TryGetValue(targetFramework, out candidates)) if (_aliases.TryGetValue(targetFramework, out candidates))
{ {

View file

@ -15,6 +15,10 @@ namespace Microsoft.Extensions.ProjectModel
public CompilerOptions CompilerOptions { get; set; } public CompilerOptions CompilerOptions { get; set; }
public int Line { get; set; }
public int Column { get; set; }
// REVIEW: Wrapping, we might do this differntly // REVIEW: Wrapping, we might do this differntly
public string WrappedProject { get; set; } public string WrappedProject { get; set; }