2012-06-04 10 views
86

Me preguntaba si había algún código de ejemplo para Makefile s (make) y CMakeLists.txt (cmake) que ambos hacen lo mismo (la única diferencia es que uno está escrito en make y el otro en cmake).Cmake vs make sample codes?

He intentado buscar 'cmake vs make', pero nunca he encontrado ninguna comparación de código. Sería realmente útil comprender las diferencias, incluso si solo fuera por un caso simple.

+15

+1 Esta es una buena pregunta; cuando comencé con 'cmake', yo también quería esto. Pero dudo que lo encuentres porque las capacidades no coinciden tan bien entre sí. Si intentas que 'cmake' actúe como' make', te volverás loco, en serio. Lo mejor es comenzar de cero. Las cosas que son triviales en 'make' están bastante involucradas en' cmake', y viceversa. –

+0

@ ErnestFriedman-Hill ¿tiene más detalles al respecto? Entonces 'make' y' cmake' son tan distintos que deberían verse más como herramientas complementarias en lugar de competir. –

+1

@Shurane - cmake no construye nada en sí mismo; crea Makefiles (y otros scripts de construcción similares), que luego ejecuta. Por lo tanto, cada vez que escriba archivos cmake, debe pensar si un comando debe aplicarse durante el tiempo de generación o durante el tiempo de compilación. Algunas acciones, por ejemplo, copiar un conjunto de archivos comodín en tiempo de compilación, son bastante complicadas, en comparación con el '' cp * .x $ (OUTDIR) '" que escribirías en un Makefile. Quizás la parte más molesta para mí es que los Makefiles generados son, por diseño, completamente no portables e inflexibles (continuación) –

Respuesta

5

Obtenga un software que use CMake como su sistema de construcción (hay muchos proyectos de código abierto para elegir como ejemplo). Obtenga el código fuente y configúrelo usando CMake. Lee los makefiles resultantes y disfruta.

Una cosa a tener en cuenta es que esas herramientas no se asignan uno a uno. La diferencia más obvia es que CMake busca dependencias entre diferentes archivos (por ejemplo, el encabezado C y los archivos fuente), mientras que deja eso a los autores del archivo MAKE.

92

El siguiente Makefile crea un ejecutable llamado prog de las fuentes prog1.c, prog2.c, prog3.c and main.c. prog está vinculado contra libmystatlib.a y libmydynlib.so que también están construidos desde la fuente. Además, prog utiliza la biblioteca libstuff.a en stuff/lib y su encabezado en stuff/include. El Makefile por defecto construye un objetivo autorización, pero ofrece también un objetivo de depuración:

#Makefile  
CC = gcc 
CPP = g++ 
RANLIB = ar rcs 
RELEASE = -c -O3 
DEBUG = -c -g -D_DEBUG 
INCDIR = -I./stuff/include 
LIBDIR = -L./stuff/lib -L. 
LIBS = -lstuff -lmystatlib -lmydynlib 
CFLAGS = $(RELEASE) 

PROGOBJS = prog1.o prog2.o prog3.o 

prog: main.o $(PROGOBJS) mystatlib mydynlib 
    $(CC) main.o $(PROGOBJS) $(LIBDIR) $(LIBS) -o prog 
debug: CFLAGS=$(DEBUG) 
debug: prog 

mystatlib: mystatlib.o 
    $(RANLIB) libmystatlib.a mystatlib.o 
mydynlib: mydynlib.o 
    $(CPP) -shared mydynlib.o -o libmydynlib.so 

%.o: %.c 
    $(CC) $(CFLAGS) $(INCDIR) $< -o [email protected] 
%.o: %.cpp 
    $(CPP) $(CFLAGS) $(INCDIR) -fPIC $< -o [email protected] 

Aquí es una CMakeLists.txt que hace (casi) exactamente lo mismo, con algunos comentarios para subrayar la similitudes con el Makefile:

