make:目标完成但$(realpath ...)找不到它

时间:2013-02-26 00:52:22

标签: solaris gnu-make nfs realpath

环境:

  • 运行NFS 3的Solaris NFS文件服务器
  • Linux或Solaris环境中出现错误
  • 使用GNU Make 3.82
  • 使用Sun Studio编译器,如果重要

这是我正在查看的构建的一个非常简化的示例:

all: ${list of shared objects to build}
  @do whatever

lib1.so: ${1s objects}
lib2.so: ${2s objects}
lib3.so: ${3s objects}
#...

%.so:
  $(call CHECK_DEPENDENCIES_EXIST)
  @${LD} ${LDFLAGS} ${^} -o ${@}

%.o : %.c
  @do stuff

%.o : %.cc
  @do stuff

define CHECK_DEPENDENCIES_EXIST =
$(if $(realpath ${^}),,$(warning No dependencies specified for ${@})false)
endef

简短& sweet:$(realpath x y z)(如果它们存在则返回x / y / z;返回一个不包含符号链接的绝对路径)在某些情况下从列表中删除文件,我认为它与NFS有关。无法预测哪个目标会失败。有时目标会在最后10次成功时失败。如果我从宏中取出@false,那么构建会继续而不会出错 - 也就是说,链接器不会抱怨所谓的丢失文件。

我会饶恕你提出的解释;这足以说明,宏有助于调试。

1 个答案:

答案 0 :(得分:2)

原来gmake中存在一个错误。来自GNU Make 3.82源代码function.c,在2026行或左右:

while ((path = find_next_token (&p, &len)) != 0 ) {
/* ... */
    if (
#ifdef HAVE_REALPATH
         realpath (in, out)
#else
         abspath (in, out) && stat (out, &st) == 0
#endif
       )
    {
      /* ... */
    }
  }
}
/* ... */

偶尔,对realpath的各种调用都会被中断(EINTR);此代码中没有任何内容检查errno,因此它只是默默地失败。

所以,并不是文件不存在,而是$(realpath ...)被信号中断(可能是gmake的子实例,表示其完成或类似的事情)和此功能并非旨在从这类事件中恢复。

解决问题:

while ((path = find_next_token (&p, &len)) != 0 ) {

...变成:

while ( errno == EINTR || (path = find_next_token (&p, &len)) != 0 ) {

||将快捷方式&防止它进入下一个令牌。