private void ResolveDependencies(Dictionary<LibraryKey, LibraryDescription> libraries, ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver, out bool requiresFrameworkAssemblies) { // Remark: the LibraryType in the key of the given dictionary are all "Unspecified" at the beginning. requiresFrameworkAssemblies = false; foreach (var pair in libraries.ToList()) { var library = pair.Value; if (Equals(library.Identity.Type, LibraryType.Package) && !Directory.Exists(library.Path)) { // If the package path doesn't exist then mark this dependency as unresolved library.Resolved = false; } // 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 // assembly (if available) var package = library as PackageDescription; if (package != null && package.Resolved && !package.Target.CompileTimeAssemblies.Any()) { var replacement = referenceAssemblyDependencyResolver.GetDescription(new LibraryRange(library.Identity.Name, LibraryType.ReferenceAssembly), TargetFramework); if (replacement?.Resolved == true) { requiresFrameworkAssemblies = true; // Remove the original package reference libraries.Remove(pair.Key); // Insert a reference assembly key if there isn't one var key = new LibraryKey(replacement.Identity.Name, LibraryType.ReferenceAssembly); if (!libraries.ContainsKey(key)) { libraries[key] = replacement; } } } } foreach (var pair in libraries.ToList()) { var library = pair.Value; library.Framework = library.Framework ?? TargetFramework; foreach (var dependency in library.Dependencies) { var keyType = dependency.Target == LibraryType.ReferenceAssembly ? LibraryType.ReferenceAssembly : LibraryType.Unspecified; var key = new LibraryKey(dependency.Name, keyType); LibraryDescription dependencyDescription; if (!libraries.TryGetValue(key, out dependencyDescription)) { if (keyType == LibraryType.ReferenceAssembly) { // a dependency is specified to be reference assembly but fail to match // then add a unresolved dependency dependencyDescription = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ?? UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); libraries[key] = dependencyDescription; } else if (!libraries.TryGetValue(new LibraryKey(dependency.Name, LibraryType.ReferenceAssembly), out dependencyDescription)) { // a dependency which type is unspecified fails to match, then try to find a // reference assembly type dependency dependencyDescription = UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); libraries[key] = dependencyDescription; } } dependencyDescription.RequestedRanges.Add(dependency); dependencyDescription.Parents.Add(library); } } }
public ProjectContext Build() { ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory; if (GlobalSettings == null) { RootDirectory = ProjectRootResolver.ResolveRootDirectory(ProjectDirectory); GlobalSettings globalSettings; if (GlobalSettings.TryGetGlobalSettings(RootDirectory, out globalSettings)) { GlobalSettings = globalSettings; } } RootDirectory = GlobalSettings?.DirectoryPath ?? RootDirectory; PackagesDirectory = PackagesDirectory ?? PackageDependencyProvider.ResolvePackagesPath(RootDirectory, GlobalSettings); ReferenceAssembliesPath = ReferenceAssembliesPath ?? FrameworkReferenceResolver.GetDefaultReferenceAssembliesPath(); var frameworkReferenceResolver = new FrameworkReferenceResolver(ReferenceAssembliesPath); LockFileLookup lockFileLookup = null; EnsureProjectLoaded(); LockFile = LockFile ?? LockFileResolver(ProjectDirectory); var validLockFile = true; string lockFileValidationMessage = null; if (LockFile != null) { validLockFile = LockFile.IsValidForProject(Project, out lockFileValidationMessage); lockFileLookup = new LockFileLookup(LockFile); } var libraries = new Dictionary<LibraryKey, LibraryDescription>(); var projectResolver = new ProjectDependencyProvider(ProjectResolver); var mainProject = projectResolver.GetDescription(TargetFramework, Project); // Add the main project libraries.Add(new LibraryKey(mainProject.Identity.Name), mainProject); LockFileTarget target = null; if (lockFileLookup != null) { target = SelectTarget(LockFile); if (target != null) { var packageResolver = new PackageDependencyProvider(PackagesDirectory, frameworkReferenceResolver); ScanLibraries(target, lockFileLookup, libraries, packageResolver, projectResolver); } } var referenceAssemblyDependencyResolver = new ReferenceAssemblyDependencyResolver(frameworkReferenceResolver); bool requiresFrameworkAssemblies; // Resolve the dependencies ResolveDependencies(libraries, referenceAssemblyDependencyResolver, out requiresFrameworkAssemblies); var diagnostics = new List<DiagnosticMessage>(); // REVIEW: Should this be in NuGet (possibly stored in the lock file?) if (LockFile == null) { diagnostics.Add(new DiagnosticMessage( ErrorCodes.NU1009, $"The expected lock file doesn't exist. Please run \"dotnet restore\" to generate a new lock file.", Path.Combine(Project.ProjectDirectory, LockFile.FileName), DiagnosticMessageSeverity.Error)); } if (!validLockFile) { diagnostics.Add(new DiagnosticMessage( ErrorCodes.NU1006, $"{lockFileValidationMessage}. Please run \"dotnet restore\" to generate a new lock file.", Path.Combine(Project.ProjectDirectory, LockFile.FileName), DiagnosticMessageSeverity.Warning)); } if (requiresFrameworkAssemblies) { var frameworkInfo = Project.GetTargetFramework(TargetFramework); if (string.IsNullOrEmpty(ReferenceAssembliesPath)) { // If there was an attempt to use reference assemblies but they were not installed // report an error diagnostics.Add(new DiagnosticMessage( ErrorCodes.DOTNET1012, $"The reference assemblies directory was not specified. You can set the location using the DOTNET_REFERENCE_ASSEMBLIES_PATH environment variable.", filePath: Project.ProjectFilePath, severity: DiagnosticMessageSeverity.Error, startLine: frameworkInfo.Line, startColumn: frameworkInfo.Column )); } else if (!frameworkReferenceResolver.IsInstalled(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} in {ReferenceAssembliesPath}", filePath: Project.ProjectFilePath, severity: DiagnosticMessageSeverity.Error, startLine: frameworkInfo.Line, startColumn: frameworkInfo.Column )); } } // Create a library manager var libraryManager = new LibraryManager(libraries.Values.ToList(), diagnostics, Project.ProjectFilePath); return new ProjectContext( GlobalSettings, mainProject, TargetFramework, target?.RuntimeIdentifier, PackagesDirectory, libraryManager, LockFile); }
private void ResolveDependencies(Dictionary<LibraryKey, LibraryDescription> libraries, ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver, out bool requiresFrameworkAssemblies) { requiresFrameworkAssemblies = false; foreach (var library in libraries.Values.ToList()) { if (Equals(library.Identity.Type, LibraryType.Package) && !Directory.Exists(library.Path)) { // If the package path doesn't exist then mark this dependency as unresolved library.Resolved = false; } library.Framework = library.Framework ?? TargetFramework; foreach (var dependency in library.Dependencies) { var keyType = dependency.Target == LibraryType.ReferenceAssembly ? LibraryType.ReferenceAssembly : LibraryType.Unspecified; var key = new LibraryKey(dependency.Name, keyType); LibraryDescription dep; if (!libraries.TryGetValue(key, out dep)) { if (Equals(LibraryType.ReferenceAssembly, dependency.Target)) { requiresFrameworkAssemblies = true; dep = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ?? UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); dep.Framework = TargetFramework; libraries[key] = dep; } else { dep = UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); libraries[key] = dep; } } dep.RequestedRanges.Add(dependency); dep.Parents.Add(library); } } }
private void ResolveDependencies(Dictionary<LibraryKey, LibraryDescription> libraries, ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver, out bool requiresFrameworkAssemblies) { // Remark: the LibraryType in the key of the given dictionary are all "Unspecified" at the beginning. requiresFrameworkAssemblies = false; foreach (var pair in libraries.ToList()) { var library = pair.Value; // 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 // assembly (if available) var package = library as PackageDescription; if (package != null && package.Resolved && package.HasCompileTimePlaceholder && !TargetFramework.IsPackageBased) { // requiresFrameworkAssemblies is true whenever we find a CompileTimePlaceholder in a non-package based framework, even if // the reference is unresolved. This ensures the best error experience when someone is building on a machine without // the target framework installed. requiresFrameworkAssemblies = true; var newKey = new LibraryKey(library.Identity.Name, LibraryType.ReferenceAssembly); var dependency = new LibraryRange(library.Identity.Name, LibraryType.ReferenceAssembly); var replacement = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework); // If the reference is unresolved, just skip it. Don't replace the package dependency if (replacement == null) { continue; } // Remove the original package reference libraries.Remove(pair.Key); // Insert a reference assembly key if there isn't one if (!libraries.ContainsKey(newKey)) { libraries[newKey] = replacement; } } } foreach (var pair in libraries.ToList()) { var library = pair.Value; library.Framework = library.Framework ?? TargetFramework; foreach (var dependency in library.Dependencies) { var keyType = dependency.Target == LibraryType.ReferenceAssembly ? LibraryType.ReferenceAssembly : LibraryType.Unspecified; var key = new LibraryKey(dependency.Name, keyType); LibraryDescription dependencyDescription; if (!libraries.TryGetValue(key, out dependencyDescription)) { if (keyType == LibraryType.ReferenceAssembly) { // a dependency is specified to be reference assembly but fail to match // then add a unresolved dependency dependencyDescription = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ?? UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); libraries[key] = dependencyDescription; } else if (!libraries.TryGetValue(new LibraryKey(dependency.Name, LibraryType.ReferenceAssembly), out dependencyDescription)) { // a dependency which type is unspecified fails to match, then try to find a // reference assembly type dependency dependencyDescription = UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); libraries[key] = dependencyDescription; } } dependencyDescription.RequestedRanges.Add(dependency); dependencyDescription.Parents.Add(library); } } // Deduplicate libraries with the same name // Priority list is backwards so not found -1 would be last when sorting by descending var priorities = new[] { LibraryType.Package, LibraryType.Project, LibraryType.ReferenceAssembly }; var nameGroups = libraries.Keys.ToLookup(libraryKey => libraryKey.Name); foreach (var nameGroup in nameGroups) { var librariesToRemove = nameGroup .OrderByDescending(libraryKey => Array.IndexOf(priorities, libraryKey.LibraryType)) .Skip(1); foreach (var library in librariesToRemove) { libraries.Remove(library); } } }
public ProjectContext Build() { var diagnostics = new List<DiagnosticMessage>(); ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory; GlobalSettings globalSettings = null; if (ProjectDirectory != null) { RootDirectory = ProjectRootResolver.ResolveRootDirectory(ProjectDirectory); GlobalSettings.TryGetGlobalSettings(RootDirectory, out globalSettings); } RootDirectory = globalSettings?.DirectoryPath ?? RootDirectory; PackagesDirectory = PackagesDirectory ?? PackageDependencyProvider.ResolvePackagesPath(RootDirectory, globalSettings); FrameworkReferenceResolver frameworkReferenceResolver; if (string.IsNullOrEmpty(ReferenceAssembliesPath)) { // Use the default static resolver frameworkReferenceResolver = FrameworkReferenceResolver.Default; } else { frameworkReferenceResolver = new FrameworkReferenceResolver(ReferenceAssembliesPath); } LockFileLookup lockFileLookup = null; EnsureProjectLoaded(); ReadLockFile(diagnostics); var validLockFile = true; string lockFileValidationMessage = null; if (LockFile != null) { if (Project != null) { validLockFile = LockFile.IsValidForProject(Project, out lockFileValidationMessage); } lockFileLookup = new LockFileLookup(LockFile); } var libraries = new Dictionary<LibraryKey, LibraryDescription>(); var projectResolver = new ProjectDependencyProvider(ProjectResolver); ProjectDescription mainProject = null; if (Project != null) { mainProject = projectResolver.GetDescription(TargetFramework, Project, targetLibrary: null); // Add the main project libraries.Add(new LibraryKey(mainProject.Identity.Name), mainProject); } LibraryRange? platformDependency = null; if (mainProject != null) { platformDependency = mainProject.Dependencies .Where(d => d.Type.Equals(LibraryDependencyType.Platform)) .Cast<LibraryRange?>() .FirstOrDefault(); } bool isPortable = platformDependency != null; LockFileTarget target = null; LibraryDescription platformLibrary = null; if (lockFileLookup != null) { target = SelectTarget(LockFile, isPortable); if (target != null) { var nugetPackageResolver = new PackageDependencyProvider(PackagesDirectory, frameworkReferenceResolver); var msbuildProjectResolver = new MSBuildDependencyProvider(Project, ProjectResolver); ScanLibraries(target, lockFileLookup, libraries, msbuildProjectResolver, nugetPackageResolver, projectResolver); if (platformDependency != null) { libraries.TryGetValue(new LibraryKey(platformDependency.Value.Name), out platformLibrary); } } } string runtime = target?.RuntimeIdentifier; if (string.IsNullOrEmpty(runtime) && TargetFramework.IsDesktop()) { // we got a ridless target for desktop so turning portable mode on isPortable = true; var legacyRuntime = RuntimeEnvironmentRidExtensions.GetLegacyRestoreRuntimeIdentifier(); if (RuntimeIdentifiers.Contains(legacyRuntime)) { runtime = legacyRuntime; } else { runtime = RuntimeIdentifiers.FirstOrDefault(); } } var referenceAssemblyDependencyResolver = new ReferenceAssemblyDependencyResolver(frameworkReferenceResolver); bool requiresFrameworkAssemblies; // Resolve the dependencies ResolveDependencies(libraries, referenceAssemblyDependencyResolver, out requiresFrameworkAssemblies); // REVIEW: Should this be in NuGet (possibly stored in the lock file?) if (LockFile == null) { diagnostics.Add(new DiagnosticMessage( ErrorCodes.NU1009, $"The expected lock file doesn't exist. Please run \"dotnet restore\" to generate a new lock file.", Path.Combine(Project.ProjectDirectory, LockFile.FileName), DiagnosticMessageSeverity.Error)); } if (!validLockFile) { diagnostics.Add(new DiagnosticMessage( ErrorCodes.NU1006, $"{lockFileValidationMessage}. Please run \"dotnet restore\" to generate a new lock file.", Path.Combine(Project.ProjectDirectory, LockFile.FileName), DiagnosticMessageSeverity.Warning)); } if (requiresFrameworkAssemblies) { var frameworkInfo = Project.GetTargetFramework(TargetFramework); if (frameworkReferenceResolver == null || string.IsNullOrEmpty(frameworkReferenceResolver.ReferenceAssembliesPath)) { // If there was an attempt to use reference assemblies but they were not installed // report an error diagnostics.Add(new DiagnosticMessage( ErrorCodes.DOTNET1012, $"The reference assemblies directory was not specified. You can set the location using the DOTNET_REFERENCE_ASSEMBLIES_PATH environment variable.", filePath: Project.ProjectFilePath, severity: DiagnosticMessageSeverity.Error, startLine: frameworkInfo.Line, startColumn: frameworkInfo.Column )); } else if (!frameworkReferenceResolver.IsInstalled(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} in {ReferenceAssembliesPath}", filePath: Project.ProjectFilePath, severity: DiagnosticMessageSeverity.Error, startLine: frameworkInfo.Line, startColumn: frameworkInfo.Column )); } } List<DiagnosticMessage> allDiagnostics = new List<DiagnosticMessage>(diagnostics); if (Project != null) { allDiagnostics.AddRange(Project.Diagnostics); } // Create a library manager var libraryManager = new LibraryManager(libraries.Values.ToList(), allDiagnostics, Project?.ProjectFilePath); return new ProjectContext( globalSettings, mainProject, platformLibrary, TargetFramework, isPortable, runtime, PackagesDirectory, libraryManager, LockFile, diagnostics); }
private void ResolveDependencies(Dictionary<LibraryKey, LibraryDescription> libraries, ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver, out bool requiresFrameworkAssemblies) { requiresFrameworkAssemblies = false; foreach (var pair in libraries.ToList()) { var library = pair.Value; if (Equals(library.Identity.Type, LibraryType.Package) && !Directory.Exists(library.Path)) { // If the package path doesn't exist then mark this dependency as unresolved library.Resolved = false; } // 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 // assembly (if available) var package = library as PackageDescription; if (package != null && package.Resolved && !package.Target.CompileTimeAssemblies.Any()) { var replacement = referenceAssemblyDependencyResolver.GetDescription(new LibraryRange(library.Identity.Name, LibraryType.ReferenceAssembly), TargetFramework); if (replacement?.Resolved == true) { requiresFrameworkAssemblies = true; // Remove the original package reference libraries.Remove(pair.Key); // Add the reference to the refernce assembly. libraries[new LibraryKey(replacement.Identity.Name)] = replacement; continue; } } library.Framework = library.Framework ?? TargetFramework; foreach (var dependency in library.Dependencies) { var keyType = dependency.Target == LibraryType.ReferenceAssembly ? LibraryType.ReferenceAssembly : LibraryType.Unspecified; var key = new LibraryKey(dependency.Name, keyType); LibraryDescription dep; if (!libraries.TryGetValue(key, out dep)) { if (Equals(LibraryType.ReferenceAssembly, dependency.Target)) { requiresFrameworkAssemblies = true; dep = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ?? UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); dep.Framework = TargetFramework; libraries[key] = dep; } else { dep = UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); libraries[key] = dep; } } dep.RequestedRanges.Add(dependency); dep.Parents.Add(library); } } }