Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake: How to tell where transitive dependency is coming from?

Tags:

cmake

I'm in the process of rewriting a legacy CMake setup to use modern features like automatic dependency propagation. (i.e. using things like target_include_directories(<target> PUBLIC <dir>) instead of include_directories(<dir>).) Currently, we manually handle all project dependency information by setting a bunch of global directory properties.

In my testing, I've found a few examples where a target in the new build will link to a library that the old build would not. I'm not linking to it explicitly, so I know this is coming from the target's dependencies, but in order to find which one(s) I have to recursively look through all of the project's CMakeLists.txts, following up the dependency hierarchy until I find one that pulls in the library in question. We have dozens of libraries so this is not a trivial process.

Does CMake provide any way to see, for each target, which of its dependencies were added explicitly, and which ones were propagated through transitive dependencies?

It looks like the --graphviz output does show this distinction, so clearly CMake knows the context internally. However, I'd like to write a tree-like script to show dependency information on the command line, and parsing Graphviz files sounds like both a nightmare and a hack.

As far as I can tell, cmake-file-api does not include this information. I thought the codemodel/target/dependencies field might work, but it lists both local and transitive dependencies mixed together. And the backtrace field of each dependency only ties back to the add_executable/add_library call for the current target.

like image 276
0x5453 Avatar asked Dec 06 '19 22:12

0x5453


People also ask

How do you fix transitive dependency?

Once you identify your package to be fixed using any of the above methods, to fix the transitive dependency, you must add a dependency to the updated version of the vulnerable package by adding it to the . csproj file. i.e such a vulnerable package needs to be made a direct dependency of your main project.

What is a transitive dependency package?

Transitive dependencyA dependency that your package indirectly uses because one of its dependencies requires it. If your package depends on A, which in turn depends on B which depends on C, then A is an immediate dependency and B and C are transitive ones.

What are direct and transitive dependencies?

In a computer program a direct dependency is functionality exported by a library, or API, or any software component that is referenced directly by the program itself. A transitive dependency is any dependency that is induced by the components that the program references directly.

How do I add dependencies to a build in CMake?

CMake provides a number of ways to incorporate such things into the build. Projects and users have the flexibility to choose between methods that best suit their needs. The primary methods of bringing dependencies into the build are the find_package () command and the FetchContent module.

What is the dependency tree?

This prints the dependency tree. It’s a text report which shows all of the dependencies in your project, both the direct and transitive dependencies. If you’re not sure what the terms ‘direct’ and ‘transitive’ mean, then scroll further down for a quick guide to dependencies and how they work in Maven!

Why is my CMake project append to CMake_module_path?

It is common for users to set the CMAKE_MODULE_PATH when running CMake, and it is common for CMake projects to append to CMAKE_MODULE_PATH to allow use of local Find module files. CMake ships Find<PackageName>.cmake files for some third party packages.

How do I view dependencies in Maven?

One of Maven’s main jobs is to handle your Java project’s dependencies. So when Maven runs, it builds a “tree” of all dependencies in your project. If you tell Maven to print a dependency tree, you will be able to see all of the dependencies in your project. Drop to a terminal.


1 Answers

You can parse dot file generated by graphviz and extract details which you want. Below is sample python script to do that.

import pydot
import sys

graph = pydot.graph_from_dot_file(sys.argv[1])
result = {}

for g in graph:
    # print(g)
    for node in g.get_node_list():
        if node.get("label") != None:
            result[node.get("label")] = []

    for edge in g.get_edges():
        result[g.get_node(edge.get_source())[0].get("label")].append(g.get_node(edge.get_destination())[0].get("label"))

for r in result:
    print(r+":"+",".join(result[r]))

You can also add this script to run from cmake as custom target, so you can call it from you build system. You can find sample cmake project here

like image 146
Manthan Tilva Avatar answered Oct 12 '22 21:10

Manthan Tilva