请解释这个makefile中变量的奇怪生命周期

时间:2017-04-20 17:20:00

标签: gcc makefile

我的all规则中的echo打印出正确的内容,但是当我将OBJS的定义移动到我评论的行时,makefile不起作用。同样,makefile运行,但是当我移动OBJS时,我收到以下错误:

  

user @ machine $ make
  OBJS = other.o main.o
  g ++ -Wall other.o main.o -o main
  g ++:错误:other.o:没有这样的文件或目录
  g ++:错误:main.o:没有这样的文件或目录

#MAKEFILE

CPP_COMP=g++

CFLAGS = -Wall

CPP_SRC = $(wildcard *.cpp) 

#Define OBJS here and the makefile works. Define OBJS *HERE* it fails as shown below.
OBJS = $(CPP_SRC:.cpp=.o)

all: $(OBJS) 
        @echo "OBJS = $(OBJS)"
        $(CPP_COMP) $(CFLAGS) $(OBJS) -o main

#*HERE*
#Why can't I put CPP_SRC and OBJS here?
#The echo statement above prints out the appropriate value even if I put the variables here.

%.o: %.cpp
        $(CPP_COMP) $(CFLAGS) -c $< -o $@

clean:
        rm *.o main

1 个答案:

答案 0 :(得分:2)

使用=(而不是:=)设置的Makefile变量在设置时不会被评估和扩展,只有在使用它们时才会被评估和扩展。定义规则时会扩展规则中使用的变量(以确定目标和先决条件是什么),但在操作实际运行之前,操作中使用的变量不会扩展。

因此,在您的示例中,将OBJS = $(CPP_SRC:.cpp=.o)设置OBJS设置为该实际字符串(使用$和所有内容)。然后,当您拥有规则all: $(OBJS)时,它会展开$(OBJS),然后展开$(CPP_SRC),然后运行$(wildcard ...命令。另一方面,操作@echo "OBJS = $(OBJS)"再次只记录没有扩展的字符串。只有当动作实际运行时(在读取整个Makefile之后发生,并且它开始计算要运行的内容)才会$(OBJS)展开。

因此,向下移动OBJS的定义意味着它在读取规则时尚未定义(因此它扩展为空字符串),但是在操作运行时定义。