C++ CMake
O Make resolve o problema de recompilar só o que mudou, mas você ainda escreve cada regra à mão, lembra de cada .h, e o Makefile só funciona onde há make e g++. O Bruno, amigo da Ana, usa Windows com o Visual Studio; a Ana usa Linux com o VS Code. Como os dois compilam o mesmo projeto? A resposta da maioria dos projetos C++ do mundo é o CMake: você descreve o projeto num arquivo simples, o CMakeLists.txt, e o CMake gera os arquivos de compilação certos para cada sistema.
- O que o CMake faz e por que ele é o padrão em projetos C++.
- Um
CMakeLists.txtmínimo, linha por linha. - Os dois passos:
cmake -B build(configurar) ecmake --build build(compilar). - Como montar o projeto da lojinha, com vários arquivos.
- Como usar o Ninja (
-G Ninja) e outro compilador. - Os erros mais comuns do CMake e como lê-los.
Todos os comandos desta aula foram executados na máquina fictícia da Ana (usuária ana, computador notebook), com o CMake 4.2, o g++ 15.2 e o Ninja do Ubuntu. No Ubuntu, o CMake e o Ninja se instalam com sudo apt install cmake ninja-build. Para conferir:
$ cmake --version cmake version 4.2.3 CMake suite maintained and supported by Kitware (kitware.com/cmake).
A ideia: a planta da casa
Um arquiteto não diz ao pedreiro "assente 2.340 tijolos na posição tal". Ele desenha a planta: dois quartos, uma cozinha, um banheiro. Cada equipe de obra lê a planta e constrói do seu jeito, com as ferramentas que tem.
| Na obra | No C++ |
|---|---|
| A planta: "dois quartos e uma cozinha" | o CMakeLists.txt: "um programa loja, feito de main.cpp e calculos.cpp, em C++23" |
| O mestre de obras, que transforma a planta em tarefas | o CMake, que gera um Makefile, um projeto do Visual Studio, um arquivo do Ninja… |
| Os pedreiros | o Make ou o Ninja, que chamam o compilador |
Por isso o CMake é chamado de gerador de sistema de build (build = "construção", o processo de compilar e ligar). Ele não compila nada sozinho: ele escreve as instruções para quem compila.
1. O CMakeLists.txt mínimo
A Ana começou com um programa de um arquivo só, numa pasta ~/cpp/cm1:
#include <print>
int main() {
std::println("Olá do CMake!");
}
Ao lado dele, ela criou um arquivo de texto com o nome exato CMakeLists.txt (com C, M e L maiúsculos):
cmake_minimum_required(VERSION 3.25) project(Ola LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(ola ola.cpp)
- cmake_minimum_required(VERSION 3.25)
- "Versão mínima exigida do CMake". Todo
CMakeLists.txtcomeça com ela. Além de recusar um CMake velho demais, ela diz ao CMake de que época é o seu arquivo, para ele se comportar como você espera. Use uma versão recente que você tenha (o Ubuntu 26.04 traz a 4.2; a 3.25 é de 2022 e já cobre tudo desta aula). - project(Ola LANGUAGES CXX)
- O nome do projeto (
Ola) e a linguagem.CXXé o nome que o CMake (e o Make) usa para C++. Sem oLANGUAGES CXX, o CMake também procuraria um compilador de C. - set(CMAKE_CXX_STANDARD 23)
set("defina") dá valor a uma variável. Esta pede o C++23, como o-std=c++23do comando padrão do guia.- set(CMAKE_CXX_STANDARD_REQUIRED ON)
- "O padrão é obrigatório": se o compilador não souber C++23, pare com erro, em vez de cair silenciosamente para um padrão mais antigo.
- add_executable(ola ola.cpp)
- "Acrescente um executável": o programa vai se chamar
olae é feito do arquivoola.cpp. Esse nome (ola) é o alvo (target), como no Make.
Os comandos do CMake são escritos como nome(argumentos), com os argumentos separados por espaço, sem vírgula e sem ;. Não diferenciam maiúsculas de minúsculas (ADD_EXECUTABLE também funciona; o costume atual é minúsculas), mas os nomes de variáveis, como CMAKE_CXX_STANDARD, sim.
2. Configurar e compilar
O CMake trabalha em dois passos. Primeiro, configurar: ler o CMakeLists.txt, procurar o compilador e gerar os arquivos de build numa pasta separada:
$ cd ~/cpp/cm1 $ cmake -B build -- The CXX compiler identification is GNU 15.2.0 -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done (0.4s) -- Generating done (0.0s) -- Build files have been written to: /home/ana/cpp/cm1/build
- -B build
- A pasta onde os arquivos gerados vão ficar (B de build). Ela é criada se não existir. O
CMakeLists.txté procurado na pasta atual. - The CXX compiler identification is GNU 15.2.0
- O CMake achou um compilador de C++: o GCC (o g++) 15.2. O
/usr/bin/c++é o nome genérico que, no Ubuntu, aponta para o g++. - Detecting… - done
- Testes que o CMake faz para descobrir do que o compilador é capaz. Só rodam na primeira configuração.
- Build files have been written to
- "Os arquivos de build foram gravados em…". Pronto para compilar.
Depois, compilar:
$ cmake --build build [ 50%] Building CXX object CMakeFiles/ola.dir/ola.cpp.o [100%] Linking CXX executable ola [100%] Built target ola $ ./build/ola Olá do CMake!
cmake --build build quer dizer "construa o que está configurado na pasta build". As linhas dizem o que está acontecendo: compilando (Building) o ola.cpp num .o, ligando (Linking) o executável, alvo pronto (Built target). O programa fica dentro da pasta build, por isso ./build/ola. Rodando de novo, sem mudar nada:
$ cmake --build build [100%] Built target ola
Nada foi recompilado: por baixo, quem trabalhou foi o Make. Veja o que o CMake gerou na pasta build:
$ ls build CMakeCache.txt CMakeFiles cmake_install.cmake Makefile « um Makefile, escrito pelo CMake ola
build separada?
Tudo o que é gerado (o Makefile, os .o, o programa, o CMakeCache.txt com as escolhas da configuração) fica lá dentro, longe do seu código. Para recomeçar do zero, basta apagar a pasta: rm -rf build. E dá para ter várias ao mesmo tempo (uma com o g++, outra com o Clang), como você vai ver na seção 5. Se o projeto usa git, ponha build/ no .gitignore.
Quando reconfigurar?
Quase nunca à mão. Se você editar o CMakeLists.txt, o cmake --build percebe e reconfigura sozinho. A Ana tinha um programa que mostra o valor de __cplusplus (veja O Pré-processador), compilado com set(CMAKE_CXX_STANDARD 20), e trocou o 20 por 23:
$ ./build/qual Compilador: GCC (g++) 15 __cplusplus = 202002 $ sed -i 's/STANDARD 20/STANDARD 23/' CMakeLists.txt $ cmake --build build && ./build/qual -- Configuring done (0.0s) « reconfigurou sozinho -- Generating done (0.0s) -- Build files have been written to: /home/ana/cpp/qual/build [ 50%] Building CXX object CMakeFiles/qual.dir/qual.cpp.o [100%] Linking CXX executable qual [100%] Built target qual Compilador: GCC (g++) 15 __cplusplus = 202302
(O sed -i trocou o texto dentro do arquivo; você pode fazer o mesmo num editor.)
Experimente: este é o programa qual.cpp da Ana. Esta caixa compila com -std=c++20, como um projeto com set(CMAKE_CXX_STANDARD 20). Rode e compare com a saída do g++ acima: aqui o compilador é o Clang, mas o padrão é o mesmo. Depois troque o 202002L do #if por 202302L e veja a outra mensagem aparecer.
#include <iostream>
int main() {
#if defined(__clang__)
std::cout << "Compilador: Clang " << __clang_major__ << '\n';
#elif defined(__GNUC__)
std::cout << "Compilador: GCC (g++) " << __GNUC__ << '\n';
#endif
std::cout << "__cplusplus = " << __cplusplus << '\n';
#if __cplusplus >= 202002L
std::cout << "Pelo menos C++20: pode usar std::format e ranges.\n";
#else
std::cout << "Padrão antigo demais para este recurso.\n";
#endif
}
3. A lojinha com vários arquivos
Agora o projeto de verdade: main.cpp, calculos.cpp e calculos.h, os de Arquivos .h e .cpp, na pasta ~/cpp/loja-cmake:
cmake_minimum_required(VERSION 3.25) project(Lojinha LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) add_executable(loja main.cpp calculos.cpp) target_compile_options(loja PRIVATE -Wall -Wextra)
- add_executable(loja main.cpp calculos.cpp)
- Os
.cppdo programa, separados por espaço. O.hnão precisa entrar: o CMake descobre sozinho quais cabeçalhos cada.cppinclui (o trabalho que você fazia à mão nas dependências doMakefile). - set(CMAKE_CXX_EXTENSIONS OFF)
- Sem esta linha, o CMake pede ao g++ o
-std=gnu++23: C++23 mais extensões próprias do GCC. Com ela, pede o-std=c++23puro, igual ao do guia, e um código que usa extensões sem querer não passa despercebido. - target_compile_options(loja PRIVATE -Wall -Wextra)
- Opções a mais para o alvo
loja: os avisos de sempre (veja Avisos).PRIVATEquer dizer "só para compilar este alvo". Os comandostarget_…sempre recebem primeiro o nome do alvo.
$ cd ~/cpp/loja-cmake $ cmake -B build -- The CXX compiler identification is GNU 15.2.0 -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done (0.6s) -- Generating done (0.0s) -- Build files have been written to: /home/ana/cpp/loja-cmake/build $ cmake --build build [ 33%] Building CXX object CMakeFiles/loja.dir/main.cpp.o [ 66%] Building CXX object CMakeFiles/loja.dir/calculos.cpp.o [100%] Linking CXX executable loja [100%] Built target loja $ ./build/loja Total: R$ 10 Com 10% de desconto: R$ 9
Faça o teste do touch da aula de Make. Mudando o cabeçalho, os dois .cpp são recompilados, mesmo sem o .h aparecer no CMakeLists.txt:
$ touch calculos.h $ cmake --build build [ 33%] Building CXX object CMakeFiles/loja.dir/calculos.cpp.o [ 66%] Building CXX object CMakeFiles/loja.dir/main.cpp.o [100%] Linking CXX executable loja [100%] Built target loja
Ver os comandos de verdade: --verbose
Para ver o comando que o CMake mandou rodar, use --verbose ("falante"). A saída é comprida, cheia de detalhes internos do Make; aqui vão só as linhas que interessam:
$ touch calculos.cpp $ cmake --build build --verbose «… linhas internas do make omitidas …» [ 33%] Building CXX object CMakeFiles/loja.dir/calculos.cpp.o /usr/bin/c++ -std=c++23 -Wall -Wextra -MD -MT CMakeFiles/loja.dir/calculos.cpp.o -MF CMakeFiles/loja.dir/calculos.cpp.o.d -o CMakeFiles/loja.dir/calculos.cpp.o -c /home/ana/cpp/loja-cmake/calculos.cpp [ 66%] Linking CXX executable loja /usr/bin/c++ -Wl,--dependency-file=CMakeFiles/loja.dir/link.d CMakeFiles/loja.dir/main.cpp.o CMakeFiles/loja.dir/calculos.cpp.o -o loja «…» [100%] Built target loja
Repare: é o mesmo -std=c++23 -Wall -Wextra -c que você digitava, e depois a ligação dos .o, como em Compilar Vários Arquivos. As opções -MD -MT … -MF … pedem ao g++ que anote quais .h cada .cpp incluiu: é assim que o CMake sabe o que recompilar quando um cabeçalho muda. No projeto de um arquivo só, sem o CMAKE_CXX_EXTENSIONS OFF, a mesma linha tinha -std=gnu++23.
Uma biblioteca dentro do projeto
Em projetos maiores, as partes viram bibliotecas internas, que um ou mais programas usam:
cmake_minimum_required(VERSION 3.25) project(Lojinha LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) add_library(calculos calculos.cpp) add_executable(loja main.cpp) target_link_libraries(loja PRIVATE calculos)
$ cmake -B build > /dev/null && cmake --build build && ./build/loja [ 25%] Building CXX object CMakeFiles/calculos.dir/calculos.cpp.o [ 50%] Linking CXX static library libcalculos.a [ 50%] Built target calculos [ 75%] Building CXX object CMakeFiles/loja.dir/main.cpp.o [100%] Linking CXX executable loja [100%] Built target loja Total: R$ 10 Com 10% de desconto: R$ 9
add_library cria a biblioteca calculos (o arquivo libcalculos.a, um pacote de .o), e target_link_libraries diz que o loja precisa dela na ligação. (O > /dev/null só esconde as mensagens da configuração.) É o mesmo comando que você vai usar para ligar bibliotecas de terceiros em Usar Bibliotecas Externas.
4. Por que CMake?
| g++ na mão | Makefile | CMake | |
|---|---|---|---|
| Recompila só o que mudou | não | sim | sim |
Descobre sozinho as dependências dos .h | não | não (você lista) | sim |
| Funciona no Windows com Visual Studio | não | não | sim |
| Abre direto em IDEs | não | pouco | sim: VS Code (extensão CMake Tools), CLion, Visual Studio, Qt Creator |
| Bibliotecas de terceiros | você passa -I, -l | você passa -I, -l | find_package + target_link_libraries |
| Bom para | um ou dois arquivos | projetos pequenos, só Linux | qualquer projeto que vai crescer ou ser compartilhado |
O mesmo CMakeLists.txt da Ana, no Windows do Bruno, gera um projeto do Visual Studio em vez de um Makefile; no Mac, gera para o Xcode ou para o Make. Quase todas as bibliotecas C++ conhecidas trazem um CMakeLists.txt, e as IDEs entendem esse arquivo: no VS Code com a extensão CMake Tools, abrir a pasta já oferece configurar e compilar (veja Editores e IDEs).
5. Ninja e outros geradores
O CMake pode gerar arquivos para vários "pedreiros". Esses formatos se chamam geradores, e se escolhem com -G. No Linux, o padrão é o Make (Unix Makefiles). Uma alternativa popular é o Ninja, um programa de build feito para ser rápido e silencioso:
$ cmake -B build-ninja -G Ninja -- The CXX compiler identification is GNU 15.2.0 -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done (0.3s) -- Generating done (0.0s) -- Build files have been written to: /home/ana/cpp/loja-cmake/build-ninja $ cmake --build build-ninja [1/3] Building CXX object CMakeFiles/loja.dir/calculos.cpp.o [2/3] Building CXX object CMakeFiles/loja.dir/main.cpp.o [3/3] Linking CXX executable loja $ ./build-ninja/loja Total: R$ 10 Com 10% de desconto: R$ 9
O comando de compilar é o mesmo, cmake --build: ele chama o Make ou o Ninja, conforme a pasta. O Ninja mostra o progresso como [2/3] ("tarefa 2 de 3") e, por padrão, usa todos os núcleos do processador ao mesmo tempo, o que faz diferença em projetos grandes. Sem nada para fazer, ele diz:
$ cmake --build build-ninja ninja: no work to do. $ touch calculos.cpp $ cmake --build build-ninja [1/2] Building CXX object CMakeFiles/loja.dir/calculos.cpp.o [2/2] Linking CXX executable loja
Outro compilador: CMAKE_CXX_COMPILER
Na configuração, -D dá valor a uma variável do CMake (como o -D do g++ define uma macro). Para usar o Clang numa terceira pasta:
$ cmake -B build-clang -G Ninja -DCMAKE_CXX_COMPILER=clang++ -- The CXX compiler identification is Clang 21.1.8 -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/clang++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done (0.5s) -- Generating done (0.0s) -- Build files have been written to: /home/ana/cpp/loja-cmake/build-clang $ cmake --build build-clang [1/3] Building CXX object CMakeFiles/loja.dir/calculos.cpp.o [2/3] Building CXX object CMakeFiles/loja.dir/main.cpp.o [3/3] Linking CXX executable loja
O compilador fica gravado no CMakeCache.txt daquela pasta. Para trocar, crie outra pasta (ou apague a antiga). Outra variável comum é -DCMAKE_BUILD_TYPE=Release (com otimizações) ou Debug (com informações para o GDB).
6. Quando dá errado
A Ana copiou um CMakeLists.txt de um tutorial antigo, que começava com cmake_minimum_required(VERSION 3.0):
$ cmake -B build CMake Error at CMakeLists.txt:1 (cmake_minimum_required): Compatibility with CMake < 3.5 has been removed from CMake. Update the VERSION argument <min> value. Or, use the <min>...<max> syntax to tell CMake that the project requires at least <min> but has been updated to work with policies introduced by <max> or earlier. Or, add -DCMAKE_POLICY_VERSION_MINIMUM=3.5 to try configuring anyway. -- Configuring incomplete, errors occurred! $ echo $? 1
O que significa: CMake Error at CMakeLists.txt:1 (cmake_minimum_required) diz onde: linha 1, no comando cmake_minimum_required. O CMake 4 deixou de imitar as versões anteriores à 3.5 (de 2016). "Atualize o valor de VERSION."
Como resolver: troque para uma versão recente, como cmake_minimum_required(VERSION 3.25). Se o projeto não é seu e você só quer compilá-lo, a própria mensagem sugere cmake -B build -DCMAKE_POLICY_VERSION_MINIMUM=3.5.
Um erro de digitação no add_executable (calculo.cpp sem o s):
$ cmake -B build
-- The CXX compiler identification is GNU 15.2.0
«… detecções …»
-- Configuring done (0.3s)
CMake Error at CMakeLists.txt:4 (add_executable):
Cannot find source file:
calculo.cpp
CMake Error at CMakeLists.txt:4 (add_executable):
No SOURCES given to target: loja
CMake Generate step failed. Build files cannot be regenerated correctly.
O que significa: "Não encontrei o arquivo-fonte calculo.cpp", na linha 4. O segundo erro é consequência do primeiro: sem conseguir ler a lista, o alvo loja ficou "sem fontes" (No SOURCES).
Como resolver: confira o nome com ls e corrija o CMakeLists.txt. Sempre leia o primeiro erro primeiro.
.cpp no add_executable
Com add_executable(loja main.cpp), a configuração passa (o CMake não sabe que faltou algo), mas a ligação falha:
$ cmake --build build [ 50%] Building CXX object CMakeFiles/loja.dir/main.cpp.o [100%] Linking CXX executable loja /usr/bin/x86_64-linux-gnu-ld.bfd: CMakeFiles/loja.dir/main.cpp.o: na função "main": main.cpp:(.text+0x1f): referência não definida para "calcularTotal(double, int)" /usr/bin/x86_64-linux-gnu-ld.bfd: main.cpp:(.text+0x98): referência não definida para "aplicarDesconto(double, double)" collect2: error: ld returned 1 exit status gmake[2]: *** [CMakeFiles/loja.dir/build.make:101: loja] Error 1 gmake[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/loja.dir/all] Error 2 gmake: *** [Makefile:91: all] Error 2
O que significa: é o undefined reference ("referência não definida") de Compilar Vários Arquivos: o calculos.cpp não entrou na ligação. As três linhas gmake no fim são o Make (o gmake é o GNU Make) avisando, em camadas, que a tarefa falhou. A causa está acima delas.
Como resolver: acrescente o arquivo: add_executable(loja main.cpp calculos.cpp).
$ cmake -B build CMake Error: The source directory "/home/ana/cpp/vazio" does not appear to contain CMakeLists.txt. Specify --help for usage, or press the help button on the CMake GUI.
O que significa: "a pasta de código não parece conter um CMakeLists.txt". Você está na pasta errada, ou o arquivo tem outro nome (cmakelists.txt, CMakeList.txt).
Como resolver: cd para a pasta do projeto e confira o nome exato. Para indicar a pasta do código sem entrar nela, use -S: cmake -S ~/cpp/loja-cmake -B build.
Referência
No CMakeLists.txt | O que faz |
|---|---|
cmake_minimum_required(VERSION 3.25) | versão mínima; sempre a primeira linha |
project(Nome LANGUAGES CXX) | nome do projeto e linguagem |
set(CMAKE_CXX_STANDARD 23) | padrão do C++ |
set(CMAKE_CXX_STANDARD_REQUIRED ON) | o padrão é obrigatório |
set(CMAKE_CXX_EXTENSIONS OFF) | -std=c++23 em vez de -std=gnu++23 |
add_executable(prog a.cpp b.cpp) | um programa e seus .cpp |
add_library(nome x.cpp) | uma biblioteca |
target_link_libraries(prog PRIVATE nome) | o programa usa a biblioteca |
target_compile_options(prog PRIVATE -Wall -Wextra) | opções de compilação do alvo |
| No terminal | O que faz |
|---|---|
cmake -B build | configura, gerando os arquivos em build |
cmake -S pasta -B build | o mesmo, com o código em outra pasta |
cmake -B build -G Ninja | usa o Ninja em vez do Make |
cmake -B build -DVAR=valor | dá valor a uma variável (CMAKE_CXX_COMPILER, CMAKE_BUILD_TYPE) |
cmake --build build | compila |
cmake --build build --verbose | compila mostrando os comandos |
cmake --build build --target clean | apaga o que foi compilado (como make clean) |
rm -rf build | recomeça do zero |
Exercícios
1. O programa e seus arquivos
Complete para criar o programa estoque com os arquivos main.cpp e estoque.cpp:
2. Os dois passos
Complete o comando que compila um projeto já configurado na pasta build:
3. O que o cmake -B build faz?
4. A Ana acrescentou frete.cpp ao projeto, mas esqueceu de pô-lo no add_executable. O que acontece no cmake --build?
5. Para que serve -G Ninja?
Missão final: conserte o CMakeLists.txt da lojinha
Missão: o editor não roda o CMake, então a Ana escreveu um pequeno verificador em C++ (aba verificador.cpp) que lê a aba CMakeLists.txt e confere o que o CMake conferiria. A pasta do projeto tem main.cpp, calculos.cpp, calculos.h, frete.cpp e frete.h, e o main.cpp usa o frete. Rode, leia as reclamações e conserte só a aba CMakeLists.txt: o programa usa std::println (precisa de C++23), há um nome de arquivo errado e falta um arquivo. Quando estiver tudo certo, aparece [100%] Built target loja.
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
// Os arquivos que existem na pasta do projeto da Ana
const std::vector<std::string> pasta = {"main.cpp", "calculos.cpp", "calculos.h", "frete.cpp", "frete.h"};
bool estaNaPasta(const std::string& nome) {
for (const std::string& a : pasta) {
if (a == nome) {
return true;
}
}
return false;
}
int main() {
std::ifstream arquivo("CMakeLists.txt");
std::stringstream conteudo;
conteudo << arquivo.rdbuf();
std::string texto = conteudo.str();
int erros = 0;
if (texto.find("cmake_minimum_required(") == std::string::npos) {
std::cout << "CMake Error: falta cmake_minimum_required(VERSION ...)\n";
++erros;
}
if (texto.find("project(") == std::string::npos) {
std::cout << "CMake Error: falta project(...)\n";
++erros;
}
int padrao = 0;
std::size_t p = texto.find("CMAKE_CXX_STANDARD ");
if (p != std::string::npos) {
std::istringstream(texto.substr(p + 19)) >> padrao;
}
if (padrao < 23) {
std::cout << "error: 'println' is not a member of 'std' (o projeto pede C++"
<< padrao << "; std::println precisa de set(CMAKE_CXX_STANDARD 23))\n";
++erros;
}
std::size_t inicio = texto.find("add_executable(");
if (inicio == std::string::npos) {
std::cout << "CMake Error: nenhum add_executable(...)\n";
return 1;
}
inicio += 15;
std::size_t fim = texto.find(')', inicio);
std::istringstream lista(texto.substr(inicio, fim - inicio));
std::string alvo, fonte;
lista >> alvo;
bool temMain = false, temCalculos = false, temFrete = false;
while (lista >> fonte) {
if (!estaNaPasta(fonte)) {
std::cout << "CMake Error at CMakeLists.txt (add_executable):\n"
<< " Cannot find source file:\n\n " << fonte << "\n\n";
++erros;
}
temMain = temMain || fonte == "main.cpp";
temCalculos = temCalculos || fonte == "calculos.cpp";
temFrete = temFrete || fonte == "frete.cpp";
}
if (erros > 0) {
return 1;
}
if (!temMain) {
std::cout << "ld: undefined reference to `main'\n";
return 1;
}
if (!temCalculos || !temFrete) {
if (!temCalculos) std::cout << "ld: undefined reference to `calcularTotal(double, int)'\n";
if (!temFrete) std::cout << "ld: undefined reference to `calcularFrete(double)'\n";
return 1;
}
std::cout << "-- Configuring done\n[100%] Built target " << alvo << '\n';
}
cmake_minimum_required(VERSION 3.25) project(Lojinha LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(loja main.cpp calculo.cpp)
cmake_minimum_required(VERSION 3.25) project(Lojinha LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(loja main.cpp calculos.cpp frete.cpp)
Resumo
- O CMake é um gerador: lê o
CMakeLists.txte escreve os arquivos de build (Make, Ninja, Visual Studio…). Por isso o mesmo projeto compila no Linux, no Windows e no Mac, e abre nas IDEs. - Mínimo:
cmake_minimum_required(VERSION 3.25),project(Nome LANGUAGES CXX),set(CMAKE_CXX_STANDARD 23)eadd_executable(prog arquivos.cpp). AcrescenteCMAKE_CXX_EXTENSIONS OFFetarget_compile_options(prog PRIVATE -Wall -Wextra). - Dois passos:
cmake -B build(configurar, uma vez) ecmake --build build(compilar, sempre). O programa fica embuild/. - O CMake descobre sozinho os
.h; liste só os.cpp. Esqueceu um:undefined reference. Nome errado:Cannot find source file. -G Ninjatroca o Make pelo Ninja;-DCMAKE_CXX_COMPILER=clang++troca o compilador. Uma pasta de build para cada combinação.