Как сделать Makefile для перекомпиляции только измененных файлов?
Я немного боролся, чтобы получить make для компиляции только файлы, которые были отредактированы. Однако у меня не было большого успеха, и все файлы перекомпилируются. Может кто-нибудь объяснить мне, почему?
Мои файлы:
main.c
a_functions.c
здесь main.c включает в себя main.h и a_functions.c включает в себя а.ч
вот мой 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)
изменение файла makefile в соответствии с предложениями кажется чтобы иметь ту же проблему::
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
2 ответов
конкретная проблема, о которой вы говорите -- Make rebuilds program1
(путем связывания объектов), даже если ничего не изменилось - в этом правиле:
program: a_functions.o main.o
gcc a_functions.o main.o -o program1
цель этого правила составляет program
, и Make предполагает, что это файл. Но поскольку такого файла нет, каждый раз, когда вы запускаете Make, Make думает, что этот файл нужно перестроить, и выполняет правило. Я предлагаю следующее:--18-->
program1: a_functions.o main.o
gcc a_functions.o main.o -o program1
или лучше, это:
program1: a_functions.o main.o
gcc $^ -o $@
или еще лучше это:
$(EXEC_FILE): a_functions.o main.o
$(CC) $^ -o $@
(и не забудьте поменять all
правила, чтобы соответствовать.)
еще несколько пунктов:
-
как отметил @paxdiablo,
a_functions.o: a_functions.c a.h main.o: main.c main.h
-
не имеет смысла связывать эти объекты вместе, если что-то в одном (возможно
main.o
) вызывает что-то в другом (вероятноa_functions.o
), поэтому я ожидал бы увидеть такую зависимость:main.o: a.h
поэтому я подозреваю, что вы есть некоторые неуместные объявления.
-
вы объявляете
objects
правило, но никогда не ссылайтесь на него. Таким образом, вы никогда не используете его; Make использует правило по умолчанию для%.o: %.c
. Я предлагаю следующее:--18-->OBJECTS = a_functions.o main.o $(OBJECTS): %: %.c $(CC) $< $(CFLAGS) -o $@
(в этом случае вы можете изменить
$(EXEC_FILE): a_functions.o main.o
to$(EXEC_FILE): $(OBJECTS)
.) Или просто так:%.o: %.c $(CC) $< $(CFLAGS) -o $@
не уверен, что это вызывает вашу конкретную проблему, но две строки:
a_functions.c: a.h
main.c: main.h
определенно неверны, потому что обычно нет команды для повторного создания файла C на основе заголовка, который он включает.
C файлы не зависят от их заголовочных файлов,объекты созданный этими файлами C.
например, a main.c
of:
#include <hdr1.h>
#include <hdr2.h>
int main (void) { return 0; }
будет makefile
как-то например:
main.o: main.c hdr1.h hdr2.h
gcc -c -o main.o main.c
изменения:
a_functions.o: a_functions.c
a_functions.c: a.h
main.o: main.c
main.c: main.h
в:
a_functions.o: a_functions.c a.h
main.o: main.c main.h
(предполагая, что a_functions.c
включает в себя a.h
и main.c
включает в себя main.h
) и попробуйте снова.
если это предположение выше неверно, вам придется сказать нам, какие файлы C включают в себя какие заголовки, чтобы мы могли сказать вам правильные правила.
если вы утверждаете, что makefile
все еще строит все даже после этих изменений, вам нужно посмотреть на два вещи.
первый-это выход из ls -l
на всех соответствующих файлов, так что вы можете увидеть, какие даты и время они имеют.
второй является фактическим выходом из make
. Выход make -d
будет особенно полезно, Так как это показывает какие файлы и даты make
используется, чтобы выяснить, что делать.
С точки зрения расследования,make
кажется, работает нормально в соответствии со следующей расшифровкой:
=====
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.