Showing Dependencies

Hi,

I would love to get some feedback on moving the “show-dependencies” functionality forward.

In its current form, the output supports 4 different formats (text, dot, json, and flatlist), yet for all of these, the level of detail is low. I worked on code that can output rich information not only about the dependencies between packages, but at the same time also show dependencies within each package. Particularly, this allows for detailed dot file output which can help visualize the graph of module dependencies within a package.

While the improved dot output is very valuable for larger projects, some legitimate concerns were raised about the maintenance burden of the added complexity for the package manager project.

It seems that there are two valid approaches:

(1) Build out show-dependencies to support a larger feature set

(2) Deprecate all of “show-dependencies” and instead build out “dump-package” to provide more detail, and in addition build a tool (outside the Swift project) that can read the “dump-package” format and generate e.g. a detailed dot file based on that.

There are obvious pros and cons to both. Having a better “show-dependencies” built-in provides far more convenience over having to use an external tool that needs to be in sync with the package manager version. Built-in functionality would have a higher visibility. An external tool, however, would reduce the maintenance burden for the package manager. And the external tool could iterate on its features independently of the Swift project.

/Daniel

I see no downside to #2... it seems like they could in theory both be done, but #2 seems to support other use cases as well so it seems like a reasonable place to start.

  • Daniel

I like #2 as well

I agree that unifying things would help other tooling, too.

As for building out dump-package, I’m curious how people feel about combining all 3 of

  • describe — Describe the current package
  • dump-package — Print parsed Package.swift as JSON
  • show-dependencies — Print the resolved dependency graph

They seem to all do very similar things: describe is a text format of dump-package’s JSON output. And show-dependencies allows for explicit output format selection, it shows package dependencies, but lacks details for those packages, whereas describe and dump-package show a lot of details, but only about the package itself (not for package dependencies).

With that, it seems like moving towards a describe sub-command with an ability to specify

  • output format selection (text, json, etc.)
  • include / exclude package dependencies
  • specify detail level (i.e. include modules / targets, include test targets)

The current dump-package and show-dependencies could then be deprecated, but forward into describe with a combination of options that correspond to their current behavior.

Alternatively, describe could be deprecated and dump-package would be the command that the other ones funnel into.

Does that sound like a good overall approach?

/Daniel

I can see an argument for combining them all under describe. I’d probably start by flushing out all the detail into dump-package, then figure out which textual renderings make sense before trying to combine though. It may turn out we want enough different behaviors that it’s clunky to put all under one syntax.

1 Like

I think we should add a new command dump-package-graph or something to emit JSON from the PackageGraph object. Rest of the commands can be built on top of it and we can think about deprecating them once we have this new command. A nice thing about describe and dump-package is not requiring a fully resolved package graph as they operate on the root package. Maybe we can add an option to dump-package-graph to handle that use-case, something like swift package dump-package-graph --root-only.

Why add a new verb versus going the other direction, dump-package --all for example?

I think "package-graph" is clearer in the sense that the most operation will performed on the entire package graph and not just the root package. Also, dump-package --all sounds a bit awkward.

I like @ddunbar’s suggestion. We could do dump-package --graph or dump-package --include-graph. That would make it more obvious what it’s about. And easier to read. Could also use --with-graph or similar. I think the naming is less critical at this point.

Do we know how many people currently use / reply on dump-package and/or its output format?

The command would then look like
swift package dump-package [--include-graph] [--exclude-targets] [--format text|json]

Once that works

  • Check if describe and show-dependencies can be replaced / deprecated / aliased
  • Decide if adding --format dot makes sense from a complexity perspective

It seems uninvasive to at least start with dump-package --graph, and then later once we have figured out how useful it is we can decide if we want to make a dump-package-graph to make the names nicer. I just don't like to proliferate top-level verbs.

Sounds fair enough

I used to until the package manager became directly linkable as a package itself. Its type‐safe Swift API is just so much nicer than a self‐built parser for an undocumented JSON data model. I have watched other tool providers make the same switch. I imagine that most of those who still read in dump-package write their tools in some other language like shell or ruby.

