Comenzando con cmake

Instalación de CMake

Dirígete a la página de descarga de CMake y obtén un binario para tu sistema operativo, p. Windows, Linux o Mac OS X. En Windows, haga doble clic en el binario para instalarlo. En Linux, ejecute el binario desde una terminal.

En Linux, también puede instalar los paquetes desde el administrador de paquetes de la distribución. En Ubuntu 16.04 puede instalar la línea de comandos y la aplicación gráfica con:

sudo apt-get install cmake
sudo apt-get install cmake-gui

En FreeBSD puede instalar la línea de comandos y la aplicación gráfica basada en Qt con:

pkg install cmake
pkg install cmake-gui

En Mac OSX, si usa uno de los administradores de paquetes disponibles para instalar su software, los más notables son MacPorts (MacPorts) y Homebrew (Homebrew), también puede instalar CMake a través de uno de a ellos. Por ejemplo, en el caso de MacPorts, escriba lo siguiente

sudo port install cmake  

instalará CMake, mientras que en caso de que use el administrador de paquetes de Homebrew, escribirá

brew install cmake

Una vez que haya instalado CMake, puede verificar fácilmente haciendo lo siguiente

cmake --version

Deberías ver algo similar a lo siguiente

cmake version 3.5.1

CMake suite maintained and supported by Kitware (kitware.com/cmake).

Proyecto simple “Hola Mundo”

Dado un archivo fuente de C++ main.cpp que define una función main(), un archivo adjunto CMakeLists.txt (con el siguiente contenido) indicará a CMake que genere las instrucciones de compilación adecuadas para el sistema actual y el compilador de C++ predeterminado .

main.cpp (Ejemplo de C++ Hello World)

#include <iostream>

int main()
{
    std::cout << "Hello World!\n";
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.4)

project(hello_world)

add_executable(app main.cpp)

Véalo en vivo en Coliru

  1. cmake_minimum_required(VERSION 2.4) establece una versión mínima de CMake requerida para evaluar el script actual.

  2. project(hello_world) inicia un nuevo proyecto de CMake. Esto desencadenará una gran cantidad de lógica interna de CMake, especialmente la detección del compilador C y C++ predeterminado.

  3. Con add_executable(app main.cpp) se crea una app de destino de compilación, que invocará el compilador configurado con algunos indicadores predeterminados para la configuración actual para compilar una ‘aplicación’ ejecutable desde el archivo fuente dado ‘main.cpp’.

Línea de comando (In-Source-Build, no recomendado)

> cmake .
...
> cmake --build .

cmake . realiza la detección del compilador, evalúa CMakeLists.txt en el directorio . dado y genera el entorno de compilación en el directorio de trabajo actual.

El comando cmake --build . es una abstracción para la llamada build/make necesaria.

Línea de comando (Fuera de fuente, recomendado)

Para mantener su código fuente limpio de cualquier artefacto de compilación, debe hacer compilaciones “fuera de la fuente”.

> mkdir build
> cd build
> cmake ..
> cmake --build .

O CMake también puede abstraer los comandos básicos del shell de su plataforma del ejemplo anterior:

> cmake -E make_directory build
> cmake -E chdir build cmake .. 
> cmake --build build 

“Hello World” como biblioteca

Este ejemplo muestra cómo implementar el programa “Hello World” como una biblioteca y cómo vincularlo con otros objetivos.

Digamos que tenemos el mismo conjunto de archivos fuente/encabezado que en https://www.wikiod.com/es/docs/cmake/862/getting-started-with-cmake/22391/hello-world-with-multiple-source-files #t=201610310659039267444 ejemplo. En lugar de construir a partir de múltiples archivos fuente, primero podemos implementar foo.cpp como una biblioteca usando add_library() y luego vincularlo con el programa principal con target_link_libraries().

Modificamos CMakeLists.txt para

cmake_minimum_required(VERSION 2.4)

project(hello_world)

include_directories(${PROJECT_SOURCE_DIR})
add_library(applib foo.cpp)
add_executable(app main.cpp)
target_link_libraries(app applib)

y siguiendo los mismos pasos obtendremos el mismo resultado.

Cambiar entre tipos de compilación, p. depurar y liberar

CMake conoce varios tipos de compilación, que generalmente influyen en los parámetros predeterminados del compilador y del enlazador (como la creación de información de depuración) o rutas de código alternativas.

De forma predeterminada, CMake puede manejar los siguientes tipos de compilación:

  • Depuración: por lo general, una compilación de depuración clásica que incluye información de depuración, sin optimización, etc.
  • Lanzamiento: Su compilación de lanzamiento típica sin información de depuración y optimización completa.
  • RelWithDebInfo:: Igual que Release, pero con información de depuración.
  • MinSizeRel: una compilación especial de Lanzamiento optimizada para el tamaño.

La forma en que se manejan las configuraciones depende del generador que se esté utilizando.

Algunos generadores (como Visual Studio) admiten varias configuraciones. CMake generará todas las configuraciones a la vez y puede seleccionar desde el IDE o usando --config CONFIG (con cmake --build) qué configuración desea construir. Para estos generadores, CMake hará todo lo posible para generar una estructura de directorio de compilación de modo que los archivos de diferentes configuraciones no se crucen entre sí.

Los generadores que solo admiten una única configuración (como Unix Makefiles) funcionan de manera diferente. Aquí, la configuración actualmente activa está determinada por el valor de la variable CMake CMAKE_BUILD_TYPE.

Por ejemplo, para elegir un tipo de compilación diferente, se podrían ejecutar los siguientes comandos de línea de comandos:

cmake -DCMAKE_BUILD_TYPE=Debug path/to/source
cmake -DCMAKE_BUILD_TYPE=Release path/to/source

Una secuencia de comandos de CMake debe evitar configurar CMAKE_BUILD_TYPE en sí mismo, ya que generalmente se considera responsabilidad de los usuarios hacerlo.

Para los generadores de configuración única, cambiar la configuración requiere volver a ejecutar CMake. Es probable que una compilación posterior sobrescriba los archivos de objetos producidos por la configuración anterior.

“Hello World” con múltiples archivos fuente

Primero podemos especificar los directorios de los archivos de encabezado mediante include_directories(), luego debemos especificar los archivos de origen correspondientes del ejecutable de destino mediante add_executable(), y asegurarnos de que haya exactamente una función main() en los archivos fuente.

El siguiente es un ejemplo simple, se supone que todos los archivos están ubicados en el directorio PROJECT_SOURCE_DIR.

principal.cpp

#include "foo.h"

int main()
{
    foo();
    return 0;
}

foo.h

void foo();

foo.cpp

#include <iostream>
#include "foo.h"

void foo()
{
    std::cout << "Hello World!\n";
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.4)

project(hello_world)

include_directories(${PROJECT_SOURCE_DIR})
add_executable(app main.cpp foo.cpp)  # be sure there's exactly one main() function in the source files

Podemos seguir el mismo procedimiento en el ejemplo anterior para construir nuestro proyecto. Luego, ejecutar app imprimirá

>./app
Hello World!