public MSBuildProjectSystem(OmnisharpWorkspace workspace, IOmnisharpEnvironment env, IOptions<OmniSharpOptions> optionsAccessor, ILoggerFactory loggerFactory, IEventEmitter emitter, IMetadataFileReferenceCache metadataReferenceCache, IFileSystemWatcher watcher, MSBuildContext context) { _workspace = workspace; _metadataReferenceCache = metadataReferenceCache; _watcher = watcher; _env = env; _options = optionsAccessor.Options.MsBuild; _logger = loggerFactory.CreateLogger<MSBuildProjectSystem>(); _emitter = emitter; _context = context; }
public void Initalize(IConfiguration configuration) { _options = new MSBuildOptions(); OptionsServices.ReadProperties(_options, configuration); var solutionFilePath = _env.SolutionFilePath; if (string.IsNullOrEmpty(solutionFilePath)) { var solutions = Directory.GetFiles(_env.Path, "*.sln"); var result = SolutionPicker.ChooseSolution(_env.Path, solutions); if (result.Message != null) { _logger.LogInformation(result.Message); } if (result.Solution == null) { return; } solutionFilePath = result.Solution; } SolutionFile solutionFile = null; _context.SolutionPath = solutionFilePath; using (var stream = File.OpenRead(solutionFilePath)) { using (var reader = new StreamReader(stream)) { solutionFile = SolutionFile.Parse(reader); } } _logger.LogInformation($"Detecting projects in '{solutionFilePath}'."); foreach (var block in solutionFile.ProjectBlocks) { if (!_supportsProjectTypes.Contains(block.ProjectTypeGuid)) { if (UnityTypeGuid(block.ProjectName) != block.ProjectTypeGuid) { _logger.LogWarning("Skipped unsupported project type '{0}'", block.ProjectPath); continue; } } if (_context.ProjectGuidToWorkspaceMapping.ContainsKey(block.ProjectGuid)) { continue; } var projectFilePath = Path.GetFullPath(Path.GetFullPath(Path.Combine(_env.Path, block.ProjectPath.Replace('\\', Path.DirectorySeparatorChar)))); _logger.LogInformation($"Loading project from '{projectFilePath}'."); var projectFileInfo = CreateProject(projectFilePath); if (projectFileInfo == null) { continue; } var compilationOptions = new CSharpCompilationOptions(projectFileInfo.OutputKind); #if DNX451 compilationOptions = compilationOptions.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default); #endif if (projectFileInfo.AllowUnsafe) { compilationOptions = compilationOptions.WithAllowUnsafe(true); } var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(projectFileInfo.Name), VersionStamp.Create(), projectFileInfo.Name, projectFileInfo.AssemblyName, LanguageNames.CSharp, projectFileInfo.ProjectFilePath, compilationOptions: compilationOptions); _workspace.AddProject(projectInfo); projectFileInfo.WorkspaceId = projectInfo.Id; _context.Projects[projectFileInfo.ProjectFilePath] = projectFileInfo; _context.ProjectGuidToWorkspaceMapping[block.ProjectGuid] = projectInfo.Id; _watcher.Watch(projectFilePath, OnProjectChanged); } foreach (var projectFileInfo in _context.Projects.Values) { UpdateProject(projectFileInfo); } }
public static ProjectFileInfo Create(MSBuildOptions options, ILogger logger, string solutionDirectory, string projectFilePath, ICollection<MSBuildDiagnosticsMessage> diagnostics) { var projectFileInfo = new ProjectFileInfo(); projectFileInfo.ProjectFilePath = projectFilePath; #if DNX451 if (!PlatformHelper.IsMono) { var properties = new Dictionary<string, string> { { "DesignTimeBuild", "true" }, { "BuildProjectReferences", "false" }, { "_ResolveReferenceDependencies", "true" }, { "SolutionDir", solutionDirectory + Path.DirectorySeparatorChar } }; if (!string.IsNullOrWhiteSpace(options.VisualStudioVersion)) { properties.Add("VisualStudioVersion", options.VisualStudioVersion); } var collection = new ProjectCollection(properties); logger.LogInformation("Using toolset {0} for {1}", options.ToolsVersion ?? collection.DefaultToolsVersion, projectFilePath); var project = string.IsNullOrEmpty(options.ToolsVersion) ? collection.LoadProject(projectFilePath) : collection.LoadProject(projectFilePath, options.ToolsVersion); var projectInstance = project.CreateProjectInstance(); var buildResult = projectInstance.Build("ResolveReferences", new Microsoft.Build.Framework.ILogger[] { new MSBuildLogForwarder(logger, diagnostics) }); if (!buildResult) { return null; } projectFileInfo.AssemblyName = projectInstance.GetPropertyValue("AssemblyName"); projectFileInfo.Name = projectInstance.GetPropertyValue("ProjectName"); projectFileInfo.TargetFramework = new FrameworkName(projectInstance.GetPropertyValue("TargetFrameworkMoniker")); projectFileInfo.SpecifiedLanguageVersion = ToLanguageVersion(projectInstance.GetPropertyValue("LangVersion")); projectFileInfo.ProjectId = new Guid(projectInstance.GetPropertyValue("ProjectGuid").TrimStart('{').TrimEnd('}')); projectFileInfo.TargetPath = projectInstance.GetPropertyValue("TargetPath"); var outputType = projectInstance.GetPropertyValue("OutputType"); switch(outputType) { case "Library": projectFileInfo.OutputKind = OutputKind.DynamicallyLinkedLibrary; break; case "WinExe": projectFileInfo.OutputKind = OutputKind.WindowsApplication; break; default: case "Exe": projectFileInfo.OutputKind = OutputKind.ConsoleApplication; break; } projectFileInfo.SourceFiles = projectInstance.GetItems("Compile") .Select(p => p.GetMetadataValue("FullPath")) .ToList(); projectFileInfo.References = projectInstance.GetItems("ReferencePath") .Where(p => !string.Equals("ProjectReference", p.GetMetadataValue("ReferenceSourceTarget"), StringComparison.OrdinalIgnoreCase)) .Select(p => p.GetMetadataValue("FullPath")) .ToList(); projectFileInfo.ProjectReferences = projectInstance.GetItems("ProjectReference") .Select(p => p.GetMetadataValue("FullPath")) .ToList(); projectFileInfo.Analyzers = projectInstance.GetItems("Analyzer") .Select(p => p.GetMetadataValue("FullPath")) .ToList(); var allowUnsafe = projectInstance.GetPropertyValue("AllowUnsafeBlocks"); if (!string.IsNullOrWhiteSpace(allowUnsafe)) { projectFileInfo.AllowUnsafe = Convert.ToBoolean(allowUnsafe); } var defineConstants = projectInstance.GetPropertyValue("DefineConstants"); if (!string.IsNullOrWhiteSpace(defineConstants)) { projectFileInfo.DefineConstants = defineConstants.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList(); } } else { // On mono we need to use this API since the ProjectCollection // isn't fully implemented #pragma warning disable CS0618 var engine = Engine.GlobalEngine; engine.DefaultToolsVersion = "4.0"; #pragma warning restore CS0618 // engine.RegisterLogger(new ConsoleLogger()); engine.RegisterLogger(new MSBuildLogForwarder(logger, diagnostics)); var propertyGroup = new BuildPropertyGroup(); propertyGroup.SetProperty("DesignTimeBuild", "true"); propertyGroup.SetProperty("BuildProjectReferences", "false"); // Dump entire assembly reference closure propertyGroup.SetProperty("_ResolveReferenceDependencies", "true"); propertyGroup.SetProperty("SolutionDir", solutionDirectory + Path.DirectorySeparatorChar); // propertyGroup.SetProperty("MSBUILDENABLEALLPROPERTYFUNCTIONS", "1"); engine.GlobalProperties = propertyGroup; var project = engine.CreateNewProject(); project.Load(projectFilePath); var buildResult = engine.BuildProjectFile(projectFilePath, new[] { "ResolveReferences" }, propertyGroup, null, BuildSettings.None, null); if (!buildResult) { return null; } var itemsLookup = project.EvaluatedItems.OfType<BuildItem>() .ToLookup(g => g.Name); var properties = project.EvaluatedProperties.OfType<BuildProperty>() .ToDictionary(p => p.Name); projectFileInfo.AssemblyName = properties["AssemblyName"].FinalValue; projectFileInfo.Name = Path.GetFileNameWithoutExtension(projectFilePath); projectFileInfo.TargetFramework = new FrameworkName(properties["TargetFrameworkMoniker"].FinalValue); if (properties.ContainsKey("LangVersion")) { projectFileInfo.SpecifiedLanguageVersion = ToLanguageVersion(properties["LangVersion"].FinalValue); } projectFileInfo.ProjectId = new Guid(properties["ProjectGuid"].FinalValue.TrimStart('{').TrimEnd('}')); projectFileInfo.TargetPath = properties["TargetPath"].FinalValue; // REVIEW: FullPath here returns the wrong physical path, we need to figure out // why. We must be setting up something incorrectly projectFileInfo.SourceFiles = itemsLookup["Compile"] .Select(b => Path.GetFullPath(Path.Combine(projectFileInfo.ProjectDirectory, b.FinalItemSpec))) .ToList(); projectFileInfo.References = itemsLookup["ReferencePath"] .Where(p => !p.HasMetadata("Project")) .Select(p => Path.GetFullPath(Path.Combine(projectFileInfo.ProjectDirectory, p.FinalItemSpec))) .ToList(); projectFileInfo.ProjectReferences = itemsLookup["ProjectReference"] .Select(p => Path.GetFullPath(Path.Combine(projectFileInfo.ProjectDirectory, p.FinalItemSpec))) .ToList(); projectFileInfo.Analyzers = itemsLookup["Analyzer"] .Select(p => Path.GetFullPath(Path.Combine(projectFileInfo.ProjectDirectory, p.FinalItemSpec))) .ToList(); var allowUnsafe = properties["AllowUnsafeBlocks"].FinalValue; if (!string.IsNullOrWhiteSpace(allowUnsafe)) { projectFileInfo.AllowUnsafe = Convert.ToBoolean(allowUnsafe); } var defineConstants = properties["DefineConstants"].FinalValue; if (!string.IsNullOrWhiteSpace(defineConstants)) { projectFileInfo.DefineConstants = defineConstants.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList(); } } #else // TODO: Shell out to msbuild/xbuild here? #endif return projectFileInfo; }