Modernizing Dependency and Package Management in C++ (Native) Projects with Visual Studio 2022 and NuGet

D@rio
6 min readJun 19, 2024

--

Link para o artigo em Português

With the end of support for Visual Studio 2015 on October 14, 2025, many native C++ projects using this version will need to migrate to Visual Studio 2022. This transition will bring several significant changes that may impact projects, such as:

  • Changing the C++ standard from version 11 to version 14
  • Updating the build toolset from version v140 to v143
  • Migrating from SDK 8.1 to SDK 10.0 or 10.x
  • Other compilation restrictions

These changes may require adjustments in the code and project configurations to ensure compatibility and performance.

Unified Redistributables Package

To advance the entire Visual Studio platform, Microsoft, since the 2015 version, has unified the Redistributables packages into a single package. This single package maintains the v140 toolset version as a dependency. This means that by installing the new Redistributable, all dependencies for the 2015, 2017, 2019, and 2022 versions will be available. Even if projects are compiled with the v143 toolset, they will still depend on the VC_Runtime v140. This new Redistributable is compatible with all toolsets: v140, v141, v142, and v143.

https://aka.ms/vs/17/release/vc_redist.x64.exe

For more information, refer to the official documentation.

Organizing Native Project Dependencies

In addition to the mentioned changes, it’s crucial to take the opportunity to organize the native dependencies of the project. Many of these dependencies may be scattered across various local and remote folders, environment variables, or macros. Moreover, many source codes that could be in libraries (libs/dlls) might be directly integrated into the project. Migrating without prior organization can increase the overall risk of the application, as well as the timeline and complexity of the process.

Leveraging NuGet for Native Libraries in C++

To address these challenges, it is advisable to divide part of the code into libraries and manage the dependencies more appropriately for new projects. In this context, packaging native libraries with NuGet stands out as an efficient solution.

What is NuGet?

NuGet is an essential tool for package management in the .NET platform, created to simplify the process of adding, removing, and updating libraries and tools in development projects. Developed by Microsoft, NuGet integrates seamlessly with Visual Studio, offering an intuitive interface for developers of all experience levels.

Key Features

  • Ease of Integration: NuGet is integrated with Visual Studio, making the installation and updating of packages extremely simple and intuitive. Through the NuGet Package Manager, developers can search, install, and update packages directly from the IDE.
  • Dependency Management: One of NuGet’s greatest advantages is the ability to automatically manage package dependencies. When a package is installed, NuGet ensures that all necessary dependencies are also installed and correctly configured.
  • Public and Private Repositories: NuGet allows the creation of public repositories, like the NuGet Gallery, where thousands of packages are available to the community. Additionally, companies and developers can set up private repositories to distribute packages internally.
  • Multi-Platform Support: Although focused on the .NET ecosystem, NuGet supports multi-platform packages, allowing development for .NET Core, .NET Framework, Xamarin, among others.

How It Works

When starting a new project or adding new features, developers can use NuGet to search for packages that meet their needs. This can be done through the Visual Studio graphical interface or via the command line using the nuget command or the .NET CLI. Once installed, NuGet manages the packages and their versions, keeping the project up-to-date and functioning correctly.

Benefits of Using NuGet

  • Efficiency: Automates the installation and updating of libraries, saving time and reducing errors.
  • Collaboration: Facilitates code sharing between different projects and teams.
  • Simplified Maintenance: With NuGet, the maintenance of libraries and tools is centralized, simplifying the update and bug-fix processes.

NuGet for Native Libraries in C++

Besides being widely used for package management in the .NET platform, NuGet also offers robust support for native C++ libraries. This extends its reach and utility, allowing C++ developers to enjoy the same dependency management and package distribution conveniences that .NET developers have.

Support for Native Libraries

NuGet supports packages containing native C++ libraries, facilitating the integration of C++ code into projects that use other languages supported by NuGet, like C#. Native packages can include .h (header files), .lib (libraries), and .dll (dynamic link libraries), as well as other necessary assets.

Key Features for C++

  • Dependency Management: Just like in .NET applications, NuGet automatically manages dependencies for C++ packages, ensuring that all required libraries are downloaded and configured correctly.
  • Simplified Project Configuration: Developers can easily add native NuGet packages to their C++ projects in Visual Studio, simplifying the process of configuring include paths and libraries, as well as setting build properties.
  • Integration with CMake: For projects using CMake, NuGet facilitates the inclusion of packages and the configuration of the build environment, integrating NuGet packages directly into CMake scripts.
  • Multi-Platform Packages: NuGet allows the creation and distribution of packages that work across multiple platforms, such as Windows, Linux, and macOS. This is particularly useful for developers who need to support various platforms with their C++ libraries.

