在同一makefile中配置不同版本

在同一makefile中配置不同版本,makefile,Makefile,我想使用同一个make文件生成几个构建。我所说的几个版本是指windows发行版,windows调试,linux发行版,linux调试,等等。我的想法是根据我正在运行的构建设置变量,如下所示: windows-release: CC:=... CFLAGS:=... OUTDIR:=windows/release OBJDIR:=$(OUTDIR)/obj EXECUTABLE:=$(OUTDIR)/exe # Would call $(EXECU

我想使用同一个make文件生成几个构建。我所说的几个版本是指
windows发行版
windows调试
linux发行版
linux调试
,等等。我的想法是根据我正在运行的构建设置变量,如下所示:

windows-release:
    CC:=...
    CFLAGS:=...
    OUTDIR:=windows/release
    OBJDIR:=$(OUTDIR)/obj
    EXECUTABLE:=$(OUTDIR)/exe
    # Would call $(EXECUTABLE) here, but it's not procedural
windows-release: CC:=...
windows-release: CFLAGS:=...
windows-release: OUTDIR:=windows/release
windows-release: OBJDIR:=$(OUTDIR)/obj
windows-release: EXECUTABLE:=$(OUTDIR)/exe

windows-debug: CC:=...
windows-debug: CFLAGS:=...
windows-debug: OUTDIR:=windows/debug
windows-debug: OBJDIR:=$(OUTDIR)/obj
windows-debug: EXECUTABLE:=$(OUTDIR)/exe

linux-release: CC:=...
linux-release: CFLAGS:=...
linux-release: OUTDIR:=linux/release
linux-release: OBJDIR:=$(OUTDIR)/obj
linux-release: EXECUTABLE:=$(OUTDIR)/bin

linux-debug: CC:=...
linux-debug: CFLAGS:=...
linux-debug: OUTDIR:=linux/debug
linux-debug: OBJDIR:=$(OUTDIR)/obj
linux-debug: EXECUTABLE:=$(OUTDIR)/bin

.SECONDEXPANSION:
windows-release windows-debug linux-release linux-debug: $$(EXECUTABLE)
然后有规则来进行实际构建:

# This will generate a static library
$(EXECUTABLE): $(OBJECTS)
    $(AR) $(ARFLAGS) $(ARLIB) $(OBJECTS)

$(OBJDIR)/%.o: src/%.cpp
    $(CC) $(CFLAGS) $< -o $@
#这将生成一个静态库
$(可执行文件):$(对象)
$(AR)$(ARFLAGS)$(ARLIB)$(对象)
$(OBJDIR)/%.o:src/%.cpp
$(CC)$(CFLAGS)$<-o$@
对于这个不完整的示例,我很抱歉,但是我还没有真正的makefile,我现在正在编写它


我可以使用makefile来完成这项工作吗?我更适合用脚本来代替吗?

你完全可以这样做。您需要的三件事是(因此make不认为windows release等是真实的文件),(因此您可以根据运行的目标设置不同的变量),并且因为前提条件的计算发生在特定于目标的上下文之外,因此特定于目标的变量不起作用)

这两个组合会让你得到这样的结果:

windows-release:
    CC:=...
    CFLAGS:=...
    OUTDIR:=windows/release
    OBJDIR:=$(OUTDIR)/obj
    EXECUTABLE:=$(OUTDIR)/exe
    # Would call $(EXECUTABLE) here, but it's not procedural
windows-release: CC:=...
windows-release: CFLAGS:=...
windows-release: OUTDIR:=windows/release
windows-release: OBJDIR:=$(OUTDIR)/obj
windows-release: EXECUTABLE:=$(OUTDIR)/exe

windows-debug: CC:=...
windows-debug: CFLAGS:=...
windows-debug: OUTDIR:=windows/debug
windows-debug: OBJDIR:=$(OUTDIR)/obj
windows-debug: EXECUTABLE:=$(OUTDIR)/exe

linux-release: CC:=...
linux-release: CFLAGS:=...
linux-release: OUTDIR:=linux/release
linux-release: OBJDIR:=$(OUTDIR)/obj
linux-release: EXECUTABLE:=$(OUTDIR)/bin

linux-debug: CC:=...
linux-debug: CFLAGS:=...
linux-debug: OUTDIR:=linux/debug
linux-debug: OBJDIR:=$(OUTDIR)/obj
linux-debug: EXECUTABLE:=$(OUTDIR)/bin

.SECONDEXPANSION:
windows-release windows-debug linux-release linux-debug: $$(EXECUTABLE)
也就是说,你也可以用普通的全局变量和条件来代替:

ifeq (windows-release,$(filter windows-release,$(MAKECMDGOALS)))
    CC:=...
    CFLAGS:=...
    OUTDIR:=windows/release
    OBJDIR:=$(OUTDIR)/obj
    EXECUTABLE:=$(OUTDIR)/exe
else ifeq (windows-debug,$(filter windows-debug,$(MAKECMDGOALS)))
    CC:=...
    CFLAGS:=...
    OUTDIR:=windows/debug
    OBJDIR:=$(OUTDIR)/obj
    EXECUTABLE:=$(OUTDIR)/exe
else ifeq (linux-release,$(filter linux-release,$(MAKECMDGOALS)))
    CC:=...
    CFLAGS:=...
    OUTDIR:=linux/release
    OBJDIR:=$(OUTDIR)/obj
    EXECUTABLE:=$(OUTDIR)/bin
else ifeq (linux-debug,$(filter linux-debug,$(MAKECMDGOALS)))
    CC:=...
    CFLAGS:=...
    OUTDIR:=linux/debug
    OBJDIR:=$(OUTDIR)/obj
    EXECUTABLE:=$(OUTDIR)/bin
endif

windows-release windows-debug linux-release linux-debug: $(EXECUTABLE)

请注意,二次扩展是一种全局修改。所有列出的目标都已应用。这可能不重要(事实上,可能是你想要的),但需要注意。绝对!谢谢你的提醒。。不过有两个问题。根据文档:
gnumake还能够为makefile中定义的部分或所有目标启用先决条件(仅)的第二次扩展。
我觉得它毕竟不是全局的,这准确吗?它只发生一次吗?我的意思是,你的例子有四个变化,但是文档中谈到了第二次扩展。下一句解释了这句话,我已经指出:
为了第二次扩展的发生,特殊目标。第二次扩展必须在使用此功能的第一个先决条件列表之前定义。
下一段第一句的部分内容进一步说明了这一点
第二次扩展特殊目标后定义的目标的所有先决条件。
。您可以这样做,将它们全部扩展默认情况下,当且仅当它们不共享任何对象文件或可执行文件时生成。使用特定于目标的变量构建的任何内容都不能在这些目标之间共享。因为make只会构建任何目标一次。因此,任何共享的目标都将由第一个需要它们的对象构建,而不会在下一个目标(使用不同标志)需要时重新构建。