Эффективное использование свойств проекта Visual Studio для нескольких проектов и конфигураций
Я всегда использовал Visual Studios, встроенную в поддержку графического интерфейса, для настройки своих проектов, часто используя таблицы свойств, чтобы несколько проектов использовали общий набор.
Один из моих главных недостатков - управление несколькими проектами, конфигурациями и платформами. Если вы просто делаете все с помощью основного графического интерфейса (щелкните правой кнопкой мыши проект -> свойства), он быстро становится беспорядочным, сложным в обслуживании и подверженным ошибкам (например, не удается правильно определить какой-либо макрос, использовать неправильную библиотеку времени выполнения и т. Д.). Имея дело с тем фактом, что разные люди помещают туда библиотеки зависимостей в разных местах (например, мои все живут в "C:\Libs\[C,C++]\[lib-name]\"), а затем часто управляют различными версиями этих библиотек по-разному (выпуск, отладка, x86, x64 и т. д.) также представляет собой большую проблему, поскольку это значительно усложняет время для его установки в новой системе, а также возникают проблемы с управлением версиями и разделением путей каждого..,
Листы свойств делают это немного лучше, но у меня не может быть одного листа с отдельными настройками для разных конфигураций и платформ (выпадающие списки выделены серым цветом), в результате чего у меня будет много листов, которые при наследовании в правильном порядке делают то, что я хочу ("x86", "x64", "debug", "release", "common", "directoryies" (решает ранее упомянутую проблему с зависимостями путем определения пользовательских макросов, таких как BoostX86LibDir) и т. д.) и если наследуется в неправильном порядке (например, "общие" перед "x64" и "отладка") приводят к таким проблемам, как попытка связать неверную версию библиотеки или неправильное именование выходных данных...
То, что я хочу, - это способ справиться со всеми этими разбросанными зависимостями и установить набор "правил", которые используются всеми моими проектами в решении, например, назвать библиотеку вывода как "mylib-[vc90,vc100]-[x86".,x64][-d].lib", без необходимости делать все это для каждого отдельного проекта, конфигурации и комбинации платформы, а затем синхронизировать их все правильно.
Мне известно о переходе на совершенно другие системы, такие как CMake, которые создают необходимые файлы, однако это усложняет другие процессы, делая такие простые задачи, как добавление нового файла в проект, дополнительными изменениями в другом месте, а это не то, чем я являюсь. Полностью доволен и тем, и другим, если только есть некоторые с интеграцией VS2010, которые могут отслеживать изменения такого рода.
7 ответов
Я только что узнал что-то, что, по моему мнению, было невозможно (это не раскрывается в графическом интерфейсе), что помогает сделать список свойств гораздо более полезным. Атрибут "Condition" многих тегов в файлах свойств проекта, и его также можно использовать в файлах.props!
Я просто собрал следующее в качестве теста, и он отлично работал и выполнил задачу 5 (общие,x64,x86, отладка, выпуск) отдельных листов свойств!
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="UserMacros">
<!--debug suffix-->
<DebugSuffix Condition="'$(Configuration)'=='Debug'">-d</DebugSuffix>
<DebugSuffix Condition="'$(Configuration)'!='Debug'"></DebugSuffix>
<!--platform-->
<ShortPlatform Condition="'$(Platform)' == 'Win32'">x86</ShortPlatform>
<ShortPlatform Condition="'$(Platform)' == 'x64'">x64</ShortPlatform>
<!--toolset-->
<Toolset Condition="'$(PlatformToolset)' == 'v90'">vc90</Toolset>
<Toolset Condition="'$(PlatformToolset)' == 'v100'">vc100</Toolset>
</PropertyGroup>
<!--target-->
<PropertyGroup>
<TargetName>$(ProjectName)-$(Toolset)-$(ShortPlatform)$(DebugSuffix)</TargetName>
</PropertyGroup>
</Project>
Единственная проблема заключается в том, что графический интерфейс свойств не может справиться с этим, проект, который использует приведенный выше лист свойств, просто сообщает унаследованные значения по умолчанию, такие как $(ProjectName) для цели.
Я сделал некоторые улучшения, может быть кому-нибудь пригодится
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="UserMacros">
<!--IsDebug: search for 'Debug' in Configuration-->
<IsDebug>$([System.Convert]::ToString( $([System.Text.RegularExpressions.Regex]::IsMatch($(Configuration), '[Dd]ebug'))))</IsDebug>
<!--ShortPlatform-->
<ShortPlatform Condition="'$(Platform)' == 'Win32'">x86</ShortPlatform>
<ShortPlatform Condition="'$(Platform)' == 'x64'">x64</ShortPlatform>
<!--build parameters-->
<BUILD_DIR>$(registry:HKEY_CURRENT_USER\Software\MyCompany\@BUILD_DIR)</BUILD_DIR>
</PropertyGroup>
<Choose>
<When Condition="$([System.Convert]::ToBoolean($(IsDebug)))">
<!-- debug macroses -->
<PropertyGroup Label="UserMacros">
<MyOutDirBase>Debug</MyOutDirBase>
<DebugSuffix>-d</DebugSuffix>
</PropertyGroup>
</When>
<Otherwise>
<!-- other/release macroses -->
<PropertyGroup Label="UserMacros">
<MyOutDirBase>Release</MyOutDirBase>
<DebugSuffix></DebugSuffix>
</PropertyGroup>
</Otherwise>
</Choose>
<Choose>
<When Condition="Exists($(BUILD_DIR))">
<PropertyGroup Label="UserMacros">
<MyOutDir>$(BUILD_DIR)\Bin\$(MyOutDirBase)_$(ShortPlatform)\</MyOutDir>
<MyIntDir>$(BUILD_DIR)\Build\$(Configuration)_$(ShortPlatform)_$(PlatformToolset)\$(ProjectGuid)\</MyIntDir>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Label="UserMacros">
<MyOutDir>$(SolutionDir)\Bin\$(MyOutDirBase)_$(ShortPlatform)\</MyOutDir>
<MyIntDir>$(SolutionDir)\Build\$(Configuration)_$(ShortPlatform)_$(PlatformToolset)\$(ProjectGuid)\</MyIntDir>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup>
<OutDir>$(MyOutDir)</OutDir>
<IntDir>$(MyIntDir)</IntDir>
<!-- some common for projects
<CharacterSet>Unicode</CharacterSet>
<LinkIncremental>false</LinkIncremental>
-->
</PropertyGroup>
</Project>
повеселись!
Раньше у меня была такая же боль за продукт моей компании (более 200 проектов). Я решил, как построить хорошую иерархию списков свойств.
Проекты наследуют таблицу свойств по типу вывода, например, x64.Debug.Dynamic.Library.vsprops. Этот файл vsprops просто наследует другие листы свойств, используя атрибут InheritedPropertySheets
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="x64.Debug.Dynamic.Binary"
InheritedPropertySheets=".\Common.vsprops;.\x64.vsprops;.\Debug.vsprops;.\Runtime.Debug.Dynamic.vsprops;.\Output.x64.Library.vsprops"
>
Вы также можете использовать переменные (т. Е. UserMacro, чье значение может быть абсолютным или даже переменные окружения) в таблицах свойств, чтобы настроить множество вещей в зависимости от ваших потребностей. Например, определение переменной BIN в Debug.vsprops
<UserMacro name="BIN" Value="Debug" />
затем, когда вы установите выходное имя в серии vsprops, скажем, Output.x64.Library.vsprops
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
OutputDirectory="$(BIN)"
>
Переменная $(BIN) будет расширена до установленного значения (в данном случае, Debug). Используя эту технику, вы можете легко построить хорошую иерархию списков свойств, чтобы удовлетворить ваши требования.
Теперь есть еще одна вещь, которую вы можете захотеть сделать: создать свои собственные шаблоны проектов, которые используют ваш набор свойств листа. Действительно сложная задача - обеспечить правильное использование шаблонов и таблиц свойств. Мой личный опыт показывает, что даже если все настроено, кто-то все равно забудет использовать шаблон для создания новых проектов...
Можно создать отдельный лист свойств для каждой конфигурации. Сделать это:
- Создайте лист свойств для конкретной конфигурации
- Откройте Менеджер недвижимости
- Щелкните правой кнопкой мыши конфигурацию (не проект), которую вы хотите изменить
- Нажмите "Добавить существующий список свойств" и добавьте свой лист
Это освобождает вас от вставки условий в один лист для нескольких конфигураций. Если у вас есть общие атрибуты, которые вы хотели бы использовать в разных конфигурациях, создайте иерархию. Верхний лист можно использовать во всех конфигурациях, а вложенные листы будут содержать только атрибут, относящийся к конфигурации
Что касается выходной библиотеки, вы можете выбрать все свои проекты, затем открыть страницы свойств, выбрать "Все конфигурации", "Все платформы", а затем установить для "Имя цели":
$(ProjectName)-$(PlatformToolset)-$(PlatformShortName)-$(Configuration)
который выдаст вывод как mylib-v100-x86-Debug.lib
Мы делаем нечто похожее на это для дополнительных библиотечных каталогов, используя $(PlatformName)
а также #(Configuration)
выбрать правильные пути к библиотекам, хотя это означает, что нужно немного поработать с начальной настройкой библиотек. например, у нас есть Boost установить свои библиотеки boost/lib.Win32
или же boost/lib.x64
,
Что касается библиотек и людей, устанавливающих их в разных местах, есть несколько вариантов. Если у вас очень надежная система управления версиями, вы можете просто поместить все в систему управления версиями, находясь в папке libs рядом с вашим источником. Это, вероятно, не сработает, если вы используете более нескольких библиотек, или если они особенно велики.
Другой вариант, который приходит на ум, - это установить переменную окружения на каждом компьютере пользователя, которая указывает на корень папки их библиотек, например LIB_ROOT=c:\libraries
и вы можете получить к нему доступ в Visual Studio как $(LIB_ROOT)
,
Если вы хотите определить некоторые пользовательские макросы, которые должны быть действительны для всего решения:
Создать
solution-global.props
файл в корневой папке вашего решенияОпределите там свои UserMacros:
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup Label="UserMacros" > <CommonUtilsDir>$(SolutionDir)Common\Utils\</CommonUtilsDir> <DriverBaseDir>$(SolutionDir)Common\DriverBase\</DriverBaseDir> </PropertyGroup> </Project>
вставить в каждый
*.vcxproj
файл, в котором вы хотите использовать свои пользовательские макросы, в этой строке:<Import Project="$(SolutionDir)solution-global.props" />
Используйте свой собственный макрос:
<AdditionalIncludeDirectories>$(CommonUtilsDir)\Source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
Работает в VS2015
Похоже, что стоит попробовать инструмент сборки - у меня дома мы используем специальный инструмент, который следит за изменениями в файлах и проектах и вычисляет зависимости и порядок компиляции. Добавление нового файла не представляет особой проблемы - компиляция выполняется с помощью msbuild.
Если бы мне нужно было скомпилировать больше, чем несколько проектов, я бы использовал что-то вроде nant: http://nant.sourceforge.net/