【问题标题】:Dependency Breaks Build依赖中断构建
【发布时间】:2013-08-26 00:07:53
【问题描述】:

我正在尝试使用 Haiku Jam 构建一个项目。 (该项目的代码可在线获取https://github.com/Andromeda-OS/LLVM。我建议至少查看该项目中的目录名称,以便您知道我在下面指的是哪些组件。)

我正在尝试(重新)构建llvm-tblgen 实用程序。 llvm-tblgenlibLLVMSupportlibLLVMTableGen 具有链接时间依赖性。如果我添加一个 Jam DEPENDS 语句以便 llvm-tblgen 要求首先构建 libLLVMSupport,那么 Jam 根本不会构建 llvm-tblgen。 Jam 输出 don't know how to make ./bin/llvm-tblgen/llvm-tblgen,并没有给我其他有用的诊断信息,即使在高详细级别运行时也是如此。

如果我从llvm-tblgen 中删除所有依赖命令,那么只有这样 Jam 才会编译该文件。但是,如果 libLLVMSupport.a 不存在,则会导致链接器错误,因为没有告诉 Jam 先编译 libLLVMSupport。但是,如果我告诉 Jam 先构建 libLLVMSupport,那么 llvm-tblgen 将根本不会构建!有什么指点吗?

【问题讨论】:

    标签: jam


    【解决方案1】:

    要分析这样的问题,您可以使用:

    jam -n -dm
    

    这会打印 make 树。在处理 make 树时会打印错误,因此您可以在 Jam 遇到它的地方看到它,并且可以轻松地追溯导致它的依赖项。在这种情况下,“Intrinsics.gen”具有不存在的依赖关系,并且 grep 在“include/llvm/Jamfile”中显示以下行:

    DEPENDS $(Intrinsics.gen) : $(Intrinsics.gen:D) $(TOP)/bin/llvm-tblgen/llvm-tblgen ;
    

    因此,如果您在顶级目录中卡顿,则后者的依赖项将扩展为“./bin/llvm-tblgen/llvm-tblgen”。由于 Jam 中的目标名称只是文字字符串 - 可能的路径不匹配 - 这与您在“bin/llvm-tblgen/Jamfile”中定义的目标“llvm-tblgen”不匹配。

    解决方案是:不要使用路径组件的目标名称,只使用文件名。如果两个不同的目标具有文件名,则将 grist 添加到其中一个或两个(例如“foo”和“foo”)以使它们再次唯一。如果在目标上正确设置了SEARCHLOCATE——几乎所有标准规则都这样做——Jam 将在用于操作时自动将目标名称解析为匹配的路径(也就是绑定目标)。例如,您的 TableGen 规则应该如下所示:

    rule TableGen
    {
      DEPENDS $(<) : llvm-tblgen $(>) ;
      TableGen1 $(<) : llvm-tblgen $(>) ;
    }
    
    actions TableGen1
    {
      $(2[1]) $(TABLEGEN_FLAGS) -I $(TOP)/generated-include -I $(TOP)/lib/Target -I $(TOP)/include -o $(1) $(2[2-])
    }
    

    “llvm-tblgen”现在作为目标传递给动作,因此自动绑定到正确的路径。

    您可以简化“include/llvm/Jamfile”:

    SubDir TOP include llvm ;
    
    MakeLocate Intrinsics.gen : $(TOP)/generated-include/llvm ;
    SEARCH on Intrinsics.td = $(SUBDIR) ;
    TableGen Intrinsics.gen : Intrinsics.td ;
    TABLEGEN_FLAGS on Intrinsics.gen = -gen-intrinsic ;
    

    通常将子目录 grist 添加到源文件(在这种情况下使用[ FGristFiles Intrinsics.td ]),因此可以抢先避免与其他目录中同名的源文件发生冲突。如果您也在其他地方使用 TableGen 规则,您可能还想将上面的 MakeLocateSEARCH 也移动到那里。我不会在此处设置TABLEGEN_FLAGS,而是将其作为 TableGen 的第三个参数并在此处设置变量,因此该规则使用起来更加方便。

    我注意到的其他一些事情:

    • 您的通配符规则过于复杂。在第一行之后你可以return $(results:BS) ;。字符串/路径操作适用于列表的每个元素,因此无需手动执行。
    • 您的 LLVMLinkExecutable 和 _GetLinkerFlags 也相当复杂。如果 LLVMLinkExecutable 的“libraries”参数始终是构建系统构建的库的缩写名称,则可以只使用 LinkLibraries $(1) : lib$(3).a ; 而不是“for”循环。该规则建立依赖关系并将库添加到链接行(使用它们的路径而不是“-L...-l...”)。

    【讨论】:

    • 其实,在看到这个答案之前,我已经自己解决了这个问题。但是,感谢您您提出的所有建议!我自己从来没有想过这些!我很快就会将它们应用到我的代码库中。
    猜你喜欢
    • 1970-01-01
    • 2011-07-21
    • 2018-08-12
    • 2015-08-12
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-16
    相关资源
    最近更新 更多