Modernizando a Gestão de Dependencias e Pacotes em Projetos C++(nativo) com Visual Studio 2022 e NuGet

D@rio
7 min readJun 18, 2024

--

Link to the article in English

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

Com o fim do suporte ao Visual Studio 2015 em 14 de outubro de 2025, muitos projetos nativos em C++ que utilizam essa versão precisarão migrar para o Visual Studio 2022. Essa transição trará algumas mudanças significativas que podem impactar os projetos, tais como:

  • Mudança do padrão do C++ da versão 11 para a versão 14
  • Atualização do toolset de compilação da versão v140 para v143
  • Migração do SDK 8.1 para o SDK 10.0 ou 10.x
  • Outras restrições de compilação

Essas alterações podem exigir ajustes no código e na configuração dos projetos para garantir compatibilidade e desempenho.

Visando a evolução de toda a plataforma do Visual Studio, a Microsoft, desde a versão de 2015, unificou os pacotes de Redistributables em um único pacote. Este pacote único mantém a versão do toolset v140 como dependência. Isso significa que, ao instalar o novo Redistributable, todas as dependências das versões 2015, 2017, 2019 e 2022 já estarão disponíveis. Mesmo que os projetos sejam compilados com o toolset v143, eles ainda dependerão do VC_Runtime v140. Este novo Redistributable é compatível com todos os toolsets: v140, v141, v142 e v143.

Para mais informações, consulte a documentação oficial.

Além das mudanças mencionadas, é crucial aproveitar a oportunidade para organizar as dependências nativas do projeto. Muitas dessas dependências podem estar (des)organizadas em diversas pastas, sejam locais, remotas, variáveis de ambiente ou macros. Além disso, muitos códigos-fonte que poderiam estar em bibliotecas (libs/dlls) podem estar diretamente integrados ao projeto. Realizar a migração sem uma organização prévia pode aumentar o risco geral da aplicação, assim como o prazo e a complexidade do processo.

Para abordar esses desafios, é recomendável dividir parte do código em bibliotecas e gerenciar as dependências de forma mais adequada para os novos projetos. Nesse contexto, o empacotamento de bibliotecas nativas com o NuGet se destaca como uma solução eficiente.

NuGet é uma ferramenta essencial para o gerenciamento de pacotes na plataforma .NET, criada para simplificar o processo de adicionar, remover e atualizar bibliotecas e ferramentas em projetos de desenvolvimento. Desenvolvido pela Microsoft, o NuGet se integra perfeitamente ao Visual Studio, oferecendo uma interface intuitiva para desenvolvedores de todos os níveis de experiência.

O que é NuGet?

Na sua essência, o NuGet é um gerenciador de pacotes para a plataforma .NET. Ele permite que desenvolvedores compartilhem código em formato de pacotes, o que facilita a reutilização e distribuição de bibliotecas e ferramentas. Um “pacote” NuGet é um arquivo .nupkg que contém arquivos de código compilado (DLLs), outros conteúdos necessários (como scripts e arquivos de configuração) e informações de manifesto que descrevem o pacote e suas dependências.

Principais Funcionalidades

  1. Facilidade de Integração: NuGet é integrado ao Visual Studio, o que torna a instalação e atualização de pacotes extremamente simples e intuitiva. Através do Gerenciador de Pacotes NuGet, desenvolvedores podem buscar, instalar e atualizar pacotes diretamente do IDE.
  2. Gerenciamento de Dependências: Uma das maiores vantagens do NuGet é a capacidade de gerenciar automaticamente as dependências dos pacotes. Quando um pacote é instalado, o NuGet garante que todas as dependências necessárias sejam também instaladas e configuradas corretamente.
  3. Repositórios Públicos e Privados: O NuGet permite a criação de repositórios públicos, como o NuGet Gallery, onde milhares de pacotes são disponibilizados para a comunidade. Além disso, empresas e desenvolvedores podem configurar repositórios privados para distribuir pacotes internamente.
  4. Suporte a Várias Plataformas: Embora seja focado no ecossistema .NET, o NuGet suporta pacotes multiplataforma, permitindo o desenvolvimento para .NET Core, .NET Framework, Xamarin, entre outros.

Como Funciona?

