De las herramientas make y cmake

1 de mayo de 2016 • fjbalon

Make es una herramienta de gestión de dependencias usada en entornos de la familia UNIX. Es una buena práctica para compilar de forma automatizada códigos compuestos y complejos, por ejemplo en códigos compuestos de códigos C en distintos ficheros con distintos ficheros de cabecera .h.

Para preparar el funcionamiento de make es necesario crear un fichero, en el cual se especifica y se configura todo lo necesario para el proceso. Este fichero es denominado makefile. Podemos decir que son las instrucciones que make debe realizar.

Como añadido, make entiende los formatos y extensiones, dando una respuesta apropiada a cada tipo de archivo.

El formato genérico para un makefile es el siguiente:

VARIABLES
...

OBJETIVO:  DEPENDENCIAS 
    COMANDO
    ...

Un makefile simple para realizar con make la compilación de un programa C sería similar al siguiente:

hola:  hola.c 
    gcc -o hola hola.c -I.\end{lstlisting}

Podemos mejorarlo aún más para que sólo compile los ficheros que han cambiado desde el 
último make, para ello sería similar al siguiente:

\begin{lstlisting}[language=make]
# Vease el cambio de los ficheros .c a .o.
# Internamente make sabe que los .o son .c 
# y asi los busca y compila; ignorando los 
# encabezados.
CC=gcc
CFLAGS=-I.

hola: hola.o
    $(CC) -o hola hola.o

En este caso si hiciéramos cambios en alguna de las cabeceras .h make no recompilaría los códigos C .c. Si quisiéramos, como generalmente debería ser, que esto ocurriese:

CC=gcc
CFLAGS=-I.
DEPS = hola.h

%.o: %.c $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS)

hola: hola.o 
    $(CC) -o hola hola.o

Podemos mejorar el makefile añadiéndole más acciones, como una acción \textit{clean} para limpiar la compilación.

CC=gcc
CFLAGS=-I.
DEPS = hola.h

%.o: %.c $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS)

hola: hola.o 
    $(CC) -o hola hola.o

clean: 
    rm -f hola hola.o

E incluso podemos hacerlo más genérico y escalable declarando los nombres de los ficheros en forma de variable:

CC=gcc
CFLAGS=-I.
DEPS = hola.h
OBJ = hola.o 

%.o: %.c $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS)

hola: $(OBJ)
    $(CC) -o $@ $^ $(CFLAGS)

# Podemos usar .PHONY para indicarle a 
# make que el target clean en este caso 
# es ficticio y no debe crear fichero; 
# ya que si existiera un fichero llamado 
# clean en el directorio no trabajaria.
.PHONY: clean
clean: 
    rm -f $(ODIR)

Por otro lado, el procedimiento CMake (véase cmake.org) o Cross Platform Make es una utilidad multiplataforma de automatización de código, que permite construir, probar y empaquetar el software. Es, en otras palabras, una suite de herramientas independientes de más alto nivel que make, y que facilita la compilación de programas C. Por ejemplo, para un fichero CMake CMakeList:

# Version minima requerida
cmake_minimum_required (VERSION 2.8)
# Nombre del proyecto
project (Hola)
# Ficheros a agregar
add_executable(hola hola.c)

Para ejecutar CMake simplemente llamamos a su comando propio seguido del fichero CMake: cmake CMakeList. La salida de este comando será un makefile.