Different target dependencies in cmake --graphviz and file-api output

Hi,

I want to read cmake target dependencies and other details like type/path via the cmake file-api for a SBOM (software bill of materials) tool I’m working on.

For this use-case I’m only interested in the direct dependencies of each target in the build-tree.

I have tested this in a sample workspace and it seems that the file-api produces a mix of direct and indirect dependencies for my targets, while the cmake --graphviz output would only contain the direct dependencies for each respective target.

As I cannot see a way to filter the indirect dependencies within the file-api output and the --graphviz output lacks other details I need, I would need to merge both results somehow. However, this solutions seems quite fragile, as there could be issues coming from duplicate names, multi configs, etc.

So, is there any option or flag on cmake file-api to get rid of the indirect dependencies of build targets?

I already checked documentation on the file-api, but cannot find anything helpful heron.

The file-api output for my sample ‘main’ target:

{
	"artifacts" : 
	[
		{
			"path" : "main/main"
		}
	],
..
	"dependencies" : 
	[
		{
			"backtrace" : 2,
			"id" : "hello::@306ed2d68c6501e8728f"
		},
		{       // this seems to be an indirect dependency introduced by dependent lib 'util'
                        // which does not show up in the --graphviz output below
			"backtrace" : 2,
			"id" : "greet::@306ed2d68c6501e8728f"
		},
		{
			"backtrace" : 4,
			"id" : "third_party_app::@037116246cbfaaeb5504"
		},
		{
			"backtrace" : 2,
			"id" : "util::@15c4a824ab2728a3f5e7"
		}
	],
...
	"type" : "EXECUTABLE"
}

The --graphviz output for my sample ‘main’ target:

digraph "main" {
node [
  fontsize = "12"
];
    "node2" [ label = "main", shape = egg ];
    "node1" [ label = "hello", shape = octagon ];
    "node2" -> "node1" [ style = dotted ] // main -> hello
    "node3" [ label = "third_party_app", shape = octagon ];
    "node2" -> "node3" [ style = dotted ] // main -> third_party_app
    "node4" [ label = "util", shape = octagon ];
    "node2" -> "node4" [ style = dotted ] // main -> util
    "node0" [ label = "greet", shape = octagon ];
    "node4" -> "node0"  // util -> greet
    "node1" [ label = "hello", shape = octagon ];
    "node0" -> "node1"  // greet -> hello
}

Thx in advance!

I know this probably isn’t so helpful, but I went down a similar route to you recently for some consulting work and I came to the conclusion that the file API output is currently unsuitable on its own for generating a SBOM. The dependencies are not specified in a way that you get a robust list of everything a target depends on. I forget the exact details, but be warned that the file API might not be giving you what you want or expect in terms of the target dependencies. And most likely, you need to know dependencies at the file level rather than just the target level, and for that you may need help from the compiler since it spits out file level dependencies as a side effect of compilation (well, some compilers do). Simply running CMake alone won’t give you all file level dependencies.

Yes, I’m also coming slowly to the conclusion, that the file-api is not suitable for my use-case. I meanwhile managed to filter the indirect dependencies by the info from the graph, just to realize that in a bigger (real) cmake project I also have orphant targets in my SBOM that are listed as interface libs in the graph, but totally missing in the file-api output. Also this ticket https://gitlab.kitware.com/cmake/cmake/-/issues/25213 makes me think I have to change my approach. Besides, for the level of details I need it’s not necessary to go to file-level (yet ;-)… Anyway, many thx for the input!