Ao iniciar um novo projeto ou ao adicionar novas funcionalidades, desenvolvedores podem usar o NuGet para buscar pacotes que atendam suas necessidades. Isso pode ser feito através da interface gráfica do Visual Studio ou via linha de comando, utilizando o comando nuget ou o .NET CLI. Uma vez instalado, o NuGet gerencia os pacotes e suas versões, mantendo o projeto atualizado e funcionando corretamente.

Benefícios do Uso do NuGet

  • Eficiência: Automatiza a instalação e atualização de bibliotecas, economizando tempo e reduzindo erros.
  • Colaboração: Facilita o compartilhamento de código entre diferentes projetos e equipes.
  • Manutenção Simplificada: Com o NuGet, a manutenção de bibliotecas e ferramentas é centralizada, o que simplifica o processo de atualização e correção de bugs.

NuGet é uma ferramenta poderosa e indispensável para desenvolvedores .NET, proporcionando um gerenciamento de pacotes eficiente e simplificado. Com sua ampla adoção e suporte, o NuGet continua a ser uma peça fundamental no desenvolvimento de software moderno, promovendo a reutilização de código e a colaboração entre desenvolvedores. Seja você um desenvolvedor iniciante ou experiente, o NuGet oferece os recursos necessários para otimizar seu fluxo de trabalho e garantir a qualidade e consistência dos seus projetos.

NuGet para Bibliotecas Nativas em C++

Além de ser amplamente utilizado para o gerenciamento de pacotes na plataforma .NET, o NuGet também oferece suporte robusto para bibliotecas nativas em C++. Isso amplia seu alcance e utilidade, permitindo que desenvolvedores C++ aproveitem as mesmas facilidades de gerenciamento de dependências e distribuição de pacotes que os desenvolvedores .NET têm desfrutado.

Suporte a Bibliotecas Nativas

NuGet suporta pacotes que contêm bibliotecas nativas em C++, facilitando a integração de código C++ em projetos que usam outras linguagens suportadas pelo NuGet, como C#. Pacotes nativos podem incluir arquivos .h (headers), .lib (libraries), e .dll (dynamic link libraries), bem como outros ativos necessários.

Principais Funcionalidades para C++

  1. Gerenciamento de Dependências: Assim como nas aplicações .NET, o NuGet gerencia automaticamente as dependências para pacotes C++, garantindo que todas as bibliotecas necessárias sejam baixadas e configuradas corretamente.
  2. Configuração de Projeto Simplificada: Desenvolvedores podem facilmente adicionar pacotes NuGet nativos aos seus projetos C++ no Visual Studio, simplificando o processo de configuração de caminhos de inclusão e bibliotecas, bem como a configuração de propriedades de build.
  3. Integração com CMake: Para projetos que utilizam CMake, o NuGet facilita a inclusão de pacotes e a configuração do ambiente de build, integrando pacotes NuGet diretamente nos scripts CMake.
  4. Pacotes Multi-Platforma: NuGet permite a criação e distribuição de pacotes que funcionam em múltiplas plataformas, como Windows, Linux, e macOS. Isso é particularmente útil para desenvolvedores que precisam suportar diversas plataformas com suas bibliotecas C++.

Como Funciona para C++?

Para usar o NuGet com bibliotecas C++, os desenvolvedores podem criar pacotes que contêm arquivos de cabeçalho e bibliotecas compiladas. Estes pacotes são então publicados em um repositório NuGet, de onde podem ser instalados em outros projetos.

O processo de instalação e atualização é simples:

  1. Busca e Instalação: Usando o Gerenciador de Pacotes NuGet no Visual Studio, desenvolvedores podem buscar e instalar pacotes de bibliotecas nativas em C++.
  2. Configuração Automática: O NuGet configura automaticamente o projeto, ajustando caminhos de inclusão e bibliotecas conforme necessário.
  3. Atualizações: Manter pacotes atualizados é fácil, com o NuGet gerenciando as versões e dependências para garantir que o projeto sempre use as bibliotecas mais recentes e estáveis.

Benefícios do Uso do NuGet para C++

  • Eficiência no Desenvolvimento: Automatiza a inclusão de bibliotecas e suas dependências, economizando tempo e esforço dos desenvolvedores.
  • Facilidade de Manutenção: Simplifica o processo de atualização de bibliotecas, assegurando que projetos utilizem as versões mais recentes e corrigidas.
  • Distribuição Simplificada: Facilita o compartilhamento de bibliotecas C++ entre diferentes projetos e equipes, promovendo a reutilização de código.