1 Like

I looked into this and implemented it such that

% swift package dump-package

will dump the root package(s)’s manifest (without resolving any dependencies), while

% swift package dump-package --graph

will resolve the dependencies and then output all manifests.

It will always output an array of manifest JSON, even if there’s only 1 element.

This seems to align well with the existing behavior and output format of dump-package — the main difference being that the existing output format is a JSON dictionary corresponding to the single root manifest. The new output is an array containing that entry.

Detailed Output
% swift package --package-path path/to/example-package-dealer dump-package
[
  {
    "cLanguageStandard" : null,
    "cxxLanguageStandard" : null,
    "dependencies" : [
      {
        "requirement" : {
          "range" : [
            {
              "lowerBound" : "3.0.0",
              "upperBound" : "4.0.0"
            }
          ]
        },
        "url" : "https:\/\/github.com\/apple\/example-package-deckofplayingcards.git"
      }
    ],
    "manifestVersion" : "4",
    "name" : "dealer",
    "pkgConfig" : null,
    "products" : [
      {
        "name" : "Dealer",
        "targets" : [
          "Dealer"
        ],
        "type" : {
          "executable" : null
        }
      }
    ],
    "providers" : null,
    "swiftLanguageVersions" : null,
    "targets" : [
      {
        "dependencies" : [
          {
            "byName" : [
              "DeckOfPlayingCards"
            ]
          }
        ],
        "exclude" : [

        ],
        "name" : "Dealer",
        "type" : "regular"
      }
    ]
  }
]

And with dependencies:

% swift package --package-path path/to/example-package-dealer dump-package --graph
[
  {
    "cLanguageStandard" : null,
    "cxxLanguageStandard" : null,
    "dependencies" : [
      {
        "requirement" : {
          "range" : [
            {
              "lowerBound" : "3.0.0",
              "upperBound" : "4.0.0"
            }
          ]
        },
        "url" : "https:\/\/github.com\/apple\/example-package-deckofplayingcards.git"
      }
    ],
    "manifestVersion" : "4",
    "name" : "dealer",
    "pkgConfig" : null,
    "products" : [
      {
        "name" : "Dealer",
        "targets" : [
          "Dealer"
        ],
        "type" : {
          "executable" : null
        }
      }
    ],
    "providers" : null,
    "swiftLanguageVersions" : null,
    "targets" : [
      {
        "dependencies" : [
          {
            "byName" : [
              "DeckOfPlayingCards"
            ]
          }
        ],
        "exclude" : [

        ],
        "name" : "Dealer",
        "type" : "regular"
      }
    ]
  },
  {
    "cLanguageStandard" : null,
    "cxxLanguageStandard" : null,
    "dependencies" : [
      {
        "requirement" : {
          "range" : [
            {
              "lowerBound" : "2.0.0",
              "upperBound" : "3.0.0"
            }
          ]
        },
        "url" : "https:\/\/github.com\/apple\/example-package-fisheryates.git"
      },
      {
        "requirement" : {
          "range" : [
            {
              "lowerBound" : "3.0.0",
              "upperBound" : "4.0.0"
            }
          ]
        },
        "url" : "https:\/\/github.com\/apple\/example-package-playingcard.git"
      }
    ],
    "manifestVersion" : "4",
    "name" : "DeckOfPlayingCards",
    "pkgConfig" : null,
    "products" : [
      {
        "name" : "DeckOfPlayingCards",
        "targets" : [
          "DeckOfPlayingCards"
        ],
        "type" : {
          "library" : [
            "automatic"
          ]
        }
      }
    ],
    "providers" : null,
    "swiftLanguageVersions" : null,
    "targets" : [
      {
        "dependencies" : [
          {
            "byName" : [
              "FisherYates"
            ]
          },
          {
            "byName" : [
              "PlayingCard"
            ]
          }
        ],
        "exclude" : [

        ],
        "name" : "DeckOfPlayingCards",
        "type" : "regular"
      },
      {
        "dependencies" : [
          {
            "byName" : [
              "DeckOfPlayingCards"
            ]
          }
        ],
        "exclude" : [

        ],
        "name" : "DeckOfPlayingCardsTests",
        "type" : "test"
      }
    ]
  },
  {
    "cLanguageStandard" : null,
    "cxxLanguageStandard" : null,
    "dependencies" : [

    ],
    "manifestVersion" : "4",
    "name" : "PlayingCard",
    "pkgConfig" : null,
    "products" : [
      {
        "name" : "PlayingCard",
        "targets" : [
          "PlayingCard"
        ],
        "type" : {
          "library" : [
            "automatic"
          ]
        }
      }
    ],
    "providers" : null,
    "swiftLanguageVersions" : null,
    "targets" : [
      {
        "dependencies" : [

        ],
        "exclude" : [

        ],
        "name" : "PlayingCard",
        "type" : "regular"
      },
      {
        "dependencies" : [
          {
            "byName" : [
              "PlayingCard"
            ]
          }
        ],
        "exclude" : [

        ],
        "name" : "PlayingCardTests",
        "type" : "test"
      }
    ]
  },
  {
    "cLanguageStandard" : null,
    "cxxLanguageStandard" : null,
    "dependencies" : [

    ],
    "manifestVersion" : "4",
    "name" : "FisherYates",
    "pkgConfig" : null,
    "products" : [
      {
        "name" : "FisherYates",
        "targets" : [
          "FisherYates"
        ],
        "type" : {
          "library" : [
            "automatic"
          ]
        }
      }
    ],
    "providers" : null,
    "swiftLanguageVersions" : null,
    "targets" : [
      {
        "dependencies" : [

        ],
        "exclude" : [

        ],
        "name" : "FisherYates",
        "type" : "regular"
      },
      {
        "dependencies" : [
          {
            "byName" : [
              "FisherYates"
            ]
          }
        ],
        "exclude" : [

        ],
        "name" : "FisherYatesTests",
        "type" : "test"
      }
    ]
  }
]

