Depm: Go 言語用モジュール依存関係可視化ツール

no extension

spiegel-im-spiegel/depmGo言語のパッケージまたはモジュール間の依存関係を可視化するコマンドラインツールである。 以下のように依存関係を図にすることも可能である。

以降で spiegel-im-spiegel/depm について簡単に紹介する。

check vulns lint status GitHub license GitHub release

簡単な使い方

-h オプションで簡単な使い方が表示される。

$ depm -h
Visualize depndency packages and modules.

Usage:
  depm [flags]
  depm [command]

Available Commands:
  help        Help about any command
  list        list modules
  module      analyze depndency modules
  package     analyze depndency packages
  version     print the version number

Flags:
      --cgo-enabled string   set CGO_ENABLED environment variable
      --debug                for debug
      --goarch string        set GOARCH environment variable
      --goos string          set GOOS environment variable
  -h, --help                 help for depm

Use "depm [command] --help" for more information about a command.

では,コマンドごとに見ていく。

パッケージ間の依存関係を調べる

depm package コマンドはパッケージ単位で依存関係を調べて結果を出力する。

$ depm package -h
analyze depndency packages.

Usage:
  depm package [flags] [package import path]

Aliases:
  package, pkg, p

Flags:
      --dot                 output by DOT language
      --dot-config string   config file for DOT language
  -h, --help                help for package
  -i, --include-internal    include internal packages
  -s, --include-standard    include standard Go library

Global Flags:
      --cgo-enabled string   set CGO_ENABLED environment variable
      --debug                for debug
      --goarch string        set GOARCH environment variable
      --goos string          set GOOS environment variable

github.com/spiegel-im-spiegel/depm パッケージを調べる場合は以下のコマンドラインとなる。

