Подтвердить что ты не робот

Как заставить 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
4b9b3361

Ответ 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.