Jak zrobić Makefile, aby przekompilować tylko zmienione pliki?

Trochę się starałem, aby make skompilował tylko pliki, które zostały edytowane. Jednak nie odniosłem większego sukcesu i wszystkie pliki zostały przekompilowane. Czy ktoś może mi wyjaśnić dlaczego?

Moje Pliki to:

main.c
a_functions.c

Gdzie główna.c zawiera main.h i a_functions.c obejmuje a. h

Oto mój 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)

Zmiana pliku makefile zgodnie z sugestiami wydaje się mieć ten sam problem::

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
Author: PeeHaa, 2011-10-19

2 answers

Specyficzny problem, o którym mówisz -- Make rebuilds program1 (poprzez ponowne połączenie obiektów) nawet jeśli nic się nie zmieniło -- jest w tej zasadzie:

program: a_functions.o main.o
    gcc a_functions.o main.o -o program1

Celem tej reguły jest program i Make zakłada, że jest to plik. Ale ponieważ nie ma takiego pliku, za każdym razem, gdy uruchamiasz Make, Make myśli, że ten plik musi zostać przebudowany i wykonuje regułę. Proponuję:

program1: a_functions.o main.o
    gcc a_functions.o main.o -o program1

Albo lepiej, to:

program1: a_functions.o main.o
    gcc $^ -o $@

Albo jeszcze lepiej to:

$(EXEC_FILE): a_functions.o main.o
    $(CC) $^ -o $@

(i nie zapomnij zmienić regułę all na dopasowaną.)

Kilka innych punktów:

  1. Jak zauważył @paxdiablo,

    a_functions.o: a_functions.c a.h
    main.o: main.c main.h
    
  2. Łączenie tych obiektów ze sobą nie ma sensu, chyba że coś w jednym (prawdopodobnie main.o) wywoła coś w drugim (prawdopodobnie a_functions.o), więc spodziewałbym się takiej zależności:

    main.o: a.h
    
    Więc podejrzewam, że masz jakieś zagubione deklaracje.
  3. Deklarujesz objects zasadę, ale nigdy Zobacz też Więc nigdy go nie używasz; Make używa domyślnej reguły dla %.o: %.c. Proponuję:

    OBJECTS = a_functions.o main.o
    $(OBJECTS): %: %.c
        $(CC) $< $(CFLAGS) -o $@
    

    (W takim przypadku możesz zmienić $(EXEC_FILE): a_functions.o main.o na $(EXEC_FILE): $(OBJECTS).) Lub po prostu to:

    %.o: %.c
        $(CC) $< $(CFLAGS) -o $@
    
 68
Author: Beta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-28 17:03:17

Nie wiem, czy to powoduje twój konkretny problem, ale dwie linie:

a_functions.c: a.h
main.c: main.h

Są zdecydowanie błędne, ponieważ generalnie nie ma polecenia, aby odtworzyć plik C na podstawie nagłówka, który zawiera.

Pliki C nie zależą od ich plików nagłówkowych, tak robią obiekty utworzone przez te pliki C.

Na przykład, a main.c z:

#include <hdr1.h>
#include <hdr2.h>
int main (void) { return 0; }

Byłoby w makefile jako coś like:

main.o: main.c hdr1.h hdr2.h
    gcc -c -o main.o main.c

Zmiana:

a_functions.o: a_functions.c
a_functions.c: a.h
main.o: main.c
main.c: main.h

Do:

a_functions.o: a_functions.c a.h
main.o: main.c main.h

(zakładając, że a_functions.c zawiera a.h i main.c zawiera main.h) i spróbuj ponownie.

Jeśli powyższe założenie jest błędne, będziesz musiał nam powiedzieć, jakie pliki C zawierają nagłówki, abyśmy mogli powiedzieć Ci poprawne reguły.


Jeśli twierdzisz, że makefile nadal wszystko buduje, nawet po tych zmianach, musisz spojrzeć na dwie rzeczy.

Pierwszy to wyjście z ls -l na wszystkich odpowiednie pliki, dzięki czemu można zobaczyć, jakie daty i godziny mają.

Drugi jest faktycznym wyjściem z make. Wyjście make -d będzie szczególnie pomocne, ponieważ pokazuje jakie pliki i daty make używają, aby dowiedzieć się, co zrobić.


Jeśli chodzi o dochodzenie, make wydaje się działać dobrze zgodnie z następującym zapisem:

=====
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.
 10
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-19 01:47:49