makefile配方特定的变量和$ @评估

时间:2019-01-22 20:59:54

标签: makefile target recipe

我正在尝试建立一个包含调试和发布目标的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:发布OBJ_DIR:obj /发布OBJS:obj / release / main.o obj / release / prime.o   将src / main.cc编译为obj / release / main.o ...   ...完成!   

     

TGT_DIR:发布OBJ_DIR:obj /发布OBJS:obj / release / main.o obj / release / prime.o   将src / prime.cc编译为obj / release / prime.o ...   ...完成了!

Wheras使调试线索导致以下意外情况:

  

TGT_DIR:调试OBJ_DIR:obj / debug OBJS:obj / debug / main.o obj / debug / prime.o   将src / main.cc编译为obj / release / main.o ...   ...完成!   

     

TGT_DIR:调试OBJ_DIR:obj / debug OBJS:obj / debug / main.o obj / debug / prime.o   将src / prime.cc编译为obj / release / prime.o ...   ...完成了!

我不知道为什么在第二种情况下$@无法评估为所需的调试版本。尽管变量似乎设置正确。执行配方时如何获得具有正确的目录名称? 预先感谢!

1 个答案:

答案 0 :(得分:0)

您有很多选择/方法来做到这一点。

  1. 一种快速的方法是检查MAKECMDGOALS的内容(这些词是make之后的字,例如release或debug)。注意:可以有一个以上的文件-但是,如果您的makefile很简单并且只有一个文件,则可以使用以下文件:

例如:

ifneq ($(MAKECMDGOALS),debug)
  TGT_DIR = $(DBG_DIR)
  OBJ_DIR = $(OBJ_ROOT_DIR)/$(TGT_DIR)
  OBJS = $(patsubst %.cc, $(OBJ_DIR)/%.o, $(SRC_LIST))
endif
  1. 另一种选择是使用第二个扩展,我只想放置一个链接:secondary expansion

  2. 另一种选择是在规则中设置一些变量,然后导出它们并再次(递归)调用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,并且变量已经设置。递归生成通常不被接受-但我发现很多次它是完成某些事情的最简单方法。

为简单起见,我可能会选择选项1。还有更多的方法可以执行此操作,但这取决于您的滚动方式-我只是在设置一些选项,使您的makefile结构或多或少都保持相同...