I think we should dump the Package object instead of Manifest as it contains more information. What do you think?

I did the manifest because that’s what the existing dump-package does. I’m fine either way, though.

I’ve updated it.

Without --graph, it still uses the Manifest to dump the JSON. If we were to use Package instead, we’d have to resolve dependencies (at least that’s my understanding, but I may be wrong here).

When using --graph, it will use the ResolvedPackage and dump that. Not that this is not a raw JSON dump — I’m trying to avoid needless repetition. E.g. reachableTargets and reachableProducts only list the name of these, since the targets and products are already listed in their respective package.

If this looks reasonable, I’ll move ahead and add a text output format to mirror the JSON output.

Detailed Output
% swift package --package-path path/to/example-package-dealer dump-package
[
  {
    "dependencies" : [
      {
        "requirement" : {
          "range" : [
            {
              "lowerBound" : "3.0.0",
              "upperBound" : "4.0.0"
            }
          ]
        },
        "url" : "https:\/\/github.com\/apple\/example-package-deckofplayingcards.git"
      }
    ],
    "manifestVersion" : "4",
    "name" : "dealer",
    "products" : [
      {
        "name" : "Dealer",
        "targets" : [
          "Dealer"
        ],
        "type" : {
          "executable" : null
        }
      }
    ],
    "targets" : [
      {
        "dependencies" : [
          {
            "byName" : [
              "DeckOfPlayingCards"
            ]
          }
        ],
        "exclude" : [

        ],
        "name" : "Dealer",
        "type" : "regular"
      }
    ]
  }
]

and

