为调试和发布目标配置makefile

时间:2019-05-29 15:45:49

标签: makefile gnu-make

考虑与以下内容类似的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时,目标文件与上一个目标文件不同,因此不会重新编译目标文件。 就是说,如果我在debugrelease目标之间切换,该如何使目标文件重新编译?

1 个答案:

答案 0 :(得分:1)

如果您要严格基于一个标签强制重新编译,请说“ Debug” vs 。 “发布”,然后您可以通过编写并取决于适当的时间戳文件来做到这一点,例如:

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

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