$ depm package github.com/spiegel-im-spiegel/depm | jq .
[
  {
    "Package": {
      "ImportPath": "github.com/spf13/cobra",
      "Module": {
        "Path": "github.com/spf13/cobra",
        "Version": "v1.1.1"
      }
    },
    "Deps": [
      {
        "ImportPath": "github.com/spf13/pflag",
        "Module": {
          "Path": "github.com/spf13/pflag",
          "Version": "v1.0.5"
        }
      }
    ]
  },
...

出力は JSON 形式なので jq コマンド等で加工可能である。 JSON 出力の構造は以下の構造体 nodeJSON の配列で表される。

type nodeJSON struct {
	Package *packageJSON
	Deps    []*packageJSON `json:",omitempty"`
}
type packageJSON struct {
	ImportPath string
	Internal   bool        `json:",omitempty"`
	CGO        bool        `json:",omitempty"`
	Unsafe     bool        `json:",omitempty"`
	Module     *moduleJSON `json:",omitempty"`
}
type moduleJSON struct {
	Path    string `json:",omitempty"`
	Version string `json:",omitempty"`
}

CGO に依存するパッケージは CGO フラグが true になる。 同様に unsafe を使っているパッケージでも Unsafetrue になる。 また -i オプションを付けてコマンドを起動すると internal パッケージも結果に含まれるが,この場合は Internal フラグが true になる。

たとえば有名な github.com/mattn/go-sqlite3 パッケージなら

$ depm package "github.com/mattn/go-sqlite3" | jq .
[
  {
    "Package": {
      "ImportPath": "github.com/mattn/go-sqlite3",
      "CGO": true,
      "Unsafe": true,
      "Module": {
        "Path": "github.com/mattn/go-sqlite3",
        "Version": "v1.14.4"
      }
    }
  }
]

のようになる。

--dot オプションで DOT 言語形式の出力にもできるため Graphviz の dot コマンドを使って図に変換することができる。

$ depm package --dot github.com/spiegel-im-spiegel/depm | dot -Tpng -o output1.png

実行結果はこんな感じ。

output1.png
output1.png

図の node と edge の属性については DOT 言語の仕様に従って簡単な装飾ができる。 TOML 形式で

[node]
  fontname = "Inconsolata"
[edge]
  color = "red"

のような設定ファイルを作って

$ depm package --dot --dot-config sample.toml "github.com/spiegel-im-spiegel/depm" | dot -Tpng -o output2.png
output2.png
output2.png

のようにできる。

パッケージのインポート・パスを省略すると,カレント・ディレクトリのパッケージを捜査する(go list コマンドで all を指定したときと同じ動作)。

モジュール間の依存関係を調べる

depm module コマンドはモジュール単位で依存関係を調べて結果を出力する。

$ depm module -h
analyze depndency modules.

Usage:
  depm module [flags] [package import path]

Aliases:
  module, mod, m

Flags:
  -u, --check-update        check updating module
      --dot                 output by DOT language
      --dot-config string   config file for DOT language
  -h, --help                help for module
  -i, --include-internal    include internal packages

Global Flags:
      --cgo-enabled string   set CGO_ENABLED environment variable
      --debug                for debug
      --goarch string        set GOARCH environment variable
      --goos string          set GOOS environment variable

$ depm module "github.com/spiegel-im-spiegel/depm" | jq .
[
  {
    "Module": {
      "Path": "github.com/spf13/cobra@v1.1.1",
      "Packages": [
        "github.com/spf13/cobra"
      ]
    },
    "Deps": [
      {
        "Path": "github.com/spf13/pflag@v1.0.5",
        "Packages": [
          "github.com/spf13/pflag"
        ]
      }
    ]
  },
...

出力は同じく JSON 形式で,以下の構造体 nodeJSON の配列で表される。

type nodeJSON struct {
	Module *moduleJSON
	Deps   []*moduleJSON `json:",omitempty"`
}
type moduleJSON struct {
	Path     string
	Replace  string   `json:",omitempty"`
	Latest   string   `json:",omitempty"`
	Main     bool     `json:",omitempty"`
	CGO      bool     `json:",omitempty"`
	Unsafe   bool     `json:",omitempty"`
	Packages []string `json:",omitempty"`
}

CGO や unsafe パッケージに関するフラグは depm package コマンドのときと同様である。 -u オプションを付けると,新しいバージョンのモジュールがある場合に Latest に情報がセットされる。

depm packageコマンドのときと同じく-dot` オプションで DOT 言語形式の出力にできる。

$ depm module --dot --dot-config sample.toml "github.com/spiegel-im-spiegel/depm" | dot -Tpng -o output3.png
output3.png
output3.png

パッケージのインポート・パスを省略すると,カレント・ディレクトリのパッケージを捜査する。 go list -m コマンドで all を指定したときと同じ動作だが,実際にはリンクしない形式的な依存モジュールは出力されない。 基本的にコード内の import に基づく依存関係のみ表示される。

モジュールの列挙

depm list コマンドは go list -m コマンドと同じ形式でモジュールの列挙を行う。

$ depm list -h
list modules, compatible 'go list -m' command

Usage:
  depm list [flags] [package import path]

Aliases:
  list, lst, l

Flags:
  -u, --check-update   check updating module
  -h, --help           help for list
  -j, --json           output by JSON format

Global Flags:
      --cgo-enabled string   set CGO_ENABLED environment variable
      --debug                for debug
      --goarch string        set GOARCH environment variable
      --goos string          set GOOS environment variable

$ depm list "github.com/spiegel-im-spiegel/depm"
github.com/BurntSushi/toml v0.3.1
github.com/emicklei/dot v0.15.0
github.com/spf13/cobra v1.1.1
github.com/spf13/pflag v1.0.5
github.com/spiegel-im-spiegel/depm v0.3.0
github.com/spiegel-im-spiegel/errs v1.0.2
github.com/spiegel-im-spiegel/gocli v0.10.3
golang.org/x/mod v0.3.0
golang.org/x/net v0.0.0-20201021035429-f5854403a974
golang.org/x/tools v0.0.0-20201105220310-78b158585360
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1

go list -m コマンドでは実際にはリンクしない形式上の依存モジュールまで表示してしまうが, depm list コマンドは基本的にコード内の import に基づく依存関係のみ表示されるため,最小限のリストに抑えられる。

-u オプションを付けると go list -m -u と同等の出力にできる。

$ depm list -u "github.com/spiegel-im-spiegel/depm"
github.com/BurntSushi/toml v0.3.1
github.com/emicklei/dot v0.15.0
github.com/spf13/cobra v1.1.1
github.com/spf13/pflag v1.0.5
github.com/spiegel-im-spiegel/depm v0.3.0
github.com/spiegel-im-spiegel/errs v1.0.2
github.com/spiegel-im-spiegel/gocli v0.10.3
golang.org/x/mod v0.3.0
golang.org/x/net v0.0.0-20201021035429-f5854403a974 [v0.0.0-20201031054903-ff519b6c9102]
golang.org/x/tools v0.0.0-20201105220310-78b158585360
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1

-j オプションを付けると go list -m -json と同等の JSON 出力にできる。

$ depm list -j "github.com/spiegel-im-spiegel/depm"
{
	"Path": "github.com/BurntSushi/toml",
	"Version": "v0.3.1",
	"Time": "2018-08-15T10:47:33Z",
	"Indirect": true,
	"Dir": "/home/spiegel/go/pkg/mod/github.com/!burnt!sushi/toml@v0.3.1",
	"GoMod": "/home/spiegel/go/pkg/mod/cache/download/github.com/!burnt!sushi/toml/@v/v0.3.1.mod"
}
{
	"Path": "github.com/emicklei/dot",
	"Version": "v0.15.0",
	"Time": "2020-10-30T08:43:19Z",
	"Indirect": true,
	"Dir": "/home/spiegel/go/pkg/mod/github.com/emicklei/dot@v0.15.0",
	"GoMod": "/home/spiegel/go/pkg/mod/cache/download/github.com/emicklei/dot/@v/v0.15.0.mod",
	"GoVersion": "1.13"
}
...

go list -m コマンドに比べると遅くなりがちなのが欠点だが,他のツールと組み合わせることを考えると使い勝手はさほど悪くないと思う。

参考文献

photo
プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
Alan A.A. Donovan (著), Brian W. Kernighan (著), 柴田 芳樹 (翻訳)
丸善出版 2016-06-20
単行本(ソフトカバー)
4621300253 (ASIN), 9784621300251 (EAN), 4621300253 (ISBN), 9784621300251 (ISBN)
評価     

著者のひとりは(あの「バイブル」とも呼ばれる)通称 “K&R” の K のほうである。この本は Go 言語の教科書と言ってもいいだろう。

reviewed by Spiegel on 2016-07-13 (powered by PA-APIv5)