在 make 3.81 中尝试使用重新分配的变量作为依赖项时观察到的奇怪行为

Bizarre behavior observed in make 3.81 when attempting to use a reassigned variable as a dependancy

本文关键字:依赖 变量 观察 分配 make 新分配      更新时间:2023-10-16

我在C++makefile上遇到了一个奇怪的问题。 我今天下午重写了它,因为我使用的旧版本让我想自杀,而且我遇到了一个关于变量重新分配和动态依赖的奇怪问题。

就此问题而言,假定以下值:

OBJMOD_MODULENAME = obj/lib/foo.o obj/lib/bar.o obj/lib/quux.o
LIBDIR         = lib/
CXX            = g++
CXXLIBLINK     = -shared
LIB            = -lm -lpt

我的目标格式如下:

modulename: OBJ_CURRENTMOD = $(OBJMOD_MODULENAME)
modulename: $(OBJMOD_MODULENAME) lib/metrics.so

稍后,以下另一种格式:

$(LIBDIR)%.so: $(OBJ_CURRENTMOD)
    $(CXX) $(CXXLIBLINK) -o $@ $(OBJ_CURRENTMOD) $(LIB)
代码块中的

行始终按照它们在代码块中的显示顺序出现,但是在调试过程中,我更改了块彼此之间的相对位置。

更改源文件并尝试使用"make modulename"重新编译后,会出现此问题。 构建目标文件按预期工作,但如果文件已存在,即忽略$(OBJ_CURRENTMOD)指定的依赖项,则不会重建库。 在库依赖项中使用$(OBJMOD_MODULENAME)按预期工作。 我已经以多种方式验证了 $(OBJ_CURRENTMOD) 的值是否符合预期(例如,将echo $(OBJ_CURRENTMOD)粘在库目标的第一行),但无论我尝试什么,由于依赖关系检查,变量似乎都没有及时更新以触发重新编译。

当我输入这个时,我发现了一个解决方法:

OBJMOD_MODULENAME = obj/lib/foo.o obj/lib/bar.o obj/lib/quux.o
LIBDIR         = lib/
CXX            = g++
CXXLIBLINK     = -shared
LIB            = -lm -lpt
modulename: OBJ_CURRENTMOD = $(OBJMOD_MODULENAME)
modulename: $(OBJMOD_MODULENAME) lib/metrics.so
$(LIBDIR)%.so: herp $(OBJ_CURRENTMOD)
    $(CXX) $(CXXLIBLINK) -o $@ $(OBJ_CURRENTMOD) $(LIB)
herp: $(OBJ_CURRENTMOD)

在变量引用之前附加的这个虚拟目标似乎迫使它更新并解决了我的问题。 这是制造中的错误还是什么? make --version 表示 GNU make 3.81。 还有其他人可以证实这种奇怪的行为吗? 我只是在做一件非常愚蠢的事情吗? 我已经盯着它看了几个小时,我不会那么惊讶。

编辑:事实证明,这并没有真正修复它,它只是每次都将其困在运行中,无论它是否需要它。

要验证更改的值,请执行以下操作:

$(LIBDIR)%.so: $(OBJ_CURRENTMOD)
    echo $(OBJ_CURRENTMOD)
    $(CXX) $(CXXLIBLINK) -o $@ $(OBJ_CURRENTMOD) $(LIB)

正如我在一条评论中所说,我不明白$(LIBDIR)%.so模式如何匹配modulename的任何先决条件,但假设metrics.so是要lib/metrics.so那么它将用于构建lib/metrics.so

正如interjay指出的那样,"与自动变量一样,这些值仅在目标配方的上下文中可用(以及其他特定于目标的赋值)。它们不能在目标模式或先决条件列表中使用,这就解释了为什么当$(OBJ_MODULENAME)中的先决条件之一发生更改时不会重新生成目标。

若要使$(OBJ_CURRENTMOD)在先决条件列表中有效,需要使用辅助扩展

      
        .二次扩展:
      $(LIBDIR)%.so: $$(OBJ_CURRENTMOD)        $(CXX) $(CXXLIBLINK) -o $@ $(OBJ_CURRENTMOD) $(LIB)

您正在使用$(LIBDIR)%.so规则的先决条件列表中OBJ_CURRENTMOD的目标特定变量值。这是不允许的:特定于目标的变量只能在目标配方中使用。

另一个问题是您正在定义变量OBJ_MODULENAME然后访问尚未分配给的其他变量$(OBJMOD_MODULENAME)