#CMakeLists.txt  
cmake_minimum_required(VERSION 2.8)     # stuff not directly 
project(example)          # related to building 

include_directories(${CMAKE_SOURCE_DIR}/stuff/include) # -I flags for compiler 
link_directories(${CMAKE_SOURCE_DIR}/stuff/lib)  # -L flags for linker 

set(PROGSRC prog1.c prog2.c prog3.c)     # define variable 

add_executable(prog main.c ${PROGSRC})     # define executable target prog, specify sources 
target_link_libraries(prog mystatlib mydynlib stuff) # -l flags for linking prog target 

add_library(mystatlib STATIC mystatlib.c)    # define static library target mystatlib, specify sources 

add_library(mydynlib SHARED mydynlib.cpp)    # define shared library target mydynlib, specify sources 
#extra flags for linking mydynlib 
set_target_properties(mydynlib PROPERTIES POSITION_INDEPENDENT_CODE TRUE) 
#alternatively: 
#set_target_properties(mydynlib PROPERTIES COMPILE_FLAGS "-fPIC") 

En este sencillo ejemplo, las diferencias más importantes son:

  • CMake rec reconoce qué compiladores usar para qué tipo de fuente. Además, invoca la secuencia correcta de comandos para cada tipo de destino. Por lo tanto, allí no hay una especificación explícita de comandos como $ (CC) ..., $ (RANLIB) ... y así sucesivamente.

  • Todos los indicadores comunes de compilador/enlazador que se ocupan de la inclusión de archivos de encabezado, bibliotecas, etc. son reemplazados por comandos independientes de plataforma/sistema de compilación.

  • indicadores de depuración se incluyen ya sea estableciendo la variable de CMAKE_BUILD_TYPE de "depuración", o pasándolo a CMake cuando se invoca el programa: cmake -DCMAKE_BUILD_TYPE:STRING=Debug.

  • CMake también ofrece la inclusión independiente de la plataforma del distintivo '-fPIC' (a través de la propiedad POSITION_INDEPENDENT_CODE) y muchos otros. Aún así, se pueden implementar ajustes más oscuros a mano en CMake así como también en un Makefile (usando COMPILE_FLAGS y propiedades similares). Por supuesto, CMake realmente comienza a brillar cuando las bibliotecas de terceros (como OpenGL) se incluyen de manera portátil.

  • El proceso de compilación tiene un paso si utiliza un archivo Makefile, es decir, escribiendo make en la línea de comandos.Para CMake, hay dos pasos: primero, necesita configurar su entorno de compilación (ya sea escribiendo cmake <source_dir> en su directorio de compilación o ejecutando algún cliente de GUI). Esto crea un Makefile o algo equivalente, según el sistema de compilación que elija (por ejemplo, make en Unixes o VC++ o MinGW + Msys en Windows). El sistema de compilación se puede pasar a CMake como un parámetro; sin embargo, CMake realiza elecciones predeterminadas razonables según la configuración de su sistema. En segundo lugar, realiza la compilación real en el sistema de compilación seleccionado.

Las fuentes y las instrucciones de construcción están disponibles en https://github.com/rhoelzel/make_cmake.

+2

¿No es el Makefile demasiado complicado? Al usar 'CPPFLAGS' en lugar de' INCDIR', uno podría haber usado las reglas integradas y la invocación explícita del compilador hubiera sido redundante. De manera similar para el manejo de ar, las reglas incorporadas también pueden cubrir eso. Además, ¿por qué configurar 'CPP' y' CC' explícitamente? Ya están configurados en buenos valores por 'make', son variables predefinidas. 'make' también reconoce qué compilador usar para qué tipo de fuente, las reglas incorporadas son muchas. –

+2

Ah, y para 'RELEASE',' -DNDEBUG' falta ... –

+1

Y muchas de estas variables deberían asignarse con ': =' en vez de '='. –