使用 BSD make,我希望对程序的调试和发布版本使用不同的编译器标志。要构建的程序的版本应通过
MODE
变量定义。我只想在必要时运行编译器,这意味着如果我构建调试版本然后构建发布版本,我想重新编译所有对象,即使它们在技术上根据 make 是最新的。
我的 makefile 的简化版本如下所示:
MODE ?= DEBUG # DEBUG or RELEASE
CFLAGS = -std=c99 -Werror -Wall -Wextra
.if $(MODE) == DEBUG
CFLAGS += -g -fsanitize=undefined,address
.endif
a.o: a.c a.h
cc -c $(CFLAGS) -o $(.TARGET) $(.ALLSRC:M*.c)
b.o: b.c a.h b.h
cc -c $(CFLAGS) -o $(.TARGET) $(.ALLSRC:M*.c)
c.o: c.c c.h
cc -c $(CFLAGS) -o $(.TARGET) $(.ALLSRC:M*.c)
program: a.o b.o c.o
cc $(CFLAGS) -o $(.TARGET) $(.ALLSRC)
这个例子第一次构建得很好,但是如果我将
MODE
更改为 RELEASE
,make 会告诉我没有什么可构建的,因为一切都已经是最新的了。
我发现实现我正在寻找的结果的唯一方法是在构建过程结束时将
MODE
变量打印到纯文本文件中,检查与当前 MODE
值是否相等,并强制如果 MODE
已更改,则在所有“可重建”目标上重建。
MODE ?= DEBUG # DEBUG or RELEASE
LAST_MODE != cat mode
CFLAGS = -std=c99 -Werror -Wall -Wextra
.if $(MODE) == DEBUG
CFLAGS += -g -fsanitize=undefined,address
.endif
.if $(MODE) != $(LAST_MODE)
rebuildable: .PHONY
.END:
printf "$(MODE)" > $(EXPORTS)/mode
.else
rebuildable: .USE
.endif
a.o: a.c a.h rebuildable
cc -c $(CFLAGS) -o $(.TARGET) $(.ALLSRC:M*.c)
b.o: b.c a.h b.h rebuildable
cc -c $(CFLAGS) -o $(.TARGET) $(.ALLSRC:M*.c)
c.o: c.c c.h rebuildable
cc -c $(CFLAGS) -o $(.TARGET) $(.ALLSRC:M*.c)
program: a.o b.o c.o rebuildable
cc $(CFLAGS) -o $(.TARGET) $(.ALLSRC:M*.o)
有没有更惯用、不那么老套的方法来做到这一点?
有没有更惯用、不那么老套的方法来做到这一点?
你必须有一些的方式来记住已经建立的模式目标。 不过,我建议,对这个问题的更自然的看法是,
Target-A-Debug
在逻辑上与Target-A-Release
是不同的目标,即使它们最终是从相同的来源构建的。 因此你应该对它们有不同的规则。
这可能会产生类似这样的结果(但如果我错误了任何
bmake
特定的语法,请原谅我):
MODE ?= DEBUG # DEBUG or RELEASE
CFLAGS_RELEASE = -std=c99 -Werror -Wall -Wextra
CFLAGS_DEBUG = $(CFLAGS_RELEASE) -g -fsanitize=undefined,address
OBJS_BASE = a.o b.o c.o
.if $(MODE) == DEBUG
MODE_SUFFIX = -debug
.else
MODE_SUFFIX = -release
.endif
all: program$(MODE_SUFFIX) .PHONY
cp $(.ALLSRC[1]) program
a-debug.o: a.c a.h
cc -c $(CFLAGS_DEBUG) -o $(.TARGET) $(.ALLSRC:M*.c)
b-debug.o: b.c a.h b.h
cc -c $(CFLAGS_DEBUG) -o $(.TARGET) $(.ALLSRC:M*.c)
c-debug.o: c.c c.h
cc -c $(CFLAGS_DEBUG) -o $(.TARGET) $(.ALLSRC:M*.c)
program-debug: $(OBJS_BASE:S/.o$/-debug.o/)
cc $(CFLAGS) -o $(.TARGET) $(.ALLSRC:M*.o)
a-release.o: a.c a.h
cc -c $(CFLAGS_RELEASE) -o $(.TARGET) $(.ALLSRC:M*.c)
b-release.o: b.c a.h b.h
cc -c $(CFLAGS_RELEASE) -o $(.TARGET) $(.ALLSRC:M*.c)
c-release.o: c.c c.h
cc -c $(CFLAGS_RELEASE) -o $(.TARGET) $(.ALLSRC:M*.c)
program-release: $(OBJS_BASE:S/.o$/-release.o/)
cc $(CFLAGS_RELEASE) -o $(.TARGET) $(.ALLSRC:M*.o)
我想可以应用一两个 bmake-ism 将这两个单独的规则列表合并为一个 - 这作为练习:-)