Как заставить Makefile перекомпилировать только измененные файлы?
Я немного пытаюсь заставить make компилировать только файлы, которые были отредактированы. Однако у меня не было большого успеха, и все файлы перекомпилировались. Может кто-нибудь объяснить мне, почему?
Мои файлы:
main.c
a_functions.c
где main.c включает main.h
и a_functions.c включает a.h
Вот мой make файл:
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)
Изменение make файла в соответствии с предложениями похоже на ту же проблему::
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
Ответы
Ответ 1
Конкретная проблема, о которой вы говорите - сделайте перестройки program1
(путем переназначения объектов), даже когда ничего не изменилось - в этом правиле:
program: a_functions.o main.o
gcc a_functions.o main.o -o program1
Цель этого правила - program
, и Make предполагает, что это файл. Но поскольку такого файла нет, каждый раз, когда вы запустите Make, Make думает, что этот файл нужно перестроить и выполняет правило. Я предлагаю следующее:
program1: a_functions.o main.o
gcc a_functions.o main.o -o program1
Или лучше, это:
program1: a_functions.o main.o
gcc $^ -o [email protected]
Или еще лучше:
$(EXEC_FILE): a_functions.o main.o
$(CC) $^ -o [email protected]
(И не забудьте изменить правило 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
. Я предлагаю следующее:
OBJECTS = a_functions.o main.o
$(OBJECTS): %: %.c
$(CC) $< $(CFLAGS) -o [email protected]
(В этом случае вы можете изменить $(EXEC_FILE): a_functions.o main.o
на $(EXEC_FILE): $(OBJECTS)
.) Или просто:
%.o: %.c
$(CC) $< $(CFLAGS) -o [email protected]
Ответ 2
Не уверен, что это вызывает вашу конкретную проблему, но две строки:
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.