% swift package --package-path path/to/example-package-dealer dump-package --graph
{
  "packages" : [
    {
      "dependencies" : [
        {
          "name" : "DeckOfPlayingCards",
          "version" : "3.0.4"
        }
      ],
      "manifestVersion" : "4",
      "name" : "dealer",
      "products" : [
        {
          "executableModule" : "Dealer",
          "name" : "Dealer"
        }
      ],
      "targets" : [
        {
          "c99name" : "Dealer",
          "dependencies" : [
            {
              "name" : "DeckOfPlayingCards",
              "productName" : "DeckOfPlayingCards",
              "type" : "product"
            }
          ],
          "name" : "Dealer",
          "type" : "executable"
        }
      ]
    },
    {
      "dependencies" : [
        {
          "name" : "FisherYates",
          "version" : "2.0.5"
        },
        {
          "name" : "PlayingCard",
          "version" : "3.0.4"
        }
      ],
      "manifestVersion" : "4",
      "name" : "DeckOfPlayingCards",
      "products" : [
        {
          "linuxMainTarget" : "DeckOfPlayingCardsPackageTests",
          "name" : "DeckOfPlayingCardsPackageTests"
        },
        {
          "name" : "DeckOfPlayingCards"
        }
      ],
      "targets" : [
        {
          "c99name" : "DeckOfPlayingCards",
          "dependencies" : [
            {
              "name" : "FisherYates",
              "productName" : "FisherYates",
              "type" : "product"
            },
            {
              "name" : "PlayingCard",
              "productName" : "PlayingCard",
              "type" : "product"
            }
          ],
          "name" : "DeckOfPlayingCards",
          "type" : "library"
        },
        {
          "c99name" : "DeckOfPlayingCardsTests",
          "dependencies" : [
            {
              "name" : "DeckOfPlayingCards",
              "type" : "target"
            }
          ],
          "name" : "DeckOfPlayingCardsTests",
          "type" : "test"
        }
      ],
      "version" : "3.0.4"
    },
    {
      "dependencies" : [

      ],
      "manifestVersion" : "4",
      "name" : "PlayingCard",
      "products" : [
        {
          "linuxMainTarget" : "PlayingCardPackageTests",
          "name" : "PlayingCardPackageTests"
        },
        {
          "name" : "PlayingCard"
        }
      ],
      "targets" : [
        {
          "c99name" : "PlayingCard",
          "dependencies" : [

          ],
          "name" : "PlayingCard",
          "type" : "library"
        },
        {
          "c99name" : "PlayingCardTests",
          "dependencies" : [
            {
              "name" : "PlayingCard",
              "type" : "target"
            }
          ],
          "name" : "PlayingCardTests",
          "type" : "test"
        }
      ],
      "version" : "3.0.4"
    },
    {
      "dependencies" : [

      ],
      "manifestVersion" : "4",
      "name" : "FisherYates",
      "products" : [
        {
          "linuxMainTarget" : "FisherYatesPackageTests",
          "name" : "FisherYatesPackageTests"
        },
        {
          "name" : "FisherYates"
        }
      ],
      "targets" : [
        {
          "c99name" : "FisherYatesTests",
          "dependencies" : [
            {
              "name" : "FisherYates",
              "type" : "target"
            }
          ],
          "name" : "FisherYatesTests",
          "type" : "test"
        },
        {
          "c99name" : "FisherYates",
          "dependencies" : [

          ],
          "name" : "FisherYates",
          "type" : "library"
        }
      ],
      "version" : "2.0.5"
    }
  ],
  "reachableProducts" : [
    "DeckOfPlayingCards",
    "Dealer",
    "FisherYates",
    "PlayingCard"
  ],
  "reachableTargets" : [
    "FisherYates",
    "PlayingCard",
    "DeckOfPlayingCards",
    "Dealer"
  ],
  "rootPackages" : [
    "dealer"
  ]
}

I’ve reworked this. I’ve split all code related to outputting package information into 3 orthogonal concepts:

Mode: output information about the root(s) only vs. about the entire graph
Style: output verbosity brief or detailed
Format: output as JSON vs. text

This leads to a better separation of concerns. And it’s conceptually easier to understand. The 2 by 2 matrix of Mode vs. Style looks like this:

Root Graph
Brief package and its targets
— similar to current describe
package and its dependencies
— similar to current show-dependencies
Detailed (almost) all details about the package
— similar to current dump-package
(almost) all details about the package
and its dependencies and their targets
— not available in current swift package

With this approach the exact same information gets output for both JSON and text outputs — it’s just formatted differently. I’ve removed the flatlist output format — you can still get to it through swift package completion-tool list-dependencies, which makes for a better place for it to live at, IMHO.

