如何在Makefile中定义规则,只编译被修改的*.cpp文件(及其依赖项),而不是所有*.cpp文件

use*_*872 9 makefile gnu-make

让我们说我有文件:

库:

  • 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
Run Code Online (Sandbox Code Playgroud)

我工作正常,但是当我编译我的程序然后更改two.cpp或two.h时我需要首先运行"make clean",因为当我第二次运行"make"时,我得到:

Nothing to be done for 'all'.
Run Code Online (Sandbox Code Playgroud)

我想以这种方式更改我的Makefile,它会识别我的更改并重新编译该文件及其依赖项(如果one.cpp使用来自two.cpp的代码,这些代码已被修改,两个文件都应该重新编译).

所以如果我修改two.cpp,make应该这样做:

g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
Run Code Online (Sandbox Code Playgroud)

但是如果one.cpp使用了被修改的two.cpp中的代码,那么请执行以下操作:

g++ -Wall -c one.cpp
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
Run Code Online (Sandbox Code Playgroud)

Bet*_*eta 12

首先,我们使目标文件成为可执行文件的先决条件.完成此操作后,program只要其中一个SRCS发生更改,Make就会重建,因此我们不需要将其OBJS作为显式目标:

all: program

program: $(OBJS)
  g++ -Wall $(OBJS) program.cpp -o program
Run Code Online (Sandbox Code Playgroud)

然后我们将头文件作为对象的先决条件,这样如果我们改变three.h,Make将重建三个.o:

$(OBJS): %.o : %.h
Run Code Online (Sandbox Code Playgroud)

最后因为one.cpp通过two.h使用来自two.cpp的代码(我希望),所以我们制作了one.ha的两个先决条件:

one.o: two.h
Run Code Online (Sandbox Code Playgroud)

为了使事情更清洁,更容易维护,我们使用自动变量:

program: $(OBJS)
  g++ -Wall $^ program.cpp -o $@
Run Code Online (Sandbox Code Playgroud)

把它们放在一起我们得到:

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
Run Code Online (Sandbox Code Playgroud)

还有一些我们可以做的事情(比如添加program.o OBJS),但这对今天来说已经足够了.