c - primer - makefile tutorial español
¿Cómo hago Makefile para recompilar solo los archivos modificados? (2)
He estado luchando un poco para hacer que compile solo los archivos que se han editado. Sin embargo no tuve mucho éxito y todos los archivos se vuelven a compilar. ¿Puede alguien explicarme por qué?
Mis archivos son:
main.c
a_functions.c
donde main.c incluye main.h y a_functions.c incluye ah
Aquí está mi makefile:
CC=gcc
CFLAGS=-Wall -I. -c
EXEC_FILE=program1
all: program
a_functions.o: a_functions.c
a_functions.c: a.h
main.o: main.c
main.c: main.h
objects: a_functions.c main.c
$(CC) a_functions.c main.c $(CFLAGS)
program: a_functions.o main.o
$(CC) a_functions.o main.o -o $(EXEC_FILE)
Cambiar el archivo make según las sugerencias parece tener el mismo problema:
all: program
a_functions.o: a_functions.c a.h
gcc a_functions.c -c
main.o: main.c main.h
gcc main.c -c
program: a_functions.o main.o
gcc a_functions.o main.o -o program1
El problema específico del que estás hablando: hacer program1
reconstrucción1 (volviendo a vincular los objetos) incluso cuando nada ha cambiado, está en esta regla:
program: a_functions.o main.o
gcc a_functions.o main.o -o program1
El objetivo de esta regla es el program
, y Make asume que es un archivo. Pero como no existe tal archivo, cada vez que ejecuta Make, Make piensa que este archivo necesita ser reconstruido y ejecuta la regla. Sugiero esto:
program1: a_functions.o main.o
gcc a_functions.o main.o -o program1
O mejor, esto:
program1: a_functions.o main.o
gcc $^ -o $@
O mejor aún esto:
$(EXEC_FILE): a_functions.o main.o
$(CC) $^ -o $@
(Y no te olvides de cambiar la regla de all
para que coincida).
Algunos otros puntos:
Como señaló @paxdiablo,
a_functions.o: a_functions.c a.h main.o: main.c main.h
No tiene sentido vincular estos objetos entre sí a menos que algo en uno (probablemente
main.o
) llame a algo en el otro (probablementea_functions.o
), así que esperaría ver una dependencia como esta:main.o: a.h
Entonces sospecho que tienes algunas declaraciones equivocadas.
Usted declara una regla de
objects
, pero nunca se refiere a ella. Así que nunca lo usas realmente; Make usa la regla predeterminada para%.o: %.c
. Sugiero esto:OBJECTS = a_functions.o main.o $(OBJECTS): %: %.c $(CC) $< $(CFLAGS) -o $@
(En este caso, puede cambiar
$(EXEC_FILE): a_functions.o main.o
a$(EXEC_FILE): $(OBJECTS)
.) O simplemente esto:%.o: %.c $(CC) $< $(CFLAGS) -o $@
No estoy seguro si esto está causando su problema específico, pero las dos líneas:
a_functions.c: a.h
main.c: main.h
definitivamente están equivocados, porque generalmente no hay un comando para volver a crear un archivo C basado en un encabezado que incluya.
Los archivos C no dependen de sus archivos de encabezado, los objetos creados por esos archivos C sí.
Por ejemplo, un main.c
de:
#include <hdr1.h>
#include <hdr2.h>
int main (void) { return 0; }
estaría en el makefile
como algo así como:
main.o: main.c hdr1.h hdr2.h
gcc -c -o main.o main.c
Cambio:
a_functions.o: a_functions.c
a_functions.c: a.h
main.o: main.c
main.c: main.h
a:
a_functions.o: a_functions.c a.h
main.o: main.c main.h
(asumiendo que a_functions.c
incluye ah
y main.c
incluye main.h
) e intente nuevamente.
Si la suposición anterior es incorrecta, tendrá que decirnos qué archivos C incluyen qué encabezados para que podamos decirle las reglas correctas.
Si su argumento es que el makefile
todavía está construyendo todo incluso después de esos cambios, necesita ver dos cosas.
El primero es el resultado de ls -l
en todos los archivos relevantes para que pueda ver qué fechas y horas tienen.
El segundo es el resultado real de make
. La salida de make -d
será especialmente útil, ya que muestra lo que los archivos y las fechas make
está utilizando para averiguar qué hacer.
En términos de investigación, make
parece funcionar bien según la siguiente transcripción:
=====
pax$ cat qq.h
#define QQ 1
=====
pax$ cat qq.c
#include "qq.h"
int main(void) { return 0; }
=====
pax$ cat qq.mk
qq: qq.o
gcc -o qq qq.o
qq.o: qq.c qq.h
gcc -c -o qq.o qq.c
=====
pax$ touch qq.c qq.h
=====
pax$ make -f qq.mk
gcc -c -o qq.o qq.c
gcc -o qq qq.o
=====
pax$ make -f qq.mk
make: `qq'' is up to date.