How do you inspect a package and its dependency graph from the command line?
Predict first
What do describe, show-dependencies and dump-package report for a small app with a local dependency?
// === run.sh ===
export GIT_AUTHOR_NAME=t GIT_AUTHOR_EMAIL=t@t GIT_COMMITTER_NAME=t GIT_COMMITTER_EMAIL=t@t
W=$(mktemp -d); cd $W
mkdir -p Lib/Sources/Lib App/Sources/App App/Tests/AppTests
cat > Lib/Package.swift <<'E'
// swift-tools-version: 6.0
import PackageDescription
let package = Package(name: "Lib", products: [.library(name: "Lib", targets: ["Lib"])], targets: [.target(name: "Lib")])
E
echo 'public let v = 1' > Lib/Sources/Lib/V.swift
cat > App/Package.swift <<'E'
// swift-tools-version: 6.0
import PackageDescription
let package = Package(name: "App", dependencies: [.package(path: "../Lib")],
targets: [.executableTarget(name: "App", dependencies: [.product(name: "Lib", package: "Lib")]),
.testTarget(name: "AppTests", dependencies: ["App"])])
E
echo 'import Lib' > App/Sources/App/main.swift
echo 'import Testing' > App/Tests/AppTests/T.swift
cd App
echo "targets: $(swift package describe --type json | python3 -c 'import json,sys; print(sorted((t["name"], t["type"]) for t in json.load(sys.stdin)["targets"]))')"
echo "dependencies: $(swift package show-dependencies --format json | python3 -c 'import json,sys; print([d["name"] for d in json.load(sys.stdin)["dependencies"]])')"
echo "manifest keys include: $(swift package dump-package | python3 -c 'import json,sys; d=json.load(sys.stdin); print([k for k in ("name","platforms","toolsVersion") if k in d])')"
- targets (App, executable) and (AppTests, test), dependency lib, manifest keys name/platforms/toolsVersion
- only the root target
- no output until the package is built
Mental model. These commands are the package’s X-ray: the manifest is what the author wrote, describe is what the build system understood.
Three read-only commands answer most “what does this package actually declare?” questions without opening Xcode. swift package describe --type json prints the evaluated manifest as seen by the build: targets with their type (library, executable, test), sources, products and platforms. swift package show-dependencies prints the resolved dependency tree (--format json for tooling), including each package’s resolved version or path. swift package dump-package prints the manifest’s raw JSON, including keys such as toolsVersion, platforms, targets and, in recent versions, traits. In the check, a small app with a local dependency reports its targets as App (executable) and AppTests (test), the dependency name Lib, and the expected manifest keys.
Why use them: as CI assertions (fail the build if a forbidden dependency appears, or if a target gains an unexpected dependency, which is how a layered module graph is kept honest, Q368), to generate a graph picture or an impact list for “affected builds” (Q373), to debug a conflict (Q619), and to audit third-party licences and sizes. Because the JSON is stable and scriptable, a 20-line script over describe can enforce architecture rules (“feature modules never depend on each other”) much more cheaply than code review. Limits: they describe the package graph, not an Xcode project’s targets (for those use xcodebuild -list or the project file), and they evaluate the manifest, so they need a working toolchain and sometimes network access to resolve remote dependencies first.
These commands read the manifest and graph without compiling anything.
Common traps
- Parsing
Package.swiftwith a regex. It is Swift code and can compute its contents; ask SwiftPM to evaluate it. - Expecting these to cover Xcode project targets. They only know SwiftPM packages.
They might follow up with
- How do I find which target imports which? The graph is in
describe; actualimportlines need a source scan, and a check of the two catches undeclared dependencies. - Can I get a visual graph? Convert the JSON to Graphviz DOT with a short script.
Related questions
- 16.7.3 Two dependencies need incompatible versions of a third. What does the resolver say, and how do you get out?
- 16.1.1 What are targets, products and modules in a Swift package, and what does a first Package.swift look like?
- 16.3.2 Why must the module dependency graph be acyclic, how do you layer it, and what does its shape do to build…
- 16.6.1 A CI pipeline takes hours on a large modular app. How do you analyse and cut it: affected builds, caching…
← How do package mirrors work, and when do you use one for a company or…