Since 3 of the 4 squares in the above table match the current show-dependencies, dump-package, and describe, I’d opt for mapping all of them into the same code and deprecating 2 of the existing 3. Alternatively, we could keep them as shorthands.

There’s no .dot output. I’d be happy to add that back, and then I’d try to make it work for all 4 Style combinations listed above. It may be better to do that separately, though.

The above separation of concerns between Mode, Style, and Format is reflected in the code as well, which should make it easier to maintain and/or extend.


Below is the output for the example-package-dealer project. Note how the JSON and text output match.

% swift dump-package --type json --style brief --mode root
Output
[
  {
    "modules" : [
      {
        "c99name" : "Dealer",
        "moduleType" : "SwiftTarget",
        "name" : "Dealer",
        "path" : "\/Users\/deggert\/Projects\/example-package-dealer\/Sources\/Dealer",
        "sources" : [
          "main.swift"
        ],
        "type" : "executable"
      }
    ],
    "name" : "dealer",
    "path" : "\/Users\/deggert\/Projects\/example-package-dealer"
  }
]
% swift dump-package --type json --style brief --mode graph
Output
[
  {
    "dependencies" : [
      {
        "dependencies" : [
          {
            "dependencies" : [

            ],
            "name" : "FisherYates",
            "path" : "\/Users\/deggert\/Projects\/example-package-dealer\/.build\/checkouts\/example-package-fisheryates-42cbd8bd",
            "url" : "https:\/\/github.com\/apple\/example-package-fisheryates.git",
            "version" : "2.0.5"
          },
          {
            "dependencies" : [

            ],
            "name" : "PlayingCard",
            "path" : "\/Users\/deggert\/Projects\/example-package-dealer\/.build\/checkouts\/example-package-playingcard-bdaf050a",
            "url" : "https:\/\/github.com\/apple\/example-package-playingcard.git",
            "version" : "3.0.4"
          }
        ],
        "name" : "DeckOfPlayingCards",
        "path" : "\/Users\/deggert\/Projects\/example-package-dealer\/.build\/checkouts\/example-package-deckofplayingcards-7c0a2312",
        "url" : "https:\/\/github.com\/apple\/example-package-deckofplayingcards.git",
        "version" : "3.0.4"
      }
    ],
    "name" : "dealer",
    "path" : "\/Users\/deggert\/Projects\/example-package-dealer",
    "url" : "\/Users\/deggert\/Projects\/example-package-dealer",
    "version" : "unspecified"
  }
]
% swift dump-package --type json --style detailed --mode root
Output
[
  {
    "dependencies" : [
      {
        "requirement" : {
          "range" : [
            {
              "lowerBound" : "3.0.0",
              "upperBound" : "4.0.0"
            }
          ]
        },
        "url" : "https:\/\/github.com\/apple\/example-package-deckofplayingcards.git"
      }
    ],
    "manifestVersion" : "v4",
    "name" : "dealer",
    "products" : [
      {
        "name" : "Dealer",
        "targets" : [
          "Dealer"
        ],
        "type" : {
          "executable" : null
        }
      }
    ],
    "targets" : [
      {
        "dependencies" : [
          {
            "byName" : [
              "DeckOfPlayingCards"
            ]
          }
        ],
        "exclude" : [

        ],
        "name" : "Dealer",
        "type" : "regular"
      }
    ]
  }
]
% swift dump-package --type json --style detailed --mode graph
Output
{
  "packages" : [
    {
      "dependencies" : [
        {
          "name" : "FisherYates",
          "version" : "2.0.5"
        },
        {
          "name" : "PlayingCard",
          "version" : "3.0.4"
        }
      ],
      "manifestVersion" : "v4",
      "name" : "DeckOfPlayingCards",
      "products" : [
        {
          "name" : "DeckOfPlayingCards"
        },
        {
          "linuxMainTarget" : "DeckOfPlayingCardsPackageTests",
          "name" : "DeckOfPlayingCardsPackageTests"
        }
      ],
      "targets" : [
        {
          "c99name" : "DeckOfPlayingCards",
          "dependencies" : [
            {
              "name" : "FisherYates",
              "productName" : "FisherYates",
              "type" : "product"
            },
            {
              "name" : "PlayingCard",
              "productName" : "PlayingCard",
              "type" : "product"
            }
          ],
          "name" : "DeckOfPlayingCards",
          "type" : "library"
        },
        {
          "c99name" : "DeckOfPlayingCardsTests",
          "dependencies" : [
            {
              "name" : "DeckOfPlayingCards",
              "type" : "target"
            }
          ],
          "name" : "DeckOfPlayingCardsTests",
          "type" : "test"
        }
      ],
      "version" : "3.0.4"
    },
    {
      "dependencies" : [

      ],
      "manifestVersion" : "v4",
      "name" : "FisherYates",
      "products" : [
        {
          "name" : "FisherYates"
        },
        {
          "linuxMainTarget" : "FisherYatesPackageTests",
          "name" : "FisherYatesPackageTests"
        }
      ],
      "targets" : [
        {
          "c99name" : "FisherYates",
          "dependencies" : [

          ],
          "name" : "FisherYates",
          "type" : "library"
        },
        {
          "c99name" : "FisherYatesTests",
          "dependencies" : [
            {
              "name" : "FisherYates",
              "type" : "target"
            }
          ],
          "name" : "FisherYatesTests",
          "type" : "test"
        }
      ],
      "version" : "2.0.5"
    },
    {
      "dependencies" : [

      ],
      "manifestVersion" : "v4",
      "name" : "PlayingCard",
      "products" : [
        {
          "name" : "PlayingCard"
        },
        {
          "linuxMainTarget" : "PlayingCardPackageTests",
          "name" : "PlayingCardPackageTests"
        }
      ],
      "targets" : [
        {
          "c99name" : "PlayingCard",
          "dependencies" : [

          ],
          "name" : "PlayingCard",
          "type" : "library"
        },
        {
          "c99name" : "PlayingCardTests",
          "dependencies" : [
            {
              "name" : "PlayingCard",
              "type" : "target"
            }
          ],
          "name" : "PlayingCardTests",
          "type" : "test"
        }
      ],
      "version" : "3.0.4"
    },
    {
      "dependencies" : [
        {
          "name" : "DeckOfPlayingCards",
          "version" : "3.0.4"
        }
      ],
      "manifestVersion" : "v4",
      "name" : "dealer",
      "products" : [
        {
          "executableModule" : "Dealer",
          "name" : "Dealer"
        }
      ],
      "targets" : [
        {
          "c99name" : "Dealer",
          "dependencies" : [
            {
              "name" : "DeckOfPlayingCards",
              "productName" : "DeckOfPlayingCards",
              "type" : "product"
            }
          ],
          "name" : "Dealer",
          "type" : "executable"
        }
      ]
    }
  ],
  "reachableProducts" : [
    "Dealer",
    "DeckOfPlayingCards",
    "FisherYates",
    "PlayingCard"
  ],
  "reachableTargets" : [
    "Dealer",
    "DeckOfPlayingCards",
    "FisherYates",
    "PlayingCard"
  ],
  "rootPackages" : [
    "dealer"
  ]
}
% swift dump-package --type text --style brief --mode root
Output
Name: dealer
Path: /Users/deggert/Projects/example-package-dealer
Modules:
    Name: Dealer
    C99name: Dealer
    Type: executable
    Module type: SwiftTarget
    Path: /Users/deggert/Projects/example-package-dealer/Sources/Dealer
    Sources: main.swift
