Patrones y variables automáticas

Para flexibilizar el uso de Make, tenemos la posibilidad de usar patrones, para crear reglas que sirvan para varios archivos. En esos casos, podemos usar algunas variables automáticas.

Cuando trabajamos con Makefiles, una de las herramientas más potentes que podemos utilizar para simplificar y flexibilizar nuestras reglas son los patrones. Estos nos permiten definir reglas generales que se aplican a múltiples archivos sin tener que escribir una regla específica para cada uno. Un ejemplo claro de esto es el uso del operador porcentaje %, que actúa como un comodín para representar uno o más caracteres en los nombres de archivo.

Por ejemplo, si definimos una regla con %.o, estamos diciendo que esa regla se aplica a cualquier archivo que termine con .o, como main.o, salida.o o calculadora.o. De forma similar, con %.c podemos referirnos a cualquier archivo fuente en C. Esto nos permite establecer una regla que, a partir de cualquier archivo .c, genere su correspondiente archivo .o. Así, a partir de main.c se generará main.o, y lo mismo para otros archivos.

Esta flexibilidad es especialmente útil cuando tenemos archivos organizados en diferentes carpetas y queremos que se compilen de manera distinta según su ubicación. Por ejemplo, podríamos tener reglas para carpeta1/%.o que dependan de carpeta1/%.c, y otras para carpeta2/%.o que dependan de carpeta2/%.c, permitiéndonos personalizar la compilación según la carpeta.

Para definir cómo se compila cada archivo, podemos usar comandos dentro de la regla que invoquen al compilador con las opciones adecuadas. Pero surge la pregunta: ¿cómo referirnos al nombre del archivo que estamos compilando dentro de la regla patrón? Aquí es donde entran en juego las variables automáticas de Make, que son variables especiales definidas por el propio sistema para facilitarnos esta tarea.

Una de las variables automáticas más útiles es $<, que representa el primer prerequisito de la regla, es decir, el archivo fuente del que depende el objetivo. Por ejemplo, si nuestra regla es para generar main.o a partir de main.c, $< será main.c. Esto es especialmente práctico cuando hay múltiples dependencias, ya que $< siempre nos da el primero, que suele ser el archivo fuente principal.

Si necesitamos referirnos a todos los prerequisitos, podemos usar $?, que expande a la lista completa de dependencias que han cambiado y que deben ser consideradas para la compilación.

Otra variable importante es $@, que representa el nombre del objetivo de la regla, es decir, el archivo que queremos generar. Por ejemplo, en la regla para generar salida.o, $@ será salida.o.

Con estas variables, podemos escribir una regla patrón para compilar archivos .c en .o de forma automática y sencilla. Por ejemplo, podríamos definir algo así:

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

Aquí, gcc es el compilador, $(CFLAGS) las opciones de compilación, -c indica que queremos compilar sin enlazar, $< es el archivo fuente .c y $@ el archivo objeto .o que queremos generar.

Al usar esta regla, cuando ejecutemos make main.o, Make sabrá que debe compilar main.c para generar main.o usando el comando indicado. Esto nos evita tener que escribir reglas específicas para cada archivo, haciendo nuestro Makefile mucho más limpio y mantenible.

Finalmente, una vez que tenemos todos los archivos .o generados, podemos enlazarlos para crear el ejecutable final. Esto también se puede automatizar en el Makefile, usando las variables y patrones para que el proceso completo de compilación y enlace sea sencillo y eficiente.

En resumen, aprovechar los patrones con el operador % y las variables automáticas como $< y $@ nos permite crear reglas genéricas que se adaptan a múltiples archivos, facilitando la gestión de proyectos con muchos archivos fuente y mejorando la claridad y mantenimiento de nuestros Makefiles.

Lista de reproducción
  1. 1
    ¿Por qué usar Make?
    7 minutos
  2. 2
    Reglas, objetivos y dependencias
    7 minutos
  3. 3
    Mi primer Makefile
    8 minutos
  4. 4
    Expansión de variables
    8 minutos
  5. 5
    Reglas implícitas
    5 minutos
  6. 6
    Recompilando dependencias
    7 minutos
  7. 7
    Patrones y variables automáticas
    6 minutos
  8. 8
    Múltiples archivos y otros aspectos finales
    6 minutos