NeuroAgent

Complete Guide: Adding Include Directories for vcpkg Ports in Visual Studio

Complete guide to adding extra include directories for vcpkg ports in Visual Studio. Learn multiple approaches including overlay port configuration, vcxproj modifications, and MSBuild properties to resolve include path conflicts.

How to add an extra include directory for a vcpkg port in Visual Studio (vcxproj) files?

I’m working with a vcpkg overlay port that requires its own include/MYLIBRARY folder to be added to the C++ include system paths. While I can easily achieve this in CMake using target_include_directories() in the port’s share/MYLIBRARY/MYLIBRARY-config.cmake file, I’m struggling to find a way to add this folder to the include directories when using .vcxproj files with Visual Studio 2022/MSBuild.

What I’ve tried so far:

  1. Patching files in the port: Fixing individual #include statements, but this isn’t feasible due to the large number of files and version updates.
  2. Adding the overlay port’s include files to consuming projects’ .vcxproj or .props files via IncludePath: This causes conflicts where functions are defined in both vcpkg_installed header files and overlay port header files.
  3. Adding $(VcpkgInstalledDir)include\MYLIBRARY\ to IncludePath: The VcpkgInstalledDir property evaluates to nothing.
  4. Adding $(MSBuildThisFileDirectory)vcpkg_installed\x64-windows\include\MYLIBRARY\ to IncludePath: This isn’t viable as it doesn’t work for other build triplets.

I’m looking for either an overlay port-based solution or a fix on the consuming project side.

NeuroAgent

To add an extra include directory for a vcpkg port in Visual Studio vcxproj files, you need to properly configure either the overlay port itself or modify the consuming project’s build configuration. The key is understanding how vcpkg’s MSBuild integration handles include directories and where your custom path should be positioned in the include search order.


Contents


Understanding vcpkg Include Directory Handling

vcpkg’s MSBuild integration automatically adds installed packages to Visual Studio project properties, including Include Directories, Link Directories, and Link Libraries source. When you use overlay ports, vcpkg attempts to load that directory as a port first, and if successful, treats it as a port with the name derived from the CONTROL or vcpkg.json file source.

The challenge you’re facing is that vcpkg’s include directories may have different priority levels than your custom overlay port include directories. According to one issue report, the include search path of vcpkg is already added before CUSTOM_INCLUDE_DIR which can cause conflicts source.


Solution 1: Configure Overlay Port Portfile.cmake

For your overlay port, you can modify the portfile.cmake to ensure the include directory is properly installed and recognized. Here’s how to structure it:

cmake
include(vcpkg_common_functions)

# Download and extract the library
vcpkg_from_github(
    OUT_SOURCE_PATH SOURCE_PATH
    REPO your-repo/your-library
    REF specific-version
    SHA512 your-hash
)

# Configure and build
vcpkg_configure_cmake(
    SOURCE_PATH ${SOURCE_PATH}
    PREFER_NINJA
)

# Install the library
vcpkg_install_cmake()

# Ensure include directory is properly installed
file(INSTALL ${SOURCE_PATH}/include/MYLIBRARY DESTINATION ${CURRENT_PACKAGES_DIR}/include)

# Install copyright
file(INSTALL ${SOURCE_PATH}/COPYING DESTINATION ${CURRENT_PACKAGES_DIR}/share/MYLIBRARY RENAME copyright)

The key is ensuring that your include/MYLIBRARY folder is properly installed to ${CURRENT_PACKAGES_DIR}/include during the port build process. This will make it available through vcpkg’s standard include directory structure.


Solution 2: Modify Consuming Project vcxproj

You can modify your Visual Studio project files to include the custom directory. The recommended approach is to use vcpkg’s integration targets:

xml
<!-- Add this to your .vcxproj file -->
<ImportGroup Label="ExtensionSettings">
  <Import Project="$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.targets" />
</ImportGroup>

However, to add your custom include directory with proper priority, you need to modify the project’s Additional Include Directories property:

xml
<ItemDefinitionGroup>
  <ClCompile>
    <AdditionalIncludeDirectories>$(VcpkgInstalledDir)include\MYLIBRARY;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
  </ClCompile>
</ItemDefinitionGroup>

The issue with $(VcpkgInstalledDir) evaluating to nothing can be resolved by using the full path pattern:

