makefile 配方特定变量和 $@ 评估
makefile recipe specific variables and $@ evaluation
我正在尝试设置一个包含调试和发布目标的生成文件。
有一些特定于目标的变量,主要是文件夹名称,在不同情况下设置正确,但不适用于 $@
自动变量。以下代码:
SRC_DIR = src
OBJ_ROOT_DIR = obj
REL_DIR = release
DBG_DIR = debug
TGT_DIR = $(REL_DIR)
SRC_LIST = main.cc prime.cc
SRC_SUFF = cc
SRCS = $(patsubst %.cc, $(SRC_DIR)/%.$(SRC_SUFF), $(SRC_LIST))
OBJ_DIR = $(OBJ_ROOT_DIR)/$(TGT_DIR)
OBJS = $(patsubst %.cc, $(OBJ_DIR)/%.o, $(SRC_LIST))
all: $(OBJS)
release: all
debug: TGT_DIR = $(DBG_DIR)
debug: OBJ_DIR = $(OBJ_ROOT_DIR)/$(TGT_DIR)
debug: OBJS = $(patsubst %.cc, $(OBJ_DIR)/%.o, $(SRC_LIST))
debug: $(OBJS)
$(OBJS):$(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(SRC_SUFF)
@echo "TGT_DIR: $(TGT_DIR) OBJ_DIR: $(OBJ_DIR) OBJS: $(OBJS)"
@echo "Compiling $< to $@ ..."
@echo "... done !"
@echo "."
运行 make release 产生以下预期输出:
TGT_DIR: release OBJ_DIR: obj/release OBJS: obj/release/main.o obj/release/prime.o
Compiling src/main.cc to obj/release/main.o ...
... done !
.
TGT_DIR: release OBJ_DIR: obj/release OBJS: obj/release/main.o obj/release/prime.o
Compiling src/prime.cc to obj/release/prime.o ...
... done !
Wheras 使 调试导致 出现以下意外情况:
TGT_DIR: debug OBJ_DIR: obj/debug OBJS: obj/debug/main.o obj/debug/prime.o
Compiling src/main.cc to obj/release/main.o ...
... done !
.
TGT_DIR: debug OBJ_DIR: obj/debug OBJS: obj/debug/main.o obj/debug/prime.o
Compiling src/prime.cc to obj/release/prime.o ...
... done !
我想不通,为什么 $@
在第二种情况下没有计算出所需的调试版本。虽然变量似乎设置正确。执行配方时如何获得正确的目录名称?
提前致谢!
你有很多选择/方法来做到这一点。
- 一种快速的方法是检查
MAKECMDGOALS
的内容(这些是 make
之后的词,例如发布或调试)。注意:可能不止一个 - 但如果您的 makefile 很简单并且只有一个,则以下将起作用:
例如:
ifneq ($(MAKECMDGOALS),debug)
TGT_DIR = $(DBG_DIR)
OBJ_DIR = $(OBJ_ROOT_DIR)/$(TGT_DIR)
OBJS = $(patsubst %.cc, $(OBJ_DIR)/%.o, $(SRC_LIST))
endif
另一种选择是使用二次扩展,我只是想放一个link:secondary expansion
另一个选择是在你的规则中设置一些变量,然后导出它们并再次调用 make(递归),也许是这样的:
例如(不完整):
# Note you can just export the ones you want but... for ease of the example:
.EXPORT_ALL_VARIABLES
debug: TGT_DIR = $(DBG_DIR)
debug: OBJ_DIR = $(OBJ_ROOT_DIR)/$(TGT_DIR)
debug: OBJS = $(patsubst %.cc, $(OBJ_DIR)/%.o, $(SRC_LIST))
debug:
$(MAKE) do_build
do_build: $(OBJS)
...etc...
在你第一次调用它的地方,在调试规则中设置一些变量。在第二个中,它直接调用 do_build 并且已经设置了变量。递归 make 通常不受欢迎 - 但我发现很多时候它是完成某些事情的最简单方法。
我可能会错误地选择选项 1。因为它很简单。有更多的方法可以做到这一点,但这在某种程度上取决于你想如何滚动——我只是设置了一些选项来保持你的 makefile 结构或多或少相同......
我正在尝试设置一个包含调试和发布目标的生成文件。
有一些特定于目标的变量,主要是文件夹名称,在不同情况下设置正确,但不适用于 $@
自动变量。以下代码:
SRC_DIR = src
OBJ_ROOT_DIR = obj
REL_DIR = release
DBG_DIR = debug
TGT_DIR = $(REL_DIR)
SRC_LIST = main.cc prime.cc
SRC_SUFF = cc
SRCS = $(patsubst %.cc, $(SRC_DIR)/%.$(SRC_SUFF), $(SRC_LIST))
OBJ_DIR = $(OBJ_ROOT_DIR)/$(TGT_DIR)
OBJS = $(patsubst %.cc, $(OBJ_DIR)/%.o, $(SRC_LIST))
all: $(OBJS)
release: all
debug: TGT_DIR = $(DBG_DIR)
debug: OBJ_DIR = $(OBJ_ROOT_DIR)/$(TGT_DIR)
debug: OBJS = $(patsubst %.cc, $(OBJ_DIR)/%.o, $(SRC_LIST))
debug: $(OBJS)
$(OBJS):$(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(SRC_SUFF)
@echo "TGT_DIR: $(TGT_DIR) OBJ_DIR: $(OBJ_DIR) OBJS: $(OBJS)"
@echo "Compiling $< to $@ ..."
@echo "... done !"
@echo "."
运行 make release 产生以下预期输出:
TGT_DIR: release OBJ_DIR: obj/release OBJS: obj/release/main.o obj/release/prime.o Compiling src/main.cc to obj/release/main.o ... ... done ! .
TGT_DIR: release OBJ_DIR: obj/release OBJS: obj/release/main.o obj/release/prime.o Compiling src/prime.cc to obj/release/prime.o ... ... done !
Wheras 使 调试导致 出现以下意外情况:
TGT_DIR: debug OBJ_DIR: obj/debug OBJS: obj/debug/main.o obj/debug/prime.o Compiling src/main.cc to obj/release/main.o ... ... done ! .
TGT_DIR: debug OBJ_DIR: obj/debug OBJS: obj/debug/main.o obj/debug/prime.o Compiling src/prime.cc to obj/release/prime.o ... ... done !
我想不通,为什么 $@
在第二种情况下没有计算出所需的调试版本。虽然变量似乎设置正确。执行配方时如何获得正确的目录名称?
提前致谢!
你有很多选择/方法来做到这一点。
- 一种快速的方法是检查
MAKECMDGOALS
的内容(这些是make
之后的词,例如发布或调试)。注意:可能不止一个 - 但如果您的 makefile 很简单并且只有一个,则以下将起作用:
例如:
ifneq ($(MAKECMDGOALS),debug)
TGT_DIR = $(DBG_DIR)
OBJ_DIR = $(OBJ_ROOT_DIR)/$(TGT_DIR)
OBJS = $(patsubst %.cc, $(OBJ_DIR)/%.o, $(SRC_LIST))
endif
另一种选择是使用二次扩展,我只是想放一个link:secondary expansion
另一个选择是在你的规则中设置一些变量,然后导出它们并再次调用 make(递归),也许是这样的:
例如(不完整):
# Note you can just export the ones you want but... for ease of the example:
.EXPORT_ALL_VARIABLES
debug: TGT_DIR = $(DBG_DIR)
debug: OBJ_DIR = $(OBJ_ROOT_DIR)/$(TGT_DIR)
debug: OBJS = $(patsubst %.cc, $(OBJ_DIR)/%.o, $(SRC_LIST))
debug:
$(MAKE) do_build
do_build: $(OBJS)
...etc...
在你第一次调用它的地方,在调试规则中设置一些变量。在第二个中,它直接调用 do_build 并且已经设置了变量。递归 make 通常不受欢迎 - 但我发现很多时候它是完成某些事情的最简单方法。
我可能会错误地选择选项 1。因为它很简单。有更多的方法可以做到这一点,但这在某种程度上取决于你想如何滚动——我只是设置了一些选项来保持你的 makefile 结构或多或少相同......