Как использовать Roslyn, когда решение содержит проекты с различными вариантами компиляции - PullRequest
0 голосов
/ 01 сентября 2018

Первоначальная проблема заключается в том, что у меня есть огромное решение, в котором проекты имеют разные параметры (например, конфигурация 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. Диагностика пуста, и "проекты" имеют правильный порядок (библиотека, затем приложение)

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

Когда «реквизит» установлен на

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

_workspace. Диагностика пуста, у "проектов" неправильный порядок:

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

и возникает исключение при выполнении «project.GetCompilationAsync (). Результат»:

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

Как заставить Roslyn учитывать настройки .sln \ .csproj?

Ответы [ 2 ]

0 голосов
/ 02 сентября 2018

Я думаю, что ответ таков: «Не поддерживается загрузка параметров компиляции конкретного проекта».

Что касается моей проблемы, я сравнил поведение с Roslyn 2.7:

С Рослин 2.7:

Когда я использую конфигурацию «Любой ЦП», GetTopologicalSortedProjects правильно работает с этим тестовым решением, и мое огромное решение компилируется без ошибок.

С Roslyn 2.9:

Я обнаружил, что ссылки на проекты в ProjectDependencyGraph :: _ referenceMap неверны, и, похоже, причина в неправильной реализации неизменяемых коллекций. При компиляции моего огромного решения (любого процессора) возникает много внутренних ошибок, в результате чего:

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()
0 голосов
/ 02 сентября 2018

Все свойства, содержащиеся в рабочей области, будут применены ко всем проектам решения, когда вы попытаетесь открыть его. Посмотрите на загрузчик и посмотрите, как он откроет решение и как он откроет каждый проект и применит свойства.

В текущем API вы должны создать свое решение и вручную изменить интересующие вас свойства для всех проектов. К сожалению, я знаю, как изменить только Platform проекта, но не Configuration, поэтому вам нужно отправить свой вопрос на домашнюю страницу roslyn . 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));
}
...