xml
<ItemDefinitionGroup>
  <ClCompile>
    <AdditionalIncludeDirectories>$(VcpkgRoot)installed\$(VcpkgTriplet)\include\MYLIBRARY;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
  </ClCompile>
</ItemDefinitionGroup>

Solution 3: Use Directory.build.props

For a more elegant solution that works across different build triplets, create a Directory.build.props file in your solution root:

xml
<Project>
  <PropertyGroup>
    <VcpkgRoot Condition="'$(VcpkgRoot)' == ''">$(USERPROFILE)\vcpkg</VcpkgRoot>
  </PropertyGroup>
  
  <ItemDefinitionGroup>
    <ClCompile>
      <AdditionalIncludeDirectories>
        $(VcpkgRoot)installed\$(VcpkgTriplet)\include\MYLIBRARY;
        %(AdditionalIncludeDirectories)
      </AdditionalIncludeDirectories>
    </ClCompile>
  </ItemDefinitionGroup>
</Project>

This approach automatically applies to all projects in your solution and adapts to different build triplets (x64-windows, x86-windows, arm64-windows, etc.) source.


Solution 4: Custom MSBuild Properties

You can also create custom MSBuild properties to handle the include directories more flexibly:

xml
<!-- In your Directory.build.props -->
<Project>
  <PropertyGroup>
    <CustomIncludeDir>$(VcpkgRoot)installed\$(VcpkgTriplet)\include\MYLIBRARY</CustomIncludeDir>
  </PropertyGroup>
  
  <ItemDefinitionGroup>
    <ClCompile>
      <AdditionalIncludeDirectories>
        $(CustomIncludeDir);
        %(AdditionalIncludeDirectories)
      </AdditionalIncludeDirectories>
    </ClCompile>
  </ItemDefinitionGroup>
</Project>

This makes it easier to manage and modify the include directory path across your solution.


Handling Include Priority Conflicts

When you have conflicts between vcpkg-installed header files and your overlay port header files, you need to control the include order. The key is to ensure your custom include directory has the appropriate priority:

  1. Higher priority than vcpkg: Add your include directory before vcpkg’s include directories
  2. Lower priority than vcpkg: Add your include directory after vcpkg’s include directories

To achieve higher priority, modify your AdditionalIncludeDirectories like this:

xml
<ItemDefinitionGroup>
  <ClCompile>
    <AdditionalIncludeDirectories>
      $(VcpkgRoot)installed\$(VcpkgTriplet)\include\MYLIBRARY;
      $(VcpkgRoot)installed\$(VcpkgTriplet)\include;
      %(AdditionalIncludeDirectories)
    </AdditionalIncludeDirectories>
  </ClCompile>
</ItemDefinitionGroup>

According to the research, vcpkg’s include directories are added automatically, so you need to position your custom directory appropriately in the sequence source.


Conclusion and Recommendations

Based on the research and analysis, here are the recommended approaches:

  1. Best Solution: Use Directory.build.props to define your custom include directory. This approach is clean, automatically works across different build triplets, and can be easily managed.

  2. Overlay Port Enhancement: Ensure your overlay port properly installs the include directory during the build process. This makes your port more self-contained and easier to use.

  3. Priority Management: Be deliberate about the order of include directories to avoid conflicts between vcpkg-installed headers and your custom headers.

  4. Avoid Hardcoded Paths: Never use hardcoded paths like $(MSBuildThisFileDirectory)vcpkg_installed\x64-windows\include\MYLIBRARY\ as they don’t work across different build configurations.

The most robust solution combines proper overlay port configuration with flexible MSBuild property management through Directory.build.props files. This approach ensures your custom include directories are properly integrated while maintaining compatibility with vcpkg’s automatic include directory management.

Sources

  1. vcpkg in MSBuild projects | Microsoft Learn
  2. Overlay ports | Microsoft Learn
  3. How can I add include directory for an imported library with higher priority than vcpkg include directories · Issue #8071 · microsoft/vcpkg
  4. Is there a way for CMake (or Visual Studio) to ignore the system-wide vcpkg integration? · microsoft/vcpkg
  5. Overlay ports · MicrosoftDocs/vcpkg-docs
  6. Installation directory layout | Microsoft Learn