<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tools on kenji.blog</title><link>http://kenji.blog/pt/categories/tools/</link><description>Recent content in Tools on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 09:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/pt/categories/tools/index.xml" rel="self" type="application/rss+xml"/><item><title>Guia de Configuração de Ambiente de Build C++ Multiplataforma usando CMake</title><link>http://kenji.blog/pt/p/cmake-cross-platform-build-environment-guide/</link><pubDate>Sat, 12 Sep 2026 09:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/cmake-cross-platform-build-environment-guide/</guid><description>&lt;img src="http://kenji.blog/p/cmake-cross-platform-build-environment-guide/img/eyecatch.jpg" alt="Featured image of post Guia de Configuração de Ambiente de Build C++ Multiplataforma usando CMake" />&lt;p>No desenvolvimento de software em C++, a escolha e a configuração de um &amp;ldquo;sistema de build&amp;rdquo; têm sido um desafio para muitos desenvolvedores há anos. Como o C++ não possui um gerenciador de pacotes padrão oficial ou um sistema de build embutido, era necessário utilizar diferentes compiladores e ferramentas de build (MSVC, GCC, Clang, Make, Ninja, etc.) para cada plataforma (Windows, Linux, macOS).&lt;/p>
&lt;p>No entanto, atualmente, o &lt;strong>CMake&lt;/strong> se consolidou como o padrão da indústria (de facto). Ao utilizar o CMake corretamente, é possível construir de forma elegante um ambiente de build multiplataforma a partir de um único &lt;code>CMakeLists.txt&lt;/code>.&lt;/p>
&lt;p>Neste artigo, explicaremos de forma minuciosa e detalhada as etapas de configuração de um ambiente de build C++ multiplataforma utilizando a versão mais recente do CMake (CMake moderno), desde os conceitos básicos até as técnicas mais avançadas.&lt;/p>
&lt;h2 id="1-o-que-é-o-cmake-o-conceito-de-sistema-de-meta-build">1. O que é o CMake? (O conceito de sistema de meta-build)
&lt;/h2>&lt;p>O CMake não é uma ferramenta que compila o código-fonte diretamente. O CMake é um &amp;ldquo;sistema gerador de sistema de build&amp;rdquo;, ou seja, um &lt;strong>sistema de meta-build (Meta-Build System)&lt;/strong>.&lt;/p>
&lt;p>O principal papel do CMake é ler um arquivo de configuração abstrato e independente de plataforma ou compilador (&lt;code>CMakeLists.txt&lt;/code>) e gerar automaticamente os scripts de build nativos ideais para cada ambiente (ex.: &lt;code>Makefile&lt;/code> no Linux, arquivos de projeto &lt;code>.sln&lt;/code> do Visual Studio no Windows, ou o rápido &lt;code>build.ninja&lt;/code>).&lt;/p>
&lt;p>O diagrama abaixo ilustra o processo de geração do CMake.&lt;/p>
&lt;div class="mermaid">graph TD
A["CMakeLists.txt (Definição de build abstrata)"] --> B["CMake (Configure &amp; Generate)"]
B --> C["Unix Makefiles"]
B --> D["Ninja Build Files"]
B --> E["Visual Studio Solutions"]
B --> F["Xcode Projects"]
C --> G["Ferramenta de Build Nativa (make, ninja, MSBuild, xcodebuild)"]
D --> G
E --> G
F --> G
G --> H["Executável / Biblioteca Compartilhada / Biblioteca Estática"]&lt;/div>
&lt;p>Dessa forma, ao colocar o CMake no meio, os desenvolvedores podem gerenciar projetos C++ sem se preocupar com as pequenas diferenças de comandos entre cada sistema operacional.&lt;/p>
&lt;h2 id="2-o-básico-do-cmake-moderno-das-variáveis-aos-alvos-targets">2. O básico do CMake Moderno: Das variáveis aos alvos (Targets)
&lt;/h2>&lt;p>A notação a partir do CMake 3.0 é chamada de &amp;ldquo;CMake Moderno&amp;rdquo;, e sua filosofia de design é fundamentalmente diferente das versões anteriores (CMake Legado). No CMake Legado, a abordagem principal era reescrever variáveis globais por diretório (ex.: usando &lt;code>include_directories()&lt;/code> ou &lt;code>link_libraries()&lt;/code>), mas isso frequentemente causava o grave efeito colateral de configurações se propagando involuntariamente para outros módulos.&lt;/p>
&lt;p>No CMake Moderno, tudo é tratado como &lt;strong>Alvo (Target)&lt;/strong> e &lt;strong>Propriedade (Property)&lt;/strong>. É semelhante à relação entre classes e variáveis de membro na programação orientada a objetos.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Alvo (Target)&lt;/strong>: Um arquivo executável (Executable) ou uma biblioteca (Library).&lt;/li>
&lt;li>&lt;strong>Propriedade (Property)&lt;/strong>: Os arquivos de código-fonte, diretórios de inclusão (include), opções de compilação, outras bibliotecas a serem linkadas e tudo o mais necessário para construir esse alvo.&lt;/li>
&lt;/ul>
&lt;p>Ao encapsular (isolar) a configuração apenas em alvos específicos, é possível ter definições de build seguras que não quebram mesmo em projetos de grande escala.&lt;/p>
&lt;h3 id="um-cmakeliststxt-mínimo">Um &lt;code>CMakeLists.txt&lt;/code> mínimo
&lt;/h3>&lt;p>Primeiramente, vejamos um &lt;code>CMakeLists.txt&lt;/code> na sua forma mais básica.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Especifica a versão mínima exigida do CMake
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Especifica o nome do projeto e a linguagem a ser utilizada
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">VERSION&lt;/span> &lt;span class="s">1.0.0&lt;/span> &lt;span class="s">LANGUAGES&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Exige o padrão C++ (C++20)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_EXTENSIONS&lt;/span> &lt;span class="s">OFF&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c"># Desabilita extensões específicas do compilador
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Definição do alvo executável
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Com apenas estas poucas linhas, completa-se a configuração de build para um arquivo executável portável que exige C++20 e tem as extensões do compilador desabilitadas.&lt;/p>
&lt;h2 id="3-dependências-e-escopo-public--private--interface">3. Dependências e Escopo: PUBLIC / PRIVATE / INTERFACE
&lt;/h2>&lt;p>O conceito mais importante e complexo para dominar o CMake Moderno são os três modificadores de acesso (escopos) &lt;strong>&lt;code>PUBLIC&lt;/code>, &lt;code>PRIVATE&lt;/code>, &lt;code>INTERFACE&lt;/code>&lt;/strong>, usados em comandos como &lt;code>target_include_directories&lt;/code> ou &lt;code>target_link_libraries&lt;/code>.&lt;/p>
&lt;p>Eles servem para controlar se as propriedades de um alvo (caminhos de inclusão ou bibliotecas dependentes) são &amp;ldquo;necessárias para a própria construção?&amp;rdquo; e se devem ser &amp;ldquo;propagadas para outros alvos que dependem dele?&amp;rdquo;.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;code>PRIVATE&lt;/code>&lt;/strong>: Necessário apenas para o build do próprio alvo. &lt;strong>Não&lt;/strong> se propaga para os alvos dependentes.&lt;/li>
&lt;li>&lt;strong>&lt;code>INTERFACE&lt;/code>&lt;/strong>: Não é necessário para o build do próprio alvo, mas se propaga para o build dos alvos dependentes (usado, por exemplo, em bibliotecas do tipo header-only).&lt;/li>
&lt;li>&lt;strong>&lt;code>PUBLIC&lt;/code>&lt;/strong>: Necessário para o build do próprio alvo e &lt;strong>também&lt;/strong> se propaga para os alvos dependentes (&lt;code>PRIVATE&lt;/code> + &lt;code>INTERFACE&lt;/code>).&lt;/li>
&lt;/ol>
&lt;p>Vejamos a propagação de dependências (Usage Requirements) ilustrada no diagrama abaixo.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Bibliotecas"
MathLib["MathLib (Biblioteca Estática)"]
NetworkLib["NetworkLib (Biblioteca Compartilhada)"]
HeaderLib["HeaderLib (Header Only)"]
end
subgraph "Aplicação"
App["Aplicação Principal"]
end
App -- "target_link_libraries(App PRIVATE MathLib)" --> MathLib
App -- "target_link_libraries(App PUBLIC NetworkLib)" --> NetworkLib
NetworkLib -- "target_link_libraries(NetworkLib INTERFACE HeaderLib)" --> HeaderLib
note1["App depende da implementação de MathLib, mas não a expõe externamente"]
note2["NetworkLib expõe a interface de HeaderLib"]&lt;/div>
&lt;h3 id="exemplo-prático-de-uso-dos-escopos">Exemplo prático de uso dos escopos
&lt;/h3>&lt;p>Suponha que uma biblioteca &lt;code>MyLib&lt;/code> use internamente &lt;code>nlohmann/json&lt;/code> na sua implementação, e o arquivo de cabeçalho público &lt;code>MyLib.hpp&lt;/code> não inclua &lt;code>nlohmann/json&lt;/code>. Neste caso, quem utiliza a &lt;code>MyLib&lt;/code> (a aplicação) não precisa saber da existência da biblioteca JSON.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Definição da biblioteca
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span> &lt;span class="s">src/MyLib.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Especificação dos diretórios de inclusão do próprio projeto
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># O diretório include é necessário para quem usa a MyLib, então é PUBLIC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># O diretório src é usado apenas na implementação da MyLib, então é PRIVATE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_include_directories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PUBLIC&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">INSTALL_INTERFACE:include&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">${&lt;/span>&lt;span class="nv">CMAKE_CURRENT_SOURCE_DIR&lt;/span>&lt;span class="o">}&lt;/span>&lt;span class="s">/src&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># A biblioteca json é usada apenas na implementação interna, então é linkada como PRIVATE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">nlohmann_json::nlohmann_json&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Por outro lado, se dentro de &lt;code>MyLib.hpp&lt;/code> houvesse &lt;code>#include &amp;lt;nlohmann/json.hpp&amp;gt;&lt;/code>, o usuário da &lt;code>MyLib&lt;/code> precisaria saber o caminho dos cabeçalhos do JSON sob pena de erro de compilação; logo, seria necessário linkar como &lt;code>PUBLIC&lt;/code>. Configurar corretamente esses escopos permite reduzir o tempo de build e prevenir o vazamento de dependências desnecessárias.&lt;/p>
&lt;h2 id="4-build-fora-da-fonte-out-of-source-build">4. Build Fora da Fonte (Out-of-source Build)
&lt;/h2>&lt;p>Uma das melhores práticas que deve ser sempre seguida ao usar o CMake é o &lt;strong>Out-of-source Build&lt;/strong> (Build fora da fonte).
Trata-se de uma técnica onde nenhum artefato de build (arquivos objeto ou executáveis) é gerado no diretório onde o código-fonte está localizado (source tree). Em vez disso, o build é realizado em um diretório dedicado separado (geralmente &lt;code>build/&lt;/code>).&lt;/p>
&lt;div class="mermaid">graph TD
Root["Raiz do Projeto (Repositório Git)"]
Root --> Src["src/"]
Root --> Inc["include/"]
Root --> CMake["CMakeLists.txt"]
Root -. "Criar diretório de build" .-> Build["build/ (Fora da fonte)"]
Build --> Obj["CMakeFiles/ (Arquivos objeto, caches)"]
Build --> Bin["Binários (MyApp.exe)"]
Build --> Gen["Makefile gerado / build.ninja"]&lt;/div>
&lt;p>Com essa estrutura, se você quiser redefinir o ambiente de build, basta excluir todo o diretório &lt;code>build&lt;/code>, mantendo a source tree limpa e facilitando o gerenciamento no Git (basta adicionar &lt;code>build/&lt;/code> no &lt;code>.gitignore&lt;/code>).&lt;/p>
&lt;h3 id="etapas-para-execução-do-build">Etapas para execução do build
&lt;/h3>&lt;p>No CMake Moderno, o build pode ser executado através de comandos comuns que não dependem do sistema operacional ou da ferramenta de build.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Configuração e Geração (Cria o diretório de build e o configura)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake -S . -B build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Build real (Compilação e Linkagem)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build build --config Release
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># (Opcional) Usar a flag -j para compilação multithread&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build build --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Aqui, &lt;code>cmake -S . -B build&lt;/code> significa &amp;ldquo;definir o diretório atual (&lt;code>.&lt;/code>) como o diretório fonte (&lt;code>-S&lt;/code>) e &lt;code>build&lt;/code> como o diretório de build (&lt;code>-B&lt;/code>)&amp;rdquo;.&lt;/p>
&lt;h2 id="5-como-introduzir-bibliotecas-de-terceiros">5. Como introduzir bibliotecas de terceiros
&lt;/h2>&lt;p>No desenvolvimento em C++, a introdução de bibliotecas externas (de terceiros) sempre foi um obstáculo. Hoje, porém, existem três abordagens principais que se tornaram o padrão.&lt;/p>
&lt;h3 id="51-find_package-pesquisa-de-bibliotecas-instaladas-no-sistema">5.1. find_package (Pesquisa de bibliotecas instaladas no sistema)
&lt;/h3>&lt;p>O método mais tradicional, onde se localiza e se linka uma biblioteca já instalada no sistema (ex.: OpenSSL ou Zlib).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">find_package&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ZLIB&lt;/span> &lt;span class="s">REQUIRED&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ZLIB_FOUND&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">ZLIB::ZLIB&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="52-fetchcontent-download-a-partir-do-código-fonte-e-integração">5.2. FetchContent (Download a partir do código-fonte e integração)
&lt;/h3>&lt;p>Um módulo introduzido no CMake 3.11 e fortalecido a partir da versão 3.14. Ele baixa o código-fonte diretamente de um repositório Git externo ou URL durante o tempo de build e o compila junto, como parte do projeto. Como as dependências podem ser centralizadas, a reprodutibilidade multiplataforma torna-se extremamente alta.&lt;/p>
&lt;p>Abaixo está um exemplo de como introduzir o GoogleTest usando o FetchContent.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">include&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">FetchContent&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">FetchContent_Declare&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">googletest&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">GIT_REPOSITORY&lt;/span> &lt;span class="s">https://github.com/google/googletest.git&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">GIT_TAG&lt;/span> &lt;span class="s">v1.14.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Torna a biblioteca disponível para o projeto
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">FetchContent_MakeAvailable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">googletest&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Criação do executável de testes e linkagem
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyTests&lt;/span> &lt;span class="s">test/main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyTests&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">gtest_main&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="53-integração-com-o-vcpkg">5.3. Integração com o vcpkg
&lt;/h3>&lt;p>Usando o &lt;strong>vcpkg&lt;/strong>, o gerenciador de pacotes para C++ liderado pela Microsoft, você pode introduzir milhares de bibliotecas facilmente. O vcpkg foi projetado para se integrar perfeitamente com o CMake.&lt;/p>
&lt;p>Ao executar o CMake, basta especificar o arquivo toolchain do vcpkg, e o &lt;code>find_package&lt;/code> procurará automaticamente pelas bibliotecas dentro do vcpkg.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE&lt;span class="o">=&lt;/span>/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Além disso, colocando um arquivo &lt;code>vcpkg.json&lt;/code> (modo de manifesto) na raiz do projeto, é possível automatizar completamente o gerenciamento de versões das bibliotecas necessárias.&lt;/p>
&lt;h2 id="6-flags-de-compilador-multiplataforma">6. Flags de compilador multiplataforma
&lt;/h2>&lt;p>Para garantir que o build funcione em qualquer ambiente, como Windows (MSVC), Linux (GCC/Clang) ou macOS (Apple Clang), é necessário definir adequadamente as flags específicas de cada compilador.&lt;/p>
&lt;p>Usando &lt;strong>Expressões de Gerador (Generator Expressions)&lt;/strong> do CMake, é possível descrever ramificações condicionais de forma declarativa, como: &amp;ldquo;se o compilador for MSVC, use esta flag; se não, use aquela&amp;rdquo;. As expressões de gerador utilizam a sintaxe &lt;code>$&amp;lt;...&amp;gt;&lt;/code> e são avaliadas na fase de geração (Generate) do sistema de build.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Exemplo de ativação do nível máximo de alertas (warnings) para todas as plataformas
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_compile_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Caso seja MSVC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">$&amp;lt;CXX_COMPILER_ID:MSVC&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">:/W4&lt;/span> &lt;span class="s">/WX&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Caso seja GCC ou Clang
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">$&amp;lt;OR:$&amp;lt;CXX_COMPILER_ID:GNU&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">,&lt;/span>&lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">CXX_COMPILER_ID:Clang&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">,&lt;/span>&lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">CXX_COMPILER_ID:AppleClang&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;gt;:-Wall&lt;/span> &lt;span class="s">-Wextra&lt;/span> &lt;span class="s">-Wpedantic&lt;/span> &lt;span class="s">-Werror&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Usando este método, evita-se o uso excessivo de condicionais como &lt;code>if(MSVC)&lt;/code>, que deixam o &lt;code>CMakeLists.txt&lt;/code> difícil de ler, e permite configurações flexíveis por alvo.&lt;/p>
&lt;h2 id="7-configurando-o-ambiente-de-testes-ctest">7. Configurando o ambiente de testes (CTest)
&lt;/h2>&lt;p>Para a garantia de qualidade num ambiente multiplataforma, a introdução de testes automatizados é indispensável. O CMake já vem com um executor de testes padrão chamado &lt;strong>CTest&lt;/strong>.&lt;/p>
&lt;p>Os passos para integrar o GoogleTest (introduzido anteriormente com &lt;code>FetchContent&lt;/code>) ao CTest são os seguintes:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Habilita a funcionalidade de testes (escrito apenas uma vez no CMakeLists.txt raiz)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">enable_testing&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span> &lt;span class="s">test/math_test.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">gtest_main&lt;/span> &lt;span class="s">MyLib&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Registra como um teste no CTest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">include&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">GoogleTest&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">gtest_discover_tests&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Após o build, basta executar o comando &lt;code>ctest&lt;/code> dentro do diretório de build e todos os testes serão executados, gerando um relatório com os resultados.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ctest --output-on-failure -C Release
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="8-a-teoria-e-o-modelo-matemático-do-sistema-de-build">8. A teoria e o modelo matemático do sistema de build
&lt;/h2>&lt;p>Mudando um pouco a perspectiva, vamos analisar a eficiência do sistema de build e da compilação paralela em projetos de grande escala usando um modelo matemático.&lt;/p>
&lt;p>A redução do tempo de build (tempo de compilação) é um problema eterno no desenvolvimento C++. Dividindo o código-fonte e compilando de forma paralela, o tempo de build pode ser reduzido. Essa melhoria de velocidade por meio da paralelização (Speedup) é modelada pela &lt;strong>Lei de Amdahl (Amdahl&amp;rsquo;s Law)&lt;/strong>.&lt;/p>
&lt;p>Considerando que a proporção da parte do programa que pode ser paralelizada é $P$, a proporção que deve ser executada sequencialmente (não paralelizável) é $1-P$, e o número de processadores utilizados é $N$, a taxa máxima de aceleração teórica total $S(N)$ é expressa pela seguinte fórmula:&lt;/p>
$$ S(N) = \frac{1}{(1 - P) + \frac{P}{N}} $$
&lt;p>No processo de build do C++, a &amp;ldquo;compilação de cada arquivo &lt;code>.cpp&lt;/code> para &lt;code>.o&lt;/code> ou &lt;code>.obj&lt;/code>&amp;rdquo; é independente e paralelizável (parte $P$), mas o &amp;ldquo;processo de união pelo vinculador (Linker) final&amp;rdquo; é essencialmente realizado de forma sequencial (parte $1-P$).&lt;/p>
&lt;p>Portanto, não importa o quão infinito seja o número de núcleos de CPU ($N \to \infty$) disponíveis, desde que exista o gargalo do tempo de linkagem, a taxa de aceleração máxima será assintótica à seguinte fórmula:&lt;/p>
$$ \lim_{N \to \infty} S(N) = \frac{1}{1 - P} $$
&lt;p>O que esta fórmula sugere é: &amp;ldquo;apenas adicionar núcleos à CPU tem um limite na redução do tempo de build&amp;rdquo;. A estratégia mais eficaz e prática de aceleração do build é aumentar a proporção $P$ e diminuir os itens a serem recompilados durante um build incremental, usando adequadamente &lt;code>PRIVATE&lt;/code> e &lt;code>INTERFACE&lt;/code> do CMake Moderno, e minimizando dependências de cabeçalho (aproveitando declarações prévias (forward declarations), etc.).&lt;/p>
&lt;p>Além disso, para a redução do tempo de linkagem, é importante mudar de bibliotecas estáticas (Static Library) para bibliotecas dinâmicas / DLL (Shared Library) ou adotar vinculadores (linkers) mais rápidos, como LLD ou Mold.&lt;/p>
&lt;p>No CMake, é possível configurar facilmente a especificação do linker da seguinte forma:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Configurando para utilizar o linker lld em ambientes Clang/GCC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">UNIX&lt;/span> &lt;span class="s">AND&lt;/span> &lt;span class="s">NOT&lt;/span> &lt;span class="s">APPLE&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">target_link_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s2">&amp;#34;-fuse-ld=lld&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="9-exemplo-prático-de-uma-estrutura-de-diretórios-complexa">9. Exemplo prático de uma estrutura de diretórios complexa
&lt;/h2>&lt;p>No desenvolvimento real de uma aplicação, a estrutura de diretórios geralmente envolve a combinação de múltiplos módulos. Por fim, mostramos a estrutura de diretórios ideal de um projeto de tamanho médio e a relação entre os arquivos &lt;code>CMakeLists.txt&lt;/code> parentes e filhos.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">ProjectRoot/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── CMakeLists.txt (Raiz: Definição de todo o projeto)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── vcpkg.json (Definição de bibliotecas dependentes)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── external/ (Módulos externos)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── include/ (Cabeçalhos públicos)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── myapp/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── src/ (Código-fonte e definições de build internas)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── main.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── math/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├── Vector3.hpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ └── Vector3.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── network/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── NetworkManager.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── tests/ (Código de testes)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── math_test.cpp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>O &lt;code>CMakeLists.txt&lt;/code> raiz contém apenas configurações de ambiente e definições de opções globais, adicionando os subdiretórios com &lt;code>add_subdirectory()&lt;/code>.&lt;/p>
&lt;p>&lt;strong>&lt;code>CMakeLists.txt&lt;/code> Raiz&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span> &lt;span class="s">LANGUAGES&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Configurações globais
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Habilitando os testes
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">enable_testing&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Adicionando subdiretórios
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">src&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">tests&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>&lt;code>src/CMakeLists.txt&lt;/code>&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Adiciona cada módulo
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">math&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">network&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Arquivo executável final
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Linkagem dos módulos
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">MathLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">NetworkLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dessa forma, ao dividir o &lt;code>CMakeLists.txt&lt;/code> por diretório e definir as dependências entre os alvos, aumenta-se a reutilização de módulos e melhora o paralelismo do build. Esse é o grande trunfo do &amp;ldquo;ambiente de build modularizado&amp;rdquo; defendido pelo CMake Moderno.&lt;/p>
&lt;h2 id="10-conclusão">10. Conclusão
&lt;/h2>&lt;p>Abordamos as etapas para a configuração de um ambiente de build C++ multiplataforma usando o CMake.
Recapitulando os pontos principais:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Entendimento do sistema de meta-build&lt;/strong>: O CMake é uma ferramenta que gera scripts de build.&lt;/li>
&lt;li>&lt;strong>Uso intenso do CMake Moderno&lt;/strong>: Não use variáveis; encapsule as configurações orientadas a &lt;strong>alvos (targets)&lt;/strong>, usando comandos como &lt;code>add_executable&lt;/code>, &lt;code>target_link_libraries&lt;/code> e &lt;code>target_include_directories&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Configuração adequada de escopos&lt;/strong>: Faça a distinção correta entre &lt;code>PUBLIC&lt;/code>, &lt;code>PRIVATE&lt;/code> e &lt;code>INTERFACE&lt;/code>, controlando a propagação das dependências.&lt;/li>
&lt;li>&lt;strong>Execução constante de build fora da fonte (Out-of-source build)&lt;/strong>: Faça o build dentro do diretório &lt;code>build/&lt;/code>, sem sujar a source tree.&lt;/li>
&lt;li>&lt;strong>Integração com terceiros&lt;/strong>: Utilize o &lt;code>FetchContent&lt;/code> e o &lt;code>vcpkg&lt;/code> de forma plena e automatize a resolução de dependências de bibliotecas.&lt;/li>
&lt;li>&lt;strong>Uso de expressões de gerador (Generator Expressions)&lt;/strong>: Absorva as diferenças de flags entre compiladores de forma inteligente.&lt;/li>
&lt;li>&lt;strong>Abordagem matemática&lt;/strong>: Tenha consciência da Lei de Amdahl, reduzindo as dependências para aumentar a eficiência da compilação paralela.&lt;/li>
&lt;/ol>
&lt;p>O CMake pode parecer intimidador e complexo no começo, mas ao dominar os conceitos de alvos e propriedades, é possível manter um ambiente de build organizado em qualquer projeto C++, por maior e mais complexo que seja. Esperamos que este artigo sirva de base para que você consiga configurar o seu ambiente de desenvolvimento C++ utilizando a sintaxe do CMake Moderno!&lt;/p></description></item></channel></rss>