Как объединить свойства в файле Directory.Build.props вместо перезаписи свойств? - PullRequest
3 голосов
/ 07 января 2020

У меня есть следующие Directory.Build.props файлы:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LibraryPath>$(BOOST_ROOT)\lib32-msvc-14.2</LibraryPath>
    <IncludePath>$(BOOST_ROOT)\</IncludePath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <LibraryPath>$(BOOST_ROOT)\lib64-msvc-14.2</LibraryPath>
    <IncludePath>$(BOOST_ROOT)\</IncludePath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LibraryPath>$(BOOST_ROOT)\lib32-msvc-14.2</LibraryPath>
    <IncludePath>$(BOOST_ROOT)\</IncludePath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <LibraryPath>$(BOOST_ROOT)\lib64-msvc-14.2</LibraryPath>
    <IncludePath>$(BOOST_ROOT)\</IncludePath>
  </PropertyGroup>
</Project>

Всякий раз, когда я загружаю (C ++) проект в подпапку (в Visual Studio 2019), проект теряет все унаследованные пути включения и библиотеки:

Унаследованные значения: Inherited Values

Я подумал, что это может быть из-за того, что я не добавил IncludePath и LibraryPath, поэтому я сделал это и изменил props файлов следующим образом:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LibraryPath>$(LibraryPath);$(BOOST_ROOT)\lib32-msvc-14.2</LibraryPath>
    <IncludePath>$(IncludePath);$(BOOST_ROOT)\</IncludePath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <LibraryPath>$(LibraryPath);$(BOOST_ROOT)\lib64-msvc-14.2</LibraryPath>
    <IncludePath>$(IncludePath);$(BOOST_ROOT)\</IncludePath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LibraryPath>$(LibraryPath);$(BOOST_ROOT)\lib32-msvc-14.2</LibraryPath>
    <IncludePath>$(IncludePath);$(BOOST_ROOT)\</IncludePath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <LibraryPath>$(LibraryPath);$(BOOST_ROOT)\lib64-msvc-14.2</LibraryPath>
    <IncludePath>$(IncludePath);$(BOOST_ROOT)\</IncludePath>
  </PropertyGroup>
</Project>

Затем перезагрузка проекта снова приводит к отсутствию унаследованных значений.

Я дважды проверил, присутствуют ли макросы, и они есть ( * Макросы VC_ и WindowsSDK_):

macros are present

Я также попытался изменить Directory.Build.props на Directory.Build.targets, чтобы загрузить его после того, как проекты был загружен, но затем файл не загружается вообще.

Как я могу убедиться, что мой Directory.Build.props наследует значения по умолчанию и добавляет мои пользовательские параметры?

Причина, по которой я хочу сделать это, потому что я мигрирую из устаревшего Microsoft.Cpp.Win32.user.props файла.

Изменение расширений on to .targets работает только для процесса сборки, но intellisense / visual Studio не обрабатывает включаемые файлы и показывает много ошибок (до компиляции). Это не предпочтительно.

Ответы [ 2 ]

2 голосов
/ 24 февраля 2020

Ответ Перри Цяня нуждается в улучшении. Вот мои проблемы:

  1. INCLUDE / LIB env vars являются глобальными для всех проектов, которые хотят использовать этот метод.
    Аргументы MSBuild должны быть установлены для каждого проекта
  2. use of user.props устарел и также является глобальным для всех проектов

Проблема с Directory.Build.props заключается в том, что он включен до определения $ (IncludePath) и $ (LibraryPath). Вы можете вручную установить пути VS по умолчанию, но это плохая практика.

