not found cmake

command not found cmake



¿Cómo se usa CMake? (2)

Aquí hay algunos videos (difíciles de encontrar, como todo sobre CMake):

Espero que esto ayude (y lástima a CMake, y su documentación deficiente, # ^ & !) :)

Es notoriamente difícil obtener información útil sobre CMake como principiante. Hasta ahora, he visto algunos tutoriales sobre cómo configurar un proyecto muy básico u otro. Sin embargo, ninguno de estos explica el razonamiento detrás de todo lo que se muestra en ellos, siempre dejando muchos agujeros por llenar.

¿Qué significa llamar a CMake en un CMakeLists? ¿Se supone que debe llamarse una vez por árbol de compilación o qué? ¿Cómo utilizo diferentes configuraciones para cada compilación si todas usan las mismas CMakeLists de la misma fuente? ¿Por qué cada subdirectorio necesita su propio CMakeLists? ¿Tendría sentido usar CMake en un CMakeLists que no sea el de la raíz del proyecto? Si es así, ¿en qué casos? ¿Cuál es la diferencia entre especificar cómo crear un archivo ejecutable o una biblioteca desde CMakeLists en su propio subdirectorio o hacerlo en CMakeLists en la raíz de todas las fuentes? ¿Puedo hacer un proyecto para Eclipse y otro para Visual Studio simplemente cambiando la opción -G cuando llamo a CMake? ¿Es así como se usa?

Ninguno de los tutoriales, páginas de documentación o preguntas / respuestas que he visto hasta ahora ofrecen ninguna información útil para comprender cómo usar CMake. Los ejemplos simplemente no son minuciosos. No importa qué tutoriales leí, siento que me falta algo importante.

Hay muchas preguntas que hacen los novatos CMake como yo que no preguntan esto explícitamente, pero que hacen obvio el hecho de que, como newbs, no tienen idea de cómo lidiar con CMake o qué hacer con eso, por lo que a pesar de una pregunta como esto puede parecer demasiado amplio para permitirlo, creo que vale la pena dejarlo y responderlo.


He respondido mi propia pregunta con los restos que he encontrado en Internet y tengo la intención de compartir la respuesta aquí. Si alguno de ustedes está familiarizado con CMake, ayúdenme a corregir cualquier error que pueda tener.

¿Para qué sirve CMake?

De acuerdo con Wikipedia:

CMake es un [...] software para administrar el proceso de compilación del software utilizando un método independiente del compilador. Está diseñado para admitir jerarquías de directorios y aplicaciones que dependen de múltiples bibliotecas. Se usa junto con entornos de compilación nativos como make, Apple Xcode y Microsoft Visual Studio.

Con CMake, ya no necesita mantener configuraciones separadas específicas para su compilador / entorno de compilación. Tienes una configuración, y eso funciona para muchos entornos. Cmake puede generar una solución de Microsoft Visual Studio, un proyecto de Eclipse o un laberinto de Makefile a partir de los mismos archivos sin cambiar nada en ellos.

Dado un grupo de directorios con código en ellos, CMake administra todas las dependencias, órdenes de compilación y otras tareas que su proyecto necesita antes de poder compilarse. En realidad, NO compila nada. Para usar CMake, debe decirle (utilizando archivos de configuración llamados CMakeLists.txt) qué ejecutables necesita compilar, a qué bibliotecas se vinculan, qué directorios hay en su proyecto y qué hay dentro de ellos, así como cualquier detalle, como indicadores o cualquier otra cosa que necesites (CMake es bastante poderoso). Si esto está configurado correctamente, entonces use CMake para crear todos los archivos que su "entorno de construcción nativo" necesita para hacer su trabajo. En Linux, de forma predeterminada, esto significa Makefiles. Entonces, una vez que ejecutas CMake, creará un grupo de archivos para su propio uso más algunos Makefile s. Todo lo que necesita hacer a continuación es escribir "make" en la consola desde la carpeta raíz cada vez que termine de editar el código, y bam, un ejecutable compilado y vinculado.

¿Cómo funciona CMake? ¿Qué hace?

Aquí hay una configuración de proyecto de ejemplo que usaré a lo largo de:

simple/ CMakeLists.txt src/ tutorial.cxx CMakeLists.txt lib/ TestLib.cxx TestLib.h CMakeLists.txt build/

El contenido de cada archivo se muestra y analiza más adelante.

CMake configura su proyecto de acuerdo con la raíz CMakeLists.txt de su proyecto, y lo hace en el directorio desde el que ejecutó cmake desde la consola. Hacer esto desde una carpeta que no es la raíz de su proyecto produce lo que se llama una compilación fuera de la fuente , lo que significa que los archivos creados durante la compilación (archivos obj, archivos lib, ejecutables, ya sabe) se colocarán en dicha carpeta , mantenido separado del código real. Ayuda a reducir el desorden y también se prefiere por otras razones, que no discutiré.

No sé qué sucederá si ejecuta cmake en cualquier otro que no sea el raíz CMakeLists.txt .

En este ejemplo, dado que quiero que todo se coloque dentro de la build/ carpeta, primero tengo que navegar allí, luego paso CMake al directorio en el que reside la raíz CMakeLists.txt .

cd build cmake ..

Por defecto, esto configura todo usando Makefiles como he dicho. Aquí es cómo debería verse la carpeta de compilación ahora:

simple/build/ CMakeCache.txt cmake_install.cmake Makefile CMakeFiles/ (...) src/ CMakeFiles/ (...) cmake_install.cmake Makefile lib/ CMakeFiles/ (...) cmake_install.cmake Makefile

¿Qué son todos estos archivos? Lo único que debe preocuparse es el archivo Makefile y las carpetas del proyecto .

Observe las carpetas src/ y lib/ . Estos han sido creados porque simple/CMakeLists.txt señala utilizando el comando add_subdirectory(<folder>) . Este comando le dice a CMake que busque en esa carpeta otro archivo CMakeLists.txt y que ejecute ese script, por lo que cada subdirectorio agregado de esta forma debe tener dentro un archivo CMakeLists.txt . En este proyecto, simple/src/CMakeLists.txt describe cómo construir el ejecutable real y simple/lib/CMakeLists.txt describe cómo construir la biblioteca. Cada destino que describe un CMakeLists.txt se colocará por defecto en su subdirectorio dentro del árbol de compilación. Entonces, después de un rápido

make

en la consola realizada desde build/ , se agregan algunos archivos:

simple/build/ (...) lib/ libTestLib.a (...) src/ Tutorial (...)

El proyecto está construido y el ejecutable está listo para ejecutarse. ¿Qué haces si quieres que los ejecutables se pongan en una carpeta específica? Establezca la variable CMake apropiada, o cambie las propiedades de un objetivo específico . Más sobre las variables CMake más adelante.

¿Cómo le digo a CMake cómo construir mi proyecto?

Aquí están los contenidos, explicados, de cada archivo en el directorio fuente:

simple/CMakeLists.txt :

cmake_minimum_required(VERSION 2.6) project(Tutorial) #add all subdirectories in this project add_subdirectory(lib) add_subdirectory(src)

La versión mínima requerida siempre debe establecerse, de acuerdo con la advertencia CMake arroja cuando no lo hace. Use cualquiera que sea su versión de CMake. El nombre de su proyecto se puede usar más adelante y sugiere que puede administrar más de un proyecto desde los mismos archivos de cmake. No voy a profundizar en eso, sin embargo. Como se mencionó anteriormente, add_subdirectory() agrega una carpeta al proyecto, lo que significa que CMake espera que tenga un CMakeLists.txt dentro, que luego se ejecutará antes de continuar. Por cierto, si tiene una función CMake definida, puede usarla desde otra CMakeLists.txt en subdirectorios, pero debe definirla antes de usar add_subdirectory() o no la encontrará. Sin embargo, CMake es más inteligente con las bibliotecas, por lo que es probable que esta sea la única ocasión en la que te encuentres con este tipo de problema.

simple/lib/CMakeLists.txt :

add_library(TestLib TestLib.cxx)

Para crear su propia biblioteca, déle un nombre y luego enumere todos los archivos desde los que está construida. Sencillo. Si fuera necesario foo.cxx otro archivo foo.cxx , escribiría add_library(TestLib TestLib.cxx foo.cxx) . Esto también funciona para archivos en otros directorios, por ejemplo add_library(TestLib TestLib.cxx ${CMAKE_SOURCE_DIR}/foo.cxx) . Más sobre la variable CMAKE_SOURCE_DIR más adelante. Otra cosa que puede hacer con esto es especificar que desea una biblioteca compartida. El ejemplo: add_library(TestLib SHARED TestLib.cxx) . No temas, aquí es donde CMake comienza a hacerte la vida más fácil. Ya sea que se comparta o no, ahora todo lo que necesita manejar para usar una biblioteca creada de esta manera es el nombre que le dio aquí. El nombre de esta biblioteca ahora es TestLib, y puede hacer referencia a él desde cualquier parte del proyecto. CMake lo encontrará.

¿Hay una mejor manera de enumerar las dependencias? Definitivamente sí , mira abajo para más información sobre esto.

simple/lib/TestLib.cxx :

#include <stdio.h> void test() { printf("testing.../n"); }

simple/lib/TestLib.h :

#ifndef TestLib #define TestLib void test(); #endif

simple/src/CMakeLists.txt :

#name the executable and all resources it depends on directly add_executable(Tutorial tutorial.cxx) #link to needed libraries target_link_libraries(Tutorial TestLib) #tell CMake where to look for the .h files target_include_directories(Tutorial PUBLIC ${CMAKE_SOURCE_DIR}/lib)

El comando add_executable() funciona exactamente igual que add_library() , excepto, por supuesto, generará un ejecutable en su lugar. Este ejecutable ahora se puede referenciar como un objetivo para cosas como target_link_libraries() . Como tutorial.cxx usa el código que se encuentra en la biblioteca TestLib, usted lo señala a CMake como se muestra. De forma similar, cualquier archivo .h #incluido por cualquier fuente en add_executable() que no esté en el mismo directorio que el origen debe agregarse de alguna manera. Si no fuera por el target_include_directories() , lib/TestLib.h no se encontraría al compilar Tutorial, por lo que toda la lib/ carpeta se agregará a los directorios de inclusión que se buscarán #includes. También puede ver el comando include_directories() que actúa de manera similar, excepto que no necesita que especifique un objetivo, ya que lo establece de forma global para todos los ejecutables. Una vez más, explicaré CMAKE_SOURCE_DIR más adelante.

simple/src/tutorial.cxx :

#include <stdio.h> #include "TestLib.h" int main (int argc, char *argv[]) { test(); fprintf(stdout,"Main/n"); return 0; }

Observe cómo se incluye el archivo "TestLib.h". No se necesita ninguna ruta; CMake se encarga de todo eso detrás de las escenas gracias a target_include_directories() .

Técnicamente hablando, en un árbol fuente simple como este, puede prescindir de CMakeLists.txt s en lib/ y src/ y simplemente agregar algo como add_executable(Tutorial src/tutorial.cxx) a simple/CMakeLists.txt . Depende de usted y de las necesidades de su proyecto.

¿Qué más debería saber para usar CMake correctamente?

(También temas relevantes para su comprensión)

Encontrar y usar paquetes : la respuesta a esta pregunta la explica mejor que nunca.

Declarar variables y funciones, usar control de flujo, etc .: consulte este tutorial que explica los conceptos básicos de lo que CMake tiene para ofrecer, además de ser una buena introducción en general.

Variables de CMake : hay muchas, por lo que lo que sigue es un curso intensivo para que vayas por el camino correcto. El wiki de CMake es un buen lugar para obtener información más detallada sobre variables y, aparentemente, otras cosas también.

Es posible que desee editar algunas variables sin reconstruir el árbol de compilación. Use ccmake para esto (edita el archivo CMakeCache.txt ). Recuerde configurar la configuración cuando termine con los cambios y luego genere los archivos make con la configuración actualizada.

Lea el tutorial mencionado anteriormente para aprender sobre el uso de variables, pero abreviado: set(<variable name> value) para cambiar o crear una variable. ${<variable name>} para usarlo.

  • CMAKE_SOURCE_DIR : el directorio raíz de la fuente. En el ejemplo anterior, esto siempre es igual a /simple
  • CMAKE_BINARY_DIR : el directorio raíz de la compilación. En el ejemplo anterior, esto es igual a simple/build/ , pero si ejecutó cmake simple/ desde una carpeta como foo/bar/etc/ , entonces todas las referencias a CMAKE_BINARY_DIR en ese árbol de compilación se convertirían en /foo/bar/etc .
  • CMAKE_CURRENT_SOURCE_DIR : el directorio en el que se encuentra el CMakeLists.txt actual. Esto significa que cambia a lo largo: imprimiendo esto desde simple/CMakeLists.txt yields /simple , e imprimiéndolo desde simple/src/CMakeLists.txt yields /simple/src
  • CMAKE_CURRENT_BINARY_DIR : CMAKE_CURRENT_BINARY_DIR la idea. Esta ruta dependería no solo de la carpeta en la que se encuentra la compilación, sino también de la CMakeLists.txt actual del script CMakeLists.txt .

¿Por qué son estos importantes? Los archivos de origen obviamente no estarán en el árbol de compilación. Si prueba algo como target_include_directories(Tutorial PUBLIC ../lib) en el ejemplo anterior, esa ruta será relativa al árbol de compilación, es decir, será como escribir ${CMAKE_BINARY_DIR}/lib , que se verá dentro de simple/build/lib/ . No hay archivos .h allí, a lo sumo encontrará libTestLib.a . En su lugar, quiere ${CMAKE_SOURCE_DIR}/lib .

  • CMAKE_CXX_FLAGS : Indicadores para pasar al compilador, en este caso el compilador de c ++. También vale la pena mencionar es CMAKE_CXX_FLAGS_DEBUG que se utilizará en su lugar si CMAKE_BUILD_TYPE se establece en DEPURAR. Hay más como estos, echa un vistazo a la wiki CMake .
  • CMAKE_RUNTIME_OUTPUT_DIRECTORY : CMAKE_RUNTIME_OUTPUT_DIRECTORY CMake dónde colocar todos los archivos ejecutables cuando se CMAKE_RUNTIME_OUTPUT_DIRECTORY . Esta es una configuración global. Puede, por ejemplo, configurarlo en bin/ y tener todo ordenado allí. EXECUTABLE_OUTPUT_PATH es similar pero obsoleto, en caso de que te tropieces con él.
  • CMAKE_LIBRARY_OUTPUT_DIRECTORY : Del mismo modo, configuración global para decirle a CMake dónde colocar todos los archivos de la biblioteca.

Propiedades de destino : puede establecer propiedades que afectan solo a un objetivo, ya sea un ejecutable o una biblioteca (o un archivo ... se entiende la idea). Aquí hay un buen ejemplo de cómo usarlo (con set_target_properties() .

¿Hay alguna manera fácil de agregar fuentes a un objetivo automáticamente? Use GLOB para listar todo en un directorio determinado bajo la misma variable. La sintaxis de ejemplo es FILE(GLOB <variable name> <directory>/*.cxx) .

¿Puedes especificar diferentes tipos de compilación? Sí, aunque no estoy seguro de cómo funciona esto o las limitaciones de esto. Probablemente requiera algo de if / thenning, pero CMake ofrece algo de soporte básico sin configurar nada, por CMAKE_CXX_FLAGS_DEBUG , por defecto para CMAKE_CXX_FLAGS_DEBUG . Puede establecer su tipo de compilación dentro de CMakeLists.txt través del set(CMAKE_BUILD_TYPE <type>) o llamando a CMake desde la consola con los indicadores apropiados, por ejemplo cmake -DCMAKE_BUILD_TYPE=Debug .

¿Algún buen ejemplo de proyectos que usan CMake? Wikipedia tiene una lista de proyectos de código abierto que usan CMake, si quieres ver eso. Los tutoriales en línea no han sido más que una decepción para mí hasta el momento en este sentido, sin embargo, esta pregunta de desbordamiento de pila tiene una configuración CMake bastante genial y fácil de entender. Vale la pena echarle un vistazo.

Usando variables de CMake en su código : Aquí hay un ejemplo rápido y sucio (adaptado de algún otro tutorial ):

simple/CMakeLists.txt :

project (Tutorial) #setting variables set (Tutorial_VERSION_MAJOR 1) set (Tutorial_VERSION_MINOR 1) #configure_file(<input> <output>) #Copies a file <input> to file <output> and substitutes variable values referenced in the file content. #So you can pass some CMake variables to the source code (in this case version numbers) configure_file ( "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" "${PROJECT_SOURCE_DIR}/src/TutorialConfig.h" )

simple/TutorialConfig.h.in :

//configured options and settings #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

Archivo resultante generado por CMake, simple/src/TutorialConfig.h :

//configured options and settings #define Tutorial_VERSION_MAJOR 1 #define Tutorial_VERSION_MINOR 1

Con el uso inteligente de estos puedes hacer cosas geniales como apagar una biblioteca y tal. Recomiendo echar un vistazo a ese tutorial, ya que hay cosas un poco más avanzadas que serán muy útiles en proyectos más grandes, tarde o temprano.

Para todo lo demás, el desbordamiento de la pila está lleno de preguntas específicas y respuestas concisas, lo cual es genial para todos, excepto para los no iniciados.