Saltar para o conteúdo

CMake

Fonte: Wikiversidade

O nome CMake é uma abreviação de "cross plataform make”, ou seja, é um sistema multiplataforma que gerencia e automatiza o processo de “build". O CMake, além disso, é um software gratuito e open-source, cujo desenvolvimento iniciou em 1999, patrocinado pela Biblioteca Nacional de Medicina dos Estados Unidos.

O CMake é comparado ao “make utility", no sentido de que ambos providenciam um sistema de “build" que podem ser utilizados para compilar programas. Porém, o CMake é mais recomendado para projetos mais complexos e multiplataformas. O CMake inclusive gera automaticamente um Makefile para o projeto e também pode ser utilizado em conjunto de diversas IDEs como Microsoft Visual Studio e Xcode.

É importante notar que o CMAKE pode gerar um ambiente nativo de compilação que pode ser utilizado não só para construir executáveis, mas também a criação de bibliotecas

A definição de como será realizado o processo de build é definida por um arquivo de configuração chamado “CMakeLists.txt” composto por comandos da forma “COMMAND (args…)“.

CMake vs Make

[editar | editar código-fonte]

Make é um sistema de compilação. Ele direciona o seu compilador e outras ferramentas de compilação para criar seu código compilado. [1]

CMake é um gerador de sistema de compilação. Pode produzir Makefiles, Ninja Build, KDEvelop ou XCode, Visual Studio. Tudo vindo do mesmo ponto de início, ou melhor, do mesmo "CMakeLists.txt". Então se um projeto é independente da plataforma (Multiplataforma), o CMake é uma maneira de torna-lo independente do sistema também. [2]

Para instalar o CMake no windows basta utilizar o instalador disponível no site do CMake. Este pode ser encontrado através do link abaixo:

Ubunto/Debian e derivados

[editar | editar código-fonte]
  • sudo apt-get install cmake
  • sudo yum install cmake
  1. Realize o Download do arquivo de instalação ".dmg" disponível no site do CMake. Link abaixo:
  1. Execute o arquivo baixado, ou seja, clique nele duas vezes.
  2. Instale o CMake, ou seja, arraste o CMake para a pasta Applications.
  3. Execute o CMake.
  4. Adicione CMake aos paths.
  • No menu "Tools" selecione "How to Install For Command Line Use". Observe o caminho indicado na caixa de diálogo que aparecerá. Por exemplo, "/Applications/CMake.app/Contents/bin/cmake-gui".

Abra o terminal e digite:

  • sudo mkdir -p /usr/local/bin
  • sudo /Applications/CMake.app/Contents/bin/cmake-gui --install=/usr/local/bin

Para verificar se tudo ocorreu corretamente digite:

  • cmake --version

Utilizando o CMake

[editar | editar código-fonte]

Configuração Mínima para Compilar

[editar | editar código-fonte]

Todo CMakeLists.txt deve conter no mínimo:

  • A especificação da versão do CMake:
cmake_minimum_required(''<VERSION NUMBER>'')
  • O nome do projeto:
project(hello)
  • Alguma ação a ser executada.

Indicar o que será construido pelo CMake, pode também indicar em qual subpasta que estarão os arquivos a serem utilizados.

Exemplos simples de CMakeLists.txt

[editar | editar código-fonte]
  • Aplicação
cmake_minimum_required(VERSION 2.8)

project(hello)

add_executable(Hello hello.cpp)
  • Biblioteca
cmake_minimum_required(VERSION 2.8)

project(hello)

add_library(Hello SHARED hello.cpp)
  • Shared Object
cmake_minimum_required(VERSION 2.8)

project(hello)

add_library(Hello OBJECT hello.cpp)

Gerando o Makefile a partir do CMakeLists.txt

[editar | editar código-fonte]

Basta utilizar o comando

cmake <Caminho para o CMakeLists.txt>

Exemplos da Utilização do CMake

[editar | editar código-fonte]

Exemplo 1 - Gerando simples executável

[editar | editar código-fonte]

Suponha o seguinte arquivo "hello.cpp" e o seguinte arquivo "CMakeLists.txt":

#include <stdio.h>

int main() {
        printf("Hello World!\n");
        return 0;
}
cmake_minimum_required(VERSION 2.8)
project(hello)
add_executable(Hello hello.cpp)

Se os arquivos "hello.cpp" e "CMakeLists.txt" estivessem em um mesmo diretório, bastaria estar nele e executar o comando

cmake .

Dessa forma, um arquivo Makefile seria gerado, então para obtermos o programa executável, bastaria executar o comando

make

Então o executável Hello seria gerado.


Exemplo 2 - Gerando um executável a partir de dois Object Files

[editar | editar código-fonte]

Suponha o seguintes arquivos:

  • "helloFunc.cpp"
#include <stdio.h>

