要分析这样的问题,您可以使用:
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”)以使它们再次唯一。如果在目标上正确设置了SEARCH 或LOCATE——几乎所有标准规则都这样做——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 规则,您可能还想将上面的 MakeLocate 和 SEARCH 也移动到那里。我不会在此处设置TABLEGEN_FLAGS,而是将其作为 TableGen 的第三个参数并在此处设置变量,因此该规则使用起来更加方便。
我注意到的其他一些事情:
- 您的通配符规则过于复杂。在第一行之后你可以
return $(results:BS) ;。字符串/路径操作适用于列表的每个元素,因此无需手动执行。
- 您的 LLVMLinkExecutable 和 _GetLinkerFlags 也相当复杂。如果 LLVMLinkExecutable 的“libraries”参数始终是构建系统构建的库的缩写名称,则可以只使用
LinkLibraries $(1) : lib$(3).a ; 而不是“for”循环。该规则建立依赖关系并将库添加到链接行(使用它们的路径而不是“-L...-l...”)。