¿Cuál es la diferencia entre usar un Makefile y CMake para compilar el código?

6 minutos de lectura

avatar de usuario
rico

Codifico en C/C++ y uso un Makefile (GNU) para compilar el código. Puedo hacer lo mismo con CMake y obtener un Makefile. Sin embargo, ¿cuál es la diferencia entre usar Makefile y CMake para compilar el código?

avatar de usuario
Angew ya no está orgulloso de SO

Make (o más bien un Makefile) es un sistema de compilación: impulsa el compilador y otras herramientas de compilación para compilar su código.

CMake es un generador de sistemas de compilación. Puede producir Makefiles, puede producir archivos de construcción Ninja, puede producir proyectos KDEvelop o Xcode, puede producir soluciones de Visual Studio. Desde el mismo punto de partida, el mismo archivo CMakeLists.txt. Entonces, si tiene un proyecto independiente de la plataforma, CMake es una forma de hacerlo también independiente del sistema de compilación.

Si tiene desarrolladores de Windows acostumbrados a Visual Studio y desarrolladores de Unix que juran por GNU Make, CMake es (uno de) el camino a seguir.

Siempre recomendaría usar CMake (u otro generador de sistemas de compilación, pero CMake es mi preferencia personal) si pretende que su proyecto sea multiplataforma o ampliamente utilizable. CMake en sí mismo también proporciona algunas características interesantes como la detección de dependencias, la gestión de la interfaz de la biblioteca o la integración con CTest, CDash y CPack.

El uso de un generador de sistemas de compilación hace que su proyecto esté más preparado para el futuro. Incluso si ahora es GNU-Make-only, ¿qué sucede si luego decide expandirse a otras plataformas (ya sea Windows o algo incrustado), o simplemente quiere usar un IDE?

  • ¡gracias! Solo para confirmar, que si solo programo en un entorno Linux, solo el archivo MAKE es adecuado, pero si quiero que el programa de Linux se ejecute en Mac, cmake es una mejor opción, ya que entiendo que no necesitamos hacer un nuevo archivo MAKE en la Mac, sino simplemente ejecutar el cmake. ¿Es ese el punto?

    – rico

    12 de septiembre de 2014 a las 10:17

  • @rish Sí, esa es la esencia. Sin embargo, tenga en cuenta que hay más formas de programar en Linux que Makefiles; consulte, por ejemplo, QtCreator, KDEvelop, Ninja. Para cada uno de estos, es “crear un proyecto y mantenerlo sincronizado con el Makefile” o “volver a ejecutar CMake”. Y, como menciona la respuesta, CMake también tiene otra funcionalidad, como el descubrimiento de dependencias (por ejemplo, find_package()) o soporte de pruebas/empaquetado.

    – Angew ya no está orgulloso de SO

    12/09/2014 a las 10:22

  • Leí que CMake no puede crear archivos MAKE no recursivos. ¿Sigue siendo cierto?

    – Máximo Egorushkin

    12/09/2014 a las 15:17

  • @Angew no recursivo es cuando make se invoca una vez con el árbol de dependencia del proyecto completo. Opuesto a recursivo cuando un archivo MAKE de nivel superior invoca archivos MAKE de subproyectos en cierto orden.

    – Máximo Egorushkin

    12/09/2014 a las 15:24

  • Esta es una debilidad importante de CMake: GNU make tiene sus defectos, pero si se toma el tiempo de aprenderlo, es extremadamente poderoso y versátil, y funciona en una enorme cantidad de plataformas. No tener un árbol de dependencias completo para analizar es una falla importante, solo busque en Google ‘marca recursiva considerada dañina’.

    – Erik Alapää

    23 de diciembre de 2015 a las 7:39

avatar de usuario
Víctor Sergio

La afirmación de que CMake es un “generador de compilación” es un error común.

No es técnicamente incorrecto; simplemente describe CÓMO funciona, pero no QUÉ hace.

En el contexto de la pregunta, hacen lo mismo: toman un montón de archivos C/C++ y los convierten en binarios.

Entonces, ¿cuál es la verdadera diferencia?

  • CMake es mucho más de alto nivel. Está diseñado para compilar C ++, para lo cual escribe mucho menos código de compilación, pero también se puede usar para compilaciones de propósito general. make también tiene algunas reglas integradas de C/C++, pero en el mejor de los casos son inútiles.

  • CMake hace una compilación de dos pasos: genera un script de compilación de bajo nivel en ninja o make o muchos otros generadores, y luego lo haces funcionar. Todas las piezas de script de shell que normalmente se apilan en Makefile sólo se ejecutan en la etapa de generación. Por lo tanto, CMake la construcción puede ser órdenes de magnitud más rápida.

  • la gramática de CMake es mucho más fácil admitir herramientas externas que make’s.

  • Una vez make construye un artefacto, olvida cómo fue construido. ¿De qué fuentes se construyó, qué indicadores del compilador? CMake lo rastrea, make te lo deja a ti. Si se eliminó una de las fuentes de la biblioteca desde la versión anterior de Makefile, make no lo reconstruirá.

  • Moderno CMake (a partir de la versión 3.algo) funciona en términos de dependencias entre “objetivos”. Un objetivo sigue siendo un único archivo de salida, pero puede tener dependencias transitivas (“públicas”/”interfaz” en términos de CMake). Estas dependencias transitivas se pueden exponer u ocultar de los paquetes dependientes. CMake administrará los directorios por usted. Con makeestá atascado en un nivel de archivo por archivo y administración de directorios a mano.

Podrías codificar algo en make usando archivos intermedios para cubrir los dos últimos espacios, pero estás solo. make contiene un Idioma completo de Turing (incluso dos, a veces tres contando Engaño); los dos primeros son horribles y el Guile practicamente nunca se usa.

Para ser honesto, esto es lo que CMake y make tienen en común: sus idiomas son bastante horribles. Esto es lo que me viene a la mente:

  • No tienen tipos definidos por el usuario;
  • CMake tiene tres tipos de datos: cadena, lista y un destino con propiedades. make tiene uno: cadena;
  • normalmente pasa argumentos a funciones configurando variables globales.
    • Esto se trata parcialmente en CMake moderno: puede establecer las propiedades de un objetivo: set_property(TARGET helloworld APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}");
  • la referencia a una variable indefinida se ignora silenciosamente de forma predeterminada;

  • Aquí hay buena información, pero un comentario es completamente incorrecto: cmake tiene un tipo LIST ya que con las funciones LIST adecuadas, lo cual es crucial para muchas tareas del sistema de compilación, hay una pequeña diferencia: cmake.org/cmake/help/git-master/command/list.html

    – resolviendoJ

    18 de febrero de 2020 a las 4:01

  • @VictorSergienko, no se preguntó en la pregunta del OP, pero estaba esperando el chiste … ¿Qué usas que sientes que es mejor que cualquiera?

    – Robert Lugg

    23 de diciembre de 2020 a las 21:42

  • Uso make por razones históricas, y lo odio. CMake no está exento de problemas también (intenta compilar de forma cruzada con él), pero para mis propios proyectos, CMake ganaría porque escribes menos código y es compatible con herramientas.

    – Víctor Sergio

    24 de diciembre de 2020 a las 1:57

  • y enterremos automake y autoconf para siempre por favor

    – pm100

    1 abr a las 0:20

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad