将调试文件添加到 makefile 构建?

Adding debug file to makefile build?

我有一个项目的 makefile,我想将其用于调试和发布版本。对于调试版本,我必须包含一个额外的 cpp 文件来保存所有单元测试。我在 makefile 中添加了一个调试选项,除了一行之外,一切似乎都正常。

我的 makefile 很长,但有问题的行在这个块中:

debug: CXXFLAGS+=-DDEBUG_TEST
debug: CXXFLAGS+=-DTEST_DIRECTORY='"$(subst /makefile,,$(abspath $(lastword $(MAKEFILE_LIST))))/tests"'
debug: SRCS+=src/test.cpp
debug: flex bison $(SRCS) $(EXE)

添加到 CXXFLAGS 的前两行已成功解析,最后一行进行了编译。但是,似乎无论我做什么,SRCS 都不会将测试文件附加到它上面。我什至打印了前后的内容,它没有显示任何变化。我做错了什么?

我在 windows 上使用 GNU Make 3.81。

编辑:我决定添加整个 makefile 来帮助回答。

CXX=g++
CXXFLAGS+=-std=c++11 -U__STRICT_ANSI__
FLEX=win_flex.exe
BISON=win_bison.exe
FLEXBISONSRCS=src/parser.cpp src/tokens.cpp src/math_parser.cpp src/math_tokens.cpp
SRCS=$(FLEXBISONSRCS) src/main.cpp src/assembler.cpp src/instruction.cpp src/util.cpp
OBJS=$(SRCS:.cpp=.o)
EXE=bin/yasa

debug: CXXFLAGS+=-DDEBUG_TEST
debug: CXXFLAGS+=-DTEST_DIRECTORY='"$(subst /makefile,,$(abspath $(lastword $(MAKEFILE_LIST))))/tests"'
debug: SRCS+=src/test.cpp

all debug: flex bison $(SRCS) $(EXE)
    @echo ' $$^: $^'
    @echo ' $$(SRCS): $(SRCS)'

$(EXE): $(OBJS)
    $(CXX) $(OBJS) -o $@

.cpp.o:
    $(CXX) $(CXXFLAGS) $< -c -o $@

flex:
    $(FLEX) -o src/tokens.cpp src/65c816.l
    $(FLEX) -o src/math_tokens.cpp src/math.l

bison:
    $(BISON) -d -o src/parser.cpp src/65c816.y
    $(BISON) -d -o src/math_parser.cpp src/math.y

rebuild: clean all

clean:
    rm src/*.o

target-specific variable assignments 的范围仅限于该目标的配方和该目标的任何先决条件的配方。

具体来说,范围 不会 扩展到先决条件列表本身。

举个例子this makefile:

SRCS := a.c b.c c.c

debug: SRCS+=d.c

all debug: $(SRCS)
        @echo ' $$^: $^'
        @echo ' $$(SRCS): $(SRCS)'

在 运行:

时生成此输出
$ make
 $^: a.c b.c c.c
 $(SRCS): a.c b.c c.c
$ make debug
 $^: a.c b.c c.c
 $(SRCS): a.c b.c c.c d.c

您可以在手册的 How make Reads a Makefile 部分阅读有关 make 如何读取 makefile 以及何时在 makefile 的不同部分扩展变量的所有信息。

如前所述,这意味着在 debug 目标的配方中使用 $(SRCS) 可以在这里工作(因为它具有正确的值),但使用自动变量则不行,但这并不是一个很好的选择(或必然甚至可能)解决方案。

另一种方法是将赋值设为全局,但仅在 debug 是正在构建的目标时才这样做。像这样:

ifneq (,$(filter debug,$(MAKECMDGOALS)))
    SRCS += src/test.cpp
endif

这不会让你 运行 make all debug 构建两者(例如),但否则会起作用。

对您的 makefile 的一些一般性评论。你会比那些 flexbison 目标做得更好,方法是教 make 如何 运行 这些输入和输出对上的命令,然后让它去做。

像这样:

src/tokens.cpp: src/65c816.l
    $(FLEX) -o $@ $^

src/math_tokens.cpp: src/math.l
    $(FLEX) -o $@ $^

src/parser.cpp: src/65c816.y
    $(BISON) -d -o $@ $^

src/math_parser.cpp: src/math.y
    $(BISON) -d -o $@ $^

并从 alldebug 先决条件中删除 flexbison。无需添加任何其他内容,make 已经知道它需要那些 .cpp 文件,现在它知道如何从源代码生成它们,所以如果需要的话它会生成。

另外 alldebug 不想依赖 $(SRCS),他们也不需要。 (他们已经通过 $(EXE)$(OBJS) 进行了传递。

None 虽然解决了问题。不幸的是,这个问题没有简单(好的)解决方案。 make 不以这种方式支持动态先决条件。

上面关于 SRCS 的有条件添加的解决方案是我认为你在这里拥有的最接近的解决方案(只要在 OBJ 赋值之前发生就应该可以正常工作)。

实际上,更好的解决方案可能是这样做:

DEBUG_OBJS=$(SRCS:.cpp=.o) src/test.o

DEBUG_EXE := bin/yasa

debug: $(DEBUG_EXE)

$(DEBUG_EXE): $(DEBUG_OBJS)
    $(CXX) $^ -o $@