I am trying to build a project using Haiku Jam. (The code for the project is available online at https://github.com/Andromeda-OS/LLVM. I recommend at least looking at the directory names in that project so that you know what components I am referring to below.)
I am trying to (re)build the llvm-tblgen utility. llvm-tblgen has a link-time dependency on libLLVMSupport and libLLVMTableGen. If I add a Jam DEPENDS statement so that llvm-tblgen requires that libLLVMSupport be built first, Jam does not build llvm-tblgen at all. Jam outputs don't know how to make ./bin/llvm-tblgen/llvm-tblgen, and gives me no other useful diagnostics, even when running at high verbosity levels.
If I remove every dependency command from llvm-tblgen, then and only then does Jam compile the file. However, if libLLVMSupport.a is not present, linker errors will result as Jam was not told to compile libLLVMSupport first. However, if I tell Jam to build libLLVMSupport first, then llvm-tblgen will not be built at all! Any pointers?
To analyze problems like this you can use:
This prints the make tree. The error is printed while processing the make tree, so you see it right where Jam encounters it and can easily track back the dependencies that lead to it. In this case "Intrinsics.gen" has the non-existent dependency and grep reveals the following line in "include/llvm/Jamfile":
So, if you're jamming in the top directory, the latter dependency expands to "./bin/llvm-tblgen/llvm-tblgen". Since target names in Jam are just literal strings -- there's no matching for possible paths happing -- this does not match the target "llvm-tblgen" you define in "bin/llvm-tblgen/Jamfile".
The solution is: Never use target names with path components, just use the file name. If two different targets have the file name, add grist to one or both of them (e.g. "foo" and "foo") to make them unique again. If
SEARCHorLOCATEis properly set on the target -- which almost all standard rules do -- Jam will automatically resolve the target name to the matching path (aka bind the target) when used in actions. For instance your TableGen rule should rather look like:"llvm-tblgen" is now passed as a target to the actions and thus automatically bound to the correct path.
You can simplify "include/llvm/Jamfile":
Usually one adds the subdirectory grist to source files (using
[ FGristFiles Intrinsics.td ]in this case), so clashes with equally named source files in other directories are avoided preemptively. If you use the TableGen rule elsewhere as well, you may also want to move the aboveMakeLocateandSEARCHthere as well. Instead of settingTABLEGEN_FLAGShere, I would make that a third parameter of TableGen and set the variable there, so the rule becomes even more convenient to use.A few other things I noted:
return $(results:BS) ;. The string/path operations are applied to each element of a list, so there's no need to do that manually.LinkLibraries $(1) : lib$(3).a ;instead of the "for" loop. The rule establishes the dependencies and adds the libraries to the link line (with their path instead of "-L... -l...").