要分析这样的问题,您可以使用:
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
or 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...”)。