有没有办法在调试模式下将 makefile 配置为 link 个额外对象?

Is there a way to configure makefile to link extra objects on debug mode?

我正在尝试编写一个支持发布模式和调试模式的 makefile,而在调试模式下,我想 link 一个额外的对象 debug.o 来覆盖调试功能。

例如:

CFLAGS = -Wall -I$(INCPATH)

INCPATH = include
TARGET = foo
OBJ = foo.o bar.o

# release mode
all: build run clear

# debug mode
debug: CFLAGS += -g -DDEBUG
debug: OBJ += debug.o
debug: build gdb-run clear

# link objects
build: $(OBJ)
    gcc $(CFLAGS) -o $(TARGET) $(OBJ)

# compile source code
%.o: %.c $(INCPATH)/*.h
    gcc $(CFLAGS) -c $@ $<

# default run mode
run:
    ./$(TARGET)

# debug run mode
gdb-run:
    gdb --args $(TARGET)

clear:
    rm -f $(OBJ) $(TARGET)

我预计它会在我调用 make debug 时扩展 $(OBJ)foo.o bar.o debug.o,但它只会扩展到 foo.o bar.o,因为目标在解析时会立即扩展。

我试过使用 .SECONDEXPANSION:,但无法解决。

而且我也尝试过 $(eval OBJ += debug.o),但这导致 $(OBJ) 扩展到 foo.o bar.o debug.o,即使 运行 make all.

这可能吗,还是我应该解决这个问题?

编辑:修正了一个拼写错误,感谢@matt

为此,我使用 GNU make "conditional" mechanism 和一个名为 MODE 的 make 变量。在你的情况下,

MODE = RELEASE
OBJ = foo.o bar.o
ifeq ($(MODE),DEBUG)
   OBJ += debug.o
endif
[...]

然后使用任一方法构建

make    # a MODE=RELEASE build by default

make MODE=DEBUG

I expected it expand $(OBJ) to foo.o bar.o debug.o

它在配方中执行此操作,但不在先决条件列表中。

6.11 Target-specific Variable Values

As with automatic variables, these values are only available within the context of a target’s recipe (and in other target-specific assignments).

所以你必须坚持使用条件来实现你的目标。

顺便说一句。 CFLAGS = -Wall -I(INCPATH) 是一个错字。 %.o: %.c $(INCPATH)/*.h 显然是错误的——在真正需要的时候使用 $(wildcard ...) 。还要将所有出现的 build 更改为 $(TARGET),因为它确实是 foo 您正在构建的内容。然后修改您的 makefile - 在每个 运行.

之后清理所有内容可能不是一个好主意