How It Works for C++

To use NuGet with C++ libraries, developers can create packages containing header files and compiled libraries. These packages are then published to a NuGet repository, from where they can be installed in other projects.

The installation and update process is simple:

  1. Search and Installation: Using the NuGet Package Manager in Visual Studio, developers can search for and install native C++ library packages.
  2. Automatic Configuration: NuGet automatically configures the project, adjusting include and library paths as necessary.
  3. Updates: Keeping packages updated is easy, with NuGet managing versions and dependencies to ensure the project always uses the latest and most stable libraries.

Benefits of Using NuGet for C++

  • Development Efficiency: Automates the inclusion of libraries and their dependencies, saving time and effort for developers.
  • Ease of Maintenance: Simplifies the process of updating libraries, ensuring projects use the latest versions and fixes.
  • Simplified Distribution: Facilitates sharing C++ libraries between different projects and teams, promoting code reuse.

Packaging a Native Project (DLL or Lib) in NuGet

Packaging a native project (DLL or Lib) in NuGet is a process that simplifies the distribution and management of native C++ libraries. Here is a step-by-step guide to creating a NuGet package for a native project:

Project Preparation

  1. Structure Your Project: Ensure your project is well-organized. Separate the header files (.h), libraries (.lib), and DLLs (.dll) into appropriate directories.
  2. Compile Your Library: Compile your DLL or Lib using Visual Studio, ensuring all necessary files are available.

Creating the .nuspec File

  1. Create a .nuspec File: This file defines the metadata of your NuGet package, such as the package ID, version, description, and dependencies.

Example .nuspec file:

<?xml version="1.0"?>
<package >
<metadata>
<id>YourPackageName</id>
<version>1.0.0</version>
<authors>YourName</authors>
<owners>YourName</owners>
<description>Your package description</description>
<dependencies>
<!-- Add your package dependencies here -->
</dependencies>
</metadata>
<files>
<file src="path\to\your\files\*.h" target="build\native\include" />
<file src="path\to\your\files\*.lib" target="build\native\lib" />
<file src="path\to\your\files\*.dll" target="build\native\bin" />
</files>
</package>

Creating the .targets File

  1. Create a .targets File: This file specifies additional configurations that should be applied to the project consuming the package.

Example .targets file:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<IncludePath Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
$(MSBuildThisFileDirectory)..\include;
</IncludePath>
<LibraryPath Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
$(MSBuildThisFileDirectory)..\lib;
</LibraryPath>
</ItemGroup>
<PropertyGroup>
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
%(AdditionalDependencies);YourLibraryName.lib;
</AdditionalDependencies>
</PropertyGroup>
</Project>

Building the NuGet Package

  1. Use the NuGet CLI: Open the terminal or command prompt and navigate to the directory where the .nuspec file is located.
  2. Command to Create the Package:
nuget pack YourPackageName.nuspec
  1. This will generate a .nupkg file containing your NuGet package.

Publishing the Package

  1. Publish to NuGet.org: If you want to share your package publicly, you can publish it to NuGet.org.

Command to publish:

nuget push YourPackageName.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey YOUR_API_KEY

2. Private Repositories: If you prefer to keep the package internal, you can configure it in a private NuGet repository (local folder, network), artifact manager like Artifactory or Nexus, or a package server like Azure DevOps Artifacts or GitHub Packages.

Conclusion

Packaging a native project in NuGet not only facilitates dependency management but also promotes code reuse and simplifies the distribution of libraries. By following these steps, you can efficiently create and publish NuGet packages for native libraries, improving the organization and maintenance of your projects.

I have created a C++ project example demonstrating a static library (static lib) using a dynamic library (dynamic lib) as a dependency, installed via NuGet. Additionally, I included a script to package our Lib project in NuGet to simplify the process. You can check the code and details in the repository: MyNuGetNativeLib.

#CPlusPlus #CPlusPlusDevelopment #VisualStudio2022 #NuGet #DependencyManagement #NativeLibraries #CppMigration #SoftwareDevelopment #CodeOptimization #TechUpgrade #MicrosoftVisualStudio #NativeCPlusPlus #ProgrammingTools #DevTools #CodePackaging #DevCommunity #CppLibraries #SoftwareEngineering #TechMigration #ProjectManagement #DevTips

--

--