最初的问题是我有一个巨大的解决方案,其中项目有不同的选项(例如,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设置?
我认为答案是“它不支持加载具体项目的编译选项”。
至于我的问题,我将行为与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()
当您尝试打开它时,工作空间中包含的所有属性都将应用于所有解决方案的项目。看看loader,看看它将如何open solution以及它如何will open每个项目和应用属性。
在当前的API中,您应该创建解决方案并手动更改所有项目的有趣属性。不幸的是,我知道如何仅更改项目的Platform
,而不是Configuration
,因此您需要将您的问题发布到roslyn home page。 Hovewer,我将展示你如何改变一个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));
}