NuGet não é apenas uma ferramenta poderosa para o ecossistema .NET, mas também uma solução eficiente para o gerenciamento de bibliotecas nativas em C++. Ele traz as mesmas vantagens de simplicidade, eficiência e manutenção centralizada para o desenvolvimento em C++, permitindo que desenvolvedores se concentrem mais em escrever código e menos em gerenciar dependências. Com seu suporte robusto e integração fácil, o NuGet se posiciona como uma ferramenta indispensável para qualquer desenvolvedor C++ que busca otimizar seu fluxo de trabalho.

Como empacotar um projeto de (Dll ou Lib) nativo em NuGet

Empacotar um projeto nativo (Dll ou Lib) em NuGet é um processo que facilita a distribuição e o gerenciamento de bibliotecas nativas em C++. Aqui está um guia passo a passo para criar um pacote NuGet para um projeto nativo:

Preparação do Projeto:

  • Estruture seu projeto: Certifique-se de que seu projeto esteja bem organizado. Separe os arquivos de cabeçalho (.h), bibliotecas (.lib), e DLLs (.dll) em diretórios apropriados.
  • Compile sua biblioteca: Compile sua DLL ou Lib usando o Visual Studio, garantindo que todos os arquivos necessários estejam disponíveis.

Criação do Arquivo .nuspec:

  • Crie um arquivo .nuspec: Este arquivo define as metainformações do seu pacote NuGet, como o ID do pacote, a versão, a descrição, e as dependências.
  • Exemplo de arquivo .nuspec:
<?xml version="1.0"?>
<package >
<metadata>
<id>NomeDoSeuPacote</id>
<version>1.0.0</version>
<authors>SeuNome</authors>
<owners>SeuNome</owners>
<description>Descrição do seu pacote</description>
<dependencies>
<!-- Adicione as dependências do seu pacote aqui -->
</dependencies>
</metadata>
<files>
<file src="caminho\para\seus\arquivos\*.h" target="build\native\include" />
<file src="caminho\para\seus\arquivos\*.lib" target="build\native\lib" />
<file src="caminho\para\seus\arquivos\*.dll" target="build\native\bin" />
</files>
</package>

Criação do Arquivo .targets:

  • Crie um arquivo .targets: Este arquivo especifica configurações adicionais que devem ser aplicadas ao projeto que consome o pacote.
  • Exemplo de arquivo .targets:
<?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);NomeDaSuaBiblioteca.lib;
</AdditionalDependencies>
</PropertyGroup>
</Project>

Compilação do Pacote NuGet:

  • Utilize a CLI do NuGet: Abra o terminal ou prompt de comando e navegue até o diretório onde está localizado o arquivo .nuspec.
  • Comando para criar o pacote:
nuget pack NomeDoSeuPacote.nuspec
  • Isso gerará um arquivo .nupkg que contém seu pacote NuGet.

Publicação do Pacote:

  • Publicar no NuGet.org: Se você deseja compartilhar seu pacote publicamente, você pode publicá-lo no NuGet.org.
  • Comando para publicar:
nuget push NomeDoSeuPacote.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey SUA_CHAVE_API
  • Repositórios Privados: Se preferir manter o pacote internamente, você pode configurá-lo em um repositório privado NuGet (Pasta local, rede), gerenciador de artefatos como o Artifactory ou Nexus, em um servidor de pacotes como o Azure DevOps Artifacts ou o GitHub Packages.

Conclusão

Empacotar um projeto nativo em NuGet não só facilita a gestão de dependências, como também promove a reutilização de código e simplifica a distribuição de bibliotecas. Seguindo esses passos, você poderá criar e publicar pacotes NuGet de bibliotecas nativas de forma eficiente, melhorando a organização e a manutenção dos seus projetos.

Criei um exemplo de projeto em C++ que demonstra uma biblioteca estática (static lib) utilizando uma biblioteca dinâmica (dynamic lib) como dependência, instalada via NuGet. Além disso, inclui um script para empacotar o nosso projeto de Lib em NuGet para simplificar o processo. Você pode conferir o código e os detalhes no repositório: MyNuGetNativeLib.

--

--