C CMake
Com dois ou três arquivos, digitar o gcc à mão funciona. Com dez, você já escreveu um Makefile. Mas o Makefile só funciona com o make, e cada sistema tem o seu jeito: o Windows usa o Visual Studio, o macOS usa o Xcode. O CMake resolve isso: você descreve o projeto uma vez, num arquivo chamado CMakeLists.txt ("lista do CMake"), e ele gera o Makefile (ou o projeto do Visual Studio, ou o do Ninja) para você. É a ferramenta de compilação mais usada em projetos C e C++ hoje.
- A escrever o
CMakeLists.txtmínimo para C:cmake_minimum_required,project(nome C),set(CMAKE_C_STANDARD 23)eadd_executable. - Os dois comandos do dia a dia:
cmake -B build(configurar) ecmake --build build(compilar). - A montar um projeto com vários arquivos
.ce.h. - A ligar os avisos com
target_compile_optionse a biblioteca de matemática comtarget_link_libraries(… m). - As versões
DebugeRelease, o Ninja e os erros mais comuns.
Todas as saídas desta aula são reais, feitas com o cmake 4.2 e o gcc 15 na máquina fictícia da Ana, na pasta ~/c/cmake. O CMake não roda no editor do guia (lá, todos os .c de uma caixa já são compilados juntos, sem precisar de nada); no seu Linux, instale com sudo apt install cmake (veja Instalar no Linux).
A ideia: a receita e a cozinha
Pense numa receita de bolo escrita de um jeito geral: "200 g de farinha, asse por 40 minutos". Ela não diz se o forno é a gás ou elétrico; cada cozinha segue a receita do seu jeito. O CMakeLists.txt é a receita: diz o que construir (um programa chamado loja, feito destes arquivos, em C23, ligado com a biblioteca de matemática). O CMake olha a "cozinha" (o sistema, o compilador instalado) e escreve as instruções concretas: no Linux, um Makefile com os comandos gcc certos.
Por isso o trabalho tem duas etapas:
- Configurar (
cmake -B build): o CMake lê a receita, procura o compilador e gera os arquivos de compilação numa pasta separada, abuild. - Compilar (
cmake --build build): o CMake chama a ferramenta gerada (omake, por padrão), que chama ogcc.
1. O CMakeLists.txt mínimo
Comece com o menor projeto possível: uma pasta ~/c/cmake/ola com dois arquivos.
#include <stdio.h>
int main(void) {
printf("Olá, CMake!\n");
return 0;
}
cmake_minimum_required(VERSION 3.20) project(ola C) set(CMAKE_C_STANDARD 23) add_executable(ola ola.c)
- CMakeLists.txt
- O nome do arquivo é obrigatório, exatamente assim, com C, M e L maiúsculos. Ele fica na pasta principal do projeto.
- cmake_minimum_required(VERSION 3.20)
- "Versão mínima exigida do CMake": a primeira linha de todo
CMakeLists.txt. Diz que o projeto foi escrito para o CMake 3.20 ou mais novo (de 2021), e o CMake passa a se comportar como aquela versão. Se o seu CMake for mais velho, ele para com um erro claro. - project(ola C)
- Dá um nome ao projeto (
ola) e diz a linguagem:C. Sem oC, o CMake procuraria também um compilador de C++, que você não precisa. - set(CMAKE_C_STANDARD 23)
setdá valor a uma variável do CMake.CMAKE_C_STANDARDé a versão do C:23= C23 (veja Versões do C). Outros valores:99,11,17.- add_executable(ola ola.c)
- "Acrescente um executável": o programa vai se chamar
olae é feito do arquivoola.c. No CMake, cada coisa que você constrói (um programa, uma biblioteca) se chama alvo (em inglês, target).
Os comandos do CMake têm o formato comando(argumento argumento …), separados por espaço, sem vírgulas e sem ponto e vírgula. Maiúsculas e minúsculas não importam nos nomes dos comandos (ADD_EXECUTABLE funciona, e você vai ver isso em projetos antigos), mas importam nas variáveis (CMAKE_C_STANDARD tem de ser em maiúsculas). Comentários começam com #.
2. Configurar e compilar
Configurar: cmake -B build
$ ls CMakeLists.txt ola.c $ cmake -B build -- The C compiler identification is GNU 15.2.0 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Configuring done (0.6s) -- Generating done (0.0s) -- Build files have been written to: /home/ana/c/cmake/ola/build
- cmake -B build
- Configura o projeto da pasta atual e põe tudo o que gerar na pasta
build(-Bde build directory, "pasta de construção"). Se ela não existe, o CMake a cria. - The C compiler identification is GNU 15.2.0
- Achou o compilador de C: o gcc 15.2 (GNU é o projeto do gcc).
- Detecting C compiler ABI info / compile features
- Testes rápidos para descobrir o que esse compilador sabe fazer (por exemplo, se ele conhece o C23).
- Check for working C compiler: /usr/bin/cc - skipped
- O
ccé o nome genérico do "compilador C do sistema"; no Ubuntu, ele é o gcc. O teste foi pulado porque o anterior já mostrou que funciona. - Configuring done / Generating done
- "Configuração feita / geração feita": leu a receita e escreveu os arquivos de compilação.
- Build files have been written to: /home/ana/c/cmake/ola/build
- Onde eles foram parar.
$ ls build CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
Lá está o Makefile que o CMake escreveu (você nunca precisa abri-lo), o CMakeCache.txt (as respostas que o CMake descobriu, guardadas para a próxima vez) e a pasta CMakeFiles (arquivos internos). Tudo o que é gerado fica dentro de build; a pasta do projeto continua limpa. Para recomeçar do zero, basta apagar a build (rm -r build).
Compilar: cmake --build build
$ cmake --build build [ 50%] Building C object CMakeFiles/ola.dir/ola.c.o [100%] Linking C executable ola [100%] Built target ola $ ./build/ola Olá, CMake!
- cmake --build build
- "Construa o que está configurado em
build". Por baixo, o CMake chamou omake. Você poderia entrar na pasta e digitarmake, mas ocmake --buildfunciona igual com qualquer gerador (seção 6). - [ 50%] Building C object CMakeFiles/ola.dir/ola.c.o
- Compilou o
ola.cpara um arquivo-objeto.o(veja Como o C Vira Programa). A porcentagem é o progresso. - [100%] Linking C executable ola
- Ligou os objetos e criou o executável.
- Built target ola
- "Alvo
olaconstruído." - ./build/ola
- O executável fica dentro da pasta
build.
Rodar de novo, sem mudar nada, não recompila: o CMake, como o make, sabe que o executável está em dia.
$ cmake --build build [100%] Built target ola
Ver os comandos de verdade: -v
Quer saber qual gcc o CMake chamou? A opção -v (verbose, "falante") mostra os comandos. O arquivo foi tocado com touch para forçar a recompilação (e as linhas foram filtradas com grep, porque o -v mostra muita coisa):
$ touch ola.c $ cmake --build build -v 2>&1 | grep -E "cc |Building|Linking" [ 50%] Building C object CMakeFiles/ola.dir/ola.c.o /usr/bin/cc -std=gnu2x -MD -MT CMakeFiles/ola.dir/ola.c.o -MF CMakeFiles/ola.dir/ola.c.o.d -o CMakeFiles/ola.dir/ola.c.o -c /home/ana/c/cmake/ola/ola.c [100%] Linking C executable ola /usr/bin/cc -Wl,--dependency-file=CMakeFiles/ola.dir/link.d CMakeFiles/ola.dir/ola.c.o -o ola
Duas surpresas: o CMAKE_C_STANDARD 23 virou -std=gnu2x, e não há -Wall -Wextra. O gnu2x é o nome antigo do C23 com as extensões do GNU (c2x era o apelido do C23 antes de ele ficar pronto, e o gcc 15 aceita os dois nomes). E os avisos, o CMake não liga sozinho: isso é com você (seção 3). As opções -MD -MT … -MF … pedem ao gcc uma lista dos .h que cada .c inclui, para o CMake saber o que recompilar quando um .h muda.
3. A lojinha com vários arquivos
Agora um projeto de verdade, em ~/c/cmake/loja: o main.c usa funções de estoque.c, declaradas em estoque.h (veja Arquivos .h e .c e Vários Arquivos). Uma delas usa round, da math.h (veja Matemática):
#ifndef ESTOQUE_H #define ESTOQUE_H double total_com_desconto(double preco, int quantidade, double desconto); double arredondar(double valor); #endif
#include <math.h>
#include "estoque.h"
double total_com_desconto(double preco, int quantidade, double desconto) {
double total = preco * quantidade;
return total - total * desconto / 100.0;
}
double arredondar(double valor) {
return round(valor * 100.0) / 100.0;
}
#include <stdio.h>
#include "estoque.h"
int main(void) {
double total = total_com_desconto(3.33, 7, 15.0);
printf("Total: R$ %.4f\n", total);
printf("Arredondado: R$ %.2f\n", arredondar(total));
return 0;
}
No add_executable, liste todos os .c do programa (os .h não precisam: eles entram pelo #include):
cmake_minimum_required(VERSION 3.20) project(loja C) set(CMAKE_C_STANDARD 23) add_executable(loja main.c estoque.c)
$ cmake -B build «… as mesmas linhas de antes …» -- Build files have been written to: /home/ana/c/cmake/loja/build $ cmake --build build [ 33%] Building C object CMakeFiles/loja.dir/main.c.o [ 66%] Building C object CMakeFiles/loja.dir/estoque.c.o [100%] Linking C executable loja /usr/bin/x86_64-linux-gnu-ld.bfd: CMakeFiles/loja.dir/estoque.c.o: na função "arredondar": estoque.c:(.text+0x7e): referência não definida para "round" collect2: error: ld returned 1 exit status gmake[2]: *** [CMakeFiles/loja.dir/build.make:117: loja] Error 1 gmake[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/loja.dir/all] Error 2 gmake: *** [Makefile:91: all] Error 2
Os dois .c compilaram, mas a ligação falhou: "referência não definida para round" (em inglês, undefined reference to 'round'). No Linux, as funções da math.h moram numa biblioteca separada, a libm (de math), que o gcc não liga sozinho. Na linha de comando, seria o -lm. As três linhas gmake… Error são o make avisando que desistiu (gmake é o nome do GNU make).
A biblioteca e os avisos: target_link_libraries e target_compile_options
A versão completa do CMakeLists.txt da lojinha, com a biblioteca, os avisos e o C23 "puro":
cmake_minimum_required(VERSION 3.20) project(loja C) set(CMAKE_C_STANDARD 23) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) add_executable(loja main.c estoque.c) target_compile_options(loja PRIVATE -Wall -Wextra) target_link_libraries(loja PRIVATE m)
- set(CMAKE_C_STANDARD_REQUIRED ON)
- "O padrão é obrigatório": se o compilador não souber C23, o CMake para com um erro, em vez de usar uma versão mais velha sem avisar.
- set(CMAKE_C_EXTENSIONS OFF)
- "Sem extensões": pede o C23 do padrão (
-std=c2x) em vez do C23 com extensões do GNU (-std=gnu2x). Assim o código fica mais fácil de compilar em outros compiladores. - target_compile_options(loja PRIVATE -Wall -Wextra)
- "Opções de compilação do alvo
loja": acrescenta-Wall -Wextraa cadagccque compila um.cdele (veja Avisos). - target_link_libraries(loja PRIVATE m)
- "Bibliotecas para ligar ao alvo
loja": am, que vira-lmna ligação. Escreva o nome sem olibe sem o-l(veja Bibliotecas). - PRIVATE
- "Só para este alvo". Faz diferença quando um alvo é uma biblioteca usada por outros (aí existem também
PUBLICeINTERFACE); para um programa, usePRIVATE.
Repare na ordem: os comandos target_… vêm depois do add_executable, porque precisam que o alvo já exista. Agora compila, e o -v mostra as opções novas:
$ cmake --build build -- Configuring done (0.0s) -- Generating done (0.0s) -- Build files have been written to: /home/ana/c/cmake/loja/build [ 33%] Building C object CMakeFiles/loja.dir/estoque.c.o [ 66%] Building C object CMakeFiles/loja.dir/main.c.o [100%] Linking C executable loja [100%] Built target loja $ ./build/loja Total: R$ 19.8135 Arredondado: R$ 19.81 $ touch estoque.c $ cmake --build build -v 2>&1 | grep -E "cc |Building|Linking" [ 33%] Building C object CMakeFiles/loja.dir/estoque.c.o /usr/bin/cc -std=c2x -Wall -Wextra -MD -MT CMakeFiles/loja.dir/estoque.c.o -MF CMakeFiles/loja.dir/estoque.c.o.d -o CMakeFiles/loja.dir/estoque.c.o -c /home/ana/c/cmake/loja/estoque.c [ 66%] Linking C executable loja /usr/bin/cc -Wl,--dependency-file=CMakeFiles/loja.dir/link.d CMakeFiles/loja.dir/main.c.o CMakeFiles/loja.dir/estoque.c.o -o loja -lm
- -- Configuring done …
- Você mudou o
CMakeLists.txte não precisou rodar ocmake -B buildde novo: ocmake --buildpercebeu e reconfigurou sozinho. - -std=c2x -Wall -Wextra
- O C23 sem extensões e os avisos, em cada compilação.
- … -o loja -lm
- A biblioteca de matemática, na ligação.
- só o estoque.c
- Depois do
touch estoque.c, só ele foi recompilado; omain.c.oantigo foi reaproveitado. Em projetos grandes, isso economiza minutos.
4. Acrescentar um arquivo
A Ana quer cobrar frete: R$ 8,90 para compras abaixo de R$ 50,00; acima disso, grátis. Ela cria frete.h e frete.c, e muda o main.c:
#include "frete.h"
double frete(double total) {
if (total >= 50.0) {
return 0.0;
}
return 8.90;
}
No CMakeLists.txt, só uma linha muda: o arquivo novo entra no add_executable.
add_executable(loja main.c estoque.c frete.c)
$ cmake --build build -- Configuring done (0.0s) -- Generating done (0.0s) -- Build files have been written to: /home/ana/c/cmake/loja/build [ 25%] Building C object CMakeFiles/loja.dir/main.c.o [ 50%] Building C object CMakeFiles/loja.dir/frete.c.o [ 75%] Linking C executable loja [100%] Built target loja $ ./build/loja Total: R$ 19.81 Frete: R$ 8.90 Total final: R$ 28.71
Recompilou o main.c (que mudou) e o frete.c (novo); o estoque.c foi reaproveitado. Se ela esquecesse o frete.c no add_executable, a ligação falharia com referência não definida para "frete" (veja "Quando dá errado").
Missão: no editor, os três .c das abas são compilados juntos, como se estivessem todos no add_executable (e a math.h não precisa do m). Mude o main.c para a compra ser de 17 unidades a R$ 3,50, sem desconto: total_com_desconto(3.50, 17, 0.0). Como 17 × 3,50 = 59,50 passa de R$ 50,00, a função de frete.c deve devolver frete grátis: a saída precisa ter Frete: R$ 0.00 e Total final: R$ 59.50.
#include <stdio.h>
#include "estoque.h"
#include "frete.h"
int main(void) {
double total = arredondar(total_com_desconto(3.33, 7, 15.0));
double f = frete(total);
printf("Total: R$ %.2f\n", total);
printf("Frete: R$ %.2f\n", f);
printf("Total final: R$ %.2f\n", total + f);
return 0;
}
#include <math.h>
#include "estoque.h"
double total_com_desconto(double preco, int quantidade, double desconto) {
double total = preco * quantidade;
return total - total * desconto / 100.0;
}
double arredondar(double valor) {
return round(valor * 100.0) / 100.0;
}
#ifndef ESTOQUE_H #define ESTOQUE_H double total_com_desconto(double preco, int quantidade, double desconto); double arredondar(double valor); #endif
#include "frete.h"
double frete(double total) {
if (total >= 50.0) {
return 0.0;
}
return 8.90;
}
#ifndef FRETE_H #define FRETE_H double frete(double total); #endif
#include <stdio.h>
#include "estoque.h"
#include "frete.h"
int main(void) {
double total = arredondar(total_com_desconto(3.50, 17, 0.0));
double f = frete(total);
printf("Total: R$ %.2f\n", total);
printf("Frete: R$ %.2f\n", f);
printf("Total final: R$ %.2f\n", total + f);
return 0;
}
5. Debug e Release
Um mesmo projeto costuma ser compilado de dois jeitos: para depurar (com -g, sem otimização, para o gdb) e para entregar (otimizado). No CMake, isso é o tipo de build, escolhido na configuração com -DCMAKE_BUILD_TYPE=… (-D dá valor a uma variável pela linha de comando). Cada tipo numa pasta própria:
$ cmake -B build-debug -DCMAKE_BUILD_TYPE=Debug > /dev/null $ cmake --build build-debug -v 2>&1 | grep -E "^/usr/bin/cc .*main" /usr/bin/cc -g -std=c2x -Wall -Wextra -MD -MT CMakeFiles/loja.dir/main.c.o -MF CMakeFiles/loja.dir/main.c.o.d -o CMakeFiles/loja.dir/main.c.o -c /home/ana/c/cmake/loja/main.c /usr/bin/cc -g -Wl,--dependency-file=CMakeFiles/loja.dir/link.d CMakeFiles/loja.dir/main.c.o CMakeFiles/loja.dir/estoque.c.o -o loja -lm $ cmake -B build-rel -DCMAKE_BUILD_TYPE=Release > /dev/null $ cmake --build build-rel -v 2>&1 | grep -E "^/usr/bin/cc .*main" /usr/bin/cc -O3 -DNDEBUG -std=c2x -Wall -Wextra -MD -MT CMakeFiles/loja.dir/main.c.o -MF CMakeFiles/loja.dir/main.c.o.d -o CMakeFiles/loja.dir/main.c.o -c /home/ana/c/cmake/loja/main.c /usr/bin/cc -O3 -DNDEBUG -Wl,--dependency-file=CMakeFiles/loja.dir/link.d CMakeFiles/loja.dir/main.c.o CMakeFiles/loja.dir/estoque.c.o -o loja -lm
(Esta sessão foi feita antes do frete.c existir; por isso ele não aparece.)
CMAKE_BUILD_TYPE | Opções do gcc | Para quê |
|---|---|---|
| (nenhum) | nenhuma | O padrão: nem otimizado, nem com -g. |
Debug | -g | Depurar com o gdb, rodar com o Valgrind. |
Release | -O3 -DNDEBUG | A versão final: otimizada e com os assert desligados (veja Testes). |
RelWithDebInfo | -O2 -g -DNDEBUG | Otimizada, mas com informações de depuração. |
MinSizeRel | -Os -DNDEBUG | Otimizada para ficar pequena. |
Uma terceira pasta, com os sanitizers, usa a variável CMAKE_C_FLAGS (opções extras para todo gcc):
$ cmake -B build-san -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS="-fsanitize=address,undefined" > /dev/null $ cmake --build build-san -v 2>&1 | grep -E "^/usr/bin/cc" /usr/bin/cc -fsanitize=address,undefined -g -std=c2x -Wall -Wextra -MD -MT CMakeFiles/loja.dir/main.c.o -MF CMakeFiles/loja.dir/main.c.o.d -o CMakeFiles/loja.dir/main.c.o -c /home/ana/c/cmake/loja/main.c «… o mesmo para estoque.c …» /usr/bin/cc -fsanitize=address,undefined -g -Wl,--dependency-file=CMakeFiles/loja.dir/link.d CMakeFiles/loja.dir/main.c.o CMakeFiles/loja.dir/estoque.c.o -o loja -lm $ ./build-san/loja Total: R$ 19.8135 Arredondado: R$ 19.81
Repare que o -fsanitize foi também para a ligação, como a aula de sanitizers exige. Cada pasta build-… é independente: dá para ter as três ao mesmo tempo.
6. Ninja e outros geradores
O CMake não compila nada sozinho: ele gera os arquivos para outra ferramenta. Essa ferramenta é o gerador. No Linux, o padrão é o make ("Unix Makefiles"). Outro muito usado é o Ninja, feito para ser rápido. Escolha com -G:
$ cmake -G Ninja -B build-ninja -- The C compiler identification is GNU 15.2.0 «… as mesmas linhas …» -- Build files have been written to: /home/ana/c/cmake/loja/build-ninja $ cmake --build build-ninja [1/3] Building C object CMakeFiles/loja.dir/main.c.o [2/3] Building C object CMakeFiles/loja.dir/estoque.c.o [3/3] Linking C executable loja
O CMakeLists.txt é o mesmo; só a saída muda (o Ninja conta as etapas, [1/3], em vez de porcentagem). No Windows, o CMake gera projetos do Visual Studio; no macOS, do Xcode. É isso que a "receita única" quer dizer.
Formas diferentes de compilar e qual usar
| Forma | Bom para | Limite |
|---|---|---|
gcc na mão | Um arquivo, um teste rápido, as aulas deste guia. | Com muitos arquivos, você recompila tudo e esquece opções. |
| Makefile | Projetos pequenos e médios no Linux; entender como a compilação funciona. | Você escreve cada regra; não funciona no Visual Studio; as dependências dos .h dão trabalho. |
| CMake | Projetos que crescem, que outras pessoas vão compilar, que precisam rodar em Linux, Windows e macOS. As IDEs (VS Code, CLion, Visual Studio, Qt Creator) abrem um CMakeLists.txt direto. | Mais uma linguagem para aprender; para um arquivo só, é exagero. |
| Meson, Bazel, xmake… | Alternativas mais novas ao CMake. | Menos comuns em projetos C. |
Qual usar: para aprender, o gcc na mão e depois o Makefile, para entender cada etapa. Quando o projeto passar de uns poucos arquivos, ou quando outra pessoa (ou outra máquina) precisar compilá-lo, use o CMake.
Quando dá errado
does not appear to contain CMakeLists.txt
$ cmake -B build CMake Error: The source directory "/home/ana/c/cmake" does not appear to contain CMakeLists.txt. Specify --help for usage, or press the help button on the CMake GUI.
O que aconteceu: você está na pasta errada ("a pasta não parece conter um CMakeLists.txt"), ou o arquivo tem outro nome (cmakelists.txt, CMakeList.txt).
Como resolver: entre na pasta do projeto (cd loja) e confira o nome exato do arquivo com ls.
Unknown CMake command
$ cmake -B build «…» CMake Error at CMakeLists.txt:6 (add_executabel): Unknown CMake command "add_executabel". -- Configuring incomplete, errors occurred!
O que aconteceu: erro de digitação no nome de um comando ("comando do CMake desconhecido"), na linha 6.
Como resolver: corrija para add_executable.
Cannot find source file
$ cmake -B build
«…»
CMake Error at CMakeLists.txt:6 (add_executable):
Cannot find source file:
estoqe.c
CMake Error at CMakeLists.txt:6 (add_executable):
No SOURCES given to target: loja
CMake Generate step failed. Build files cannot be regenerated correctly.
O que aconteceu: um arquivo listado no add_executable não existe ("não acho o arquivo-fonte"): aqui, estoqe.c em vez de estoque.c. O segundo erro ("nenhum arquivo dado ao alvo") é consequência do primeiro.
Como resolver: corrija o nome. Os caminhos são relativos à pasta do CMakeLists.txt.
.c no add_executable: referência não definida
$ cmake --build build «…» [100%] Linking C executable loja /usr/bin/x86_64-linux-gnu-ld.bfd: CMakeFiles/loja.dir/main.c.o: na função "main": main.c:(.text+0x2a): referência não definida para "total_com_desconto" /usr/bin/x86_64-linux-gnu-ld.bfd: main.c:(.text+0x5e): referência não definida para "arredondar" collect2: error: ld returned 1 exit status «… as linhas gmake … Error …»
O que aconteceu: o CMakeLists.txt tinha só add_executable(loja main.c). O main.c compilou (o estoque.h declara as funções), mas ninguém compilou o estoque.c, onde elas estão.
Como resolver: liste todos os .c: add_executable(loja main.c estoque.c). Se o nome que falta for round, sqrt, pow…, o que falta é o target_link_libraries(loja PRIVATE m).
Compatibility with CMake < 3.5 has been removed from CMake.
$ 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!
O que aconteceu: o projeto tem cmake_minimum_required(VERSION 2.8), comum em tutoriais e projetos antigos. O CMake 4 não sabe mais se comportar como versões anteriores à 3.5.
Como resolver: no seu projeto, suba a versão (VERSION 3.20). Num projeto de outra pessoa que você só quer compilar, a própria mensagem dá o atalho: cmake -B build -DCMAKE_POLICY_VERSION_MINIMUM=3.5.
cmake_minimum_required() should be called prior to this top-level project() call
O que aconteceu: faltou a linha cmake_minimum_required (ou ela veio depois do project). É só um aviso (CMake Warning (dev), "aviso para desenvolvedores"): o projeto ainda compila.
Como resolver: ponha cmake_minimum_required(VERSION 3.20) como primeira linha.
cmake --build sem ter configurado
$ cmake --build b2 Error: /home/ana/c/cmake/ola/b2 is not a directory
O que aconteceu: a pasta b2 não existe: o cmake -B b2 nunca foi rodado (ou você errou o nome). Se a configuração falhou no meio, a mensagem é outra, como gmake: Makefile: Arquivo ou diretório inexistente.
Como resolver: rode cmake -B build primeiro e conserte os erros que ele mostrar; depois, cmake --build build.
Referência rápida
| No terminal | O que faz |
|---|---|
cmake -B build | Configura o projeto da pasta atual na pasta build. |
cmake -B build -DCMAKE_BUILD_TYPE=Debug | Configura com -g (ou Release: -O3 -DNDEBUG). |
cmake -G Ninja -B build | Usa o Ninja em vez do make. |
cmake --build build | Compila o que mudou. |
cmake --build build -v | Compila mostrando os comandos. |
cmake --build build --clean-first | Apaga os .o e recompila tudo. |
rm -r build | Recomeça do zero. |
No CMakeLists.txt | O que faz |
|---|---|
cmake_minimum_required(VERSION 3.20) | Versão mínima do CMake (primeira linha). |
project(nome C) | Nome do projeto e linguagem. |
set(CMAKE_C_STANDARD 23) | Versão do C (99, 11, 17, 23). |
set(CMAKE_C_STANDARD_REQUIRED ON) | Exige essa versão. |
set(CMAKE_C_EXTENSIONS OFF) | -std=c2x em vez de -std=gnu2x. |
add_executable(prog a.c b.c) | Cria o alvo prog com esses arquivos. |
target_compile_options(prog PRIVATE -Wall -Wextra) | Opções de compilação do alvo. |
target_link_libraries(prog PRIVATE m) | Liga bibliotecas (m = -lm). |
# texto | Comentário. |
Exercícios
1. Configurar
Complete o comando que configura o projeto na pasta build:
2. Compilar
Complete o comando que compila o projeto já configurado em build:
3. A biblioteca de matemática
O programa calc usa sqrt e a ligação falhou com referência não definida para "sqrt". Complete:
4. Três arquivos
O programa jogo é feito de main.c, tabuleiro.c e tabuleiro.h. Complete:
5. Você mudou o CMakeLists.txt (acrescentou um arquivo). O que precisa fazer?
6. Qual tipo de build você usa para depurar com o gdb?
Resumo
- O
CMakeLists.txtdescreve o projeto; o CMake gera os arquivos de compilação (Makefile, Ninja, Visual Studio…) para cada sistema. - Mínimo para C:
cmake_minimum_required(VERSION 3.20),project(nome C),set(CMAKE_C_STANDARD 23),add_executable(prog arquivos.c…). - Dia a dia:
cmake -B builduma vez; depois,cmake --build builda cada mudança. O executável fica embuild/. - Os avisos não vêm ligados:
target_compile_options(prog PRIVATE -Wall -Wextra). Amath.hprecisa detarget_link_libraries(prog PRIVATE m). -DCMAKE_BUILD_TYPE=Debugpara depurar,Releasepara entregar; uma pastabuild-…para cada versão.-vmostra os comandosgccde verdade: use para conferir o que o CMake está fazendo.