0
0

Gradle: タスクの依存関係の図を描く(Graphviz 使用)

Posted at

lr.png

タスク間の依存関係を出力してくれる Gradle プラグインはあるようなのですが、木じゃなくてグラフ(DAG)で見たかったり、プラグイン使わなくても済むならそれでもいいな……みたいな気分があって自前で書いてみました。

Gradle 8.9 で確認しました。

(他所で書いていたものを引っ越してきました。元の公開日は 2024-07-28 です。)

手順

(1) build.gradle に以下を追記

def generateDotSrc(tasks, idMap, edges) {
  def nodePart = ""

  tasks.each { task ->
    def id = idMap[task]
    def style = ""
    if (task.getActions().size == 0) {
      style = "dashed"
    }
    def label = task.getName()
    // def label = "${task.getProject().getName()}\\n${task.getName()}"
    nodePart += """  ${id} [ label = "${label}"; style = "${style}"; ];""" + "\n"
  }

  def edgePart = ""

  edges.each { taskFrom, taskTo ->
    def idFrom = idMap[taskFrom]
    def idTo = idMap[taskTo]
    edgePart += "  ${idFrom} -> ${idTo};" + "\n"
  }

  """
digraph {
  graph [
    rankdir = LR; // 左 → 右の向きに配置
  ];
  node [
    fontname = "monospace";
  ];

  ${nodePart}

  ${edgePart}
}
  """
}

gradle.taskGraph.whenReady { taskExecutionGraph ->
  def tasks = taskExecutionGraph.getAllTasks()
  // .findAll { task -> task.getProject().getName() == "..." } // 必要に応じて

  def edges = []
  tasks.each { taskFrom ->
    taskExecutionGraph.getDependencies(taskFrom).each { taskTo ->
      edges << [taskFrom, taskTo]
    }
  }

  def idMap = [:] // task => node id
  tasks.eachWithIndex { task, i ->
    idMap[task] = "n${i}"
  }

  def dotSrc = generateDotSrc(tasks, idMap, edges)
  // println dotSrc
  file("task_graph.dot").text = dotSrc
}

(2) 実行して Graphviz 用のコードを出力

gradle {タスク名} --dry-run

  # 例
gradle build --dry-run
  # → task_graph.dot に出力される
  • 実際にタスクを実行する必要はなくて図が欲しいだけなので --dry-run を付けて実行する
  • タスクが実行されてもよいなら --dry-run なしでもいい

(3) Graphviz で画像を生成

dot -Tsvg task_graph.dot > task_graph.svg

lr.png

こういう図ができあがります。枠が破線になっているのはアクションを持たない集約用のタスク。

rl.png

依存先が左に来るようにしたもの。Gradle のドキュメントで見かけるのはこっちのスタイルですね。

メモ

gradle.taskGraph.whenReady { taskExecutionGraph ->
  taskExecutionGraph.getAllTasks()
}

でタスクの一覧が取得できるのと、

taskExecutionGraph.getDependencies(taskFrom)

で各タスクの依存先タスクを取得できるところがポイント。グラフを描くのに必要な情報はこれで揃う。

なので、たとえば build.gradle ではノード・エッジの情報を抜き出して出力するところだけ行って残りは別のプログラムに任せる作りにすれば、 build.gradle 側の責務をより小さくできる。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0