Как добавить дополнительный каталог включения для порта vcpkg в файлах Visual Studio (vcxproj)?
Я работаю с оверлей-портом vcpkg, который требует наличия собственного каталога include/MYLIBRARY в путях включения системы C++. Хотя я легко могу добиться этого в CMake с помощью target_include_directories() в файле порта share/MYLIBRARY/MYLIBRARY-config.cmake, я не могу найти способ добавить этот каталог в каталоги включения при использовании файлов .vcxproj с Visual Studio 2022/MSBuild.
Что я уже пробовал:
- Модификация файлов в порте: исправление отдельных директив #include, но это нецелесообразно из-за большого количества файлов и обновлений версий.
- Добавление файлов включения оверлей-порта в файлы .vcxproj или .props потребляющих проектов через IncludePath: это приводит к конфликтам, когда функции определены как в файлах заголовков vcpkg_installed, так и в файлах заголовков оверлей-порта.
- Добавление $(VcpkgInstalledDir)include\MYLIBRARY\ в IncludePath: свойство VcpkgInstalledDir не оценивается и остается пустым.
- Добавление $(MSBuildThisFileDirectory)vcpkg_installed\x64-windows\include\MYLIBRARY\ в IncludePath: это не подходит, так как не работает для других триплетов сборки.
Я ищу либо решение на основе оверлей-порта, либо исправление на стороне потребляющего проекта.
Добавление дополнительного каталога включений для порта vcpkg в файлах vcxproj Visual Studio
Чтобы добавить дополнительный каталог включений для порта vcpkg в файлах vcxproj Visual Studio, необходимо правильно настроить либо сам оверлейный порт, либо изменить конфигурацию сборки потребляющего проекта. Ключевым моментом является понимание того, как интеграция MSBuild vcpkg обрабатывает каталоги включений и где должен быть расположен ваш пользовательский путь в порядке поиска включений.
Содержание
- Понимание обработки каталогов включений vcpkg
- Решение 1: Настройка оверлейного порта Portfile.cmake
- Решение 2: Модификация vcxproj потребляющего проекта
- Решение 3: Использование Directory.build.props
- Решение 4: Пользовательские свойства MSBuild
- Обработка конфликтов приоритета включений
- Заключение и рекомендации
Понимание обработки каталогов включений vcpkg
Интеграция MSBuild vcpkg автоматически добавляет установленные пакеты в свойства проекта Visual Studio, включая каталоги включений, каталоги компоновки и библиотеки компоновки источник. Когда вы используете оверлейные порты, vcpkg пытается загрузить этот каталог как порт в первую очередь, и в случае успеха рассматривает его как порт с именем, производным от файла CONTROL или vcpkg.json источник.
Проблема, с которой вы сталкиваетесь, заключается в том, что каталоги включений vcpkg могут иметь разные уровни приоритета, чем каталоги включений вашего пользовательского оверлейного порта. Согласно одному из отчетов о проблемах, путь поиска включений vcpkg уже добавляется до CUSTOM_INCLUDE_DIR, что может вызывать конфликты источник.
Решение 1: Настройка оверлейного порта Portfile.cmake
Для вашего оверлейного порта вы можете изменить portfile.cmake, чтобы обеспечить правильную установку и распознавание каталога включений. Вот как это структурировать:
include(vcpkg_common_functions)
# Скачивание и распаковка библиотеки
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO your-repo/your-library
REF specific-version
SHA512 your-hash
)
# Настройка и сборка
vcpkg_configure_cmake(
SOURCE_PATH ${SOURCE_PATH}
PREFER_NINJA
)
# Установка библиотеки
vcpkg_install_cmake()
# Обеспечение правильной установки каталога включений
file(INSTALL ${SOURCE_PATH}/include/MYLIBRARY DESTINATION ${CURRENT_PACKAGES_DIR}/include)
# Установка файла авторских прав
file(INSTALL ${SOURCE_PATH}/COPYING DESTINATION ${CURRENT_PACKAGES_DIR}/share/MYLIBRARY RENAME copyright)
Ключевым моментом является обеспечение правильной установки папки include/MYLIBRARY в ${CURRENT_PACKAGES_DIR}/include в процессе сборки порта. Это сделает ее доступной через стандартную структуру каталогов включений vcpkg.
Решение 2: Модификация vcxproj потребляющего проекта
Вы можете изменить файлы проекта Visual Studio, чтобы включить пользовательский каталог. Рекомендуемый подход - использовать цели интеграции vcpkg:
<!-- Добавьте это в ваш файл .vcxproj -->
<ImportGroup Label="ExtensionSettings">
<Import Project="$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.targets" />
</ImportGroup>
Однако для добавления вашего пользовательского каталога включений с правильным приоритетом вам нужно изменить свойство “Дополнительные каталоги включений” проекта:
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(VcpkgInstalledDir)include\MYLIBRARY;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
Проблему с тем, что $(VcpkgInstalledDir) не оценивается, можно решить, используя шаблон полного пути:
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(VcpkgRoot)installed\$(VcpkgTriplet)\include\MYLIBRARY;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
Решение 3: Использование Directory.build.props
Для более элегантного решения, которое работает с различными тройками сборки, создайте файл Directory.build.props в корне вашего решения:
<Project>
<PropertyGroup>
<VcpkgRoot Condition="'$(VcpkgRoot)' == ''">$(USERPROFILE)\vcpkg</VcpkgRoot>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>
$(VcpkgRoot)installed\$(VcpkgTriplet)\include\MYLIBRARY;
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
</Project>
Этот подход автоматически применяется ко всем проектам в вашем решении и адаптируется к различным тройкам сборки (x64-windows, x86-windows, arm64-windows и т.д.) источник.
Решение 4: Пользовательские свойства MSBuild
Вы также можете создать пользовательские свойства MSBuild для более гибкой обработки каталогов включений:
<!-- В вашем Directory.build.props -->
<Project>
<PropertyGroup>
<CustomIncludeDir>$(VcpkgRoot)installed\$(VcpkgTriplet)\include\MYLIBRARY</CustomIncludeDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>
$(CustomIncludeDir);
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
</Project>
Это упрощает управление и изменение пути к каталогу включений в вашем решении.
Обработка конфликтов приоритета включений
Когда у вас возникают конфликты между файлами заголовков, установленными vcpkg, и файлами заголовков вашего оверлейного порта, вам нужно контролировать порядок включений. Ключевым моментом является обеспечение соответствующего приоритета для вашего пользовательского каталога включений:
- Высокий приоритет по сравнению с vcpkg: Добавьте ваш каталог включений перед каталогами включений vcpkg
- Низкий приоритет по сравнению с vcpkg: Добавьте ваш каталог включений после каталогов включений vcpkg
Для достижения высокого приоритета измените AdditionalIncludeDirectories следующим образом:
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>
$(VcpkgRoot)installed\$(VcpkgTriplet)\include\MYLIBRARY;
$(VcpkgRoot)installed\$(VcpkgTriplet)\include;
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
Согласно исследованиям, каталоги включений vcpkg добавляются автоматически, поэтому вам необходимо правильно расположить ваш пользовательский каталог в последовательности источник.
Заключение и рекомендации
На основе проведенных исследований и анализа, вот рекомендуемые подходы:
-
Лучшее решение: Используйте
Directory.build.propsдля определения вашего пользовательского каталога включений. Этот подход является чистым, автоматически работает с различными тройками сборки и может быть легко управляемым. -
Улучшение оверлейного порта: Убедитесь, что ваш оверлейный пор правильно устанавливает каталог включений в процессе сборки. Это делает ваш порт более самодостаточным и легким в использовании.
-
Управление приоритетом: Будьте целенаправленны в порядке каталогов включений для избежания конфликтов между заголовками, установленными vcpkg, и вашими пользовательскими заголовками.
-
Избегайте жестко заданных путей: Никогда не используйте жестко заданные пути, такие как
$(MSBuildThisFileDirectory)vcpkg_installed\x64-windows\include\MYLIBRARY\, так как они не работают с различными конфигурациями сборки.
Наиболее надежное решение сочетает правильную настройку оверлейного порта с гибким управлением свойствами MSBuild через файлы Directory.build.props. Этот подход обеспечивает правильную интеграцию ваших пользовательских каталогов включений при сохранении совместимости с автоматическим управлением каталогами включений vcpkg.
Источники
- vcpkg в проектах MSBuild | Microsoft Learn
- Оверлейные порты | Microsoft Learn
- Как добавить каталог включений для импортируемой библиотеки с более высоким приоритетом, чем каталоги включений vcpkg · Проблема #8071 · microsoft/vcpkg
- Существует ли способ для CMake (или Visual Studio) игнорировать системную интеграцию vcpkg? · microsoft/vcpkg
- Оверлейные порты · MicrosoftDocs/vcpkg-docs
- Структура каталога установки | Microsoft Learn