A cargo subcommand for creating GraphViz DOT files and dependency graphs

Related tags

Graphics cargo-graph
Overview

cargo-graph

Linux: Build Status

A cargo subcommand for building GraphViz DOT files of dependency graphs. This subcommand was originally based off and inspired by the project cargo-dot by Max New

Demo

Let's say we wanted to build a dependency graph of cargo-count but we wanted optional dependencies to use red dashed lines and black boxes, and regular (aka "build") dependencies to use orange lines to green diamonds, one would run the following.

NOTE: GraphViz dot needs to be installed to produce the .PNG from the dotfile

$ cargo graph --optional-line-style dashed --optional-line-color red --optional-shape box --build-shape diamond --build-color green --build-line-color orange > cargo-count.dot
$ dot -Tpng > rainbow-graph.png cargo-count.dot

NOTE: It's also possible to run cargo graph [options] | dot [options] > [file] instead of individual commands

The first command produces a GraphViz DOT file which looks like this:

digraph dependencies {
  N0[label="cargo-count",shape=diamond,color=green];
  N1[label="ansi_term",shape=box];
  N2[label="clap",shape=diamond,color=green];
  N3[label="clippy",shape=box];
  N4[label="glob",shape=diamond,color=green];
  N5[label="regex",shape=diamond,color=green];
  N6[label="tabwriter",shape=diamond,color=green];
  N7[label="aho-corasick",shape=diamond,color=green];
  N8[label="memchr",shape=diamond,color=green];
  N9[label="bitflags",shape=diamond,color=green];
  N10[label="strsim",shape=diamond,color=green];
  N11[label="unicode-normalization",shape=diamond,color=green];
  N12[label="libc",shape=diamond,color=green];
  N13[label="regex-syntax",shape=diamond,color=green];
  N14[label="unicode-width",shape=diamond,color=green];
  N0 -> N1[label="",style=dashed,color=red];
  N0 -> N2[label="",color=orange];
  N0 -> N3[label="",style=dashed,color=red];
  N0 -> N4[label="",color=orange];
  N0 -> N5[label="",color=orange];
  N0 -> N6[label="",color=orange];
  N7 -> N8[label="",color=orange];
  N2 -> N1[label="",style=dashed,color=red];
  N2 -> N9[label="",color=orange];
  N2 -> N10[label="",color=orange];
  N3 -> N11[label="",color=orange];
  N8 -> N12[label="",color=orange];
  N5 -> N7[label="",color=orange];
  N5 -> N8[label="",color=orange];
  N5 -> N13[label="",color=orange];
  N6 -> N14[label="",color=orange];
}

The second command produces a PNG image of the graph which looks like:

cargo-count dependencies

Now, why someone would do that to a graph is a different story...but it's possible :)

Installing

cargo-graph can be installed with cargo install

$ cargo install cargo-graph

This may require a nightly version of cargo if you get an error about the install command not being found. You may also compile and install the traditional way by following the instructions below.

Compiling

Follow these instructions to compile cargo-count, then skip down to Installation.

  1. Ensure you have current version of cargo and Rust installed
  2. Clone the project $ git clone https://github.com/kbknapp/cargo-graph && cd cargo-graph
  3. Build the project $ cargo build --release (NOTE: There is a large performance difference when compiling without optimizations, so I recommend always using --release to enable to them)
  4. Once complete, the binary will be located at target/release/cargo-graph

Installation and Usage

All you need to do is place cargo-graph somewhere in your $PATH. Then run cargo graph anywhere in your project directory. For full details see below.

Linux / OS X

You have two options, place cargo-graph into a directory that is already located in your $PATH variable (To see which directories those are, open a terminal and type echo "${PATH//:/\n}", the quotation marks are important), or you can add a custom directory to your $PATH

Option 1 If you have write permission to a directory listed in your $PATH or you have root permission (or via sudo), simply copy the cargo-graph to that directory # sudo cp cargo-graph/usr/local/bin

Option 2 If you do not have root, sudo, or write permission to any directory already in $PATH you can create a directory inside your home directory, and add that. Many people use $HOME/.bin to keep it hidden (and not clutter your home directory), or $HOME/bin if you want it to be always visible. Here is an example to make the directory, add it to $PATH, and copy cargo-graph there.

