首页 > 解决方案 > 为调试和发布目标配置 makefile

问题描述

考虑类似于以下内容的 Makefile:

CC = gcc
CXX = g++
CXXFLAGS += -std=c++11

SRCDIR = .
OBJECTS = \
    file1.o \
    file2.o \
    file3.o
THREADS = 1


all: release

release: CXXFLAGS += -DNUM_THREADS=$(THREADS)
release: main

debug: CXXFLAGS += -g -DDEBUG -DVERBOSENESS=3 -DNUM_THREADS=$(THREADS)
debug: main

# Build main executable...
main: $(OBJECTS)
    $(CXX) $(CXXFLAGS) -o $@ $^

# Compile all object files...
file1.o: $(SRCDIR)/file1.cpp
    $(CXX) $(CXXFLAGS) -c $^
file2.o: $(SRCDIR)/file2.cpp
    $(CXX) $(CXXFLAGS) -c $^
file3.o: $(SRCDIR)/file3.cpp
    $(CXX) $(CXXFLAGS) -c $^

这仅适用于第一个make:换句话说,当我make使用与前一个目标不同的目标启动时,不会重新编译目标文件。也就是说,如果我在目标文件之间进行更改,我该如何重新编译目标debug文件release

标签: makefilegnu-make

解决方案


如果您想严格基于一个标签强制重新编译,请说 "Debug". “发布”,然后您可以通过编写并根据适当的时间戳文件来完成,如下所示:

TYPE = Debug

#
# ... conditional settings based on $(TYPE) ...
#

OBJS = prog.o

all: test

prog: $(OBJS)
    $(CC) -o $@ $(OBJS)

$(OBJS): $(TYPE)-mode-stamp

$(TYPE)-mode-stamp: last-mode-stamp
    touch $@
    touch -r $@ last-mode-stamp

last-mode-stamp:
    touch $@

clean:
    @rm *-mode-stamp $(OBJS) prog

假设您通过设置变量来选择构建类型$(TYPE),可能是通过命令行。所有目标文件都$(TYPE)-mode-stamp具有先决条件,因此如果该文件已过期,则将重新构建所有目标文件,以及将其中任何一个作为先决条件的任何文件。 $(TYPE)-mode-stamp本身具有last-mode-stamp作为先决条件,因此如果前者比后者旧,或者后者本身已过时,则更新前者。将两个文件的时间戳设置为当前时间的配方$(TYPE)-mode-stamp,这样

  1. $(TYPE)-mode-stamp不再过时last-mode-stamp, 和
  2. last-mode-stamp比可能存在的任何 OtherType-mode-stamp 更新。

如果最初不存在,则创建没有任何先决条件(但带有配方)的规则。last-mode-stamp

请注意,这与监视任何构建工具或标志是否更改完全不同且正交。


推荐阅读