void myHello(char * msg) {
        printf("%s", msg);
}
  • "helloUse.cpp"
void myHello( char * msg);
int main () {
        myHello("Hello World!\n");
}
  • "CMakeLists.txt"
cmake_minimum_required(VERSION 2.8)
project(hello)
add_executable(Hello helloFunc.cpp helloUse.cpp)

Se os arquivos "hello.cpp" e "CMakeLists.txt" estivessem em um mesmo diretório, bastaria estar nele e executar o comando

cmake .

Dessa forma, um arquivo Makefile seria gerado, então para obtermos o programa executável, bastaria executar o comando

make

Então o executável Hello seria gerado.

É interessante notar que o CMake identifica que object files devem ser gerados e posteriormente linkados sem que isso seja especificado.

  • Comparação entre o CMAKE e o Makefile para esse exemplo:

Para atingir esse objetivo com o Makefile o seguinte código seria necessário:

hello: helloFunc.o helloUse.o
    gcc helloFunc.o helloUse.o -o hello

helloFunc.o: helloFunc.c
    gcc -c helloFunc.c

helloUse.o: helloUse.c
    gcc -c helloUse.c

Em ambos os exemplos estamos executando o comando cmake no diretório onde os nossos arquivos ("*.cpp" e "CMakeLists.txt") se encontram. Isso não é recomendado pois o cmake gera alguns arquivos e pastas inúteis para nós. Para evitarmos que esses tipos de arquivos se misturem com o conteúdo do nosso projeto, criamos uma nova pasta, normalmente chamada "build" e rodamos o cmake indicando em qual pasta está o "CMakeLists.txt"(nesse exemplo está junto com os arquivos *.cpp). Para realizar o que foi dito acima, basta executar os seguintes comandos:

mkdir build
cd build
cmake ..

Dessa forma, os arquivos relacionados ao processo de build ficam separados do restante dos arquivos.


É bastante comum criarmos uma estrutura em que na pasta raiz do projeto colocamos o arquivo "CMakeLists.txt" e criamos uma pasta "src" e outra pasta "build".

O arquivo "CMakeLists.txt" na pasta raiz do projeto pode conter o seguinte código:

cmake_minimum_required(VERSION 2.8)
project(hello)
add_subdirectory( src )

Dessa forma, quando executarmos o comando cmake, ele procurará o conteúdo necessário dentro da src, indicada na linha 3, para realizar a build.

Dentro da pasta src, podemos adicionar um outro "CMakeLists.txt" que especificará como a build será feita.

set(CMAKE_C_FLAGS "-Wall")
file( GLOB SRCS *.c *.h)
add_executable(hello ${SRCS} )

Neste caso, a primeira linha indica quais flags de compilação serão utilizadas. A linha 2 é responsável por procurar todos os arquivos com extensão ".c" e ".h" e associá-los a variável SRCS, que está sendo utilizada na linha 3. A linha 3 diz para montar o executável "hello" utilizando os arquivos relacionados a SRCS.

Outros Comandos

[editar | editar código-fonte]

Alguns comandos além dos citados

  • set

Manualmente adicionar sources.

set (SRC_DIR "${ROOT}/src")
  • message

Mostra uma mensagem na tela.

message( STATUS "mensagem")
  • file
file( GLOB SRCS ${SRC_DIR}/*.cpp).

Adiciona a SRCS todos os arquivos terminados com cpp, permitido operações com ele posteriormente.

  • option

Possibilita habilitar e desabilitar opções pela linha de comando. Por exemplo:

//CMakeLists.txt
option(MyOption "MyOption" OFF)

- Opção para MyOption.


//Command line
cmake -DMyOption=ON MyProjectFolder

- Setar MyOption para ON.

  • include_directories

Adiciona os headers presentes na pasta indicada para o ambiente de Build.

include_directories(include)
  • target_link_libraries
target_link_libraries (${PROJ_NAME} ${TE_LIBRARIES})

O exemplo representa que o projeto PROJ_NAME precisa ser linkado com a biblioteca TE_LIBRARIES.


  • list

Operações com listas. Opções:

- list(LENGTH <list> <output variable>)

- list(GET <list> <element index> [<element index> ...] <output variable>)

- list(APPEND <list> [<element> ...])

- list(FIND <list> <value> <output variable>)

- list(INSERT <list> <element_index> <element> [<element> ...])

- list(REMOVE_ITEM <list> <value> [<value> ...])

- list(REMOVE_AT <list> <index> [<index> ...])

- list(REMOVE_DUPLICATES <list>)

- list(REVERSE <list>)

- list(SORT <list>)


  • foreach

Executa um grupo de comandos para cada elemento em uma lista.

foreach(loop_var arg1 arg2 ...)
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
endforeach(loop_var)
  1. https://www.gnu.org/software/make/
  2. https://cmake.org/cmake/help/v3.8/manual/cmake.1.html