[Ubuntu 18.04] PlantUMLがクラス図で引く線が必要以上に長いときの対処法


はじめに

UMLや簡単なフローチャートなんかを書くときは、Chromeの拡張であるPlantUML Viewer(リンク切れ)を使っていました。リアルタイムでプレビューを確認しながら作業できたので、とても便利だったんですよね。

しかし現在は拡張じたいが削除されてしまい、使うことができません。

そこでやむをえずローカルにPlantUMLをインストールして適当なクラス図を書いてみたところ、↓のような画像が出力されました。なんかレイアウトがおかしいな…異様に線長くね?

さすがにこれは見づらいなあと思ったものの、原因を調べるのが面倒なのでしばらくはブラウザでPlantUML Serverを開いて作業していましたが、ずっとこれを使い続けるのは不便!これでは常用はできないので、調べてみた記録です。

環境

後述しますが、おそらくUbuntu 18.04 ~ Ubuntu 19.10の間でこの現象が発生すると思います。

Ubuntu 20.04ではこの現象は起きません。

まず普通にインストールして使ってみる

aptにパッケージがあるので、これ一行でPlantUMLの導入はすんでしまいます。

sudo apt -y install plantuml

そして試しに動かしてみたら、↑に貼った画像のような有様でして…。

線がやたら長くなってしまう原因

公式HPに次のようにありました:

Test your GraphViz installation

Important note about version

PlantUML should be working with any version of Graphviz, starting with 2.26.3

The following versions have been tested, and are known to work:

  • 2.26.3
  • 2.28
  • 2.30.1
  • 2.34
  • 2.36
  • 2.38

The following version is known to have a lot of issues with PlantUML, so please do not use it:

  • 2.40.1

PlantUMLは、シーケンス図など以外はGraphvizを使ってUMLを描画します。公式の記述によると、Graphviz2.40.1は不具合が多数あるので使っちゃダメなんだそうです。

Graphvizは、前項でPlantUMLをインストールするときに、一緒にインストールされています。

まさかと思い、インストールされたGraphvizのバージョンを確認すると、

java -jar /usr/share/plantuml/plantuml.jar -testdot

# => The environment variable GRAPHVIZ_DOT has not been set
#    Dot executable is /usr/bin/dot
#    Dot version: dot - graphviz version 2.40.1 (20161225.0304)
#    Installation seems OK. File generation OK

ばっちり2.40.1を使っていました。ということで、どうやら原因はPlantUMLではなく、Graphvizにあったようでした。

PlantUMLのフォーラムにも同じ質問があがっており(Possible bug with relation in rectangle? (screenshot) - PlantUML Q&A)、Graphviz2.38を使えば間違いなさそうに書いてあります。

解決策:Graphvizをビルド

フォーラムや公式の説明を見る限りだとGraphvizの2.38を使えば間違いないようなんですが、2020/05/24現在、最新の安定版はすでに2.44になっていて、今からけっこう古くなった2.38を入れるのもなあ、、、と思い、この現象が直っていることを祈りつつ、とりあえず最新版をビルドしてみることにしました。

GitLabGraphviz公式からソースコードをダウンロードし、ビルドします。

curl -LO https://www2.graphviz.org/Packages/stable/portable_source/graphviz-2.44.0.tar.gz
tar xvzf graphviz-2.44.0.tar.gz
cd graphviz-2.44.0
./configure
make
sudo make install

スムーズにいけば、Graphvizがビルドされてインストールできます。

私の環境では問題なくビルドできましたが、足りないパッケージがあって途中でエラーになった場合は、おそらく次のようにすることでビルドに必要なパッケージをインストールできると思います。

sudo apt build-dep graphviz

インストール後、バージョンを確認。

java -jar /usr/share/plantuml/plantuml.jar -testdot

# => The environment variable GRAPHVIZ_DOT has not been set
#    Dot executable is /usr/bin/dot
#    Dot version: dot - graphviz version 2.44.0 (20200408.0750)
#    Installation seems OK. File generation OK

ちゃんとGraphviz2.44がインストールできています。

さっそく冒頭のソースからUMLを再生成。

線が短くなってる!直った!!

この現象が起きるUbuntuのバージョン

試しにUbuntu 20.04でもaptでPlantUMLをインストールして使ってみたところ、この現象は起こりませんでした。

aptで配布されているGraphvizのバージョンはUbuntu Package Search Results -- graphvizによると、

xenial (16.04LTS) (graphics): rich set of graph drawing tools
2.38.0-12ubuntu2: amd64 arm64 armhf i386 powerpc ppc64el s390x
xenial-updates (graphics): rich set of graph drawing tools
2.38.0-12ubuntu2.1: amd64 arm64 armhf i386 powerpc ppc64el s390x
bionic (18.04LTS) (graphics): rich set of graph drawing tools [universe]
2.40.1-2: amd64 arm64 armhf i386 ppc64el s390x
eoan (19.10) (graphics): rich set of graph drawing tools [universe]
2.40.1-7build1: amd64 arm64 armhf i386 ppc64el s390x
focal (20.04LTS) (graphics): rich set of graph drawing tools [universe]
2.42.2-3build2: amd64 arm64 armhf i386 ppc64el s390x

となっており、18.04以前は2.38、20.04以降は2.42がインストールされるためこの現象は起きないようです。2.41はaptでインストールされることがないバージョンなので正しく動作するのかはわかりませんが、とりあえずGraphviz2.42以降をインストールしておけば問題ないみたいです。

おまけ : VimでPlantUML

ググれば他の方の詳しい記事がたくさんヒットしますが、私がVimでPlantUMLを書くときの設定をご紹介します。

私は仮想マシン上でVimを立ち上げてUMLを書いてSVGに書き出し、ホストマシンで立ち上げたブラウザからそれを見る、という書き方をしています。リアルタイムプレビューやファイル更新を検知した自動リロードなんかはできない状況なので、PlantUMLの変換の呼出しとブラウザのリロードは手動でおこなっています。

ファイル保存時に自動でSVGに変換する仕組みにしたい場合は、次のように書けます(拡張子は.puにしています)。

" 同期的に実行
autocmd BufWritePost *.pu !java -jar /usr/share/plantuml/plantuml.jar -Djava.awt.headless=true -tsvg %
" バックグラウンドで非同期に実行(要dispatch.vim)
autocmd BufWritePost *.pu Dispatch java -jar /usr/share/plantuml/plantuml.jar -Djava.awt.headless=true -tsvg %

上のコマンドだとファイルを保存するたびに変換が終わるまで待たされるので、dispatch.vimをインストールして下のように書くと、非同期に変換をおこなえます。

私は保存するたびに変換が走るのはちょっとうっとおしいと感じたので、plantuml-syntaxvim-quickrunを入れて次のようにvim-quickrunを設定し、変換したいときに<Leader>rで呼出す、というやり方にしました。

let g:quickrun_config = {
\   'plantuml': {
\       'exec':      'java -jar /usr/share/plantuml/plantuml.jar -Djava.awt.headless=true -tsvg %s',
\       'outputter': 'message'
\   }
\}

上記の方法のいずれにおいても、コマンド実行後は{保存したファイル名}.svgがカレントディレクトリに生成されます。