<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Builds - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/categorias/linguagem/builds/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Thu, 25 Dec 2025 13:18:15 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://mcu.tec.br/wp-content/uploads/2025/02/Robo-para-o-site-MCU.tec_.br-512x512-1-150x150.png</url>
	<title>Builds - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Introdução ao CMake em Projetos STM32 Gerados pelo CubeMX</title>
		<link>https://mcu.tec.br/linguagem/builds/introducao-ao-cmake-em-projetos-stm32-gerados-pelo-cubemx/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=introducao-ao-cmake-em-projetos-stm32-gerados-pelo-cubemx</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Thu, 25 Dec 2025 13:16:31 +0000</pubDate>
				<category><![CDATA[Builds]]></category>
		<category><![CDATA[bibliotecas estáticas STM32]]></category>
		<category><![CDATA[CMake arm-none-eabi]]></category>
		<category><![CDATA[CMake bare metal]]></category>
		<category><![CDATA[CMake CubeMX]]></category>
		<category><![CDATA[CMake firmware embarcado]]></category>
		<category><![CDATA[CMake para microcontroladores]]></category>
		<category><![CDATA[CMake STM32]]></category>
		<category><![CDATA[CMakeLists STM32]]></category>
		<category><![CDATA[CubeMX CMake]]></category>
		<category><![CDATA[GCC ARM CMake]]></category>
		<category><![CDATA[STM32 build system]]></category>
		<category><![CDATA[STM32 CMake tutorial]]></category>
		<category><![CDATA[STM32 fora da IDE]]></category>
		<category><![CDATA[toolchain CMake STM32]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1069</guid>

					<description><![CDATA[<p>Aprenda a usar o CMake de forma profissional em projetos STM32 gerados pelo CubeMX. Este guia completo e didático explica a história do CMake, os problemas que ele resolve, e como aplicá-lo corretamente em sistemas embarcados bare-metal. O artigo aborda em profundidade diretivas como project, add_executable, add_library, target_sources, target_include_directories, target_compile_definitions, target_link_libraries, uso consciente de file(GLOB), integração de BLOBs binários, criação de bibliotecas estáticas reutilizáveis, configuração de perfis de build, uso de CMakePresets.json e separação correta de toolchains via arquivos .cmake. Inclui um exemplo ideal e comentado de CMakeLists.txt para STM32, além de um arquivo de toolchain arm-none-eabi-gcc.cmake, mostrando como gerar .elf, .bin e .hex fora de IDEs proprietárias. Conteúdo técnico, prático e focado em boas práticas de engenharia de firmware.</p>
<p>The post <a href="https://mcu.tec.br/linguagem/builds/introducao-ao-cmake-em-projetos-stm32-gerados-pelo-cubemx/">Introdução ao CMake em Projetos STM32 Gerados pelo CubeMX</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">A história do CMake e o problema que ele veio resolver</h2>



<p class="wp-block-paragraph">O CMake surge no início dos anos 2000, criado por <strong>Bill Hoffman</strong> no contexto do Kitware, com um objetivo muito claro: <strong>resolver o problema da portabilidade e da complexidade crescente dos sistemas de build</strong>. Até então, projetos em C e C++ dependiam fortemente de <em>Makefiles</em> escritos manualmente, profundamente acoplados ao sistema operacional, ao compilador e até mesmo à estrutura de diretórios da máquina do desenvolvedor. Em projetos pequenos isso era administrável, mas à medida que o software crescia — especialmente em ambientes multiplataforma — o custo de manutenção dos Makefiles se tornava proibitivo.</p>



<p class="wp-block-paragraph">O problema se agravava em projetos embarcados. Cada microcontrolador exige um conjunto específico de flags de compilação, scripts de linkedição, opções de ABI (Application Binary Interface), suporte a assembly, bibliotecas de runtime reduzidas (<code>newlib-nano</code>, <code>nosys</code>, etc.) e, frequentemente, múltiplos perfis de build (Debug, Release, Profiling). Manter tudo isso sincronizado manualmente em Makefiles diferentes era uma fonte constante de erros sutis, builds não reproduzíveis e dependência excessiva do conhecimento tácito do desenvolvedor.</p>



<p class="wp-block-paragraph">O CMake nasce justamente como uma <strong>ferramenta de meta-build</strong>. Ele não compila código diretamente. Em vez disso, descreve o projeto em um nível mais alto, declarativo, e gera os arquivos de build adequados para o ambiente alvo: Makefiles, Ninja, projetos para IDEs como Eclipse, Visual Studio ou Xcode. Essa abordagem separa claramente <strong>o que o projeto é</strong> de <strong>como ele será construído</strong> em cada plataforma.</p>



<p class="wp-block-paragraph">No contexto de sistemas embarcados, essa separação é fundamental. O mesmo projeto pode ser compilado com GCC bare-metal (<code>arm-none-eabi-gcc</code>), Clang, ou até toolchains customizadas fornecidas por fabricantes. O CMake permite encapsular essas diferenças em <strong>arquivos de toolchain</strong>, mantendo o <code>CMakeLists.txt</code> do projeto limpo, legível e focado na arquitetura do software, e não nos detalhes do compilador.</p>



<h2 class="wp-block-heading">Por que o CMake se encaixa tão bem com projetos STM32</h2>



<p class="wp-block-paragraph">Projetos STM32 gerados pelo CubeMX possuem uma característica importante: eles <strong>não são apenas aplicações</strong>, mas sim <strong>sistemas completos</strong>, compostos por código C, assembly, bibliotecas HAL, CMSIS, drivers específicos do microcontrolador, além de um script de linkedição altamente acoplado ao layout de memória do chip. O CubeMX tradicionalmente gera projetos voltados para IDEs específicas (STM32CubeIDE, Keil, IAR), mas isso cria um forte <em>lock-in</em> da ferramenta.</p>



<p class="wp-block-paragraph">Ao adotar o CMake como sistema de build, o projeto STM32 passa a ser <strong>agnóstico de IDE</strong>. Ele pode ser compilado via linha de comando, integrado a pipelines de CI/CD, analisado por ferramentas como <code>clangd</code>, <code>clang-tidy</code> e <code>cppcheck</code>, ou aberto em qualquer editor moderno. Além disso, o CMake facilita a <strong>modularização do projeto</strong>, permitindo separar claramente o código gerado pelo CubeMX do código de aplicação, das bibliotecas externas e das bibliotecas internas reutilizáveis.</p>



<p class="wp-block-paragraph">Outro ponto crucial é que o CMake trabalha com o conceito de <strong>targets</strong>. Em vez de pensar apenas em arquivos <code>.c</code> e <code>.o</code>, o desenvolvedor passa a modelar o sistema em termos de executáveis, bibliotecas estáticas, bibliotecas de interface e dependências explícitas entre elas. Isso se encaixa perfeitamente no mundo embarcado moderno, onde reutilização, isolamento de responsabilidades e controle fino de símbolos e includes são essenciais para manter projetos grandes sustentáveis ao longo do tempo.</p>



<h2 class="wp-block-heading">CMake como fundação para arquiteturas escaláveis em firmware</h2>



<p class="wp-block-paragraph">Quando usamos CMake corretamente em um projeto STM32, deixamos de ter apenas um “script de build” e passamos a ter uma <strong>descrição formal da arquitetura do firmware</strong>. Bibliotecas como drivers, middlewares, stacks de comunicação ou camadas de abstração de hardware podem ser modeladas como bibliotecas estáticas independentes. Cada uma define seus próprios includes, defines e flags de compilação, que são propagados automaticamente para quem as consome.</p>



<p class="wp-block-paragraph">Isso elimina uma classe inteira de problemas comuns em projetos embarcados: defines globais espalhados, includes duplicados, dependências implícitas e flags de compilação inconsistentes entre módulos. Além disso, o CMake facilita a criação de <strong>perfis de build</strong> (Debug, Release, Coverage, Profiling), algo essencial quando se trabalha com análise temporal, WCET, uso de heap, watermark de pilha e instrumentação de RTOS.</p>



<p class="wp-block-paragraph">Em resumo, o CMake não é apenas uma alternativa ao Makefile tradicional. Ele é uma <strong>camada de engenharia de software aplicada ao processo de build</strong>, especialmente poderosa quando combinada com projetos STM32 gerados pelo CubeMX.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Estrutura básica de um projeto CMake para STM32 gerado pelo CubeMX</h2>



<p class="wp-block-paragraph">Ao abrir um projeto STM32 baseado em CMake, a primeira impressão costuma ser de estranhamento para quem vem de Makefiles tradicionais ou do ecossistema fechado de IDEs como o STM32CubeIDE. Isso acontece porque o CMake não descreve comandos de compilação de forma direta, mas sim <strong>relações estruturais</strong> entre os elementos do projeto. Antes de entender cada diretiva isoladamente, é fundamental compreender a <strong>estrutura conceitual</strong> que sustenta um projeto CMake bem organizado para firmware.</p>



<p class="wp-block-paragraph">Em projetos STM32 modernos, especialmente aqueles que nascem a partir do CubeMX, o ponto de entrada é sempre um arquivo chamado <code>CMakeLists.txt</code> localizado na raiz do projeto. Esse arquivo funciona como o <strong>manifesto do firmware</strong>: ele declara qual é o projeto, quais linguagens são usadas, quais bibliotecas fazem parte do sistema, quais arquivos devem ser compilados e como tudo isso se conecta para gerar o binário final, geralmente um arquivo <code>.elf</code>.</p>



<p class="wp-block-paragraph">Uma característica importante é que esse <code>CMakeLists.txt</code> de nível superior <strong>não deve conter tudo</strong>. Em projetos bem estruturados, ele atua como um orquestrador, delegando responsabilidades para outros <code>CMakeLists.txt</code> menores espalhados pela árvore do projeto. É exatamente isso que vemos em projetos gerados ou adaptados a partir do CubeMX, onde o código automático fica isolado em uma subpasta, normalmente algo como <code>cmake/stm32cubemx</code>, enquanto o código da aplicação permanece sob controle direto do desenvolvedor.</p>



<p class="wp-block-paragraph">Essa separação é essencial. O código gerado pelo CubeMX pode ser regenerado a qualquer momento, enquanto o código da aplicação e a lógica de build precisam permanecer estáveis. O CMake favorece esse modelo ao permitir a inclusão explícita de subdiretórios, tornando claro o limite entre código gerado e código autoral.</p>



<h2 class="wp-block-heading">A diretiva <code>cmake_minimum_required</code>: controle de compatibilidade e previsibilidade</h2>



<p class="wp-block-paragraph">Toda configuração CMake começa com a diretiva <code>cmake_minimum_required</code>. Embora muitos desenvolvedores a encarem como uma formalidade, ela desempenha um papel crítico em projetos embarcados. Essa diretiva define <strong>a versão mínima do CMake necessária para interpretar corretamente o script</strong>, garantindo que comportamentos antigos, obsoletos ou inconsistentes não sejam utilizados de forma implícita.</p>



<p class="wp-block-paragraph">Em firmware, previsibilidade é tudo. Diferenças sutis no comportamento do sistema de build podem resultar em flags omitidas, bibliotecas ligadas em ordem incorreta ou até mesmo em binários que funcionam em Debug, mas falham em Release. Ao exigir explicitamente uma versão mínima, o projeto estabelece uma linha de base clara para todos os desenvolvedores e para sistemas de integração contínua.</p>



<p class="wp-block-paragraph">Na prática, projetos STM32 modernos costumam exigir versões relativamente recentes do CMake, pois funcionalidades como <code>FetchContent</code>, presets (<code>CMakePresets.json</code>) e melhor suporte a toolchains cruzadas evoluíram bastante nas últimas versões. Definir essa versão logo no início do arquivo evita erros difíceis de rastrear mais adiante e deixa claro que o projeto não foi pensado para ambientes legados.</p>



<p class="wp-block-paragraph">Além disso, essa diretiva influencia o modo como o CMake interpreta várias outras instruções. Sem ela, o CMake entra em um modo de compatibilidade que pode alterar silenciosamente o comportamento de comandos fundamentais. Em sistemas embarcados, onde cada byte e cada flag importam, esse tipo de ambiguidade é simplesmente inaceitável.</p>



<h2 class="wp-block-heading">A diretiva <code>project()</code>: identidade formal do firmware</h2>



<p class="wp-block-paragraph">Logo após definir a versão mínima do CMake, encontramos a diretiva <code>project()</code>. Essa é uma das instruções mais importantes de todo o sistema de build, pois é nela que o firmware passa a existir formalmente como um projeto CMake. Ao declarar o projeto, você não está apenas dando um nome simbólico ao binário final, mas também inicializando internamente todo o modelo de build que o CMake utilizará.</p>



<p class="wp-block-paragraph">Em projetos STM32, o nome do projeto geralmente coincide com o nome do arquivo final <code>.elf</code>, e frequentemente reflete o hardware alvo ou a função principal do firmware. Isso não é apenas uma convenção estética. O nome do projeto passa a ser utilizado implicitamente em diversas outras diretivas, como na criação do executável, na geração de mensagens de log e na organização dos artefatos de build.</p>



<p class="wp-block-paragraph">Além do nome, a diretiva <code>project()</code> também declara as linguagens utilizadas. Em firmware STM32, isso quase sempre inclui C e Assembly. Ao fazer isso explicitamente, o CMake passa a configurar corretamente compiladores, regras de build e extensões de arquivos para cada linguagem, algo fundamental quando se trabalha com arquivos <code>.s</code> ou <code>.S</code> de startup e rotinas de baixo nível.</p>



<p class="wp-block-paragraph">Outro ponto relevante é que a chamada a <code>project()</code> marca o momento em que variáveis globais do CMake passam a estar disponíveis de forma consistente. Por isso, boas práticas recomendam que a maior parte das configurações estruturais do projeto aconteça <strong>após</strong> essa diretiva, garantindo que o ambiente esteja completamente inicializado.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Definição do padrão da linguagem e controle do compilador</h2>



<p class="wp-block-paragraph">Em sistemas embarcados, definir explicitamente o padrão da linguagem não é um detalhe estético, mas um requisito técnico. O comportamento do compilador, a disponibilidade de recursos da linguagem e até a geração de código variam significativamente entre diferentes padrões do C. O CMake resolve essa questão de forma clara e declarativa por meio de variáveis específicas que descrevem <strong>qual versão da linguagem o projeto exige</strong>, e não apenas qual compilador será usado.</p>



<p class="wp-block-paragraph">A variável <code>CMAKE_C_STANDARD</code> estabelece o padrão mínimo do C que o projeto aceita. Em projetos STM32 gerados pelo CubeMX, é comum adotar o C11, pois ele oferece um bom equilíbrio entre modernidade e compatibilidade com toolchains bare-metal. Ao definir esse valor, o CMake garante que o compilador seja invocado com as flags corretas para ativar esse padrão, independentemente de qual GCC esteja instalado no sistema.</p>



<p class="wp-block-paragraph">Complementando isso, <code>CMAKE_C_STANDARD_REQUIRED</code> força o compilador a respeitar exatamente o padrão definido. Sem essa diretiva, o compilador pode silenciosamente aceitar um padrão diferente, mais antigo ou mais permissivo, o que abre espaço para comportamentos inesperados. Em firmware, onde cada compilação precisa ser reprodutível, esse tipo de ambiguidade não é aceitável.</p>



<p class="wp-block-paragraph">Já a variável <code>CMAKE_C_EXTENSIONS</code> controla se extensões específicas do compilador — como as extensões GNU — podem ser utilizadas. Em projetos STM32, muitas bibliotecas, incluindo partes do HAL e até do CMSIS, dependem de extensões do GCC. Por isso, permitir essas extensões costuma ser uma decisão consciente, e não um efeito colateral. O CMake torna essa decisão explícita, documentando a dependência do projeto em recursos fora do padrão estrito da linguagem.</p>



<p class="wp-block-paragraph">Esse conjunto de definições cria um <strong>contrato claro entre o firmware e o compilador</strong>, algo essencial quando o mesmo projeto pode ser compilado em máquinas diferentes, por pessoas diferentes ou em pipelines automatizados.</p>



<h2 class="wp-block-heading">Tipos de build: Debug, Release e além</h2>



<p class="wp-block-paragraph">Uma das maiores vantagens do CMake em relação a Makefiles artesanais é o tratamento nativo de <strong>tipos de build</strong>. Em firmware, isso vai muito além de simplesmente ativar ou desativar otimizações. Um build Debug normalmente inclui símbolos de depuração, otimizações mínimas e, muitas vezes, instrumentação adicional para análise de tempo, uso de memória e comportamento do RTOS. Já um build Release prioriza desempenho, tamanho do binário e previsibilidade temporal.</p>



<p class="wp-block-paragraph">A variável <code>CMAKE_BUILD_TYPE</code> é o mecanismo básico pelo qual o CMake seleciona esse comportamento. Ao definir um valor padrão quando essa variável não está presente, o projeto garante que o build não ocorra em um estado indefinido. Isso é especialmente importante em ambientes embarcados, onde rodar um binário “meio Debug, meio Release” pode gerar resultados enganosos durante testes de campo.</p>



<p class="wp-block-paragraph">Mais importante do que a existência de Debug e Release é o fato de que o CMake permite <strong>estender esse conceito</strong>. É comum em projetos STM32 mais maduros existirem perfis adicionais, como builds para análise de WCET, builds com logs detalhados, builds para testes de estresse ou builds voltados exclusivamente para validação de consumo de energia. O sistema de build deixa de ser apenas um meio de gerar um <code>.elf</code> e passa a ser uma ferramenta estratégica de engenharia.</p>



<p class="wp-block-paragraph">Essa flexibilidade se torna ainda mais poderosa quando combinada com arquivos como <code>CMakePresets.json</code>, que permitem descrever esses perfis de forma padronizada e reutilizável, eliminando a necessidade de longas linhas de comando e reduzindo drasticamente erros humanos.</p>



<h2 class="wp-block-heading">Ativação explícita das linguagens C e Assembly</h2>



<p class="wp-block-paragraph">Em firmware STM32, o uso de Assembly não é opcional. Arquivos de startup, rotinas de inicialização da pilha, vetores de interrupção e, em alguns casos, otimizações críticas de desempenho exigem suporte explícito a código Assembly. O CMake trata isso de forma direta por meio da diretiva <code>enable_language</code>.</p>



<p class="wp-block-paragraph">Ao habilitar C e ASM de forma explícita, o projeto informa ao CMake que esses dois tipos de código fazem parte da arquitetura do firmware. Isso permite que o sistema de build configure corretamente as regras de compilação, extensões reconhecidas e até flags específicas para cada linguagem. Ignorar essa etapa pode levar a erros difíceis de diagnosticar, especialmente quando arquivos <code>.s</code> ou <code>.S</code> são tratados incorretamente como texto ou ignorados durante o build.</p>



<p class="wp-block-paragraph">Outro ponto relevante é que, ao declarar explicitamente as linguagens, o projeto se torna mais claro para ferramentas externas. Editores, analisadores estáticos e sistemas de indexação conseguem entender melhor a natureza do código, o que melhora significativamente a experiência de desenvolvimento em projetos de médio e grande porte.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Criação do firmware com <code>add_executable()</code>: o nascimento do binário <code>.elf</code></h2>



<p class="wp-block-paragraph">Em projetos embarcados, o executável gerado pelo CMake não é apenas um programa no sentido tradicional, mas sim a <strong>imagem completa do firmware</strong>, contendo código, dados, vetores de interrupção, tabelas de inicialização e referências explícitas ao layout de memória definido no script de linkedição. No CMake, esse artefato nasce por meio da diretiva <code>add_executable()</code>.</p>



<p class="wp-block-paragraph">Ao chamar <code>add_executable</code>, o projeto declara formalmente a existência de um alvo executável. No contexto STM32, esse alvo representa o firmware que será gravado na flash do microcontrolador. Diferente de ambientes desktop, o executável não será “executado” pelo sistema operacional, mas sim carregado por um programador ou bootloader. Ainda assim, para o CMake, ele é tratado como um executável completo, com regras claras de compilação e linkedição.</p>



<p class="wp-block-paragraph">Uma característica interessante é que, em projetos bem estruturados, o <code>add_executable</code> normalmente aparece <strong>sem listar arquivos fonte diretamente</strong>. Isso não é um erro, mas sim uma decisão arquitetural. O alvo é criado vazio e, ao longo do <code>CMakeLists.txt</code>, vai recebendo fontes, includes, defines e bibliotecas por meio de outras diretivas mais específicas. Esse modelo favorece a modularização e evita grandes listas monolíticas de arquivos difíceis de manter.</p>



<p class="wp-block-paragraph">Essa abordagem se encaixa muito bem com projetos CubeMX, onde o código gerado automaticamente pode ser adicionado ao executável a partir de um subdiretório específico, mantendo o arquivo principal limpo e legível. O executável passa a ser o ponto de convergência de vários módulos independentes, refletindo com clareza a arquitetura do firmware.</p>



<h2 class="wp-block-heading">Criação de bibliotecas estáticas com <code>add_library()</code></h2>



<p class="wp-block-paragraph">Se o <code>add_executable</code> representa o firmware final, <code>add_library</code> representa os <strong>blocos de construção</strong> que compõem esse firmware. Em projetos STM32 profissionais, bibliotecas estáticas são fundamentais para organizar o código, promover reutilização e limitar o acoplamento entre módulos.</p>



<p class="wp-block-paragraph">Ao criar uma biblioteca estática no CMake, você está definindo um conjunto coeso de funcionalidades que pode ser compilado de forma independente e depois ligado ao firmware principal. Isso é extremamente comum para drivers, camadas de abstração, middlewares e até para o próprio HAL, quando se deseja maior controle sobre o processo de build.</p>



<p class="wp-block-paragraph">No CMake, bibliotecas estáticas permitem encapsular não apenas arquivos fonte, mas também includes, defines e opções de compilação específicas daquele módulo. Isso significa que um driver pode expor suas dependências de forma explícita, e o executável que o utiliza herda essas informações automaticamente. Esse modelo elimina a necessidade de repetir configurações globais e reduz drasticamente erros de integração.</p>



<p class="wp-block-paragraph">Em projetos derivados do CubeMX, é comum transformar partes do código gerado em bibliotecas internas, isolando, por exemplo, a inicialização do hardware da lógica da aplicação. O CMake torna esse processo natural, incentivando uma arquitetura mais limpa e sustentável ao longo do tempo.</p>



<h2 class="wp-block-heading">O papel central de <code>target_sources()</code></h2>



<p class="wp-block-paragraph">Uma vez criados os alvos — executáveis ou bibliotecas — surge a necessidade de associar arquivos fonte a eles. É aqui que entra a diretiva <code>target_sources</code>. Em vez de listar arquivos diretamente na criação do alvo, o CMake permite adicioná-los de forma incremental e contextualizada.</p>



<p class="wp-block-paragraph">Essa abordagem é especialmente poderosa em firmware STM32, pois diferentes módulos podem contribuir com arquivos para o mesmo alvo sem que isso gere dependências implícitas ou confusão estrutural. O código gerado pelo CubeMX, por exemplo, pode ser adicionado a partir de um subdiretório específico, enquanto o código da aplicação é adicionado em outro ponto do projeto.</p>



<p class="wp-block-paragraph">Além disso, <code>target_sources</code> ajuda a documentar a origem dos arquivos. Ao ler o <code>CMakeLists.txt</code>, fica claro quais fontes pertencem a qual módulo e como elas se integram ao firmware final. Isso facilita manutenção, revisão de código e onboarding de novos desenvolvedores.</p>



<p class="wp-block-paragraph">Outro benefício importante é que essa diretiva respeita o escopo do alvo. Um arquivo fonte adicionado a uma biblioteca não “vaza” automaticamente para outros alvos, o que reforça o isolamento entre módulos e previne dependências acidentais.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Includes e headers: controle preciso com <code>target_include_directories()</code></h2>



<p class="wp-block-paragraph">Em projetos STM32 tradicionais, especialmente aqueles criados diretamente dentro de IDEs, é muito comum encontrar <strong>listas globais de includes</strong>, aplicadas indiscriminadamente a todo o projeto. Esse modelo funciona no início, mas rapidamente se torna frágil: headers passam a depender implicitamente de outros headers, conflitos de nomes surgem e o acoplamento entre módulos cresce silenciosamente.</p>



<p class="wp-block-paragraph">O CMake resolve esse problema ao introduzir um modelo baseado em <strong>escopo</strong>, e a diretiva <code>target_include_directories()</code> é o coração dessa abordagem. Em vez de dizer “estes diretórios fazem parte do projeto”, você passa a dizer “estes diretórios fazem parte deste alvo”. Essa diferença conceitual muda completamente a forma como o firmware é organizado.</p>



<p class="wp-block-paragraph">Quando um diretório de include é associado a um alvo específico — seja um executável ou uma biblioteca — apenas aquele alvo e seus consumidores diretos terão acesso a esses headers. Isso permite que cada módulo exponha exatamente o que precisa ser exposto, nada mais. Em firmware STM32, isso é essencial para separar, por exemplo, drivers de hardware, código de aplicação e camadas de abstração.</p>



<p class="wp-block-paragraph">Outro aspecto importante é o <strong>nível de visibilidade</strong>: PRIVATE, PUBLIC e INTERFACE. Um include marcado como PRIVATE só é usado internamente pelo alvo. PUBLIC é usado pelo alvo e também propagado para quem o linkar. INTERFACE não é usado pelo próprio alvo, mas apenas pelos consumidores. Essa distinção é extremamente poderosa para firmware, pois permite criar bibliotecas que funcionam como contratos bem definidos entre módulos.</p>



<p class="wp-block-paragraph">Ao adotar esse modelo, o projeto deixa de depender de “includes mágicos” e passa a ter uma estrutura previsível, rastreável e muito mais fácil de manter ao longo dos anos.</p>



<h2 class="wp-block-heading">Definições de compilação e macros com <code>target_compile_definitions()</code></h2>



<p class="wp-block-paragraph">Macros de compilação são inevitáveis em sistemas embarcados. Defines como <code>STM32F4xx</code>, <code>USE_HAL_DRIVER</code>, opções de debug, flags de instrumentação ou seleção de periféricos fazem parte do dia a dia. O problema surge quando essas macros são definidas globalmente, sem controle de escopo.</p>



<p class="wp-block-paragraph">A diretiva <code>target_compile_definitions()</code> resolve exatamente isso. Assim como acontece com includes, as definições passam a pertencer a um alvo específico. Isso significa que um driver pode declarar suas próprias macros, um middleware pode exigir determinadas configurações, e o executável final herda apenas aquilo que faz sentido para ele.</p>



<p class="wp-block-paragraph">Em projetos STM32 baseados em CubeMX, isso é particularmente relevante porque o código gerado assume a existência de certos defines. Ao propagar essas definições corretamente para bibliotecas externas ou módulos internos, o CMake garante que todo o código seja compilado sob o mesmo contexto, evitando erros sutis e difíceis de diagnosticar.</p>



<p class="wp-block-paragraph">Outro ponto importante é que essas macros passam a ser documentadas implicitamente pelo sistema de build. Ao inspecionar o <code>CMakeLists.txt</code>, fica claro quais símbolos existem, por que existem e onde são utilizados. Isso é um ganho enorme em projetos de longa duração ou com múltiplos desenvolvedores.</p>



<h2 class="wp-block-heading">Organização modular com <code>add_subdirectory()</code></h2>



<p class="wp-block-paragraph">Uma das maiores forças do CMake em projetos STM32 é a possibilidade de <strong>fragmentar o sistema de build</strong> em múltiplos arquivos pequenos e coesos. A diretiva <code>add_subdirectory()</code> é o mecanismo que permite isso.</p>



<p class="wp-block-paragraph">Ao adicionar um subdiretório, o CMake passa a processar o <code>CMakeLists.txt</code> contido naquele diretório como parte do projeto principal. Isso é exatamente o que permite isolar o código gerado pelo CubeMX em uma pasta dedicada, mantendo o arquivo principal enxuto e focado na arquitetura do firmware.</p>



<p class="wp-block-paragraph">Esse modelo também favorece a criação de bibliotecas internas bem definidas. Cada módulo pode ter seu próprio <code>CMakeLists.txt</code>, declarando fontes, includes, defines e dependências de forma local. O projeto principal apenas conecta esses módulos, sem precisar conhecer seus detalhes internos.</p>



<p class="wp-block-paragraph">Em firmware STM32 mais complexos, essa organização é o que torna viável a manutenção ao longo do tempo. O build deixa de ser um arquivo monolítico e passa a refletir a estrutura real do software.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Linkedição em firmware STM32 com <code>target_link_libraries()</code></h2>



<p class="wp-block-paragraph">Diferente de aplicações desktop, a linkedição em sistemas embarcados não é apenas uma etapa final automática do build. Ela define <strong>o que realmente entra no firmware</strong>, como o código é organizado na memória e até quais partes do código serão eliminadas pelo linker. No CMake, o controle desse processo é feito principalmente por meio da diretiva <code>target_link_libraries()</code>.</p>



<p class="wp-block-paragraph">Ao usar <code>target_link_libraries</code>, você declara explicitamente que um alvo depende de outro. No caso de um firmware STM32, isso normalmente significa ligar o executável principal a bibliotecas estáticas que representam o HAL, CMSIS, drivers, middlewares ou módulos internos do projeto. O ponto central é que o CMake transforma essa declaração em <strong>ordem correta de linkedição</strong>, algo extremamente sensível em ambientes bare-metal.</p>



<p class="wp-block-paragraph">Em sistemas embarcados, a ordem das bibliotecas importa. Diferente de ambientes com linker dinâmico, o linker bare-metal resolve símbolos em uma única passagem ou em grupos explícitos. O CMake entende essa necessidade e organiza a linha de link automaticamente com base nas dependências declaradas entre os targets. Isso elimina a prática perigosa de “testar ordens até funcionar”.</p>



<p class="wp-block-paragraph">Outro aspecto importante é que, ao linkar bibliotecas como targets CMake — e não como arquivos <code>.a</code> soltos — o sistema de build passa a conhecer não apenas o binário da biblioteca, mas também seus includes, defines e opções de compilação. Isso cria um encadeamento coerente de dependências, reduzindo drasticamente inconsistências entre módulos.</p>



<h2 class="wp-block-heading">Bibliotecas estáticas, descarte de código e otimizações agressivas</h2>



<p class="wp-block-paragraph">Em firmware STM32, quase sempre se trabalha com <strong>linkedição com garbage collection de seções</strong> (<code>--gc-sections</code>). Isso significa que qualquer função ou dado não referenciado será eliminado do binário final. Esse comportamento é desejável para reduzir tamanho, mas exige disciplina arquitetural.</p>



<p class="wp-block-paragraph">Quando uma biblioteca estática é linkada ao firmware, apenas as partes efetivamente utilizadas entram no <code>.elf</code>. Porém, se a ordem de link estiver errada ou se símbolos forem referenciados apenas indiretamente (por exemplo, via ponteiros de função), o linker pode descartar código essencial. O uso correto de <code>target_link_libraries</code> ajuda a minimizar esse risco, pois o CMake mantém a relação explícita entre quem fornece e quem consome símbolos.</p>



<p class="wp-block-paragraph">Além disso, o uso de bibliotecas bem definidas permite aplicar opções de compilação diferentes para cada módulo. Drivers críticos podem ser compilados com otimizações específicas, enquanto código de diagnóstico pode ser compilado de forma mais conservadora. O CMake torna esse tipo de ajuste local e controlável, algo praticamente inviável com Makefiles globais.</p>



<h2 class="wp-block-heading">Diretórios de bibliotecas e o papel de <code>target_link_directories()</code></h2>



<p class="wp-block-paragraph">Embora o uso de <code>target_link_directories()</code> exista, em projetos STM32 bem estruturados ele deve ser usado com cautela. Essa diretiva adiciona caminhos de busca para bibliotecas durante a linkedição, mas não cria dependências explícitas entre targets. Por isso, ela é considerada uma solução de menor nível.</p>



<p class="wp-block-paragraph">Em firmware moderno com CMake, a prática recomendada é quase sempre trabalhar com <strong>targets reais</strong>, criados via <code>add_library()</code>, e ligá-los diretamente ao executável. Isso torna o build mais robusto, mais legível e menos dependente de detalhes implícitos do ambiente.</p>



<p class="wp-block-paragraph">Ainda assim, existem cenários legítimos para <code>target_link_directories</code>, como a integração com bibliotecas pré-compiladas fornecidas por fabricantes ou com blobs binários. Nesses casos, o CMake permite isolar esse comportamento em pontos bem definidos do projeto, evitando que ele se espalhe de forma descontrolada.</p>



<h2 class="wp-block-heading">O script de linkedição e sua relação com o CMake</h2>



<p class="wp-block-paragraph">Em projetos STM32, o script de linkedição (<code>.ld</code>) é tão importante quanto o código-fonte. Ele define o mapa de memória do microcontrolador, separa flash, RAM, stack, heap e regiões especiais. O CMake não substitui esse script, mas <strong>orquestra seu uso</strong>.</p>



<p class="wp-block-paragraph">Ao configurar corretamente as flags de linkedição no CMake, o script <code>.ld</code> passa a fazer parte formal do processo de build. Isso significa que diferentes perfis de build podem usar scripts diferentes, algo extremamente útil para cenários como bootloaders, aplicações dual-bank ou firmware com atualização segura.</p>



<p class="wp-block-paragraph">Mais uma vez, o CMake atua como um integrador arquitetural, garantindo que compilador, linker e layout de memória trabalhem de forma coerente.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Coleções de arquivos e BLOBs com <code>file(GLOB …)</code></h2>



<p class="wp-block-paragraph">O CMake oferece a diretiva <code>file(GLOB …)</code> como uma forma de criar automaticamente listas de arquivos a partir de padrões, algo semelhante ao uso de curingas no shell. Em projetos embarcados, essa funcionalidade costuma gerar debates acalorados, pois envolve um equilíbrio delicado entre <strong>conveniência e previsibilidade</strong>.</p>



<p class="wp-block-paragraph">Quando usamos <code>file(GLOB)</code>, o CMake percorre um diretório e coleta todos os arquivos que correspondem a um determinado padrão, como todos os <code>.c</code> ou <code>.h</code>. Isso permite reduzir listas extensas e repetitivas de arquivos, especialmente em módulos com grande quantidade de fontes homogêneas, como drivers ou middlewares.</p>



<p class="wp-block-paragraph">Em projetos STM32 derivados do CubeMX, esse mecanismo pode ser útil para lidar com conjuntos de arquivos que seguem uma estrutura estável, como diretórios de drivers ou bibliotecas externas que não sofrem alterações frequentes. Nesses casos, o GLOB atua como uma forma de <strong>declaração implícita de intenção</strong>: todo arquivo daquele tipo naquele diretório faz parte do módulo.</p>



<p class="wp-block-paragraph">No entanto, existe um ponto crítico: o CMake <strong>não reavalia automaticamente os GLOBs quando novos arquivos são adicionados</strong>. Isso significa que, se um desenvolvedor cria um novo arquivo <code>.c</code>, ele pode não ser incluído no build até que o CMake seja reconfigurado. Em firmware, onde builds automatizados e reprodutibilidade são essenciais, esse comportamento precisa ser compreendido e controlado.</p>



<p class="wp-block-paragraph">Por isso, a recomendação prática é clara: usar <code>file(GLOB)</code> apenas em diretórios cujo conteúdo é considerado <strong>estável</strong>, ou em bibliotecas externas que não fazem parte do ciclo de desenvolvimento diário. Para o código principal da aplicação, listas explícitas de arquivos continuam sendo a opção mais segura e transparente.</p>



<h2 class="wp-block-heading">BLOBs binários: quando o código não é tudo</h2>



<p class="wp-block-paragraph">Em projetos STM32 reais, nem tudo é código-fonte. É comum lidar com <strong>BLOBs binários</strong>, como tabelas de fontes, imagens, firmware de coprocesso, certificados, ou até microcódigos proprietários fornecidos por terceiros. Integrar esses artefatos ao firmware exige cuidado, e o CMake oferece ferramentas adequadas para isso.</p>



<p class="wp-block-paragraph">Uma abordagem comum é tratar esses BLOBs como arquivos de entrada do processo de build, convertendo-os em objetos ou seções específicas que serão linkadas ao firmware. O CMake permite gerenciar esses arquivos como fontes do alvo, mesmo que não sejam compilados no sentido tradicional.</p>



<p class="wp-block-paragraph">O ponto central aqui é que o CMake não faz distinção conceitual entre “código” e “dados”. Ele trabalha com artefatos que participam do processo de geração do binário final. Isso torna possível incorporar recursos binários ao firmware de forma controlada, documentada e reproduzível.</p>



<p class="wp-block-paragraph">Quando combinado com scripts de conversão e regras customizadas, o CMake se torna uma ferramenta poderosa para integrar dados externos ao firmware STM32, sem recorrer a soluções ad hoc ou etapas manuais frágeis.</p>



<h2 class="wp-block-heading">Perfis de build e <code>CMakePresets.json</code></h2>



<p class="wp-block-paragraph">À medida que projetos STM32 crescem, o simples uso de <code>CMAKE_BUILD_TYPE</code> passa a não ser suficiente. Diferentes desenvolvedores, máquinas e pipelines precisam gerar builds consistentes sem depender de longas linhas de comando. É aqui que entram os <strong>presets do CMake</strong>.</p>



<p class="wp-block-paragraph">O arquivo <code>CMakePresets.json</code> permite definir perfis de configuração e build de forma declarativa. Em vez de memorizar comandos, o desenvolvedor escolhe um preset, e o CMake aplica automaticamente gerador, diretórios de build, toolchain e variáveis de cache. Isso reduz drasticamente erros humanos e melhora a experiência de uso.</p>



<p class="wp-block-paragraph">Em projetos STM32, presets são especialmente úteis para encapsular diferentes toolchains, placas-alvo ou modos de operação. Um mesmo projeto pode gerar firmware para múltiplas variantes de hardware sem que isso se torne um pesadelo de manutenção.</p>



<p class="wp-block-paragraph">Além disso, presets se integram muito bem com editores modernos e ferramentas de automação, tornando o fluxo de desenvolvimento mais profissional e previsível.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Toolchains cruzadas no CMake: separando o “como compilar” do “que compilar”</h2>



<p class="wp-block-paragraph">Em sistemas embarcados, o compilador <strong>não roda no mesmo ambiente do software gerado</strong>. Compilamos no host (Linux, Windows ou macOS) para executar em um microcontrolador ARM Cortex-M. Esse modelo exige uma <strong>toolchain cruzada</strong>, normalmente baseada no <code>arm-none-eabi-gcc</code>. O CMake trata essa realidade de forma elegante ao separar completamente o conceito de projeto do conceito de toolchain.</p>



<p class="wp-block-paragraph">No CMake, a toolchain não deve ser definida dentro do <code>CMakeLists.txt</code> principal. Em vez disso, ela é descrita em um <strong>arquivo <code>.cmake</code> dedicado</strong>, passado ao CMake no momento da configuração. Essa decisão arquitetural é extremamente importante, pois evita que o projeto fique acoplado a um compilador específico ou a caminhos absolutos do sistema.</p>



<p class="wp-block-paragraph">Um arquivo de toolchain define coisas como:</p>



<ul class="wp-block-list">
<li>qual compilador C e ASM será usado</li>



<li>qual linker será invocado</li>



<li>quais ferramentas auxiliares (objcopy, size, objdump) fazem parte do fluxo</li>



<li>quais flags são obrigatórias para aquela arquitetura</li>
</ul>



<p class="wp-block-paragraph">No contexto STM32, esse arquivo encapsula todo o conhecimento sobre a plataforma Cortex-M, deixando o restante do projeto livre para se concentrar na <strong>arquitetura do firmware</strong>, e não em detalhes do compilador.</p>



<h2 class="wp-block-heading">Arquivos de toolchain para STM32 e CubeIDE</h2>



<p class="wp-block-paragraph">Quando usamos o GCC fornecido pelo STM32CubeIDE, a toolchain já existe, mas normalmente está escondida dentro da IDE. Ao trabalhar com CMake, precisamos <strong>tornar isso explícito</strong>. É exatamente para isso que surgem arquivos como <code>cubeide-gcc.cmake</code>.</p>



<p class="wp-block-paragraph">Esse tipo de arquivo informa ao CMake onde encontrar o compilador <code>arm-none-eabi-gcc</code>, qual prefixo usar, como tratar o assembler e quais ferramentas adicionais fazem parte do toolchain. Além disso, ele define que o sistema alvo não é um sistema operacional tradicional, mas sim um ambiente bare-metal.</p>



<p class="wp-block-paragraph">Essa distinção é crucial. Ao informar ao CMake que o sistema alvo não possui libc padrão, filesystem ou runtime POSIX, evitamos que ele tente realizar testes de compilação ou linkedição incompatíveis com microcontroladores. O build passa a ser previsível e alinhado com a realidade do hardware.</p>



<p class="wp-block-paragraph">Outro benefício direto é que o mesmo projeto pode ser compilado com toolchains diferentes apenas trocando o arquivo de toolchain, sem tocar em uma única linha do <code>CMakeLists.txt</code> principal. Isso é extremamente valioso em ambientes profissionais, onde certificações, auditorias ou requisitos de longo prazo exigem controle fino sobre a ferramenta de compilação.</p>



<h2 class="wp-block-heading">Integração da toolchain com presets e automação</h2>



<p class="wp-block-paragraph">Quando combinamos arquivos de toolchain com <code>CMakePresets.json</code>, o fluxo de build se torna ainda mais robusto. O preset passa a declarar explicitamente qual toolchain deve ser usada, qual gerador será adotado e onde os artefatos de build serão gerados.</p>



<p class="wp-block-paragraph">Isso elimina a dependência de documentação informal do tipo “compile assim no seu computador” e transforma o processo de build em algo <strong>reproduzível por definição</strong>. Qualquer desenvolvedor, ou mesmo um sistema de integração contínua, consegue gerar exatamente o mesmo firmware a partir do mesmo código-fonte.</p>



<p class="wp-block-paragraph">Em projetos STM32 maiores, é comum ter presets separados para diferentes placas, diferentes microcontroladores ou diferentes perfis de memória. O CMake lida com isso de forma natural, sem duplicação de código e sem gambiarras.</p>



<h2 class="wp-block-heading">Arquivos de apoio: includes, perfis e configuração externa</h2>



<p class="wp-block-paragraph">À medida que o projeto cresce, surge a necessidade de arquivos auxiliares para organizar o build. Em vez de concentrar tudo no <code>CMakeLists.txt</code> principal, o CMake incentiva a criação de arquivos <code>.cmake</code> especializados: um para toolchain, outro para configuração de RTOS, outro para opções de análise, outro para perfis de instrumentação.</p>



<p class="wp-block-paragraph">Essa abordagem se encaixa perfeitamente com firmware STM32 moderno, onde diferentes builds podem habilitar logs, medições de tempo, análise de stack ou até funcionalidades experimentais. Cada uma dessas variações pode ser descrita de forma limpa e modular, sem poluir a lógica central do projeto.</p>



<p class="wp-block-paragraph">O resultado final é um sistema de build que deixa de ser um obstáculo e passa a ser um <strong>ativo técnico</strong> do projeto.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Fluxo completo de build: do CubeMX ao firmware final</h2>



<p class="wp-block-paragraph">Uma vez compreendidos os conceitos fundamentais do CMake, o fluxo de trabalho em um projeto STM32 torna-se claro, previsível e altamente profissional. O ponto de partida continua sendo o <strong>STM32CubeMX</strong>, responsável por gerar o código de inicialização, HAL, CMSIS e o script de linkedição. A diferença é que, em vez de amarrar o projeto a uma IDE específica, o CubeMX passa a ser apenas <strong>um gerador de código</strong>, e não o dono do processo de build.</p>



<p class="wp-block-paragraph">Após gerar ou atualizar o código, o projeto é estruturado de forma que esse conteúdo fique isolado em um subdiretório, normalmente tratado como um módulo independente. O <code>CMakeLists.txt</code> principal atua como o orquestrador, conectando esse código gerado à aplicação, às bibliotecas internas e às dependências externas. Essa separação garante que futuras regenerações do CubeMX não quebrem a arquitetura do projeto.</p>



<p class="wp-block-paragraph">A etapa seguinte é a <strong>configuração do build</strong>. Aqui, o CMake lê o <code>CMakeLists.txt</code>, o arquivo de toolchain e, quando presentes, os presets. Esse momento não gera binários; ele apenas constrói o modelo interno do projeto. É nesse ponto que erros de configuração, caminhos incorretos ou inconsistências arquiteturais aparecem — e é exatamente onde eles devem aparecer.</p>



<p class="wp-block-paragraph">Com a configuração concluída, o processo de <strong>compilação e linkedição</strong> passa a ser mecânico. O CMake invoca o compilador correto, aplica as flags definidas, executa o linker com o script apropriado e gera o arquivo <code>.elf</code>, que representa o firmware completo. A partir dele, ferramentas auxiliares convertem o binário para <code>.bin</code> ou <code>.hex</code>, prontos para gravação no microcontrolador.</p>



<p class="wp-block-paragraph">Esse fluxo é repetível, automatizável e independente de IDE, o que representa um salto de maturidade em relação a projetos embarcados tradicionais.</p>



<h2 class="wp-block-heading">Geração de bibliotecas estáticas reutilizáveis</h2>



<p class="wp-block-paragraph">Um dos maiores ganhos ao adotar CMake em projetos STM32 é a facilidade de <strong>criar e reutilizar bibliotecas estáticas</strong>. Drivers, middlewares, camadas de abstração e até subsistemas inteiros podem ser encapsulados em bibliotecas independentes, com seus próprios includes, defines e opções de compilação.</p>



<p class="wp-block-paragraph">Essas bibliotecas deixam de ser “copiadas e coladas” entre projetos e passam a ser <strong>componentes versionáveis</strong>, facilmente integrados por meio de <code>add_subdirectory()</code> ou mecanismos como <code>FetchContent</code>. O CMake garante que cada biblioteca seja compilada no contexto correto e ligada de forma consistente ao firmware final.</p>



<p class="wp-block-paragraph">Esse modelo é essencial para quem mantém múltiplos projetos STM32 ou deseja construir uma base técnica sólida ao longo do tempo. O build passa a refletir a arquitetura do software, e não apenas uma sequência de comandos.</p>



<h2 class="wp-block-heading">Erros comuns e armadilhas em STM32 + CMake</h2>



<p class="wp-block-paragraph">Apesar de poderoso, o CMake não perdoa descuidos conceituais. Um erro frequente é tratar o <code>CMakeLists.txt</code> como um Makefile disfarçado, concentrando tudo em um único arquivo, com variáveis globais e pouca modularização. Isso anula grande parte dos benefícios do sistema.</p>



<p class="wp-block-paragraph">Outro problema recorrente é misturar configurações de toolchain com lógica do projeto. Sempre que o <code>CMakeLists.txt</code> começa a conter caminhos absolutos para compiladores ou flags específicas de uma máquina, o projeto perde portabilidade imediatamente. A separação entre <strong>toolchain</strong> e <strong>projeto</strong> é inegociável em ambientes profissionais.</p>



<p class="wp-block-paragraph">O uso indiscriminado de <code>file(GLOB)</code> também merece atenção. Embora conveniente, ele pode comprometer a reprodutibilidade do build se usado sem critério. Em firmware, previsibilidade sempre deve pesar mais do que comodidade.</p>



<p class="wp-block-paragraph">Por fim, a falta de entendimento sobre escopos — PRIVATE, PUBLIC e INTERFACE — costuma gerar projetos frágeis, cheios de dependências implícitas. O CMake oferece as ferramentas para evitar isso, mas cabe ao engenheiro usá-las corretamente.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Exemplo ideal de <code>CMakeLists.txt</code> para STM32 (CubeMX) + arquivo <code>.cmake</code> de toolchain</h2>



<p class="wp-block-paragraph">Abaixo vai um <strong>exemplo de referência</strong> (um “padrão ouro” pragmático) para projetos STM32 gerados pelo CubeMX. Ele aplica <strong>todas as diretivas que discutimos</strong> e deixa claro, por comentários, <strong>por que cada parte existe</strong>. Em seguida, incluo um <strong>arquivo <code>.cmake</code></strong> de toolchain para <code>arm-none-eabi-gcc</code> (modelo compatível com GCC do CubeIDE ou GNU Arm Embedded).</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Observação importante: este exemplo assume uma árvore típica:</p>



<ul class="wp-block-list">
<li><code>Core/</code> e <code>Drivers/</code> vindos do CubeMX</li>



<li><code>startup/</code> com startup assembly</li>



<li><code>linker/</code> com o <code>.ld</code></li>



<li><code>app/</code> para seu código autoral</li>



<li><code>cmake/</code> para toolchain e helpers</li>
</ul>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><code>CMakeLists.txt</code> (raiz do projeto)</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># ============================================================
#  CMakeLists.txt - Projeto STM32 (CubeMX) com arquitetura limpa
# ============================================================

# 1) Garante previsibilidade de comportamento do CMake.
cmake_minimum_required(VERSION 3.22)

# 2) Declara formalmente o projeto e as linguagens.
#    Em STM32 quase sempre é C + ASM (startup).
project(stm32_firmware
  VERSION 1.0.0
  LANGUAGES C ASM
)

# 3) Controle do padrão de linguagem (contrato explícito com o compilador).
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
# Em STM32, frequentemente extensões GNU são úteis (HAL/CMSIS às vezes dependem).
set(CMAKE_C_EXTENSIONS ON)

# 4) Define um build type padrão quando o gerador é single-config (Makefiles/Ninja).
#    Em multi-config (ex.: Visual Studio), isso é ignorado.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
endif()

# 5) Diretórios principais do projeto
set(APP_DIR       ${CMAKE_SOURCE_DIR}/app)
set(CORE_DIR      ${CMAKE_SOURCE_DIR}/Core)
set(DRIVERS_DIR   ${CMAKE_SOURCE_DIR}/Drivers)
set(STARTUP_DIR   ${CMAKE_SOURCE_DIR}/startup)
set(LINKER_DIR    ${CMAKE_SOURCE_DIR}/linker)

# 6) Script de linker (ajuste para o .ld do seu MCU)
set(LINKER_SCRIPT ${LINKER_DIR}/STM32xxxx_FLASH.ld)

# ------------------------------------------------------------
#  BLOBS / Coleções de arquivos (file(GLOB))
#  Use com critério: recomendado para diretórios estáveis (ex.: Drivers).
#  Para app/ prefira listas explícitas (reprodutibilidade).
# ------------------------------------------------------------
file(GLOB HAL_SOURCES
  ${DRIVERS_DIR}/STM32*/Src/*.c
  ${DRIVERS_DIR}/CMSIS/Device/ST/*/Source/Templates/*.c
)

# Exemplo de “BLOB”: um binário que você quer embutir no firmware
# (pode ser fonte, lookup table, certificado, etc.)
set(BLOB_BIN ${CMAKE_SOURCE_DIR}/assets/blob.bin)

# ------------------------------------------------------------
#  7) Biblioteca estática para HAL/CMSIS (reutilizável)
# ------------------------------------------------------------
add_library(stm32_hal STATIC)

# Adiciona fontes do HAL/CMSIS (coleção via GLOB; diretório estável)
target_sources(stm32_hal PRIVATE
  ${HAL_SOURCES}
  # Se você tem system_stm32xxxx.c gerado pelo CubeMX, inclua aqui.
  ${CORE_DIR}/Src/system_stm32xxxx.c
)

# Includes do HAL/CMSIS
target_include_directories(stm32_hal PUBLIC
  ${CORE_DIR}/Inc
  ${DRIVERS_DIR}/CMSIS/Include
  ${DRIVERS_DIR}/CMSIS/Device/ST/STM32xxxx/Include
  ${DRIVERS_DIR}/STM32xxxx_HAL_Driver/Inc
)

# Defines exigidos pelo CubeMX/HAL (escopo bem definido)
target_compile_definitions(stm32_hal PUBLIC
  USE_HAL_DRIVER
  STM32xxxx
)

# Flags específicas por target (ex.: warnings do HAL)
# (Você pode ajustar e mover para um helper .cmake se quiser.)
target_compile_options(stm32_hal PRIVATE
  -Wall -Wextra
)

# ------------------------------------------------------------
#  8) Biblioteca estática para sua camada de aplicação (opcional, mas ideal)
# ------------------------------------------------------------
add_library(app_lib STATIC)

# Para o código autoral, prefira listar explicitamente as fontes:
target_sources(app_lib PRIVATE
  ${APP_DIR}/src/app_main.c
  ${APP_DIR}/src/app_tasks.c
  ${APP_DIR}/src/app_drivers.c
)

target_include_directories(app_lib PUBLIC
  ${APP_DIR}/include
)

target_compile_definitions(app_lib PUBLIC
  APP_VERSION=\"${PROJECT_VERSION}\"
)

# Dependência explícita: app usa HAL
target_link_libraries(app_lib PUBLIC stm32_hal)

# ------------------------------------------------------------
#  9) Firmware final (ELF)
# ------------------------------------------------------------
add_executable(${PROJECT_NAME}.elf)

# Startup (ASM) e fontes CubeMX “Core”
target_sources(${PROJECT_NAME}.elf PRIVATE
  ${STARTUP_DIR}/startup_stm32xxxx.s
  ${CORE_DIR}/Src/main.c
  ${CORE_DIR}/Src/stm32xxxx_it.c
  ${CORE_DIR}/Src/stm32xxxx_hal_msp.c
  ${CORE_DIR}/Src/syscalls.c
  ${CORE_DIR}/Src/sysmem.c
)

# Inclui o BLOB no build (como dependência para empacotar/gerar header, se necessário)
# Aqui mostramos como gerar um .o a partir de .bin (técnica comum).
# Isso requer objcopy da toolchain.
set(BLOB_OBJ ${CMAKE_BINARY_DIR}/blob.o)

add_custom_command(
  OUTPUT ${BLOB_OBJ}
  COMMAND ${CMAKE_OBJCOPY} -I binary -O elf32-littlearm -B arm ${BLOB_BIN} ${BLOB_OBJ}
  DEPENDS ${BLOB_BIN}
  COMMENT "Convertendo BLOB binário em objeto linkável: blob.o"
)

# Adiciona o blob.o ao firmware
target_sources(${PROJECT_NAME}.elf PRIVATE ${BLOB_OBJ})

# Includes do firmware (o executável também pode precisar de headers específicos)
target_include_directories(${PROJECT_NAME}.elf PRIVATE
  ${CORE_DIR}/Inc
  ${APP_DIR}/include
)

# Defines do firmware (ex.: debug, features)
target_compile_definitions(${PROJECT_NAME}.elf PRIVATE
  # Exemplo: liga logs em Debug
  $&lt;$&lt;CONFIG:Debug>:APP_LOG_ENABLE=1>
)

# Linka bibliotecas internas (ordem e dependências ficam claras)
target_link_libraries(${PROJECT_NAME}.elf PRIVATE
  app_lib
  stm32_hal
)

# 10) Flags de link: script .ld, map, gc-sections
target_link_options(${PROJECT_NAME}.elf PRIVATE
  -T${LINKER_SCRIPT}
  -Wl,-Map=${PROJECT_NAME}.map
  -Wl,--gc-sections
  -Wl,--print-memory-usage
)

# (Opcional) Se você precisa apontar diretórios extras de bibliotecas pré-compiladas:
# Use com cautela. Prefira targets CMake quando possível.
# target_link_directories(${PROJECT_NAME}.elf PRIVATE ${CMAKE_SOURCE_DIR}/third_party/lib)

# ------------------------------------------------------------
#  11) Geração de .bin e .hex a partir do .elf
# ------------------------------------------------------------
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
  COMMAND ${CMAKE_OBJCOPY} -O ihex   $&lt;TARGET_FILE:${PROJECT_NAME}.elf> ${PROJECT_NAME}.hex
  COMMAND ${CMAKE_OBJCOPY} -O binary $&lt;TARGET_FILE:${PROJECT_NAME}.elf> ${PROJECT_NAME}.bin
  COMMAND ${CMAKE_SIZE} $&lt;TARGET_FILE:${PROJECT_NAME}.elf>
  COMMENT "Gerando artefatos: .hex, .bin e exibindo size"
)
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">============================================================</span></span>
<span class="line"><span style="color: #D8DEE9FF">#  </span><span style="color: #D8DEE9">CMakeLists</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">txt</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Projeto</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">STM32</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">CubeMX</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">com</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">arquitetura</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">limpa</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">============================================================</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">Garante</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">previsibilidade</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">comportamento</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CMake</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #88C0D0">cmake_minimum_required</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">VERSION</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.22</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">Declara</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">formalmente</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">projeto</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">e</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> linguagens</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #D8DEE9FF">#    </span><span style="color: #D8DEE9">Em</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STM32</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">quase</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sempre</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">é</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">C</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ASM</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">startup</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #88C0D0">project</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">stm32_firmware</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">VERSION</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1.0</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">0</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">LANGUAGES</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">C</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ASM</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">Controle</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">padrão</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">linguagem</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">contrato</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">explícito</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">com</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">compilador</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_C_STANDARD</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">11</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_C_STANDARD_REQUIRED</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ON</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Em</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STM32</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">frequentemente</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">extensões</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">GNU</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">são</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">úteis</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">HAL</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">CMSIS</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">às</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">vezes</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">dependem</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_C_EXTENSIONS</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ON</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">Define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">um</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">build</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">type</span><span style="color: #D8DEE9FF"> padrão quando o gerador é single-config (Makefiles/Ninja).</span></span>
<span class="line"><span style="color: #D8DEE9FF">#    Em multi-config (ex.: Visual Studio), isso é ignorado.</span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NOT</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CMAKE_BUILD_TYPE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AND</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NOT</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CMAKE_CONFIGURATION_TYPES</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_BUILD_TYPE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Debug</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CACHE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STRING</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Build type</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FORCE</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">endif</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #B48EAD">5</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">Diretórios</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">principais</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">projeto</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">APP_DIR</span><span style="color: #D8DEE9FF">       </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">CMAKE_SOURCE_DIR</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CORE_DIR</span><span style="color: #D8DEE9FF">      </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">CMAKE_SOURCE_DIR</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">Core</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">DRIVERS_DIR</span><span style="color: #D8DEE9FF">   </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">CMAKE_SOURCE_DIR</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">Drivers</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">STARTUP_DIR</span><span style="color: #D8DEE9FF">   </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">CMAKE_SOURCE_DIR</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">startup</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LINKER_DIR</span><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">CMAKE_SOURCE_DIR</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">linker</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #B48EAD">6</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">Script</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">linker</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">ajuste</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">ld</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">seu</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MCU</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LINKER_SCRIPT</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">LINKER_DIR</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">STM32xxxx_FLASH</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">ld</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D8DEE9FF">#  </span><span style="color: #D8DEE9">BLOBS</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Coleções</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">arquivos</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">file</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">GLOB</span><span style="color: #D8DEE9FF">))</span></span>
<span class="line"><span style="color: #D8DEE9FF">#  </span><span style="color: #D8DEE9">Use</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">com</span><span style="color: #D8DEE9FF"> critério</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">recomendado</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">diretórios</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">estáveis</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">ex</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">: </span><span style="color: #D8DEE9">Drivers</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #D8DEE9FF">#  </span><span style="color: #D8DEE9">Para</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">prefira</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">listas</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">explícitas</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">reprodutibilidade</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">------------------------------------------------------------</span></span>
<span class="line"><span style="color: #88C0D0">file</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">GLOB</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_SOURCES</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">DRIVERS_DIR</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">STM32</span><span style="color: #81A1C1">*/</span><span style="color: #D8DEE9">Src</span><span style="color: #616E88">/*.c</span></span>
<span class="line"><span style="color: #616E88">  ${DRIVERS_DIR}/CMSIS/Device/ST/*/</span><span style="color: #D8DEE9">Source</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">Templates</span><span style="color: #616E88">/*.c</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Exemplo de “BLOB”: um binário que você quer embutir no firmware</span></span>
<span class="line"><span style="color: #616E88"># (pode ser fonte, lookup table, certificado, etc.)</span></span>
<span class="line"><span style="color: #616E88">set(BLOB_BIN ${CMAKE_SOURCE_DIR}/assets/blob.bin)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># ------------------------------------------------------------</span></span>
<span class="line"><span style="color: #616E88">#  7) Biblioteca estática para HAL/CMSIS (reutilizável)</span></span>
<span class="line"><span style="color: #616E88"># ------------------------------------------------------------</span></span>
<span class="line"><span style="color: #616E88">add_library(stm32_hal STATIC)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Adiciona fontes do HAL/CMSIS (coleção via GLOB; diretório estável)</span></span>
<span class="line"><span style="color: #616E88">target_sources(stm32_hal PRIVATE</span></span>
<span class="line"><span style="color: #616E88">  ${HAL_SOURCES}</span></span>
<span class="line"><span style="color: #616E88">  # Se você tem system_stm32xxxx.c gerado pelo CubeMX, inclua aqui.</span></span>
<span class="line"><span style="color: #616E88">  ${CORE_DIR}/Src/system_stm32xxxx.c</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Includes do HAL/CMSIS</span></span>
<span class="line"><span style="color: #616E88">target_include_directories(stm32_hal PUBLIC</span></span>
<span class="line"><span style="color: #616E88">  ${CORE_DIR}/Inc</span></span>
<span class="line"><span style="color: #616E88">  ${DRIVERS_DIR}/CMSIS/Include</span></span>
<span class="line"><span style="color: #616E88">  ${DRIVERS_DIR}/CMSIS/Device/ST/STM32xxxx/Include</span></span>
<span class="line"><span style="color: #616E88">  ${DRIVERS_DIR}/STM32xxxx_HAL_Driver/Inc</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Defines exigidos pelo CubeMX/HAL (escopo bem definido)</span></span>
<span class="line"><span style="color: #616E88">target_compile_definitions(stm32_hal PUBLIC</span></span>
<span class="line"><span style="color: #616E88">  USE_HAL_DRIVER</span></span>
<span class="line"><span style="color: #616E88">  STM32xxxx</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Flags específicas por target (ex.: warnings do HAL)</span></span>
<span class="line"><span style="color: #616E88"># (Você pode ajustar e mover para um helper .cmake se quiser.)</span></span>
<span class="line"><span style="color: #616E88">target_compile_options(stm32_hal PRIVATE</span></span>
<span class="line"><span style="color: #616E88">  -Wall -Wextra</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># ------------------------------------------------------------</span></span>
<span class="line"><span style="color: #616E88">#  8) Biblioteca estática para sua camada de aplicação (opcional, mas ideal)</span></span>
<span class="line"><span style="color: #616E88"># ------------------------------------------------------------</span></span>
<span class="line"><span style="color: #616E88">add_library(app_lib STATIC)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Para o código autoral, prefira listar explicitamente as fontes:</span></span>
<span class="line"><span style="color: #616E88">target_sources(app_lib PRIVATE</span></span>
<span class="line"><span style="color: #616E88">  ${APP_DIR}/src/app_main.c</span></span>
<span class="line"><span style="color: #616E88">  ${APP_DIR}/src/app_tasks.c</span></span>
<span class="line"><span style="color: #616E88">  ${APP_DIR}/src/app_drivers.c</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">target_include_directories(app_lib PUBLIC</span></span>
<span class="line"><span style="color: #616E88">  ${APP_DIR}/include</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">target_compile_definitions(app_lib PUBLIC</span></span>
<span class="line"><span style="color: #616E88">  APP_VERSION=\&quot;${PROJECT_VERSION}\&quot;</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Dependência explícita: app usa HAL</span></span>
<span class="line"><span style="color: #616E88">target_link_libraries(app_lib PUBLIC stm32_hal)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># ------------------------------------------------------------</span></span>
<span class="line"><span style="color: #616E88">#  9) Firmware final (ELF)</span></span>
<span class="line"><span style="color: #616E88"># ------------------------------------------------------------</span></span>
<span class="line"><span style="color: #616E88">add_executable(${PROJECT_NAME}.elf)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Startup (ASM) e fontes CubeMX “Core”</span></span>
<span class="line"><span style="color: #616E88">target_sources(${PROJECT_NAME}.elf PRIVATE</span></span>
<span class="line"><span style="color: #616E88">  ${STARTUP_DIR}/startup_stm32xxxx.s</span></span>
<span class="line"><span style="color: #616E88">  ${CORE_DIR}/Src/main.c</span></span>
<span class="line"><span style="color: #616E88">  ${CORE_DIR}/Src/stm32xxxx_it.c</span></span>
<span class="line"><span style="color: #616E88">  ${CORE_DIR}/Src/stm32xxxx_hal_msp.c</span></span>
<span class="line"><span style="color: #616E88">  ${CORE_DIR}/Src/syscalls.c</span></span>
<span class="line"><span style="color: #616E88">  ${CORE_DIR}/Src/sysmem.c</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Inclui o BLOB no build (como dependência para empacotar/gerar header, se necessário)</span></span>
<span class="line"><span style="color: #616E88"># Aqui mostramos como gerar um .o a partir de .bin (técnica comum).</span></span>
<span class="line"><span style="color: #616E88"># Isso requer objcopy da toolchain.</span></span>
<span class="line"><span style="color: #616E88">set(BLOB_OBJ ${CMAKE_BINARY_DIR}/blob.o)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">add_custom_command(</span></span>
<span class="line"><span style="color: #616E88">  OUTPUT ${BLOB_OBJ}</span></span>
<span class="line"><span style="color: #616E88">  COMMAND ${CMAKE_OBJCOPY} -I binary -O elf32-littlearm -B arm ${BLOB_BIN} ${BLOB_OBJ}</span></span>
<span class="line"><span style="color: #616E88">  DEPENDS ${BLOB_BIN}</span></span>
<span class="line"><span style="color: #616E88">  COMMENT &quot;Convertendo BLOB binário em objeto linkável: blob.o&quot;</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Adiciona o blob.o ao firmware</span></span>
<span class="line"><span style="color: #616E88">target_sources(${PROJECT_NAME}.elf PRIVATE ${BLOB_OBJ})</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Includes do firmware (o executável também pode precisar de headers específicos)</span></span>
<span class="line"><span style="color: #616E88">target_include_directories(${PROJECT_NAME}.elf PRIVATE</span></span>
<span class="line"><span style="color: #616E88">  ${CORE_DIR}/Inc</span></span>
<span class="line"><span style="color: #616E88">  ${APP_DIR}/include</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Defines do firmware (ex.: debug, features)</span></span>
<span class="line"><span style="color: #616E88">target_compile_definitions(${PROJECT_NAME}.elf PRIVATE</span></span>
<span class="line"><span style="color: #616E88">  # Exemplo: liga logs em Debug</span></span>
<span class="line"><span style="color: #616E88">  $&lt;$&lt;CONFIG:Debug&gt;:APP_LOG_ENABLE=1&gt;</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># Linka bibliotecas internas (ordem e dependências ficam claras)</span></span>
<span class="line"><span style="color: #616E88">target_link_libraries(${PROJECT_NAME}.elf PRIVATE</span></span>
<span class="line"><span style="color: #616E88">  app_lib</span></span>
<span class="line"><span style="color: #616E88">  stm32_hal</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># 10) Flags de link: script .ld, map, gc-sections</span></span>
<span class="line"><span style="color: #616E88">target_link_options(${PROJECT_NAME}.elf PRIVATE</span></span>
<span class="line"><span style="color: #616E88">  -T${LINKER_SCRIPT}</span></span>
<span class="line"><span style="color: #616E88">  -Wl,-Map=${PROJECT_NAME}.map</span></span>
<span class="line"><span style="color: #616E88">  -Wl,--gc-sections</span></span>
<span class="line"><span style="color: #616E88">  -Wl,--print-memory-usage</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># (Opcional) Se você precisa apontar diretórios extras de bibliotecas pré-compiladas:</span></span>
<span class="line"><span style="color: #616E88"># Use com cautela. Prefira targets CMake quando possível.</span></span>
<span class="line"><span style="color: #616E88"># target_link_directories(${PROJECT_NAME}.elf PRIVATE ${CMAKE_SOURCE_DIR}/third_party/lib)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88"># ------------------------------------------------------------</span></span>
<span class="line"><span style="color: #616E88">#  11) Geração de .bin e .hex a partir do .elf</span></span>
<span class="line"><span style="color: #616E88"># ------------------------------------------------------------</span></span>
<span class="line"><span style="color: #616E88">add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD</span></span>
<span class="line"><span style="color: #616E88">  COMMAND ${CMAKE_OBJCOPY} -O ihex   $&lt;TARGET_FILE:${PROJECT_NAME}.elf&gt; ${PROJECT_NAME}.hex</span></span>
<span class="line"><span style="color: #616E88">  COMMAND ${CMAKE_OBJCOPY} -O binary $&lt;TARGET_FILE:${PROJECT_NAME}.elf&gt; ${PROJECT_NAME}.bin</span></span>
<span class="line"><span style="color: #616E88">  COMMAND ${CMAKE_SIZE} $&lt;TARGET_FILE:${PROJECT_NAME}.elf&gt;</span></span>
<span class="line"><span style="color: #616E88">  COMMENT &quot;Gerando artefatos: .hex, .bin e exibindo size&quot;</span></span>
<span class="line"><span style="color: #616E88">)</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">Arquivo de toolchain: <code>cmake/toolchains/arm-none-eabi-gcc.cmake</code></h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly># ============================================================
#  arm-none-eabi-gcc.cmake - Toolchain STM32 (GCC bare-metal)
#  Use com: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=...
# ============================================================

# Diz ao CMake que estamos compilando para um sistema "genérico" (bare-metal).
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)

# Evita que o CMake tente rodar executáveis gerados (não rodam no host).
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

# Prefixo padrão da toolchain GNU Arm Embedded / CubeIDE
set(TOOLCHAIN_PREFIX arm-none-eabi)

# Permite sobrescrever via ambiente, útil em CI:
# export ARM_GCC_PATH=/caminho/para/bin
if(DEFINED ENV{ARM_GCC_PATH})
  set(ARM_GCC_BIN "$ENV{ARM_GCC_PATH}")
else()
  set(ARM_GCC_BIN "") # usa PATH
endif()

# Compiladores
set(CMAKE_C_COMPILER   ${ARM_GCC_BIN}${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_ASM_COMPILER ${ARM_GCC_BIN}${TOOLCHAIN_PREFIX}-gcc)

# Ferramentas auxiliares (usadas para .bin/.hex e size)
set(CMAKE_OBJCOPY ${ARM_GCC_BIN}${TOOLCHAIN_PREFIX}-objcopy CACHE FILEPATH "")
set(CMAKE_SIZE    ${ARM_GCC_BIN}${TOOLCHAIN_PREFIX}-size    CACHE FILEPATH "")

# Flags de arquitetura (AJUSTE conforme seu MCU: cortex-m4/m7/m33 etc.)
set(ARCH_FLAGS "-mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard")

# Flags comuns
set(COMMON_FLAGS
  "${ARCH_FLAGS} -ffunction-sections -fdata-sections -fno-common"
)

# Debug vs Release pode ser refinado no projeto ou via presets
set(CMAKE_C_FLAGS_INIT "${COMMON_FLAGS}")
set(CMAKE_ASM_FLAGS_INIT "${COMMON_FLAGS}")

# Flags típicas de link em bare-metal (você complementa no target_link_options)
set(CMAKE_EXE_LINKER_FLAGS_INIT
  "${ARCH_FLAGS} -Wl,--gc-sections"
)

# (Opcional) Se você usa newlib-nano e nosys
# set(CMAKE_EXE_LINKER_FLAGS_INIT
#   "${CMAKE_EXE_LINKER_FLAGS_INIT} -specs=nano.specs -specs=nosys.specs"
# )
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">============================================================</span></span>
<span class="line"><span style="color: #D8DEE9FF">#  </span><span style="color: #D8DEE9">arm</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">none</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">eabi</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">gcc</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">cmake</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Toolchain</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">STM32</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">GCC</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bare</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">metal</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">#  </span><span style="color: #D8DEE9">Use</span><span style="color: #D8DEE9FF"> com</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cmake</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">S</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">B</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">build</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">DCMAKE_TOOLCHAIN_FILE</span><span style="color: #81A1C1">=...</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">============================================================</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Diz</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ao</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CMake</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">que</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">estamos</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">compilando</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">um</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sistema</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">genérico</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">bare</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">metal</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_SYSTEM_NAME</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Generic</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_SYSTEM_PROCESSOR</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">arm</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Evita</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">que</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CMake</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tente</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rodar</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">executáveis</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">gerados</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">não</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rodam</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">no</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">host</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_TRY_COMPILE_TARGET_TYPE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">STATIC_LIBRARY</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Prefixo</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">padrão</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">da</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">toolchain</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">GNU</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Arm</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Embedded</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CubeIDE</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">TOOLCHAIN_PREFIX</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">arm</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">none</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">eabi</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Permite</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sobrescrever</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">via</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ambiente</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">útil</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">em</span><span style="color: #D8DEE9FF"> CI</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">export</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ARM_GCC_PATH</span><span style="color: #81A1C1">=/</span><span style="color: #D8DEE9">caminho</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">para</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">bin</span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">DEFINED</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ENV</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">ARM_GCC_PATH</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">ARM_GCC_BIN</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{ARM_GCC_PATH}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">ARM_GCC_BIN</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #D8DEE9FF">) # </span><span style="color: #D8DEE9">usa</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PATH</span></span>
<span class="line"><span style="color: #88C0D0">endif</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Compiladores</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_C_COMPILER</span><span style="color: #D8DEE9FF">   </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">ARM_GCC_BIN</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">TOOLCHAIN_PREFIX</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">gcc</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_ASM_COMPILER</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">ARM_GCC_BIN</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">TOOLCHAIN_PREFIX</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">gcc</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Ferramentas</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">auxiliares</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">usadas</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">bin</span><span style="color: #81A1C1">/</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">hex</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">e</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">size</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_OBJCOPY</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">ARM_GCC_BIN</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">TOOLCHAIN_PREFIX</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">objcopy</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CACHE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FILEPATH</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_SIZE</span><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">ARM_GCC_BIN</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">TOOLCHAIN_PREFIX</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">size</span><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">CACHE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FILEPATH</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Flags</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">arquitetura</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">AJUSTE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">conforme</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">seu</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MCU</span><span style="color: #D8DEE9FF">: </span><span style="color: #D8DEE9">cortex</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">m4</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">m7</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">m33</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">etc</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">ARCH_FLAGS</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">-mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Flags</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">comuns</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">COMMON_FLAGS</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${ARCH_FLAGS} -ffunction-sections -fdata-sections -fno-common</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Debug</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">vs</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Release</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pode</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ser</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">refinado</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">no</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">projeto</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ou</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">via</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">presets</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_C_FLAGS_INIT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${COMMON_FLAGS}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_ASM_FLAGS_INIT</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${COMMON_FLAGS}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Flags</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">típicas</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">link</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">em</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bare</span><span style="color: #81A1C1">-</span><span style="color: #88C0D0">metal</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">você</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">complementa</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">no</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">target_link_options</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_EXE_LINKER_FLAGS_INIT</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${ARCH_FLAGS} -Wl,--gc-sections</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># (</span><span style="color: #D8DEE9">Opcional</span><span style="color: #D8DEE9FF">) </span><span style="color: #D8DEE9">Se</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">você</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">usa</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">newlib</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">nano</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">e</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">nosys</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_EXE_LINKER_FLAGS_INIT</span></span>
<span class="line"><span style="color: #D8DEE9FF">#   </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${CMAKE_EXE_LINKER_FLAGS_INIT} -specs=nano.specs -specs=nosys.specs</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF"># )</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">CMake como ferramenta de engenharia, não apenas de build</h2>



<p class="wp-block-paragraph">Adotar CMake em projetos STM32 não é apenas uma escolha técnica; é uma <strong>decisão de engenharia de software</strong>. Ele transforma o processo de build em algo declarativo, previsível e alinhado com boas práticas modernas, aproximando o desenvolvimento embarcado do rigor encontrado em sistemas de maior escala.</p>



<p class="wp-block-paragraph">Quando bem utilizado, o CMake deixa de ser um obstáculo e passa a ser um <strong>mapa formal da arquitetura do firmware</strong>. Ele documenta dependências, explicita decisões técnicas e reduz drasticamente o custo de manutenção ao longo do tempo.</p>



<p class="wp-block-paragraph">Para projetos STM32 gerados pelo CubeMX, essa combinação representa o melhor dos dois mundos: a produtividade do gerador de código da ST e a flexibilidade de um sistema de build profissional, independente de IDEs proprietárias.</p><p>The post <a href="https://mcu.tec.br/linguagem/builds/introducao-ao-cmake-em-projetos-stm32-gerados-pelo-cubemx/">Introdução ao CMake em Projetos STM32 Gerados pelo CubeMX</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1069</post-id>	</item>
		<item>
		<title>Como Estruturar um Projeto Profissional com CMake para o RP2040: Guia Didático Passo a Passo</title>
		<link>https://mcu.tec.br/linguagem/builds/como-estruturar-um-projeto-profissional-com-cmake-para-o-rp2040-guia-didatico-passo-a-passo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=como-estruturar-um-projeto-profissional-com-cmake-para-o-rp2040-guia-didatico-passo-a-passo</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 01 Aug 2025 01:06:42 +0000</pubDate>
				<category><![CDATA[Builds]]></category>
		<category><![CDATA[build system CMake]]></category>
		<category><![CDATA[CMake]]></category>
		<category><![CDATA[CMakeLists.txt]]></category>
		<category><![CDATA[compile_commands.json]]></category>
		<category><![CDATA[env.cmake]]></category>
		<category><![CDATA[firmware embarcado]]></category>
		<category><![CDATA[lwIP MQTT]]></category>
		<category><![CDATA[microcontrolador com Wi-Fi]]></category>
		<category><![CDATA[MQTT embedded]]></category>
		<category><![CDATA[projeto embarcado]]></category>
		<category><![CDATA[projeto RP2040]]></category>
		<category><![CDATA[Raspberry Pi Pico]]></category>
		<category><![CDATA[RP2040]]></category>
		<category><![CDATA[SDK Pico]]></category>
		<category><![CDATA[stdio UART]]></category>
		<category><![CDATA[stdio USB]]></category>
		<category><![CDATA[toolchain para RP2040]]></category>
		<category><![CDATA[variável de ambiente]]></category>
		<category><![CDATA[Wi-Fi no RP2040]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=635</guid>

					<description><![CDATA[<p>Aprenda a estruturar corretamente um projeto para o microcontrolador RP2040 utilizando CMake. Este guia didático passo a passo explica cada linha do CMakeLists.txt, desde variáveis de ambiente até a geração do firmware .uf2, com foco em boas práticas e clareza para iniciantes.</p>
<p>The post <a href="https://mcu.tec.br/linguagem/builds/como-estruturar-um-projeto-profissional-com-cmake-para-o-rp2040-guia-didatico-passo-a-passo/">Como Estruturar um Projeto Profissional com CMake para o RP2040: Guia Didático Passo a Passo</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">No universo do desenvolvimento embarcado, a jornada do iniciante pode parecer repleta de barreiras invisíveis. Uma das mais frequentes – e subestimadas – está na <strong>estruturação correta do projeto</strong>, especialmente quando se trata de plataformas modernas como o <strong>RP2040</strong>, o microcontrolador da Raspberry Pi Foundation. Antes mesmo de escrever a primeira linha de código C, é essencial compreender como preparar o ambiente de compilação, como organizar os arquivos e como garantir que tudo esteja pronto para transformar ideias em firmware funcional.</p>



<p class="wp-block-paragraph">Neste contexto, o sistema de build <strong>CMake</strong> se torna uma ferramenta central. Apesar de sua aparência intimidadora para quem está começando, o CMake é uma ponte poderosa entre o código-fonte e o binário que rodará no seu dispositivo. Ele permite organizar dependências, configurar variáveis, compilar múltiplos arquivos e até mesmo lidar com diferentes toolchains de forma automatizada. E quando combinamos o CMake com o ecossistema do RP2040, especialmente com o <strong>Pico SDK</strong>, temos um ambiente robusto, escalável e flexível — desde projetos educacionais até aplicações industriais.</p>



<p class="wp-block-paragraph">Por isso, este artigo tem como objetivo guiar o leitor iniciante <strong>passo a passo</strong> pela análise de um projeto real baseado no RP2040, explicando detalhadamente cada trecho do arquivo <code>CMakeLists.txt</code> e os scripts auxiliares que compõem a infraestrutura de build. Vamos abordar o papel de cada linha, o porquê das decisões adotadas, e quais boas práticas estão sendo aplicadas — além de sugerir melhorias e comparações com abordagens de outras plataformas.</p>



<p class="wp-block-paragraph">Este não é apenas um guia técnico: é também um convite à compreensão. Ao final desta leitura, você não apenas será capaz de compilar um projeto com confiança, mas também entenderá <strong>por que cada etapa é importante</strong>. Assim, poderá adaptar seus projetos futuros com segurança e domínio técnico, explorando todo o potencial do RP2040.</p>



<p class="wp-block-paragraph">Prepare seu editor de texto e acompanhe cada seção com atenção — pois cada linha que vamos explorar é um pequeno degrau em direção à maestria no desenvolvimento embarcado moderno.</p>



<p class="wp-block-paragraph">Para este artigo foi usado os seguintes arquivos CMakeLists.txt:</p>



<ul class="wp-block-list">
<li><a href="https://github.com/carlosdelfino/embarcatech_etapa_2_cap_2_Tarefa-Pr-tica-IOT-3/blob/main/rp2040_mqtt_server_example/CMakeLists.txt">https://github.com/carlosdelfino/embarcatech_etapa_2_cap_2_Tarefa-Pr-tica-IOT-3/blob/main/rp2040_mqtt_server_example/CMakeLists.txt</a> </li>



<li><a href="https://github.com/carlosdelfino/embarcatech_etapa_2_cap_2_Tarefa-Pr-tica-IOT-3/blob/main/rp2040_mqtt_client_example/CMakeLists.txt ">https://github.com/carlosdelfino/embarcatech_etapa_2_cap_2_Tarefa-Pr-tica-IOT-3/blob/main/rp2040_mqtt_client_example/CMakeLists.txt </a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><strong>1. Configuração Inicial do CMake: Definindo Versão e Padrões do Projeto</strong></h2>



<p class="wp-block-paragraph">Logo no início do arquivo <code>CMakeLists.txt</code>, temos um trecho essencial para garantir a compatibilidade e padronização do ambiente de compilação. Veja abaixo:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="cmake_minimum_required(VERSION 3.13)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">cmake_minimum_required</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">VERSION</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.13</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_C_STANDARD</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">11</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_CXX_STANDARD</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">17</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_EXPORT_COMPILE_COMMANDS</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ON</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong><code>cmake_minimum_required(VERSION 3.13)</code></strong><br>Esta linha define a <strong>versão mínima do CMake</strong> exigida para processar corretamente este projeto. O valor <code>3.13</code> é uma escolha segura para projetos com RP2040, pois é compatível com as versões mais estáveis do SDK da Raspberry Pi e da extensão para VSCode. Se o desenvolvedor tentar compilar o projeto com uma versão mais antiga do CMake, ele receberá uma mensagem de erro clara, evitando comportamento indefinido ou suporte incompleto a recursos.</li>



<li><strong><code>set(CMAKE_C_STANDARD 11)</code></strong><br>Define que o código C será compilado segundo o <strong>padrão C11</strong>, uma versão estável e moderna da linguagem C, que inclui melhorias importantes como <em>atomics</em>, <em>static assertions</em> e melhor suporte a multithreading.</li>



<li><strong><code>set(CMAKE_CXX_STANDARD 17)</code></strong><br>Determina que, caso o projeto inclua arquivos em C++, eles devem seguir o padrão <strong>C++17</strong>. Este padrão oferece recursos como <em>structured bindings</em>, <em>if constexpr</em>, e <em>std::optional</em>, que podem ser úteis em aplicações mais complexas.</li>



<li><strong><code>set(CMAKE_EXPORT_COMPILE_COMMANDS ON)</code></strong><br>Esta opção gera o arquivo <code>compile_commands.json</code>, que descreve os comandos de compilação de cada fonte no projeto. Ele é extremamente útil para ferramentas externas como <strong>servidores de linguagem (LSPs)</strong>, <strong>linters</strong> e <strong>analisadores estáticos</strong>, como o <code>clangd</code>.</li>
</ol>



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>A escolha de <strong>C11 e C++17</strong> é apropriada: garante modernidade sem sacrificar a compatibilidade com a maioria dos toolchains usados no mundo embarcado.</li>



<li>A inclusão de <code>CMAKE_EXPORT_COMPILE_COMMANDS</code> mostra preocupação com a <strong>qualidade do desenvolvimento</strong>, pois favorece a integração com IDEs modernas e ferramentas de verificação de código.</li>



<li>Poderia ser interessante tornar os padrões configuráveis via variável de cache (<code>CACHE STRING</code>), permitindo ao usuário customizar sem alterar diretamente o CMakeLists.txt.</li>
</ul>



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f530.png" alt="🔰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Para iniciantes:</strong> Pense nesta seção como o &#8220;acordo inicial&#8221; entre você e o compilador. Aqui você diz: “vamos trabalhar com a linguagem C moderna, C++ moderno e quero um ambiente que me ajude a detectar erros logo no começo”.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Boas práticas:</strong> Sempre explicite o padrão da linguagem em projetos embarcados. Evita surpresas e garante consistência entre diferentes ambientes de build.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Dica extra:</strong> O <code>compile_commands.json</code> pode ser usado por ferramentas como o <strong>clang-tidy</strong> ou <strong>cppcheck</strong> para inspeções profundas do seu código.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><strong>2. Configuração da Extensão VSCode e Inclusão do SDK</strong></h2>



<p class="wp-block-paragraph">Após definir os padrões iniciais de compilação, o projeto introduz uma etapa importante para integração com o ambiente de desenvolvimento e o SDK do RP2040. Veja o trecho a seguir:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# == DO NOT EDIT THE FOLLOWING LINES for the Raspberry Pi Pico VS Code Extension to work ==
if(WIN32)
    set(USERHOME $ENV{USERPROFILE})
else()
    set(USERHOME $ENV{HOME})
endif()
set(sdkVersion 2.1.1)
set(toolchainVersion 14_2_Rel1)
set(picotoolVersion 2.1.1)
set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake)
if (EXISTS ${picoVscode})
    include(${picoVscode})
endif()
# ====================================================================================
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">DO</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NOT</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EDIT</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">THE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FOLLOWING</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LINES</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Raspberry</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pi</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pico</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">VS</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Code</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Extension</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">work</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">WIN32</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">USERHOME</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$ENV</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">USERPROFILE</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">USERHOME</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$ENV</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">HOME</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">endif</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">sdkVersion</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2.1</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">toolchainVersion</span><span style="color: #D8DEE9FF"> 14</span><span style="color: #D8DEE9">_2_Rel1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">picotoolVersion</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2.1</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">picoVscode</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">USERHOME</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">/</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">pico</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">sdk</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">cmake</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">pico</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">vscode</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">cmake</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">EXISTS</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">picoVscode</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">include</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">picoVscode</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">endif</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">====================================================================================</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong>Bloco condicional <code>if(WIN32)</code>&#8230;</strong><br>Aqui é verificado se o sistema operacional é Windows (<code>WIN32</code>). Se for, define a variável <code>USERHOME</code> como o caminho da variável de ambiente <code>USERPROFILE</code>. Caso contrário (Linux/macOS), usa <code>HOME</code>.<br>Isso garante <strong>portabilidade do projeto entre sistemas operacionais</strong>, o que é essencial para ambientes colaborativos e didáticos.</li>



<li><strong><code>set(sdkVersion ...)</code>, <code>toolchainVersion ...</code>, <code>picotoolVersion ...)</code></strong><br>Essas linhas servem como <strong>metadados informativos</strong> que descrevem as versões usadas no ambiente de desenvolvimento. Embora não sejam diretamente utilizadas pelo CMake nesta etapa, são úteis para documentação, scripts externos ou para controle de consistência do ambiente de build.</li>



<li><strong><code>set(picoVscode ...)</code> e <code>include(...)</code></strong><br>Essa etapa tenta localizar o arquivo <code>pico-vscode.cmake</code>, que é utilizado pela extensão oficial da Raspberry Pi no VSCode para configurar corretamente o ambiente.<br>Se o arquivo existir, ele é incluído, permitindo que recursos como <strong>auto-complete</strong>, <strong>debug remoto</strong>, e <strong>templates automáticos</strong> funcionem adequadamente.</li>
</ol>



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>O uso de <code>EXISTS</code> para checar a presença do arquivo evita erros e torna o projeto mais robusto.</li>



<li>Esta seção é essencial para <strong>ambientes com suporte a IDEs modernas</strong>, mas pode ser <strong>omitida com segurança</strong> se o projeto for construído apenas via terminal.</li>



<li>A presença dos comentários <code>DO NOT EDIT</code> é uma prática comum para marcar blocos sensíveis que são exigidos por ferramentas externas.</li>
</ul>



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f0.png" alt="🧰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Para iniciantes:</strong> Essa parte pode parecer obscura à primeira vista, mas pense nela como a “ponte” entre o CMake e o seu editor (VSCode). Se ela estiver funcionando, você terá suporte a <strong>atalhos, intellisense e debug facilitado</strong>.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f30d.png" alt="🌍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Dica de compatibilidade:</strong> Quando você compartilha seu projeto com colegas usando Windows e você usa Linux (ou vice-versa), esse bloco ajuda a manter tudo funcionando sem dor de cabeça.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Importante saber:</strong> Se o arquivo <code>pico-vscode.cmake</code> não estiver instalado, o build ainda funcionará — mas <strong>você perderá integração com o VSCode</strong>.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><strong>3. Parametrização por Ambiente: Importando o <code>env.cmake</code></strong></h2>



<p class="wp-block-paragraph">Este bloco mostra como carregar configurações externas e definir valores padrão para variáveis críticas de conexão, como Wi-Fi e MQTT. Veja o trecho abaixo:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="if(EXISTS &quot;${CMAKE_SOURCE_DIR}/env.cmake&quot;)
    include(&quot;${CMAKE_SOURCE_DIR}/env.cmake&quot;)
    message(STATUS &quot;Arquivo env.cmake carregado com sucesso.&quot;)
else()
    message(FATAL_ERROR &quot;Arquivo env.cmake não encontrado!&quot;)
endif()
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">EXISTS</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${CMAKE_SOURCE_DIR}/env.cmake</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">include</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${CMAKE_SOURCE_DIR}/env.cmake</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">message</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">STATUS</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Arquivo env.cmake carregado com sucesso.</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">message</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">FATAL_ERROR</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Arquivo env.cmake não encontrado!</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">endif</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong><code>if(EXISTS "${CMAKE_SOURCE_DIR}/env.cmake")</code></strong><br>Verifica se o arquivo <code>env.cmake</code> existe no diretório raiz do projeto. Essa verificação é crucial para não interromper o processo de configuração se o arquivo estiver ausente ou mal posicionado.</li>



<li><strong><code>include(...)</code></strong><br>Se o arquivo existir, ele é carregado e suas variáveis passam a ser conhecidas no escopo do CMake. Isso permite separar a <strong>configuração sensível ou personalizada</strong> (como senhas e tópicos MQTT) do corpo principal do projeto.</li>



<li><strong><code>message(STATUS "...")</code> e <code>message(FATAL_ERROR "...")</code></strong><br>Usadas para informar claramente ao usuário o sucesso ou falha dessa etapa. Um erro fatal é gerado se o <code>env.cmake</code> estiver ausente, forçando o desenvolvedor a corrigi-lo antes de prosseguir — uma forma de evitar builds incompletos ou configurações erradas.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">A seguir, são aplicadas validações adicionais:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="if(NOT DEFINED ENV{WIFI_SSID})
    message(WARNING &quot;Variável WIFI_SSID não definida no .env.&quot;)
    set(ENV{WIFI_SSID} &quot;ArvoreDosSaberes&quot;)
endif()
# ... outros blocos semelhantes para WIFI_PASSWORD, MQTT_BROKER, etc.
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NOT</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">DEFINED</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ENV</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">WIFI_SSID</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">message</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">WARNING</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Variável WIFI_SSID não definida no .env.</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">ENV</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">WIFI_SSID</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">ArvoreDosSaberes</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">endif</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">outros</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">blocos</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">semelhantes</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">WIFI_PASSWORD</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MQTT_BROKER</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">etc</span><span style="color: #ECEFF4">.</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<p class="wp-block-paragraph">Cada bloco verifica se uma variável de ambiente essencial está definida (<code>ENV{VARIAVEL}</code>). Se não estiver, ele:</p>



<ul class="wp-block-list">
<li>Emite um <strong>aviso não fatal</strong>, alertando o usuário;</li>



<li>Define um valor <strong>padrão razoável</strong> para que o build continue.</li>
</ul>



<p class="wp-block-paragraph">Ao final, todas as variáveis são capturadas explicitamente para o escopo interno do CMake:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="set(WIFI_SSID &quot;$ENV{WIFI_SSID}&quot;)
set(WIFI_PASSWORD &quot;$ENV{WIFI_PASSWORD}&quot;)
set(MQTT_BROKER &quot;$ENV{MQTT_BROKER}&quot;)
set(MQTT_BASE_TOPIC &quot;$ENV{MQTT_BASE_TOPIC}&quot;)
set(MQTT_RACK_NUMBER &quot;$ENV{MQTT_RACK_NUMBER}&quot;)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">WIFI_SSID</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{WIFI_SSID}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">WIFI_PASSWORD</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{WIFI_PASSWORD}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MQTT_BROKER</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{MQTT_BROKER}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MQTT_BASE_TOPIC</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{MQTT_BASE_TOPIC}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MQTT_RACK_NUMBER</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{MQTT_RACK_NUMBER}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>O uso do <code>env.cmake</code> permite separar configuração de ambiente do código — uma excelente prática que segue os princípios da engenharia de software moderna.</li>



<li>Fornecer valores padrão facilita testes e uso didático, mas o ideal seria mover os valores <strong>sensíveis (como senhas)</strong> para fora do controle de versão (usando, por exemplo, <code>.gitignore</code>).</li>



<li>Poderia haver uma variável global ou opção no CMake para <strong>desativar temporariamente os erros fatais</strong>, facilitando builds rápidos durante o desenvolvimento.</li>
</ul>



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9ea.png" alt="🧪" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Analogia simples:</strong> Pense no <code>env.cmake</code> como um “cartão de visita” que você entrega ao projeto, dizendo quem você é (SSID, senha, broker). Assim, ele sabe com quem falar e como se comportar.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4c1.png" alt="📁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Organização é tudo:</strong> Ao manter essas variáveis fora do <code>CMakeLists.txt</code>, você pode trocar de rede ou broker sem reconfigurar o projeto inteiro — basta editar ou substituir o <code>env.cmake</code>.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6ab.png" alt="🚫" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Cuidado comum:</strong> Não deixar o <code>env.cmake</code> com credenciais sensíveis visíveis em repositórios públicos. Para isso, use <code>.gitignore</code>.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><strong>4. Inicialização do SDK e Definição do Executável</strong></h2>



<p class="wp-block-paragraph">Com todas as variáveis e configurações preparadas, o próximo passo é estruturar o projeto de forma que o SDK da Raspberry Pi Pico possa ser utilizado corretamente, e o firmware final seja construído como um <strong>executável nomeado</strong>. O trecho em destaque é o seguinte:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)

project(firmware_client_mqtt C CXX ASM)

# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Pull</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Raspberry</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pi</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pico</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">SDK</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">must</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">be</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">before</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">project</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">include</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">pico_sdk_import</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">cmake</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">project</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">C</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CXX</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ASM</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Initialise</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Raspberry</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pi</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pico</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SDK</span></span>
<span class="line"><span style="color: #88C0D0">pico_sdk_init</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong><code>include(pico_sdk_import.cmake)</code></strong><br>Este comando inclui o script <code>pico_sdk_import.cmake</code>, normalmente localizado na raiz do SDK da Raspberry Pi. Ele é responsável por <strong>carregar as bibliotecas, drivers e configurações internas</strong> que fazem parte do Pico SDK.<br>É essencial que esta linha venha <strong>antes do comando <code>project(...)</code></strong>, pois o SDK precisa estar carregado para que o CMake reconheça suas funções auxiliares como <code>pico_sdk_init()</code> ou <code>pico_enable_stdio_usb()</code>.</li>



<li><strong><code>project(firmware_client_mqtt C CXX ASM)</code></strong><br>Define oficialmente o nome do projeto, bem como os tipos de código que ele conterá:
<ul class="wp-block-list">
<li><code>C</code>: código C (linguagem base do projeto);</li>



<li><code>CXX</code>: suporte a C++, mesmo que opcional;</li>



<li><code>ASM</code>: suporte à linguagem Assembly, caso você deseje manipular diretamente registradores ou realizar otimizações de baixo nível.</li>
</ul>
</li>



<li><strong><code>pico_sdk_init()</code></strong><br>Esta função é uma <strong>macro do Pico SDK</strong> que realiza a configuração padrão do ambiente, ativando funcionalidades como drivers de hardware (<code>hardware_gpio</code>, <code>hardware_adc</code>, etc.), bibliotecas utilitárias e integração com o sistema de build.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Em seguida, o projeto define o binário principal:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="add_executable(firmware_client_mqtt
    firmware_client_mqtt.c
)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">add_executable</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">c</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">E depois configura nome e versão para fins de organização:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="pico_set_program_name(firmware_client_mqtt &quot;firmware_client_mqtt&quot;)
pico_set_program_version(firmware_client_mqtt &quot;0.1&quot;)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">pico_set_program_name</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">firmware_client_mqtt</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">pico_set_program_version</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">0.1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol start="4" class="wp-block-list">
<li><strong><code>add_executable(...)</code></strong><br>Esta linha define o <strong>arquivo principal a ser compilado</strong>, neste caso, <code>firmware_client_mqtt.c</code>. O nome dado ao executável será usado como base para gerar o binário <code>.uf2</code> (formato de firmware usado pelo RP2040).<br>Também é possível incluir múltiplos arquivos <code>.c</code>, <code>.cpp</code> ou <code>.s</code> (Assembly) se o projeto for modularizado.</li>



<li><strong><code>pico_set_program_name</code> e <code>pico_set_program_version</code></strong><br>Estes comandos definem metadados do projeto, como nome e versão, que podem ser usados por ferramentas de depuração ou sistemas de versionamento. Embora opcionais, são úteis em ambientes colaborativos ou industriais.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>Esta seção está <strong>tecnicamente correta</strong> e bem estruturada, seguindo as recomendações do Pico SDK.</li>



<li>O uso explícito de <code>C</code>, <code>CXX</code> e <code>ASM</code> torna o projeto mais <strong>versátil</strong> e pronto para escalar em complexidade.</li>



<li>O nome do projeto (<code>firmware_client_mqtt</code>) é repetido em vários pontos. Poderia ser definido via uma variável (<code>set(PROJECT_NAME firmware_client_mqtt)</code>) para facilitar manutenção futura.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Analogia prática:</strong> Essa parte é como “ligar a tomada” do seu projeto. Você diz ao sistema: “meu projeto se chama X, usa essas linguagens, e quero usar as bibliotecas do SDK da Raspberry Pi”.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Dica extra:</strong> Ao compilar, o CMake vai gerar automaticamente arquivos <code>.elf</code>, <code>.bin</code> e <code>.uf2</code>, prontos para serem gravados na flash do RP2040.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f5c3.png" alt="🗃" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Boas práticas:</strong> Sempre modularize seu código desde o começo. Mesmo que só tenha um arquivo <code>.c</code>, mantenha espaço para crescer (ex: <code>src/</code>, <code>include/</code>).</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><strong>5. Ativando Entradas/Saídas e Ligando Bibliotecas Essenciais</strong></h2>



<p class="wp-block-paragraph">Depois de declarar o executável e configurar seu nome e versão, o projeto define como o firmware irá se comunicar com o mundo externo — por portas seriais ou USB — e quais bibliotecas devem ser incluídas na hora da linkagem. Veja o trecho:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="pico_enable_stdio_uart(firmware_client_mqtt 0)
pico_enable_stdio_usb(firmware_client_mqtt 1)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">pico_enable_stdio_uart</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">pico_enable_stdio_usb</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong><code>pico_enable_stdio_uart(&lt;target> &lt;boolean>)</code></strong><br>Define se a <strong>UART (porta serial física)</strong> será usada como saída padrão (<code>stdout</code>) do programa. No exemplo acima, o valor <code>0</code> desativa a UART. Isso pode ser útil se o projeto não utilizar os pinos GPIO dedicados à UART, ou se estiver usando USB para comunicação com o PC.</li>



<li><strong><code>pico_enable_stdio_usb(&lt;target> &lt;boolean>)</code></strong><br>Ativa a comunicação serial via <strong>USB virtual (CDC)</strong>. Com <code>1</code>, o firmware pode imprimir mensagens no terminal conectado via cabo USB — muito útil para debug com ferramentas como <code>minicom</code>, <code>PuTTY</code>, <code>Thonny</code> ou o console do VSCode.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Em seguida, são declaradas as bibliotecas necessárias à aplicação:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="target_link_libraries(firmware_client_mqtt
    pico_stdlib
    pico_cyw43_arch_lwip_threadsafe_background
    pico_lwip_mqtt
)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">target_link_libraries</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">pico_stdlib</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">pico_cyw43_arch_lwip_threadsafe_background</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">pico_lwip_mqtt</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol start="3" class="wp-block-list">
<li><strong><code>target_link_libraries(...)</code></strong><br>Essa linha especifica quais bibliotecas serão <strong>ligadas (linkadas)</strong> ao firmware durante a compilação.
<ul class="wp-block-list">
<li><code>pico_stdlib</code>: a <strong>biblioteca padrão</strong> do SDK, que fornece funções básicas como <code>printf</code>, controle de pinos, delays, etc.</li>



<li><code>pico_cyw43_arch_lwip_threadsafe_background</code>: fornece <strong>acesso ao chip Wi-Fi CYW43</strong> (usado no RP2040 W) em modo cooperativo com a pilha TCP/IP lwIP.</li>



<li><code>pico_lwip_mqtt</code>: adiciona suporte ao <strong>protocolo MQTT</strong> com base na biblioteca lwIP, permitindo que o firmware se comunique com brokers MQTT como o Mosquitto, HiveMQ, etc.</li>
</ul>
</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>Desativar UART e ativar apenas USB (como neste projeto) é uma escolha moderna e prática, já que a maioria dos computadores não possui porta serial física.</li>



<li>O uso de <code>pico_lwip_mqtt</code> demonstra um foco em <strong>conectividade IoT</strong>. Esta biblioteca ainda é pouco documentada fora dos exemplos oficiais, então usar os exemplos do SDK como base é uma boa prática.</li>



<li>Poderia ser interessante encapsular as bibliotecas adicionais em uma função auxiliar (<code>add_custom_dependencies()</code>), principalmente em projetos maiores.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50c.png" alt="🔌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Para iniciantes:</strong> Pense na UART e na USB como “canais de conversa” entre o RP2040 e o mundo externo. Você pode escolher usar um, ambos, ou nenhum.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f0.png" alt="🧰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Boas práticas:</strong> Se for usar UART, lembre-se de configurar os pinos no firmware (<code>gpio_set_function(...)</code>). Se usar USB, não esqueça que a comunicação começa <strong>após a USB ser enumerada pelo host</strong> — o que leva alguns milissegundos após reset.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f310.png" alt="🌐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Importante saber:</strong> A biblioteca <code>pico_cyw43_arch_lwip_threadsafe_background</code> executa tarefas de rede em segundo plano, sem precisar de um RTOS. Ideal para projetos simples mas que precisam de conectividade Wi-Fi confiável.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><strong>6. Inclusão de Diretórios e Definição de Macros de Conexão</strong></h2>



<p class="wp-block-paragraph">Com a estrutura principal pronta e as bibliotecas já ligadas, o projeto agora configura o acesso aos diretórios de cabeçalhos e exporta as variáveis de ambiente para uso direto no código C:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="target_include_directories(firmware_client_mqtt PRIVATE ${CMAKE_CURRENT_LIST_DIR})
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">target_include_directories</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PRIVATE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">CMAKE_CURRENT_LIST_DIR</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong><code>target_include_directories(...)</code></strong><br>Especifica para o compilador onde ele deve procurar os arquivos <code>.h</code> durante a compilação.
<ul class="wp-block-list">
<li><code>firmware_client_mqtt</code>: é o alvo (o executável).</li>



<li><code>PRIVATE</code>: significa que esses diretórios são usados <strong>apenas internamente</strong> para este alvo (e não propagados a outras dependências).</li>



<li><code>${CMAKE_CURRENT_LIST_DIR}</code>: refere-se ao diretório atual onde está o <code>CMakeLists.txt</code>. Isso permite que o <code>main.c</code> e outros arquivos no mesmo diretório acessem os headers locais diretamente.</li>
</ul>
</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">Agora, as variáveis de ambiente definidas anteriormente são “injetadas” no código-fonte como macros com <code>#define</code>, utilizando o comando:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="target_compile_definitions(firmware_client_mqtt PRIVATE 
    WIFI_SSID=\&quot;${WIFI_SSID}\&quot; 
    WIFI_PASSWORD=\&quot;${WIFI_PASSWORD}\&quot; 
    MQTT_BROKER=\&quot;${MQTT_BROKER}\&quot; 
    MQTT_BASE_TOPIC=\&quot;${MQTT_BASE_TOPIC}\&quot;
    MQTT_RACK_NUMBER=\&quot;${MQTT_RACK_NUMBER}\&quot;
)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">target_compile_definitions</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PRIVATE</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">WIFI_SSID</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">\</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${WIFI_SSID}</span><span style="color: #EBCB8B">\&quot;</span><span style="color: #D8DEE9"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">WIFI_PASSWORD</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">\</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${WIFI_PASSWORD}</span><span style="color: #EBCB8B">\&quot;</span><span style="color: #D8DEE9"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">MQTT_BROKER</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">\</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${MQTT_BROKER}</span><span style="color: #EBCB8B">\&quot;</span><span style="color: #D8DEE9"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">MQTT_BASE_TOPIC</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">\</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${MQTT_BASE_TOPIC}</span><span style="color: #EBCB8B">\&quot;</span></span>
<span class="line"><span style="color: #A3BE8C">    MQTT_RACK_NUMBER=</span><span style="color: #EBCB8B">\&quot;</span><span style="color: #A3BE8C">${MQTT_RACK_NUMBER}</span><span style="color: #EBCB8B">\&quot;</span></span>
<span class="line"><span style="color: #D8DEE9">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol start="2" class="wp-block-list">
<li><strong><code>target_compile_definitions(...)</code></strong><br>Insere <strong>macros de pré-processador</strong> no projeto. Na prática, é como se o CMake escrevesse automaticamente estas linhas no seu código: <code>#define WIFI_SSID "ArvoreDosSaberes" #define WIFI_PASSWORD "Arduino2022" #define MQTT_BROKER "mqtt.rapport.tec.br" #define MQTT_BASE_TOPIC "rack_inteligente" #define MQTT_RACK_NUMBER "3"</code> Isso permite que o código-fonte seja <strong>genérico e portátil</strong>, pegando os dados do ambiente e não de strings fixas.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>O uso de <code>target_compile_definitions</code> é <strong>altamente recomendável</strong>, pois centraliza a configuração no CMake em vez de espalhar definições pelo código-fonte.</li>



<li>A sintaxe de escape com <code>\"...\"</code> garante que as strings sejam corretamente interpretadas como literais no código C. Uma falha comum de iniciantes é esquecer essas aspas.</li>



<li>Em projetos maiores, pode-se usar arquivos <code>.h</code> autogerados a partir do CMake para organizar essas definições (ex: <code>config.h.in</code> com <code>configure_file()</code>).</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Para iniciantes:</strong> Pense que você está mandando um bilhete do CMake para o seu código C. Esse bilhete diz: “ei, aqui está o nome da sua rede Wi-Fi e os dados do MQTT”.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Erros comuns:</strong> Se você esquecer de escapar as aspas (<code>\"</code>), o compilador vai entender errado a definição e gerar erros como “expected identifier”.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e1.png" alt="🛡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Boas práticas:</strong> Nunca inclua senhas reais ou dados sensíveis diretamente no <code>main.c</code>. Use sempre esse método de parametrização, ou proteja via arquivos ignorados no Git.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><strong>7. Geração dos Arquivos de Saída: <code>pico_add_extra_outputs</code></strong></h2>



<p class="wp-block-paragraph">No final do arquivo, encontramos a seguinte linha:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="pico_add_extra_outputs(firmware_client_mqtt)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">pico_add_extra_outputs</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<p class="wp-block-paragraph">Este comando é uma <strong>macro fornecida pelo Pico SDK</strong> que automatiza a criação de diferentes formatos de saída do firmware. A partir do executável gerado (<code>firmware_client_mqtt.elf</code>), ela cuida de produzir também:</p>



<ul class="wp-block-list">
<li><code>firmware_client_mqtt.bin</code>: imagem binária “crua”, usada em alguns programadores.</li>



<li><code>firmware_client_mqtt.uf2</code>: formato específico do RP2040, utilizado para arrastar e soltar o firmware diretamente na unidade USB visível quando o RP2040 está em modo de bootloader.</li>



<li>Arquivos <code>.map</code>, <code>.hex</code>, <code>.dis</code> ou <code>.lst</code> também podem ser gerados, dependendo das opções do CMake.</li>
</ul>



<p class="wp-block-paragraph">Tudo isso acontece de forma automática, dispensando a escrita manual de comandos extras.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>O uso de <code>pico_add_extra_outputs</code> é <strong>obrigatório</strong> em projetos com RP2040 se você quiser gerar arquivos <code>.uf2</code>, que são os mais práticos para upload via USB.</li>



<li>Essa macro também <strong>facilita o debug</strong>, já que o <code>.elf</code> gerado pode ser carregado diretamente por ferramentas como GDB, OpenOCD ou o depurador do VSCode.</li>



<li>Poderia ser complementada com scripts de pós-build para, por exemplo, copiar o <code>.uf2</code> para um diretório específico ou ativar gravação automática via <code>picotool</code>.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9fe.png" alt="🧾" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Para iniciantes:</strong> Essa etapa é como pedir ao compilador: “não me dê só o resultado final, me dê também outras versões do programa — uma para o bootloader, outra para depurar, outra para backup”.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4be.png" alt="💾" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Boas práticas:</strong> Após cada build, confira a pasta <code>build/</code> — os arquivos <code>.uf2</code>, <code>.elf</code> e <code>.bin</code> estarão lá. O <code>.uf2</code> é o que você deve <strong>arrastar e soltar</strong> no RP2040 quando ele estiver em modo boot (pressionando o botão BOOTSEL).</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a6.png" alt="🚦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Dica de produtividade:</strong> Se você estiver usando VSCode com a extensão oficial, essa macro garante que o botão “Build” funcione corretamente e gere o <code>.uf2</code> automaticamente.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Finalização da Análise Técnica</h3>



<p class="wp-block-paragraph">Com essa última linha, fechamos a análise completa e detalhada do arquivo <code>CMakeLists.txt</code>. Todas as etapas — desde configuração básica, carregamento do SDK, definição do executável, inclusão de bibliotecas, parâmetros de ambiente até a geração dos arquivos finais — foram explicadas com clareza e espírito didático.</p>



<p class="wp-block-paragraph">Perfeito! Vamos então à conclusão geral do artigo, amarrando todo o conteúdo de forma coesa e didática.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><strong>Conclusão</strong></h2>



<p class="wp-block-paragraph">Ao longo deste artigo, percorremos — linha por linha — a estrutura de um <code>CMakeLists.txt</code> real utilizado em um projeto baseado no microcontrolador <strong>RP2040</strong>, com foco em conectividade Wi-Fi e MQTT. O objetivo foi mais do que explicar comandos: buscamos desenvolver no leitor a compreensão do <strong>porquê</strong> de cada configuração, tornando-o capaz de <strong>analisar, adaptar e evoluir seus próprios projetos</strong>.</p>



<p class="wp-block-paragraph">Iniciamos com a definição dos padrões de compilação e seguimos pela configuração do ambiente de desenvolvimento, mostrando como tornar o projeto compatível com ferramentas modernas como o VSCode. Depois, vimos como separar parâmetros de configuração em arquivos auxiliares (<code>env.cmake</code>) e como capturar variáveis de ambiente de forma segura e elegante. Em seguida, exploramos a inicialização do SDK, a declaração do executável, a ativação dos canais de comunicação via USB e UART, a ligação com bibliotecas críticas como <code>pico_lwip_mqtt</code>, e, por fim, a geração dos arquivos <code>.uf2</code> e <code>.elf</code> prontos para gravação.</p>



<p class="wp-block-paragraph">Além do conteúdo técnico, discutimos <strong>boas práticas</strong> como:</p>



<ul class="wp-block-list">
<li>Separar configuração do código-fonte com <code>env.cmake</code>;</li>



<li>Utilizar <code>target_compile_definitions</code> para injetar parâmetros no pré-processador;</li>



<li>Escapar corretamente strings definidas no CMake;</li>



<li>Manter o projeto modular e escalável com <code>target_include_directories</code> e <code>target_link_libraries</code>;</li>



<li>Evitar hardcoding de dados sensíveis e trabalhar com variáveis de ambiente.</li>
</ul>



<p class="wp-block-paragraph">Esse conhecimento é <strong>fundamental para qualquer desenvolvedor embarcado que deseje usar o RP2040 de forma profissional e segura</strong>. A compreensão profunda da infraestrutura de build é o que separa um programador iniciante de um desenvolvedor capaz de integrar sistemas complexos, automatizar tarefas, e resolver problemas de forma elegante.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><strong>Próximos Passos</strong></h2>



<p class="wp-block-paragraph">Se você chegou até aqui, parabéns! Seu próximo passo pode ser:</p>



<ul class="wp-block-list">
<li>Explorar o conteúdo do arquivo <code>env.cmake</code> em detalhes;</li>



<li>Modularizar seu projeto criando subdiretórios como <code>src/</code> e <code>include/</code>;</li>



<li>Automatizar tarefas de pós-build, como upload via <code>picotool</code>;</li>



<li>Adicionar testes unitários usando CMocka ou Unity em conjunto com CMake;</li>



<li>Criar templates de projetos reutilizáveis com base nessa estrutura.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><strong>Indicações de Leitura Complementar</strong></h2>



<ul class="wp-block-list">
<li><a href="https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf">Documentação oficial do Pico SDK</a></li>



<li><a href="https://www.jetbrains.com/help/clion/quick-cmake-tutorial.html">Tutorial CMake da JetBrains</a></li>



<li><a href="https://interrupt.memfault.com/blog/firmware-build-systems">CMake para Embedded (platformIO-style)</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"></p><p>The post <a href="https://mcu.tec.br/linguagem/builds/como-estruturar-um-projeto-profissional-com-cmake-para-o-rp2040-guia-didatico-passo-a-passo/">Como Estruturar um Projeto Profissional com CMake para o RP2040: Guia Didático Passo a Passo</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">635</post-id>	</item>
	</channel>
</rss>
