我正在尝试制作一个Makefile,它使用一个特定目标变量来指定对象文件和最终可执行文件的输出目录。 我的想法是维护两个独立的二进制版本,一个是 "发布 "版本,一个是包含额外调试信息的 "调试 "版本。
我的问题是,"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
至少你的编译规则被打破了。一个非语音的配方 必须 创建一个目标。$@
,不 $(OUTPUT_DIR)$@
.
也可以考虑将目录依赖关系转换为 唯命是从 前提条件。
最后,为了得到适当的 $(OUTPUT_DIR)
内的先决条件列表,你必须使用 二次扩建否则,全局定义 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
特定于目标的变量只有在目标的配方及其递归先决条件的上下文中才能使用。也就是 特定目标变量不能作为目标或先决条件使用。.
一个变通的方法是使用makefile 那里.