Эффективное использование свойств проекта Visual Studio для нескольких проектов и конфигураций

Я всегда использовал Visual Studios со встроенной поддержкой графического интерфейса для настройки моих проектов, часто используя листы свойств, чтобы несколько проектов использовали общий набор.

Одна из моих основных проблем с этим - управление несколькими проектами, конфигурациями и платформами. Если вы просто делаете все с основным графическим интерфейсом (щелкните правой кнопкой мыши проект -> свойства), он быстро превращается в беспорядок, сложный в обслуживании и подверженный ошибкам (например, неспособность правильно определить какой-либо макрос или использование неправильной библиотеки времени выполнения и т. Д.). Имея дело с тем фактом, что разные люди помещают библиотеки зависимостей в разные места (например, все мои находятся в "C: \ Libs \ [C, C ++] \ [lib-name] \"), а затем часто управляют разными версиями этих библиотек по-разному (выпуск, отладка, x86, x64 и т. д.) также является большой проблемой, поскольку это значительно усложняет время его настройки в новой системе, а также возникают проблемы с контролем версий и разделением путей для всех .. .

Листы свойств делают это немного лучше, но у меня не может быть одного листа с отдельными настройками для разных конфигураций и платформ (выпадающие списки неактивны), в результате у меня есть много листов, которые, если унаследованы в правильном порядке, делают то, что я хочу ( «x86», «x64», «отладка», «выпуск», «общий», «каталоги» (решает ранее упомянутую проблему зависимости путем определения пользовательских макросов, таких как BoostX86LibDir) и т. д.), и если они унаследованы в неправильном порядке (например, «common» перед «x64» и «debug») приводят к таким проблемам, как попытка связать неправильную версию библиотеки или неправильное имя вывода ...

Мне нужен способ справиться со всеми этими разрозненными зависимостями и настроить набор «правил», которые используются всеми моими проектами в решении, например, присвоить выходной библиотеке имя mylib- [vc90, vc100] - [x86 , x64] [- d] .lib ", без необходимости делать все это для каждого отдельного проекта, конфигурации и комбинации платформы, а затем правильно синхронизировать их.

Я знаю о переходе на совершенно другие системы, такие как CMake, которые создают необходимые файлы, однако это затем усложняет ситуацию в другом месте, делая так, что даже простые задачи, такие как добавление нового файла в проект, требуют дополнительных изменений в другом месте, что я не являюсь полностью доволен ни тем, ни другим, если только нет некоторых с интеграцией VS2010, которые могут отслеживать такого рода изменения.


person Fire Lancer    schedule 17.08.2010    source источник
comment
Я чувствую вашу боль: в нашем продукте работает более 600 проектов vcproj. :(   -  person C Johnson    schedule 17.08.2010


Ответы (6)


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

person Fire Lancer    schedule 17.08.2010
comment
Да, в VS2k10 листы свойств намного мощнее. Жаль, что все это не раскрывается через IDE. Я сделал нечто подобное, и это действительно упрощает ситуацию. - person jalf; 07.01.2011
comment
Если вам нужны более продвинутые функции String, вы можете использовать методы System.String: msdn.microsoft.com/en-us/library/ Пример:` ‹ShortHasRelPos› $ (Configuration.ToLower (). LastIndexOf ('rel')) ‹/ShortHasRelPos› - person Oliver Zendel; 18.04.2014
comment
Как я могу применить это решение? Куда мне его поместить и как сообщить Visual Studio, что я хочу, чтобы он использовался по умолчанию? - person user2023370; 02.04.2015
comment
Я никогда не делал это по умолчанию, потому что это может испортить проекты, которые мне не принадлежат (например, сторонние библиотеки и примеры проектов), хотя есть листы свойств по умолчанию, хранящиеся где-то (забудьте), которые вы можете редактировать. Таким образом, я просто помещаю их в свой каталог решений, а затем в окне диспетчера свойств Visual Studio вы можете просто использовать Добавить существующий лист свойств (вы также можете создавать новые там, но графический интерфейс по-прежнему не предоставляет средств даже для базовой платформы / конфигурации. условные обозначения на листах свойств). Это также правильно работает с несколькими разработчиками / исходным кодом. - person Fire Lancer; 02.04.2015

Внес некоторые улучшения, может кому-нибудь пригодится

<?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>

развлекайся!

person lunicon    schedule 04.02.2011
comment
Когда это будет оценено? При загрузке проекта? Я хотел бы добавить настраиваемые правила копирования после сборки на страницу свойств, чтобы копировать только те библиотеки DLL, которые фактически связаны с проектом. Как вы думаете, это возможно? - person Bim; 19.05.2016
comment
Бим, я думаю, что он оценивается перед сборкой, поскольку он считывает переменные из реестра (см. $ (Registry: key)). - person lunicon; 20.05.2016

Раньше у меня была такая же боль за продукт моей компании (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). Используя эту технику, вы можете легко построить красивую иерархию листов свойств в соответствии с вашими требованиями.

Теперь есть еще одна вещь, которую вы, возможно, захотите сделать: создать собственные шаблоны проектов, использующие ваш набор подшивок свойств. Реальная трудность - обеспечить правильное использование шаблонов и листов свойств. По моему личному опыту, даже если все настроено, кто-то все равно забудет использовать шаблон для создания новых проектов ...

person Peon the Great    schedule 11.01.2011

Для каждой конфигурации можно создать отдельную страницу свойств. Сделать это:

  1. Создайте страницу свойств для конкретной конфигурации
  2. Откройте Property Manager
  3. Щелкните правой кнопкой мыши конфигурацию (не проект), которую вы хотите изменить.
  4. Нажмите «Добавить существующий лист свойств» и добавьте свой лист.

Это избавляет вас от необходимости вставлять условия в один лист для нескольких конфигураций. Если у вас есть некоторые общие атрибуты, которые вы хотели бы использовать в разных конфигурациях, создайте иерархию. Верхний лист можно использовать во всех конфигурациях, а вложенные листы будут содержать только атрибут, зависящий от конфигурации.

person gogisan    schedule 16.04.2012
comment
ИДЕАЛЬНО! благодаря. Таким образом, вы также можете создавать новые страницы в каждом узле конфигурации. Легко попасть в ловушку редактирования общей страницы, которая влияет на все конфигурации, даже если доступ к ней осуществляется под каждым узлом конфигурации. - person Justin; 28.10.2015

Что касается выходной библиотеки, вы можете выбрать все свои проекты, затем открыть страницы свойств, выбрать Все конфигурации, Все платформы, а затем установить для Целевого имени:

$(ProjectName)-$(PlatformToolset)-$(PlatformShortName)-$(Configuration)

что даст результат вроде mylib-v100-x86-Debug.lib

Мы делаем что-то подобное и для дополнительных каталогов библиотек, используя $(PlatformName) и #(Configuration), чтобы выбрать правильные пути к библиотекам, хотя это означает, что нужно немного возиться с начальной настройкой библиотек. например, мы должны ускорить установку своих библиотек до boost/lib.Win32 или boost/lib.x64.


Что касается библиотек и людей, устанавливающих их в разных местах, есть несколько вариантов. Если у вас очень надежная система управления версиями, вы можете просто поместить все в систему управления версиями, живя в папке libs рядом с исходным кодом. Это, вероятно, не сработает, если вы используете больше, чем несколько библиотек, или если они особенно велики.

Другой вариант, который приходит на ум, - установить переменную среды на каждом пользовательском компьютере, которая указывает на корень папки их библиотек, например LIB_ROOT=c:\libraries, и затем вы можете получить к ней доступ в Visual Studio как $(LIB_ROOT).

person ngoozeff    schedule 17.08.2010
comment
Я уже сделал несколько подобных вещей, но есть библиотеки, которые используют что-то еще в своих именах (например, opt вместо release, -d вместо -Debug) и т. Д., Что по-прежнему требует множества специальных правил (моя отладка .props и release.props настраивают пользовательские макросы, чтобы помочь с этим, при этом common.props фактически устанавливает пути include / lib). Не рассматривал это с ускорением, хорошая идея (было бы еще лучше, если бы автоматическое связывание включало не с использованием тех же имен для сборок x86 и x64, но люди boost.build, похоже, не думают, что это проблема ) - person Fire Lancer; 17.08.2010
comment
Я предполагаю, что ваше PlatformShortName произошло от x86.props и x64.props, которые должны быть правильно унаследованы или что-то в этом роде, или это просто недокументировано? - person Fire Lancer; 17.08.2010
comment
@Fire Lancer: честно говоря, я не уверен, откуда взялось PlatformShortName. Я думаю, что он должен быть встроенным, потому что у нас нет ничего особенного в наших списках свойств. - person ngoozeff; 17.08.2010
comment
@FireLancer: Мы взломали скрипт сборки boost, чтобы включить платформу в имя библиотеки. Это действительно требует, чтобы у нас был собственный boost_version.h, но автоматическое связывание работает как шарм, нам нужно только добавить boost.props файл в проект, и мы готовы к работе. Конечно, если бы мы знали об условиях в props-файлах, это могло бы быть лучше ... Определенно менее болезненно ... - person Andreas Magnusson; 07.05.2013

Похоже, стоит попробовать инструмент сборки - у меня дома мы используем специально созданный инструмент, который отслеживает изменения в файлах и проектах и ​​определяет зависимости и порядок компиляции. Добавление нового файла не составляет большого труда - компиляция выполняется с помощью msbuild.

Если бы мне пришлось скомпилировать больше, чем несколько проектов, я бы использовал что-то вроде nant: http://nant.sourceforge.net/

person Rune Andersen    schedule 13.01.2011