Чтобы использовать преемника user.props Directory.Build.props и IntelliSense, я предлагаю использовать AdditionalIncludeDirectories и AdditionalLibraryDirectories.
Вот пример конфигурации Directory.Build.props:

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ImportGroup Label="PropertySheets" />
  <PropertyGroup Label="UserMacros">
    <BoostPath>$(BOOST_ROOT)</BoostPath>    
    <BoostPlatform Condition="'$(Platform)'=='Win32'">lib32</BoostPlatform>
    <BoostPlatform Condition="'$(Platform)'=='x64'">lib64</BoostPlatform>
    <BoostDebug Condition="'$(Configuration)'=='Debug'">\debug</BoostDebug>
  </PropertyGroup>
  <ItemDefinitionGroup>
    <ClCompile>
      <AdditionalIncludeDirectories>$(BoostPath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <AdditionalLibraryDirectories>$(BoostPath)\$(BoostPlatform)-msvc-$([System.Text.RegularExpressions.Regex]::replace($(PlatformToolset), "v(\d+)(\d)$", "$1.$2"))$BoostDebug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
    </Link>
  </ItemDefinitionGroup>
</Project>

Если вы хотите задать дополнительные пути внутри проекта, обязательно добавьте ;%(AdditionalIncludeDirectories) или ;%(AdditionalLibraryDirectories) соответственно, чтобы включить пути из файла props.

Установите свойство BoostDebug, где бы вы ни скомпилировали отладочные библиотеки. В этом примере это будет lib32-msv c -14.2 / debug /

Термин регулярное выражение $([System.Text.RegularExpressions.Regex]::replace($(PlatformToolset), "v(\d+)(\d)$", "$1.$2")) преобразует набор инструментов платформы, например v142, в приложение пути к lib 14.2.

Для удобства чтения было бы лучше инициализировать его в PropertyGroup, но $(PlatformToolset) не будет инициализироваться при анализе файла props. К счастью AdditionalLibraryDirectories оценивается во время соединения, когда будет установлено $(PlatformToolset).

Если вы хотите улучшить читаемость или вам нужны более сложные операции на $(PlatformToolset), я предлагаю использовать Directory.Build.targets Конфигурация дополнительно. Когда этот файл проанализирован, $(PlatformToolset) уже будет инициализирован.
Пример Directory.Build.targets :

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ImportGroup Label="PropertySheets" />
  <PropertyGroup Label="UserMacros">
    <BoostToolset>$([System.Text.RegularExpressions.Regex]::replace($(PlatformToolset), "v(\d+)(\d)$", "$1.$2"))</BoostPlatform>
  </PropertyGroup>
  <ItemDefinitionGroup>
    <Link>
      <AdditionalLibraryDirectories>$(BoostPath)\$(BoostPlatform)-msvc-$(BoostToolset)$BoostDebug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
    </Link>
  </ItemDefinitionGroup>
</Project>
1 голос
/ 08 января 2020

Как я могу убедиться, что мой Directory.Build.props наследует значения по умолчанию и добавляет мои пользовательские параметры?

Я думаю, вы не можете использовать Directory.Build.props для перезаписи системы свойство в пользовательском интерфейсе свойства проекта.

По вашим данным, LibraryPath и IncludePath потеряли там значения. Обратите внимание, что эта информация о порядке импорта Directory.Build.props:

Directory.Build.props импортирована в Microsoft.Common.props очень рано, и свойства, определенные позже, для нее недоступны. Поэтому избегайте ссылок на свойства, которые еще не определены (и будут иметь пустое значение).

Directory.Build.targets импортирован из Microsoft.Common.targets после импорта файлов .targets из пакетов NuGet. Таким образом, он может переопределять свойства и цели, определенные в большинстве логов сборки c, но иногда вам может понадобиться настроить файл проекта после окончательного импорта.

Вы можете обратиться к эта ссылка .

Подробно, Directory.Build.props как шаг для инициализации проекта и всегда запускается до Microsoft.Common.props, который устанавливает значения по умолчанию для большинства системных свойств, таких как LibraryPath и IncludePath. Поэтому в начале, это нормально, что значения пусты. После этого, когда он выполняет Microsoft.Common.props, он имеет следующее:

<Includepath Condidtion="'$(Includepath)'==''">$(VC_IncludePath)......</Includepath >

И вы добавляете $(BOOST_ROOT)\lib32-msvc-14.2 к Includepath в Directory.Build.props, поэтому при выполнении следующего шага Includepath имеет значение, поэтому он пропускает операцию назначения системных значений и не перезаписывает значения на этом шаге и вызывает это странное поведение.

Для Directory.Build.targets он выполняет операцию переопределения на конец, когда оба свойства includepath и LibraryPath получили системные значения, и с переопределением проблем нет. Но вы можете получить эти значения только при запуске проекта, как вы показали позже.

Вкратце, Directory.Build.props подходит для определения некоторых свойств, которые будут использоваться или перезаписаны позже, а Directory.Build.targets подходит для перезаписывая значения, которые уже определены в процессе сборки.

Предложение

1) Чтобы установить включаемые каталоги, вы можете добавить их в свой ВКЛЮЧИТЬ переменную окружения. Вы можете установить переменные INCLUDE и LIB следующим образом:

set INCLUDE=xxxx
set LIB=xxxx\lib32-msvc-14.2

И затем добавить /p:"VCBuildAdditionalOptions= /useenv" к аргументам MSBuild, чтобы он принимал переменные INCLUDE и LIB.

Вы можете обратиться к this .

2) Или вы можете использовать свою начальную функцию в пути C:\Users\UserName\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.xxx.user.props, чтобы добавить в нее дополнительный includepath, librarypath, например:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ImportGroup Label="PropertySheets">
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <IncludePath>C:\any-name\include;$(IncludePath)</IncludePath>
    <LibraryPath>C:\any-name\lib;$(LibraryPath)</LibraryPath>
  </PropertyGroup>
  <ItemDefinitionGroup />
  <ItemGroup />
</Project>

Надеюсь, это поможет вам.

...