Simply change bin to whatever you'd like to name the directory, and .bashrc to whatever your shell startup file is (usually .bashrc, .bash_profile, or .zshrc)

$ mkdir ~/bin
$ echo "export PATH=$PATH:$HOME/bin" >> ~/.bashrc
$ cp cargo-graph~/bin
$ source ~/.bashrc

Windows

On Windows 7/8 you can add directory to the PATH variable by opening a command line as an administrator and running

C:\> setx path "%path%;C:\path\to\cargo-graph\binary"

Otherwise, ensure you have the cargo-graph binary in the directory which you operating in the command line from, because Windows automatically adds your current directory to PATH (i.e. if you open a command line to C:\my_project\ to use cargo-graph ensure cargo-graph.exe is inside that directory as well).

Options

There are a few options for using cargo-graph which should be somewhat self explanatory.

USAGE:
    cargo graph [FLAGS] [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -I, --include-versions    Include the dependency version on nodes
    -V, --version    Prints version information

OPTIONS:
        --build-color <COLOR>            Color for regular deps (Defaults to 'black')
                                          [values: blue black yellow purple green red white orange]
        --build-deps <true|false>        Should build deps be in the graph? (Defaults to 'true')
                                         ex. --build-deps=false OR --build-deps=no
        --build-line-color <COLOR>       Line color for regular deps (Defaults to 'black')
                                          [values: blue black yellow purple green red white orange]
        --build-line-style <STYLE>       Line style for build deps (Defaults to 'solid')
                                          [values: solid dotted dashed]
        --build-shape <SHAPE>            Shape for regular deps (Defaults to 'round')
                                          [values: box round diamond triangle]
        --dev-color <COLOR>              Color for dev deps (Defaults to 'black')
                                          [values: blue black yellow purple green red white orange]
        --dev-deps <true|false>          Should dev deps be included in the graph? (Defaults to 'false')
                                         ex. --dev-deps=true OR --dev-deps=yes
        --dev-line-color <COLOR>         Line color for dev deps (Defaults to 'black')
                                          [values: blue black yellow purple green red white orange]
        --dev-line-style <STYLE>         Line style for dev deps (Defaults to 'solid')
                                          [values: solid dotted dashed]
        --dev-shape <SHAPE>              Shape for dev deps (Defaults to 'round')
                                          [values: box round diamond triangle]
        --dot-file <FILE>                Output file (Default to stdout)
        --lock-file <FILE>               Specify location of .lock file (Default 'Cargo.lock')
        --manifest-file <FILE>           Specify location of manifest file (Default 'Cargo.toml')
        --optional-color <COLOR>         Color for optional deps (Defaults to 'black')
                                          [values: blue black yellow purple green red white orange]
        --optional-deps <true|false>     Should optional deps be in the graph? (Defaults to 'true')
                                         ex. --optional-deps=false OR --optional-deps=no
        --optional-line-color <COLOR>    Line color for optional deps (Defaults to 'black')
                                          [values: blue black yellow purple green red white orange]
        --optional-line-style <STYLE>    Line style for optional deps (Defaults to 'solid')
                                          [values: solid dotted dashed]
        --optional-shape <SHAPE>         Shape for optional deps (Defaults to 'round')
                                          [values: box round diamond triangle]

License

cargo-graph is released under the terms of the MIT. See the LICENSE-MIT file for the details.

Dependencies Tree

cargo-graph dependencies

Comments
  • "duplicated" regular and dev-dependencies are not separated

    I've got a crate with a mess like this:

    [dependencies]
    memchr = "0.1"
    quickcheck = { version = "0.2", optional = true }
    itertools = { version = "0.4", optional = true }
    odds = { version = "0.2", optional = true }
    jetscii = {version = "0.3", features= ["unstable"], optional = true }
    
    [dev-dependencies]
    regex = "0.1"
    itertools = "0.4"
    odds = "0.2"
    
    custom_derive = "0.1"
    newtype_derive = "0.1"
    rand = "0.3.10"
    
    P3: need to have T: bug C: dev-dep-graph 
    opened by bluss 9
  • Error when running `cargo graph`

    Error when running `cargo graph`

    <stdin>:1:2: 1:3 error: unknown start of token: \\
    <stdin>:1 C\:> setx path \"%path%;C:\path\to\cargo-graph\binary\"
               ^
    thread '<unnamed>' panicked at 'Box<Any>', ../src/libsyntax/parse/lexer/mod.rs:1227
    Could not document `cargo-graph`.
    
    opened by bvssvni 9
  • Show different versions of a crate separately

    Show different versions of a crate separately

    Previously, cargo graph would merge all versions of a crate into a single node. However, a dependency graph may include multiple versions of the same crate. It is helpful to have a graph that shows which dependencies bring in an older version of a crate.

    Now, instead of using only the name to identify a node in the graph, we use both the name and the version. For the project's direct dependencies, we take the version from the [root] table in Cargo.lock.

    Since Cargo.toml doesn't contain the actual version used for dependencies, we can't properly initialize the list of dependencies while parsing Cargo.toml. However, Cargo.toml contains one piece of information that isn't in Cargo.lock: the kind of dependency (build, dev or optional). Instead of using a single Dep struct to store the information from both sources, we now use two structs: DeclaredDep, which represents a dependency declared in Cargo.toml, and ResolvedDep, which represents a resolved dependency in Cargo.lock.

    The kind of dependency on a ResolvedDep is propagated to indirect dependencies once the whole graph has been filled. Instead of having a single kind on a ResolvedDep, we use a set of flags so that we assign the correct kind when an indirect dependency is used through direct dependencies with different kinds.

    When --include-versions is not passed, nodes for crates with multiple versions in the graph will show the version anyway, in order to disambiguate the nodes that would otherwise have the same text.

    Closes #27. Closes #28.

    opened by FraGag 7
  • Fix remove orphans

    Fix remove orphans

    I investigated #24 and I found 2 problems:

    • When an orphan node was detected and removed, the indexes in the nodes vector changed for all the nodes after it, but the edges were not updated to match new indexes. It then triggered an out-of-bound panic on the next loop execution. Also, edges originating from the removed node were not removed.
    • The preliminary bound check was incorrect and did not remove edges pointing at/originating from 1-past the number of nodes, resulting in an out-of-bound panic in the next loop.
    opened by ghost 7
  • cargo graph does not work with cargo workspaces

    cargo graph does not work with cargo workspaces

    When using workspaces, Cargo.toml's [root] is basically just backwards compatibility and no longer points to master crate. This makes graph incomplete, cause it doesn't contain all crates from the workspace.

    Full description of an issue can be found here: https://github.com/rust-lang/cargo/issues/3203

    opened by debris 5
  • Panic in DepGraph::render_to

    Panic in DepGraph::render_to

    Follow up on #15. Graph with deps look nice. Without dev-deps, it panics:

    Node N14 doesn't exist, but it tries to add the edge N3 -> N14. N3 is memchr so the only thing it should link to is libc.

    $ RUST_BACKTRACE=1 ~/bin/cargo-graph graph 
    thread '<main>' panicked at 'called `Option::unwrap()` on a `None` value', ../src/libcore/option.rs:367
    stack backtrace:
       1:     0x5599470a91a0 - sys::backtrace::tracing::imp::write::h2121cc3fd481a5bfxXt
       2:     0x5599470ab565 - panicking::log_panic::_<closure>::closure.41181
       3:     0x5599470aafe0 - panicking::log_panic::h274f0982d2d31f5d62x
       4:     0x55994709ed93 - sys_common::unwind::begin_unwind_inner::ha197e3d3bf39738b4Ps
       5:     0x55994709f128 - sys_common::unwind::begin_unwind_fmt::h377d567d53530218aPs
       6:     0x5599470a8801 - rust_begin_unwind
       7:     0x5599470d7d6f - panicking::panic_fmt::hd08c5b6fdb7b10daxuL
       8:     0x5599470d8048 - panicking::panic::h588d88296fb1b1954sL
       9:     0x559946f4f942 - option::_<impl>::unwrap::unwrap::h16263530560132818147
                            at ../src/libcore/macros.rs:20
      10:     0x559946f4ee67 - graph::_<impl>::label::h10115180723912119468
                            at src/graph.rs:17
      11:     0x559946f490ff - graph::_<impl>::render_to::h7564755762930757336
                            at src/graph.rs:142
      12:     0x559946f43159 - execute::h2d7033028e348fb8ogc
                            at src/main.rs:390
      13:     0x559946f3d2ed - main::h75e0a80141ee56f0Ifc
                            at src/main.rs:378
      14:     0x5599470aad84 - sys_common::unwind::try::try_fn::h1190371136003024825
      15:     0x5599470a8648 - __rust_try
      16:     0x5599470aaa26 - rt::lang_start::h63ca0c2ab43f095fe0x
      17:     0x559946f43399 - main
      18:     0x7f94da5bdb44 - __libc_start_main
      19:     0x559946f30c38 - <unknown>
      20:                0x0 - <unknown>
    digraph dependencies {
            N0[label="twoway"];
            N1[label="itertools"];
            N2[label="jetscii"];
            N3[label="memchr"];
            N4[label="odds"];
            N5[label="quickcheck"];
            N6[label="rand"];
            N7[label="advapi32-sys"];
            N8[label="winapi"];
            N9[label="winapi-build"];
            N10[label="libc"];
            N11[label="log"];
            N12[label="unreachable"];
            N13[label="void"];
            N0 -> N1[label=""];
            N0 -> N2[label=""];
            N0 -> N3[label=""];
            N0 -> N4[label=""];
            N0 -> N5[label=""];
            N0 -> N6[label=""];
            N0 -> N7[label=""];
            N0 -> N8[label=""];
            N0 -> N9[label=""];
            N3 -> N14
    
    
    P3: need to have T: bug C: dev-dep-graph 
    opened by bluss 2
  • Some dependencies are wrong

    Some dependencies are wrong

    Trying to update the dependency graph for https://github.com/PistonDevelopers/opengl_graphics

    $ cargo graph --optional-deps false --dev-deps false | dot -Tpng > Cargo.png
    

    This gets a graph where vecmath has wrong dependencies:

    cargo

    The only dependency of "vecmath" is "piston-float", but the graph shows these:

    • kernel32-sys
    • bitflags
    • num
    • winapi-build
    opened by bvssvni 1
  • Does not work with Cargo 1.41 toml format

    Does not work with Cargo 1.41 toml format

    Don't know if you're still working on this, but I hope you are! It looks like Cargo 1.41 changed up the format of the Cargo.lock file, so now this only outputs error: No root table found for toml file. If it's an easy fix I might be able to make a PR for it.

    Thanks!

    opened by icefoxen 1
  • duplicate key: `version`

    duplicate key: `version`

    Hi! I wanted to generate a dependency graph for mn mnemonic but cargo-graph gives me the error

    File { fd: 3, path: "/home/swym/tmp/mnemonic/Cargo.toml", read: true, write: false }:11:1-11:8 duplicate key: version

    I failed to find a duplicate version key manually and also tomlcheck confirms that Cargo.lock seems fine.

    gh won't let me attach Cargo.lock but you should be able to reproduce by git cloning mnemonic...

    opened by herrgahr 2
  • Bump version

    Bump version

    The version of cargo-graph published on crates.io doesn't incorporate the fix for issue #40. Bump the version number so that cargo install can automatically pull in the fixed version.

    opened by trombonehero 2
  • feat: implements links to crates.io based on the package and version …

    feat: implements links to crates.io based on the package and version …

    While reviewing the dependencies of a project, it is quite common to review the details of a certain package on crates.io.

    Graphviz can render hyperlinks on nodes and edges when the output is svg, postscript or map. This change adds a href property on the nodes in the dot file. The url for the href is currently set to https://crates.io/(?P<package>.*)(/(?P<version>.*))?

    opened by verpeteren 0
Releases(v0.2.0)
Owner
Kevin K.
I love to code, skydive, and do the things.
Kevin K.
Construct graphs from parsed source code

tree-sitter-graph The tree-sitter-graph library defines a DSL for constructing arbitrary graph structures from source code that has been parsed using

null 102 Nov 23, 2022
Python library for embedding large graphs in 2D space, using force-directed layouts.

Graph Force A python/rust library for embedding graphs in 2D space, using force-directed layouts. Installation pip install graph_force Usage The first

Niko Abeler 159 Dec 29, 2022
svgcleaner could help you to clean up your SVG files from the unnecessary data.

svgcleaner svgcleaner helps you clean up your SVG files, keeping them free from unnecessary data. Table of Contents Purpose Goals Alternatives Charts

Evgeniy Reizner 1.5k Jan 9, 2023
CLI for image processing with histograms, binary treshold and other functions

Image-Processing-CLI-in-Rust CLI for processing images in Rust. Some implementation is custom and for some functionality it uses 3rd party libraries.

Miki Graf 25 Jul 24, 2022
GLFW3 bindings and idiomatic wrapper for Rust.

glfw-rs GLFW bindings and wrapper for The Rust Programming Language. Example extern crate glfw; use glfw::{Action, Context, Key}; fn main() { le

PistonDevelopers 546 Jan 3, 2023
Safe and rich Rust wrapper around the Vulkan API

Vulkano See also vulkano.rs. Vulkano is a Rust wrapper around the Vulkan graphics API. It follows the Rust philosophy, which is that as long as you do

null 3.6k Jan 3, 2023
A cool, fast maze generator and solver written in Rust

MazeCruncher Welcome to maze cruncher! Download Standalone Here Usage To get started, just run the standalone .exe in target/release or compile and ru

null 69 Sep 20, 2022
A high-performance SVG renderer, powered by Rust based resvg and napi-rs.

resvg-js resvg-js is a high-performance SVG renderer, powered by Rust based resvg and napi-rs. Fast, safe and zero dependencies! No need for node-gyp

一丝 744 Jan 7, 2023
Sub-pixel precision light spot rendering library for astronomy and video tracking applications.

Planetarium Sub-pixel precision light spot rendering library for astronomy and video tracking applications. Example usage use planetarium::{Canvas, Sp

Sergey Kvachonok 5 Mar 27, 2022
A simple and elegant, pipewire graph editor

pw-viz A simple and elegant, pipewire graph editor This is still a WIP, node layouting is kinda jank at the moment. Installation A compiled binary is

null 180 Dec 27, 2022
Szalinski: A Tool for Synthesizing Structured CAD Models with Equality Saturation and Inverse Transformations

Szalinski: A Tool for Synthesizing Structured CAD Models with Equality Saturation and Inverse Transformations

UW PLSE 24 Aug 15, 2022
Real-time 3D orientation visualization of a BNO055 IMU using Bissel and Bevy

orientation This is a demonstration of real-time visualization of the attitude of a BNO055 IMU across a wireless network to a Bevy app using the Bisse

chris m 4 Dec 10, 2022
Small, lightweight and fast library for rendering text with wgpu.

wgpu-text wgpu-text is a wrapper over glyph-brush for fast and easy text rendering in wgpu. This project was inspired by and is similar to wgpu_glyph,

Leon 20 Nov 30, 2022
Theorem relational dependencies automatic extraction and visualization as a graph for Lean4.

Lean Graph Interactive visualization of dependencies for any theorem/definitions in your Lean project. How to use In your browser: lean-graph.com Or r

Patrik Číhal 8 Jan 3, 2024
Toy language that output pseudocode, pascal and graphviz dot

pseudoc pseudoc is a project I made for school because we needed to write our programs in three different formats: Pascal, pseudocode (similar in stru

João Capucho 2 Apr 6, 2022
The library provides basic functions to work with Graphviz dot lang from rust code.

Description The library provides the basic access to the graphs in graphviz format with ability to import into or export from it. Base examples: Parse

Boris 28 Dec 16, 2022
Track and query Cargo dependency graphs.

cargo-guppy: track and query dependency graphs This repository contains the source code for: guppy: a library for performing queries on Cargo dependen

guppy 42 Dec 30, 2022
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
Automated license checking for rust. cargo lichking is a Cargo subcommand that checks licensing information for dependencies.

cargo-lichking Automated license checking for rust. cargo lichking is a Cargo subcommand that checks licensing information for dependencies. Liches ar

Nemo157 120 Dec 19, 2022
cargo-lambda a Cargo subcommand to help you work with AWS Lambda

cargo-lambda cargo-lambda is a Cargo subcommand to help you work with AWS Lambda. This subcommand compiles AWS Lambda functions natively and produces

David Calavera 184 Jan 5, 2023