解决方案包含具有不同编译选项的项目时如何使用Roslyn

时间:2018-09-01 19:14:19

标签: roslyn

最初的问题是我有一个巨大的解决方案,其中项目具有不同的选项(例如x64或x86配置,是否允许使用不安全的代码等等)。 我正在尝试使用Roslyn(2.9.0)来使用DEBUG x64配置编译\解析该解决方案。某些项目的编译失败,因为仅应使用“ DEBUG x86”。

我使用“ DEBUG x64”配置创建一个测试解决方案。

Project A is a console application (DEBUG x64). 
Project B is a library (DEBUG x86)

并编写此代码:

MSBuildLocator.RegisterDefaults();
_workspace = MSBuildWorkspace.Create(props);
_workspace.SkipUnrecognizedProjects = false;
_solution = _workspace.OpenSolutionAsync(solutionFilePath).Result;
var projectsGpaph = _solution.GetProjectDependencyGraph();
var projects = projectsGpaph.GetTopologicallySortedProjects();

未设置“道具”时

_workspace.Diagnostics为空,并且“项目”的顺序正确(库,然后是应用)

B: project.CompilationOptions.Platform is AnyCpu
A: project.CompilationOptions.Platform is AnyCpu32BitPreferred

将“道具”设置为

var props = new Dictionary<string, string>()
{
    {"Configuration", "Debug"},
    {"Platform", "x64"}     
};

_workspace.Diagnostics为空,“项目”的顺序错误:

A: project.CompilationOptions.Platform is X64
B: project.CompilationOptions.Platform is X64

执行我的“ project.GetCompilationAsync()。Result”时引发了异常:

System.ArgumentException: 'Reference of type 
'Microsoft.CodeAnalysis.UnresolvedMetadataReference' is not valid for this 
compilation.
Parameter name: references[0]'

如何强制Roslyn考虑.sln \ .csproj设置?

2 个答案:

答案 0 :(得分:2)

我认为答案是“不支持加载具体项目的编译选项”。

对于我的问题,我将其行为与Roslyn 2.7进行了比较:

使用Roslyn 2.7:

当我使用“任何CPU”配置时,GetTopologicallySortedProjects可以在该测试解决方案上正常工作,并且庞大的解决方案可以正确编译。

使用Roslyn 2.9:

我发现ProjectDependencyGraph :: _ referencesMap中的项目引用是错误的,并且看起来原因是不可变集合的错误实现。 当我编译庞大的解决方案(任何CPU)时,存在许多内部错误,因此:

System.AggregateException: One or more errors occurred. ---> System.ArgumentNullException: Value cannot be null.
Parameter name: key
   at System.Collections.Immutable.Requires.FailArgumentNullException(String parameterName)
   at System.Collections.Immutable.Requires.NotNullAllowStructs[T](T value, String parameterName)
   at System.Collections.Immutable.ImmutableDictionary`2.TryGetValue(TKey key, TValue& value)
   at Microsoft.CodeAnalysis.MSBuild.CommandLineArgumentReader.ReadDebugInfo()
   at Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArgumentReader.ReadCore()
   at Microsoft.CodeAnalysis.MSBuild.CommandLineArgumentReader.Read()
   at Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArgumentReader.Read(ProjectInstance project)
   at Microsoft.CodeAnalysis.CSharp.CSharpProjectFile.ReadCommandLineArgs(ProjectInstance project)
   at Microsoft.CodeAnalysis.MSBuild.ProjectFile.GetCommandLineArgs(ProjectInstance project)
   at Microsoft.CodeAnalysis.MSBuild.ProjectFile.CreateProjectFileInfo(ProjectInstance project)
   at Microsoft.CodeAnalysis.MSBuild.ProjectFile.<BuildProjectFileInfoAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.CodeAnalysis.MSBuild.ProjectFile.<GetProjectFileInfosAsync>d__16.MoveNext()

答案 1 :(得分:0)

当您尝试打开工作区中包含的所有属性时,它们将应用于所有解决方案的项目。查看loader,看看它如何open solution,以及如何will open每个项目并应用属性。

在当前的API中,您应该创建自己的解决方案,并手动更改所有项目的对您感兴趣的属性。不幸的是,我知道如何仅更改项目的Platform,而不更改Configuration,因此您需要将问题发布到roslyn home page。主持人,我将向您展示如何更改Platform

...
foreach (var project in _solution.Projects.ToList())
{
    // NOTE: you will need to a little "function", that will be convert "x64" to Platform.X64 and so on
    solution = solution.WithProjectCompilationOptions(project.Id, project.CompilationOptions.WithPlatform(Platform.X64));
}