【问题标题】:gmake: a target completes but $(realpath ...) doesn't find itgmake:目标完成但 $(realpath ...) 没有找到它
【发布时间】:2013-02-26 00:52:22
【问题描述】:

环境方面的东西:

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

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

我会省去冗长的解释;可以说,宏对调试很有帮助。

【问题讨论】:

    标签: solaris gnu-make nfs realpath


    【解决方案1】:

    原来 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 的子实例,表示其完成或类似的东西),而这个函数不是t 旨在从此类事件中恢复。

    解决问题:

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

    ...变成:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多