makefile将特定变量作为先决条件

时间:2012-05-30 21:33:39

标签: makefile gnu-make

相关:Target-specific Variables as Prerequisites in a Makefile

我正在尝试制作一个Makefile,它使用特定于目标的变量来指定目标文件和最终可执行文件的输出目录。我们的想法是维护两个独立的二进制版本,一个'发布'版本和一个带有额外调试信息的'debug'版本。

我的问题是'make'每次都做一个干净的构建,即使我没有改变一件事。我很确定这是因为'make'是在'debug'或'release'目标的先决条件中的变量声明之前评估目标'corewars'的先决条件。

Makefile如下所示。

CXX=g++
LD=g++
LDFLAGS=
CXXFLAGS=-Iinclude -Wall -Wextra
OBJECTS=main.o Machine.o Core.o ProcessQueue.o Instruction.o
OUTPUT_DIR:=Test/

.PHONY: default
.PHONY: all
.PHONY: release
default: release
all: release
release: OUTPUT_DIR:=Release/
release: corewars

.PHONY: debug
debug: CXXFLAGS+=-DDEBUG -g
debug: OUTPUT_DIR:=Debug/
debug: corewars

corewars: $(OUTPUT_DIR) $(addprefix $(OUTPUT_DIR),$(OBJECTS))
    $(LD) -o $(addprefix $(OUTPUT_DIR),corewars) $(addprefix $(OUTPUT_DIR),$(OBJECTS))

Release:
    mkdir -p $@
Debug:
    mkdir -p $@

%.o: %.cpp include/%.h
    $(CXX) -c $(CXXFLAGS) $< -o $(OUTPUT_DIR)$@


.PHONY: clean
clean:
    $(RM) -r Release
    $(RM) -r Debug

2 个答案:

答案 0 :(得分:12)

至少你的编译规则被破坏了。 A non-phony recipe must create a target, $@, not $(OUTPUT_DIR)$@.

还要考虑将目录依赖项转换为order-only先决条件。

最后,要在先决条件列表中获得$(OUTPUT_DIR)的正确值,您必须使用secondary expansion,否则,将使用全局定义OUTPUT_DIR:=Test/而不是特定于目标之一。

我不知道,如何在没有二次扩展和vpath魔法的情况下修复你的Makefile。我个人首先设置环境(找出OUTPUT_DIR的值等),然后用适当的值重新执行Make。

ifndef OUTPUT_DIR

.PHONY: default all release debug

default all: release

release: export OUTPUT_DIR := Release/
debug:   export OUTPUT_DIR := Debug/
debug:   export EXTRA_CXXFLAGS := -DDEBUG -g

release debug:
    @$(MAKE)

else

# ...
CXXFLAGS := -Iinclude -Wall -Wextra $(EXTRA_CXXFLAGS)

PROGRAM := $(OUTPUT_DIR)corewars
OBJECTS := $(addprefix $(OUTPUT_DIR), \
    main.o Machine.o Core.o ProcessQueue.o Instruction.o)

# Default target.
$(PROGRAM): $(OBJECTS) | $(OUTPUT_DIR)
    $(LD) -o $@ $<

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

$(OUTPUT_DIR):
    mkdir -p $@

endif # OUTPUT_DIR

答案 1 :(得分:0)

特定于目标的变量仅在目标配方及其递归先决条件的上下文中可用。也就是说,特定于目标的变量不能用作目标或先决条件

一种解决方法是生成文件there