1) Если не хочется заморачиваться с импортами своих .props и .targets файлов в каждый проект, то можно создать файл Directory.Build.props и/или Directory.Build.targets, которые импортируются автоматически.
2) Лучше избегать $(SolutionDir), потому что он существует только если солюшен строится из Студии. На билд-сервере ваши проекты будут строиться голым MSBuild, который использует .sln только чтобы получить список проектов и билд-завсимостей, после чего каждый проект строится изолировано от солюшена. Если надо привязаться к стабильному пути, то лучше использовать $(MSBuildThisFileDirectory), который равен пути к самому props/targets-файлу. Если такой файл лежит рядом c .sln, то это даст надёжный переносимый эквивалент $(SolutionDir).
3) Бывает так, что солюшен не плоский (все проекты в одной папке), а иерархическй, т.е. проекты разбиты по поддиректориям (например, пачка проектов в поддиректории Core, другая пака в поддиректории Client, третья — в поддиректории Server и т.д), и в таком случае на каждом уровне иерархии могут появляться собственные настройки, в дополнение к общим. Например, все проекты в Client подключают один набор заголовочный файлов и библиотек и используют один набор параметров, все проекты в Server — другой набор, и при этом все проекты вообще должны использовать общий solution-wide набор. В таком сценарии можно использовать комбо из приёмов 1 и 2, положив на каждом уровне иерархии по файлику Directory.Build.* примерно такого вида:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Импортируем вышележащий Directory.Build.props, если таковой есть. В самом верхнем файле этого можно не добавлять. -->
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
<!-- Для удобства делаем короткий алиас для $(MSBuildThisFileDirectory) -->
<PropertyGroup>
<_ThisDir>$(MSBuildThisFileDirectory)</_ThisDir>
</PropertyGroup>
<!-- Добавляем параметры, общие для всех подпроектов в данной иерархии -->
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(_ThisDir)Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ResourceCompile>
<AdditionalIncludeDirectories>$(_ThisDir)Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
...
</ItemDefinitionGroup>
</Project>
Они подключатся автоматически, и все параметры протянутся по иерархии сверху вниз, от корня к каждому подпроекту.
4) Лучше не использовать дефолтные $(OutDir) и $(IntDir), которые по умолчанию гадят прямо в папку проекта (in-source build), и приучиться всегда строить во внешнюю папку (out-of-source build), которая находится за пределами солюшена, и может даже за пределами репозитория.
Во-первых, меньше шансов случайно закоммитить мусор в source control; проще настроить .gitignore.
Во-вторых, облегчается поиск по исходникам без открытия студии (из Far-а, например) — не нужен фильтр для исключеня .exe;.obj;.pch;....
В-третьих, можно быстро сделать clean и освободить кучу места на диске, не открывая студии — достаточно удалить одну-единственную директорию, а не лазить по всему дереву проекта, удаляя папки /Debug, /Release, /obj, /bin, /generated и т.п.
В-четвёртых, на билд-сервере проекты часто билдаются именно out-of-source, валя всё в одну папку, и иногда это тихо ломает ваш in-source билд. Например, два проекта зависят от одной DLL, копируя их каждый в свой output. Но вот версии незаметно разбежались. Пока строим локально из студии, каждый проект получает свою версию, и работает нормально, разработчик считает, что всё отлично. Но когда делатся "сводный" билд в общую папку на билд-сервере, то одна версия может затереть другую, недетерминированным способом (в зависимости от порядка и времени билда каждого проекта), и это может долго оставаться незамеченным. Если делать "сводные" билды сразу, локально, то больше шансов заметить, что разные файлы с одинаковыми именами перетирают друг друга.
Настраивать $(OutDir) тоже удобно одним общим props-файликом вроде такого:
Здесь использутся $(SolutionDir) потому что эта настройка нужна только для Студии, на билд-сервере путь задаётся билд-конфигурацией. Нужно только удалить $(OutDir) и $(IntDir) из каждого .vcxproj-файла.
Если кому-то всё же неудобно, что все файлы валятся в одну папку, то достаточно изменить BuildDirSuffix на $(Configuration).$(Platform)\$(MSBuildProjectName).
Если же кому-то неудобно искать бинарники вдалеке от сорцов, то в Студии легко создать тул, чтобы открывать целевую папку: "Tools > External Tools > Add", Title="Open target director&y", Command="C:\Windows\explorer.exe", Arguments="$(BinDir)", после чего комбинация "Alt+T-Y" в студии будет мгновенно открывать папку с построенными бинарниками.
Нашёл хороший способ для получения дат, купонов, амортизаций по облигациям.
Пример запроса:
https://iss.moex.com/iss/statistics/engines/stock/markets/bonds/bondization?from=2020-02-01&till=2020-02-20&start=0&limit=100&iss.only=amortizations,coupons
Выдаёт все купоны по всем облигациям между указанными датами
Некрокоммент, но может кому-то будет полезно.
1) Если не хочется заморачиваться с импортами своих
.props
и.targets
файлов в каждый проект, то можно создать файлDirectory.Build.props
и/илиDirectory.Build.targets
, которые импортируются автоматически.2) Лучше избегать
$(SolutionDir)
, потому что он существует только если солюшен строится из Студии. На билд-сервере ваши проекты будут строиться голым MSBuild, который использует.sln
только чтобы получить список проектов и билд-завсимостей, после чего каждый проект строится изолировано от солюшена. Если надо привязаться к стабильному пути, то лучше использовать$(MSBuildThisFileDirectory)
, который равен пути к самомуprops/targets
-файлу. Если такой файл лежит рядом c.sln
, то это даст надёжный переносимый эквивалент$(SolutionDir)
.3) Бывает так, что солюшен не плоский (все проекты в одной папке), а иерархическй, т.е. проекты разбиты по поддиректориям (например, пачка проектов в поддиректории
Core
, другая пака в поддиректорииClient
, третья — в поддиректорииServer
и т.д), и в таком случае на каждом уровне иерархии могут появляться собственные настройки, в дополнение к общим. Например, все проекты вClient
подключают один набор заголовочный файлов и библиотек и используют один набор параметров, все проекты вServer
— другой набор, и при этом все проекты вообще должны использовать общий solution-wide набор. В таком сценарии можно использовать комбо из приёмов 1 и 2, положив на каждом уровне иерархии по файликуDirectory.Build.*
примерно такого вида:Они подключатся автоматически, и все параметры протянутся по иерархии сверху вниз, от корня к каждому подпроекту.
4) Лучше не использовать дефолтные
$(OutDir)
и$(IntDir)
, которые по умолчанию гадят прямо в папку проекта (in-source build), и приучиться всегда строить во внешнюю папку (out-of-source build), которая находится за пределами солюшена, и может даже за пределами репозитория.Во-первых, меньше шансов случайно закоммитить мусор в source control; проще настроить
.gitignore
.Во-вторых, облегчается поиск по исходникам без открытия студии (из Far-а, например) — не нужен фильтр для исключеня
.exe;.obj;.pch;...
.В-третьих, можно быстро сделать clean и освободить кучу места на диске, не открывая студии — достаточно удалить одну-единственную директорию, а не лазить по всему дереву проекта, удаляя папки /Debug, /Release, /obj, /bin, /generated и т.п.
В-четвёртых, на билд-сервере проекты часто билдаются именно out-of-source, валя всё в одну папку, и иногда это тихо ломает ваш in-source билд. Например, два проекта зависят от одной DLL, копируя их каждый в свой output. Но вот версии незаметно разбежались. Пока строим локально из студии, каждый проект получает свою версию, и работает нормально, разработчик считает, что всё отлично. Но когда делатся "сводный" билд в общую папку на билд-сервере, то одна версия может затереть другую, недетерминированным способом (в зависимости от порядка и времени билда каждого проекта), и это может долго оставаться незамеченным. Если делать "сводные" билды сразу, локально, то больше шансов заметить, что разные файлы с одинаковыми именами перетирают друг друга.
Настраивать
$(OutDir)
тоже удобно одним общимprops
-файликом вроде такого:Здесь использутся
$(SolutionDir)
потому что эта настройка нужна только для Студии, на билд-сервере путь задаётся билд-конфигурацией. Нужно только удалить$(OutDir)
и$(IntDir)
из каждого.vcxproj
-файла.Если кому-то всё же неудобно, что все файлы валятся в одну папку, то достаточно изменить
BuildDirSuffix
на$(Configuration).$(Platform)\$(MSBuildProjectName)
.Если же кому-то неудобно искать бинарники вдалеке от сорцов, то в Студии легко создать тул, чтобы открывать целевую папку: "Tools > External Tools > Add", Title="Open target director&y", Command="C:\Windows\explorer.exe", Arguments="$(BinDir)", после чего комбинация "Alt+T-Y" в студии будет мгновенно открывать папку с построенными бинарниками.