Есть ли простой способ заставить Visual Studio 2015 использовать определенную утилиту ToolsVersion?
При создании проекта или решения с использованием определенной версии msbuild
я могу выбрать более раннюю цепочку инструментов .net с помощью переключателя /toolsversion
или /tv
:
"C:\Program Files (x86)\MSBuild\14.0\bin\msbuild" /tv:12.0 amazing.sln
Это Just Works для всех версий msbuild
, а версия csc.exe
и т.д. правильно выбрана на основе вышеперечисленного:
> "C:\Program Files (x86)\MSBuild\14.0\bin\msbuild" /tv:4.0 amazing.sln
...
CoreCompile:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe ...
...
> "C:\Program Files (x86)\MSBuild\14.0\bin\msbuild" /tv:12.0 amazing.sln
...
CoreCompile:
C:\Program Files (x86)\MSBuild\12.0\bin\Csc.exe ...
...
Если я не укажу /tv
, то в зависимости от какой версии msbuild, которую я использую, и ряда переменных среды, я могу получить любой из:
- Инструмент ToolsVersion, указанный в элементе верхнего уровня в файле проекта
- Инструмент ToolsVersion, соответствующий версии
msbuild.exe
Я использую
- Значение из
msbuild.exe.config
- Значение из реестра
(см. различные версии страницы "Параметры переопределения параметров инструмента" в MSDN).
Итак, чтобы иметь сборки, которые имеют согласованные результаты на сервере сборки и на моей локальной машине, я использую /tv
при запуске msbuild.exe
(на самом деле это принудительно применяется в psake
script, который также гарантирует, что он использует соответствующую версию msbuild.exe
).
Однако Я не могу использовать переключатель /tv
при создании с помощью Visual Studio. Вместо этого Visual Studio 2013 и выше будут использовать инструментальную цепочку .net, поставляемую с этой версией Visual Studio, если:
- Установлена переменная среды
MSBUILDLEGACYDEFAULTTOOLSVERSION
и...
- ... все файлы проекта имеют атрибут ToolsVersion, установленный для версии, которую я хочу использовать.
Это так барокко, что я не могу поверить, что кто-то на самом деле это делает. Мои вопросы таковы:
- Кто-нибудь делает
MSBUILDLEGACYDEFAULTTOOLSVERSION
вещь?
- Если нет, существует ли другой способ заставить Visual Studio использовать конкретную утилиту ToolsVersion, не использующую версию Visual Studio, поставляемую с этой утилитой ToolsVersion? Что-то, что можно было бы сохранить в контроле версий (например, в проекте или в каком-либо другом файле настроек) было бы идеальным.
И наконец:
- Мне все равно? Учитывая, что каждая последующая версия компилятора С# должна иметь возможность обрабатывать входные данные предыдущих версий, и я могу установить целевую структуру .net и уровень языка С# в файле проекта, достаточно ли этого для обеспечения повторяемости сборки?
(Мое предубеждение в том, что я должен заботиться, поскольку:
- Я хочу, чтобы сборки в среде IDE и на сервере сборки были одинаковыми (конечно)
- Я хочу иметь возможность использовать VS2015 (и будущие версии), потому что это лучшая среда IDE, чем предыдущие, но я не хочу быть обязанным использовать новую инструментальную цепочку, пока не решит.
Возможно, я хочу слишком много...)
Для конкретного примера проблемы см. мой репозиторий msbuild-vs-vs2015-toolsversion в github.
Некоторое предположение: я спрашиваю об этом, потому что у нас недавно возникла ошибка построения CI, когда один из моих коллег представил код С# 6.0, который скомпилирован с Roslyn на их копии Visual Studio 2015, но не прошел в CI, потому что использует предыдущий релиз .net toolchain (они использовали автоматическое свойство без сеттера, что прекрасно в Roslyn, но не в более ранних версиях). Мы будем обновлять сборку CI до Roslyn, но я хотел посмотреть, не можем ли мы предотвратить подобное событие в будущем.
Ответы
Ответ 1
Я решил это, написав расширение Visual Studio, которое временно устанавливает переменную среды MSBUILDDEFAULTTOOLSVERSION
на время сборки; значение, которое будет использоваться, считывается из файла .toolsversion
в том же каталоге, что и файл .sln
. Psake script считывает один и тот же файл .toolsversion
и передает значение в /tv
.
Код расширения можно найти здесь: https://github.com/guyboltonking/set-toolsversion-extension. К сожалению, на данный момент я не работаю с С++ или даже с Visual Studio, поэтому я не могу оказать ему никакой поддержки (но могу сказать, что я использовал его без каких-либо проблем в течение нескольких месяцев).
Престижность @efaruk за напоминание о существовании MSBUILDDEFAULTTOOLSVERSION
.
Изменить: Благодаря @mbadawi23 теперь можно использовать расширение как с VS2015, так и с VS2017.
Ответ 2
Примечание. Вы всегда можете создать файл msbuild для создания своего проекта, используя его или самостоятельно изменить свой проект, и вы можете условно определить версию своего инструмента (https://msdn.microsoft.com/en-us/library/7z253716.aspx) (.csproj также является структурированным msbuild script с разным расширением, и он также будет совместим с VS).
С уважением...
Edit:
https://msdn.microsoft.com/en-us/library/bb383985.aspx
установив свойство $(ProjectToolsVersion)
в проекте в рамках решения. Это позволяет вам создавать проект в решении с версией набора инструментов, которая отличается от версии других проектов.
Итак, я думаю, у вас есть ваш ответ;)
Ответ 3
Чтобы принудительно использовать определенную версию С# в Visual Studio 2015, вы можете войти в свойства проекта → Build → Advanced → Language Version.
Если вы установите значение 5, компилятор будет жаловаться на функции С# 6: Функция "..." недоступна на С# 5. Используйте язык версии 6 или выше.
Alternativly ReSharper также имеет некоторые инструменты для этого.
Ответ 4
То, что вы видите в Visual Studio (инструменты и т.д.) и код, лежащий за ними, не входит в состав скомпилированных данных, они являются просто визуальным/читаемым представлением при компиляции их как более ранней версии VS, которую вы создаете исполняемый из этой версии.
Пожалуйста, имейте в виду, что при компиляции в качестве предыдущей версии .NET вы можете потерять функциональность, такую как асинхронные функции.