0

环境资料:

  • 运行 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

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

我就不给你冗长的解释了;可以说,宏有助于调试。

4

1 回答 1

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 ) {

||快捷方式并阻止它继续前进到下一个令牌。

于 2013-02-26T21:26:49.113 回答