% swift dump-package --type text --style brief --mode graph
Output
Name: dealer
Url: /Users/deggert/Projects/example-package-dealer
Version: unspecified
Path: /Users/deggert/Projects/example-package-dealer
Dependencies:
    Name: DeckOfPlayingCards
    Url: https://github.com/apple/example-package-deckofplayingcards.git
    Version: 3.0.4
    Path: /Users/deggert/Projects/example-package-dealer/.build/checkouts/example-package-deckofplayingcards-7c0a2312
    Dependencies:
        Name: FisherYates
        Url: https://github.com/apple/example-package-fisheryates.git
        Version: 2.0.5
        Path: /Users/deggert/Projects/example-package-dealer/.build/checkouts/example-package-fisheryates-42cbd8bd
        Dependencies:
        
        Name: PlayingCard
        Url: https://github.com/apple/example-package-playingcard.git
        Version: 3.0.4
        Path: /Users/deggert/Projects/example-package-dealer/.build/checkouts/example-package-playingcard-bdaf050a
        Dependencies:
% swift dump-package --type text --style detailed --mode root
Output
Name: dealer
Manifest version: v4
Dependencies:
    Url: https://github.com/apple/example-package-deckofplayingcards.git
    Requirement:
        Range:
            Lower bound: 3.0.0
            Upper bound: 4.0.0
