Как определить правила в Makefile для компиляции только тех файлов * .cpp, которые были изменены (и их зависимостей), а не всех файлов * .cpp - PullRequest
9 голосов
/ 21 июня 2010

Допустим, у меня есть файлы:

Libs:

  • one.cpp, one.h
  • two.cpp, two.h
  • three.cpp, three.h

Программа:

  • program.cpp

Есть ли способ создать Makefile, который будеткомпилировать только тот * .cpp, который был изменен из последней компиляции?

В настоящее время у меня есть что-то подобное:

SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)

all: $(OBJS) program

.cpp.o:
    g++ -Wall -c $<

program:
    g++ -Wall $(OBJS) program.cpp -o program

clean:
    rm -f $(OBJS) program

Я отлично работаю, но когда я компилирую свою программу, а затем меняю два.cpp or two.h Сначала мне нужно запустить «make clean», потому что когда я запускаю второй «make», я получаю:

Nothing to be done for 'all'.

Я хотел бы изменить свой Makefile таким образом, чтобы он распознал мойизменяет и перекомпилирует этот файл и его зависимости (если one.cpp использует код из two.cpp, который был изменен, оба файла должны быть перекомпилированы).

Так что, если я изменяю two.cpp, make должен выполнить:

g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program

Но если one.cpp использует код из two.cpp, который был изменен, make shold do:

g++ -Wall -c one.cpp
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program

Ответы [ 3 ]

12 голосов
/ 21 июня 2010

Сначала мы создаем объектные файлы предварительные условия исполняемого файла.Как только это будет сделано, Make будет перестраивать program каждый раз, когда изменяется одно из SRCS, поэтому нам не нужно OBJS в качестве явной цели:

all: program

program: $(OBJS)
  g++ -Wall $(OBJS) program.cpp -o program

Затем мы создаем предварительные условия для файлов заголовкаобъекты, так что если мы изменим three.h, Make перестроит three.o:

$(OBJS): %.o : %.h

И, наконец, поскольку one.cpp использует код из two.cpp с помощью two.h (я надеюсь),мы создаем two.ha для one.o:

one.o: two.h

И чтобы сделать вещи чище и проще в обслуживании, мы используем автоматические переменные:

program: $(OBJS)
  g++ -Wall $^ program.cpp -o $@

Соберите все вместеи мы получаем:

SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)

all: program

$(OBJS): %.o : %.h

one.o: two.h

.cpp.o:
  g++ -Wall -c $<

program: $(OBJS)
  g++ -Wall $^ program.cpp -o $@

clean:
  rm -f $(OBJS) program

Есть еще несколько вещей, которые мы могли бы сделать (например, добавив program.o к OBJS), но на сегодня этого достаточно.

1 голос
/ 21 июня 2010

Добавьте файлы, от которых зависит выполнение команды, справа от целевого имени.

Пример:

default: hello.c
   gcc -o hello.bin hello.c

install: hello.bin
   cp hello.bin ../
0 голосов
/ 21 июня 2010

Все, что вам нужно сделать, это сказать make, что файл .o зависит от файла .cpp:

%.cpp.o: %.cpp
    g++ -Wall -c -o $@ $<
...