Комментарии 24
Вот спасибо. Всё самое интересное как всегда — to be continue… ждем.
0
«Любой проект Microsoft Visual Studio является скриптом MSBuild» — не совсем так. Все «коробочные» типы проектов в VS являются MSBuild-скриптами, это да. Но исторически это было не так (VC++ до VS2010 имел свой формат, и еще был Setup project), и в общем случае это некорректно, т.к. формат файла проекта отдается целиком на откуп проектной системе (project system — компоненту, отвечающему за загрузку и работу с данным конкретном типа проекта).
0
Вы правы. По поводу project system, то в будущих частях, я надеюсь, расскажу про создание своей системы проектов(это пункт 4й плана действий, если Вы не заметили), а пока я посчитал, что упоминание про это бессмысленно. По поводу истории — я прекрасно её знаю(сижу на студии с версии 5.0 — эта которая 97) поэтому и начал с 2010 т.к. между 2010 и 2012, 2013 — разница в проектных системах минимальна.
0
Описанный вами способ добавления свойств — это не MSBuild вообще, а конкретно те виды проектов, которые построены на Common Project System (это проектная система, изначально появившаяся в VS 2010 для C++-проектов, а на сегодня используется также для WinStore JavaScript проектов, и .NET vNext / Project K / .kproj). Для обычных C#/VB проектов, например, это работать не будет. Для F#, Python, Node.js, PHP — тоже. Тут та же проблема — каждая проектная система реализует эти штуки сама и по-своему; в CPS сделали такое вот декларативное описание пропертей, в других — что-то еще.
В C# добавить свои свойства вполне можно, но там придется еще рисовать руками property page для их редактирования, и в целом это все будет выглядеть совсем по-другому.
В C# добавить свои свойства вполне можно, но там придется еще рисовать руками property page для их редактирования, и в целом это все будет выглядеть совсем по-другому.
+3
$(BlaBlaBla) — это не макрос, это способ адресации Свойства (Property) в MSBuild.
Вообще все остальное, включая ваши наборы свойств выглядит как мало относящееся к MSBuild. Props и Targets это просто «соглашения», можете именовать как угодно, но студия любит их и например может дать возможность редактировать ваши собственные props в окне свойств проекта.
int19h А в чем отличия этой Common Project System от стандартной системы сборки проектов в MSBuild? И почему декларативное описание свойств не будет работать? Мсбилд всегда так работает, ну или я не правильно понимаю ваше высказывание.
Вообще все остальное, включая ваши наборы свойств выглядит как мало относящееся к MSBuild. Props и Targets это просто «соглашения», можете именовать как угодно, но студия любит их и например может дать возможность редактировать ваши собственные props в окне свойств проекта.
int19h А в чем отличия этой Common Project System от стандартной системы сборки проектов в MSBuild? И почему декларативное описание свойств не будет работать? Мсбилд всегда так работает, ну или я не правильно понимаю ваше высказывание.
+2
про $(BlaBlaBla) — я написал в терминологии студии, чтобы людям было привычнее. А в студии эти штуки как раз находятся под кнопкой «Macros». Мои наборы свойств включаются в проект студии, который является скриптом MSBuild и не упоминать его неправильно, понятно, что для сборки из консоли они не нужны, но ведь статья относится к MVS, а не чисто к MSBuild. К тому же в следующих частях я уже перейду уже к сборке — а это уже MSBuild в чистом виде.
Props и Targets это просто «соглашения» — Вы статью читали? Там про это написано.
Props и Targets это просто «соглашения» — Вы статью читали? Там про это написано.
0
То, что они где-то находятся в IDE — не определяет их предназначение. Вы такими выдуманными обозначениями запутаете читателей еще больше, а потом опять будем видеть жалобы на то, что кто-то потратил уйму времени (как автор) просматривая targets мсбилда и все равно ничего не понял.
Да, статью я читал. На соглашения я указал потому, что если им следовать — можно получить некоторые встроенные в msbuild(и поставляемые targets) ништяки. Если не следовать — можно сделать все то же самое, но руками и через «мучения».
Да, статью я читал. На соглашения я указал потому, что если им следовать — можно получить некоторые встроенные в msbuild(и поставляемые targets) ништяки. Если не следовать — можно сделать все то же самое, но руками и через «мучения».
+1
Нет, тут как раз все правильно. Надо четко понимать, что свойства MSBuild и свойства проекта в VS — это две совершенно разные вещи, которые иногда пересекаются как деталь реализации данного конкретного типа проектов.
+2
Ок. т.е. получается в данном случае они не только используют свойства как способ хранения, но и используют такой же синтаксис? Или все-таки они заимствуют синтаксис из мсбилда, потому что само строковое значение будет интерпретироваться\разворачиваться не студией, а мсбилдом? Кто их разворачивает, эти «макросы»? Если второе — то все-таки это сущность билда, а не макрос студии.
+1
Конкретно $(BlaBlaBla) — на практике это сущность MSBuild, да, и разворачивает их он (если попросят).
Под капотом там создается экземпляр класса Project, а на нем дергается метод GetEvaluatedProperty, который и возвращает развернутое значение. При записи, соответственно, зовется SetProperty. Для редактирования же значение проперти обычно читается в исходном виде непосредственно из коллекции Properties, чтобы отобразить его точно в том виде, в котором оно было в файле проекта, со всеми $(...).
Про Macros я просто пропустил. Это (точнее — project macros) терминология, специфичная для C++-проектов, больше её никто не использует. Если мне не изменяет память, она осталась с тех времен, когда C++-проекты были не MSBuild. По факту на сегодня она просто отдается на откуп мсбилду, но в документации, тем не менее, она зачем-то описана как отдельная сущность.
(гипотетически, если MSBuild завтра внезапно умрет, то макросы его переживут, поэтому какой-то смысл в том, чтобы говорить о них в отдельности, наверное есть)
Под капотом там создается экземпляр класса Project, а на нем дергается метод GetEvaluatedProperty, который и возвращает развернутое значение. При записи, соответственно, зовется SetProperty. Для редактирования же значение проперти обычно читается в исходном виде непосредственно из коллекции Properties, чтобы отобразить его точно в том виде, в котором оно было в файле проекта, со всеми $(...).
Про Macros я просто пропустил. Это (точнее — project macros) терминология, специфичная для C++-проектов, больше её никто не использует. Если мне не изменяет память, она осталась с тех времен, когда C++-проекты были не MSBuild. По факту на сегодня она просто отдается на откуп мсбилду, но в документации, тем не менее, она зачем-то описана как отдельная сущность.
(гипотетически, если MSBuild завтра внезапно умрет, то макросы его переживут, поэтому какой-то смысл в том, чтобы говорить о них в отдельности, наверное есть)
+3
и да, проект становится проектом «студии» если у него соответствующий ProjectGuid, а не невинные импорты
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
0
>> А в чем отличия этой Common Project System от стандартной системы сборки проектов в MSBuild? И почему декларативное описание свойств не будет работать? Мсбилд всегда так работает, ну или я не правильно понимаю ваше высказывание.
Тут мне придется разлиться мысию по древу, немного определиться с терминологией, и углубиться в историю.
С точки зрения MSBuild, «проект» — это просто корневой скрипт системы сборки, точка входа в неё. Никакого другого смысла в него не вкладывается, и обычные VS-термины вроде «файлов проекта» или там «выходной сборки» на этом уровне смысла не имеют. Есть просто набор properties (по сути, скалярных переменных), items (коллекций), и targets (функций), который выполняется. Все.
С точки зрения VS, «проект» — это отнюдь не MSBuild-скрипт, и даже вообще не обязательно файл. Это просто некоторый COM-объект в памяти, реализующий интерфейсы IVsProject и IVsHierarchy, и ряд связанных с ними. Соответственно, «проектная система» (project system) — это реализация конкретной фабрики (IVsProjectFactory) для создания таких объектов, и реализации этих самых объектов для этой конкретной фабрики. Вся эта система очень абстрактна, и то, как именно реализован проект под капотом, может сильно варьироваться, в т.ч. и откуда грузится при открытии проекта, и куда пишется при сохранении. На практике постепенно пришли к единому знаменателю в виде MSBuild-скриптов, чтобы логика билда, по крайней мере, у всех проектных систем была одна.
При этом реализация всего остального в проектной системе (т.е. собственно IVsProject и IVsHierarchy — интерфейсы, ответственные за наполнение Solution Explorer, открытие редакторов для документов etc) по прежнему различается. В частности, если взять тот же VS 2010, то в нем C++ — это одна реализация (что забавно, написанная на C#), C# и VB — совершенно другая (что еще более забавно, написанная на C++), F# — третья (форк MPF — примера по написанию проектной системы из VS SDK), Setup project — четвертая. Если ставить расширения, то, например, Python Tools и Node.js Tools — это будет пятая (тоже форк MPF, но не имеет родства с C#), PHP Tools — шестая (форк PTVS), RemObjects Oxygene — седьмая (что-то свое, но, кажется, тоже форк MPF). Плюс есть всякие мелкие вспомогательные проектные системы, не привязанные к языкам, и не имеющие смысла сами по себе — например, Cloud Service Project в Azure SDK.
Понятно, что подобный зоопарк приводит к головной боли в виде необходимости реализовывать одни и те же фичи по десять раз. Поэтому периодически предпринимаются попытки написать одну универсальную проектную систему, которая покроет все требования, и может быть использована и кастомизирована всеми языками под свои нужды. Как правило, это работало примерно так, как описано в xkcd про стандарты (например, проектная система C#/VB была именно такой попыткой, но в итоге её никто больше использовать не стал). К VS 2010 очередной попыткой стал CPS, который вырос из переписывания проектной системы C++ (старая не использовала MSBuild, поэтому её все равно надо было переделывать). Попыткой, похоже, успешной, потому как его подхватали JS, и теперь вот .NET Core.
Возвращаясь к терминологии — с точки зрения VS самой по себе (не включая стандартные проектные системы), понятия «свойства проекта» в общем случае не существует. Есть фиксированный набор свойств у корневой иерархии проекта (IVsHierarchy), есть понятие «конфигурация» (IVsCfg) и «платформа», и, в общем-то, все. Все остальное — это штуки, специфичные для каждой проектной системы, и какие они вообще есть (и есть ли!), и где и как хранятся — решает именно она. На практике, опять же, есть некоторые общие вещи вроде выходного файла, но даже для них в общем случае нет одного универсального интерфейса, через который их можно получить из любого произвольного проекта. Есть IVsBuildPropertyStorage (который появился одновременно с MSBuild и проектной системой для С#/VB на его основе), который поддерживают все MSBuild-based проектные системы — но, в принципе, они это делать не обязаны.
Графический интерфейс для редактирования этих свойств тоже реализуется проектной системой. VS здесь предоставляет костыли в виде реализации COM property pages, но каждая конкретная страница целиком и полностью на откупе у проектной системы.
Для систем, которые в качестве файлового формата для проекта используют MSBuild, наиболее очевидный маппинг свойств на файл — это MSBuild properties (а для файлов проекта — соответственно, MSBuild items). Обратное неверно, т.е. далеко не каждое свойство в MSBuild является свойством проекта в данной системе, и не каждый item является файлом проекта. Собственно, если сделать дамп свойств после чтения какого-нибудь шарпного или плюсового проекта, их там будет с пару сотен, и из них только несколько десятков видны в VS как свойства проекта. Остальное — по сути, просто временные переменные. Что есть что, решает опять же проектная система.
Так вот, в случае с CPS, это решение не зашито в код системы, как во всех остальных случаях, а вынесено в декларативные описания в сам MSBuild-скрипт. Т.е. файл проекта, а точнее, импортируемые им .targets и .props файлы, описывают, как его надо интерпретировать, и в частности, какие именно MSBuild-свойства должны быть отображены в UI, и каким именно образом. Это как раз и есть PropertyPageSchema, и используемые им XML-файлы (которые на самом деле XAML). И вся эта машинерия — специфична именно для CPS, и работает только с его проектами. К MSBuild она прямого отношения не имеет, и последний рассматривает её просто как обычный набор свойств и items, никак ни с чем не связанный и не имеющий никакого сакрального смысла. В сборке, соответственно, она тоже не участвует.
Тут мне придется разлиться мысию по древу, немного определиться с терминологией, и углубиться в историю.
С точки зрения MSBuild, «проект» — это просто корневой скрипт системы сборки, точка входа в неё. Никакого другого смысла в него не вкладывается, и обычные VS-термины вроде «файлов проекта» или там «выходной сборки» на этом уровне смысла не имеют. Есть просто набор properties (по сути, скалярных переменных), items (коллекций), и targets (функций), который выполняется. Все.
С точки зрения VS, «проект» — это отнюдь не MSBuild-скрипт, и даже вообще не обязательно файл. Это просто некоторый COM-объект в памяти, реализующий интерфейсы IVsProject и IVsHierarchy, и ряд связанных с ними. Соответственно, «проектная система» (project system) — это реализация конкретной фабрики (IVsProjectFactory) для создания таких объектов, и реализации этих самых объектов для этой конкретной фабрики. Вся эта система очень абстрактна, и то, как именно реализован проект под капотом, может сильно варьироваться, в т.ч. и откуда грузится при открытии проекта, и куда пишется при сохранении. На практике постепенно пришли к единому знаменателю в виде MSBuild-скриптов, чтобы логика билда, по крайней мере, у всех проектных систем была одна.
При этом реализация всего остального в проектной системе (т.е. собственно IVsProject и IVsHierarchy — интерфейсы, ответственные за наполнение Solution Explorer, открытие редакторов для документов etc) по прежнему различается. В частности, если взять тот же VS 2010, то в нем C++ — это одна реализация (что забавно, написанная на C#), C# и VB — совершенно другая (что еще более забавно, написанная на C++), F# — третья (форк MPF — примера по написанию проектной системы из VS SDK), Setup project — четвертая. Если ставить расширения, то, например, Python Tools и Node.js Tools — это будет пятая (тоже форк MPF, но не имеет родства с C#), PHP Tools — шестая (форк PTVS), RemObjects Oxygene — седьмая (что-то свое, но, кажется, тоже форк MPF). Плюс есть всякие мелкие вспомогательные проектные системы, не привязанные к языкам, и не имеющие смысла сами по себе — например, Cloud Service Project в Azure SDK.
Понятно, что подобный зоопарк приводит к головной боли в виде необходимости реализовывать одни и те же фичи по десять раз. Поэтому периодически предпринимаются попытки написать одну универсальную проектную систему, которая покроет все требования, и может быть использована и кастомизирована всеми языками под свои нужды. Как правило, это работало примерно так, как описано в xkcd про стандарты (например, проектная система C#/VB была именно такой попыткой, но в итоге её никто больше использовать не стал). К VS 2010 очередной попыткой стал CPS, который вырос из переписывания проектной системы C++ (старая не использовала MSBuild, поэтому её все равно надо было переделывать). Попыткой, похоже, успешной, потому как его подхватали JS, и теперь вот .NET Core.
Возвращаясь к терминологии — с точки зрения VS самой по себе (не включая стандартные проектные системы), понятия «свойства проекта» в общем случае не существует. Есть фиксированный набор свойств у корневой иерархии проекта (IVsHierarchy), есть понятие «конфигурация» (IVsCfg) и «платформа», и, в общем-то, все. Все остальное — это штуки, специфичные для каждой проектной системы, и какие они вообще есть (и есть ли!), и где и как хранятся — решает именно она. На практике, опять же, есть некоторые общие вещи вроде выходного файла, но даже для них в общем случае нет одного универсального интерфейса, через который их можно получить из любого произвольного проекта. Есть IVsBuildPropertyStorage (который появился одновременно с MSBuild и проектной системой для С#/VB на его основе), который поддерживают все MSBuild-based проектные системы — но, в принципе, они это делать не обязаны.
Графический интерфейс для редактирования этих свойств тоже реализуется проектной системой. VS здесь предоставляет костыли в виде реализации COM property pages, но каждая конкретная страница целиком и полностью на откупе у проектной системы.
Для систем, которые в качестве файлового формата для проекта используют MSBuild, наиболее очевидный маппинг свойств на файл — это MSBuild properties (а для файлов проекта — соответственно, MSBuild items). Обратное неверно, т.е. далеко не каждое свойство в MSBuild является свойством проекта в данной системе, и не каждый item является файлом проекта. Собственно, если сделать дамп свойств после чтения какого-нибудь шарпного или плюсового проекта, их там будет с пару сотен, и из них только несколько десятков видны в VS как свойства проекта. Остальное — по сути, просто временные переменные. Что есть что, решает опять же проектная система.
Так вот, в случае с CPS, это решение не зашито в код системы, как во всех остальных случаях, а вынесено в декларативные описания в сам MSBuild-скрипт. Т.е. файл проекта, а точнее, импортируемые им .targets и .props файлы, описывают, как его надо интерпретировать, и в частности, какие именно MSBuild-свойства должны быть отображены в UI, и каким именно образом. Это как раз и есть PropertyPageSchema, и используемые им XML-файлы (которые на самом деле XAML). И вся эта машинерия — специфична именно для CPS, и работает только с его проектами. К MSBuild она прямого отношения не имеет, и последний рассматривает её просто как обычный набор свойств и items, никак ни с чем не связанный и не имеющий никакого сакрального смысла. В сборке, соответственно, она тоже не участвует.
+5
Классно, спасибо за пояснения, как работает мсбилд я знаю неплохо, а вот такие детали про проектные системы и их проекции на систему сборки — очень полезны.
Кстати такой технический вопрос — можно ли убедить студию что ей нужно отрисовать содержимое файла Х как набор свойств проекта в GUI (т.е. убедить ее в том, что «проектная система — C#, но вот тут отрисуй пожалуйста используя другой компонент, из CPS» ), или это все жестко связано с расширениями и внутренними Guid? А то я сейчас покопался — и обнаружил что куда-то пропал графический редактор свойств в С#, похоже раньше это мне какое-то расширение делало… Не то что бы очень надо, просто любопытно, можно ли так обмануть систему…
Кстати такой технический вопрос — можно ли убедить студию что ей нужно отрисовать содержимое файла Х как набор свойств проекта в GUI (т.е. убедить ее в том, что «проектная система — C#, но вот тут отрисуй пожалуйста используя другой компонент, из CPS» ), или это все жестко связано с расширениями и внутренними Guid? А то я сейчас покопался — и обнаружил что куда-то пропал графический редактор свойств в С#, похоже раньше это мне какое-то расширение делало… Не то что бы очень надо, просто любопытно, можно ли так обмануть систему…
+1
Можно, понятие редактора не привязано к проектной системе — ассоциация идет обычно по типу файла (т.е. расширению). Проектная система может перехватить открытие файла и насильно заставить открыть какой-то редактор по умолчанию для данного типа, отличный от глобального умолчания (например, PTVS перехватывает открытие .html в Django-проектах, чтобы открыть их в своем редакторе, который понимает синтаксис Django). Но в любом случае остается вариант в виде Open With в контекстном меню файла — там будут вообще все зарегистрированные в VS редакторы, и можно выбрать любой. Вполне вероятно, что ваш редактор где-то там :)
+2
Спасибо! А про написание аддинов к Студии не будет ничего?
0
Поправил пару опечаток.
0
Автору конечно спасибо за проделанный труд, но тут стоило бы заметить что MSBuild так же покрыт огромным слоем пыли и пепла. Для людей, кто ищет современные средства построения (build) могу посоветовать FAKE или PSAKE, они оба в той или иной мере используют, под капотом, MSBuild, но они просто северное сияние по сравнению с бараньими тестикулами обычным MSBuild.
-2
А еще есть TFS — вообще гуй есть и можно в workflow в drag-and-drop стиле редактировать, не то что ваши тестикулярные скриптовые языки. Типа ура…
Обычно, необходимость в скриптовых и императивных языках возникает когда в команде многие не способны ( в силу ограниченности кругозора) понимать XML мсбилда и его декларативность. Ну это в общем проблемы команды, а не мсбилда. Хоть на batch пишите, только все эти обвязки — как забивать гвозди микроскопом — от непонимания.
Обычно, необходимость в скриптовых и императивных языках возникает когда в команде многие не способны ( в силу ограниченности кругозора) понимать XML мсбилда и его декларативность. Ну это в общем проблемы команды, а не мсбилда. Хоть на batch пишите, только все эти обвязки — как забивать гвозди микроскопом — от непонимания.
-1
Так же наверное как и потребность в использовании языков высокого уровня возникает когда в команде многие не способны(в силу ограниченности кругозора) понимать всей красоты и мощи Assembler. И это тоже не проблемы Assembler.
MSBuild недружествен к восприятию, хотите продуктивности используйте высокоуровневые DSL как FAKE, любите хардкор и хотите им обременять всю команду спускайтесь на MSBuild.
Насчет TFS и его workflow, он обречен в его современном виде, что есть хорошо, посмотрите какова тенденция TFS 2015 и поймете о чем речь.
Мое мнение в том что не нужно тратить время и нервы на MSBuild, лучше брать высокоуровневые билд-системы. Как FAKE, sbt (из стана врагов), gulp (из стана неприятеля).
MSBuild недружествен к восприятию, хотите продуктивности используйте высокоуровневые DSL как FAKE, любите хардкор и хотите им обременять всю команду спускайтесь на MSBuild.
Насчет TFS и его workflow, он обречен в его современном виде, что есть хорошо, посмотрите какова тенденция TFS 2015 и поймете о чем речь.
Мое мнение в том что не нужно тратить время и нервы на MSBuild, лучше брать высокоуровневые билд-системы. Как FAKE, sbt (из стана врагов), gulp (из стана неприятеля).
-1
Эти системы (я про fake &psake) направлены на другое — это просто обертка, которая прячет от вас функциональную часть сборки. Мсбилд — возможность заглянуть и понять что происходит под капотом. Просто не понимая что внутри — невозможно модифицировать систему чтобы она делала что нужно вам, всегда будут ритуальные пляски — а вот такой плагин добавим, а вот такой модуль, а еще их надо вызвать в строгом порядке, а между вызовами очистить вот эту папку. Это называется культ карго.
Да, мсбилд использует не самый дружественный синтаксис, да, весь каскад импортов и переопределенных свойств может вызвать мигрень, да, половина таргетов для не основных продуктов написана криворукими идиотами, но понимание самой системы сборки дает вам знание о том, что происходит когда вы вызываете msbuild ./mylib.csproj. А также вы знаете как повлиять на это, в любой билд системе. И это кстати совсем не хардкор 8-)
PS про TFS — ппкс, и спасибо за наводку, как то пропустил что появились детали 2015…
Да, мсбилд использует не самый дружественный синтаксис, да, весь каскад импортов и переопределенных свойств может вызвать мигрень, да, половина таргетов для не основных продуктов написана криворукими идиотами, но понимание самой системы сборки дает вам знание о том, что происходит когда вы вызываете msbuild ./mylib.csproj. А также вы знаете как повлиять на это, в любой билд системе. И это кстати совсем не хардкор 8-)
PS про TFS — ппкс, и спасибо за наводку, как то пропустил что появились детали 2015…
0
Для интересующихся ещё на тему расширений Microsoft Visual Studio: Руководство по разработке модулей расширений на C# для Visual Studio 2005-2012 и Atmel Studio.
+1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Visual Studio Extensibility. Часть первая: MSBuild