Products:
    Name: Dealer
    Targets: Dealer
    Type:
        Executable: 
Targets:
    Name: Dealer
    Exclude:
    Dependencies:
        By name: DeckOfPlayingCards
    Type: regular
% swift dump-package --type text --style detailed --mode graph
Output
Root packages: dealer
Packages:
    Name: DeckOfPlayingCards
    Version: 3.0.4
    Manifest version: v4
    Targets:
        Name: DeckOfPlayingCards
        C99name: DeckOfPlayingCards
        Type: library
        Dependencies:
            Type: product
            Name: FisherYates
            Product name: FisherYates
            
            Type: product
            Name: PlayingCard
            Product name: PlayingCard
        
        Name: DeckOfPlayingCardsTests
        C99name: DeckOfPlayingCardsTests
        Type: test
        Dependencies:
            Type: target
            Name: DeckOfPlayingCards
    Products:
        Name: DeckOfPlayingCards
        
        Name: DeckOfPlayingCardsPackageTests
        Linux main target: DeckOfPlayingCardsPackageTests
    Dependencies:
        Name: FisherYates
        Version: 2.0.5
        
        Name: PlayingCard
        Version: 3.0.4
    
    Name: FisherYates
    Version: 2.0.5
    Manifest version: v4
    Targets:
        Name: FisherYates
        C99name: FisherYates
        Type: library
        Dependencies:
        
        Name: FisherYatesTests
        C99name: FisherYatesTests
        Type: test
        Dependencies:
            Type: target
            Name: FisherYates
    Products:
        Name: FisherYates
        
        Name: FisherYatesPackageTests
        Linux main target: FisherYatesPackageTests
    Dependencies:
    
    Name: PlayingCard
    Version: 3.0.4
    Manifest version: v4
    Targets:
        Name: PlayingCard
        C99name: PlayingCard
        Type: library
        Dependencies:
        
        Name: PlayingCardTests
        C99name: PlayingCardTests
        Type: test
        Dependencies:
            Type: target
            Name: PlayingCard
    Products:
        Name: PlayingCard
        
        Name: PlayingCardPackageTests
        Linux main target: PlayingCardPackageTests
    Dependencies:
    
    Name: dealer
    Manifest version: v4
    Targets:
        Name: Dealer
        C99name: Dealer
        Type: executable
        Dependencies:
            Type: product
            Name: DeckOfPlayingCards
            Product name: DeckOfPlayingCards
    Products:
        Name: Dealer
        Executable module: Dealer
    Dependencies:
        Name: DeckOfPlayingCards
        Version: 3.0.4
Reachable targets:
    Dealer
    DeckOfPlayingCards
    FisherYates
    PlayingCard
Reachable products:
    Dealer
    DeckOfPlayingCards
    FisherYates
    PlayingCard
1 Like

I encountered the same problem as you did. That's why I created https://swiftdeps.com/ to address the issue. With this tool, you can visualize the graph of module dependencies within a package, between packages, or even embedded frameworks in an Xcode project. Furthermore, you can interact with the graph to enhance your experience.

@deggert I’d love to use this new feature of dump-package! Where is the implementation? I don’t see these command-line options in Swift 5.10.