ノート

Windows で OpenJDK を CLion で読めない問題へのパッチ

Windows で OpenJDK のコードを CLion で読めるようにする Patch.java について。

OpenJDK の​コードを​ CLion で​読もうと​して​ make compile-commands を​実行すると,build/<構成名>/compile_commands.json が​生成されます。​ ところが,​これを​そのまま​ CLion に​読み込ませると,​環境に​よっては​プロジェクトが​真っ赤に​なり,​インクルードも​定義ジャンプも​およそ​愉快ではない​状態に​なります。

CLion の読み込みエラー

 この​記事では,​その​ compile_commands.json を​ CLion が​読みやすい​形へ​変換する​ために​ Patch.java を​書いたので,​紹介します。

使い方#

 make compile-commands が​終わった​あと,compile_commands.json が​生成された​ディレクトリへ​ Patch.java を​置き,​以下のように​実行します。

$ java Patch.java compile_commands.json

 既存の​ compile_commands.json は​上​書きされます。​ 元の​ファイルは​ compile_commands.json.old と​して​バック・アップされますから,​多少やらかしても​戻れます。

 出力先を​分けたい​場合は,​第 2 引数を​指定します。

$ java Patch.java compile_commands.json compile_commands.clion.json

 この​場合,​入力ファイルは​上​書きされず,​指定した​出力先に​パッチ済みの​ファイルが​作られます。

何が​問題なのか#

 compile_commands.json は,​ある​ソース・ファイルを​どの​コンパイラ・オプションで​コンパイルするかを​ IDE や​言語サーバへ​伝える​ための​ファイルです。​ OpenJDK 側でも​これを​生成できる​ため,​普通に​考えると​ CLion は​これを​読めば​よいはずです。

 しかし,​Windows 上の​ OpenJDK ビルドでは,​CLion が​うまく​処理できない​コマンド行が​混ざります。​ た​とえば,​空白を​含む Visual Studio の​パス,-pathmap:,​プリコンパイル済みヘッダ周りの​オプション,​結合された​ /I... 形式の​インクルード・パスなどです。

 コンパイラから​すれば​意味の​ある​指定でも,​CLion の​ Compilation Database と​して​食わせると,​そこで​詰まります。​ 結果と​して,​実際には​存在する​ヘッダが​見えなかったり,​コンパイラを​正しく​認識できなかったりします。

パッチが​やっている​こと#

 Patch.java は,​OpenJDK が​生成した​ compile_commands.json の​各エントリを​読み,​CLion が​扱いやすい​形へ​整えます。​ 大きくは​以下の​変換を​しています。

  • command 文字列を​ arguments 配列へ​変換する。
  • file の​パスを​ canonical path へ直す。
  • CLion が​扱いにくい -pathmap: 引数を​取り除く。
  • プリコンパイル済みヘッダ関連の​引数を​取り除く。
  • /Ipath や​ -Ipath を​ /I, path の​ 2 引数へ​分ける。
  • Windows の​絶対パスに​含まれる​余分な​バックスラッシュを​正規化する。
  • コンパイラの​パスに​空白が​含まれる​場合,​可能なら​短い​ 8.3 形式の​パスへ​変換する。

 要するに,​ビルド用の​ compile_commands.json から,​CLion が​読むための​ compile_commands.json へ​寄せる​処理です。​ ビルドその​ものを​正しく​する​ための​パッチではなく,​IDE に​読ませる​ための​ゴニョりです。

実行結果#

 実行すると,​どれくらい​変換したかが​表示されます。

Converted entries: 1234
Removed -pathmap args: 1234
Removed PCH args: 2468
Split include args: 9876
Normalized path args: 5432
Shortened compiler paths: 1234
Wrote: C:\path\to\jdk\build\windows-x86_64-server-release\compile_commands.json

 数字は​環境や​ビルド構成に​よって​変わります。​ Converted entries が​ 0 に​なっている​場合は,​対象の​ファイルを​間違えているか,​想定と​違う​形式の​ compile_commands.json を​渡している​可能性が​あります。

注意点#

 この​パッチは,​OpenJDK の​ make compile-commands が​生成する​ JSON を​対象に​しています。​ 一般の​ compile_commands.json を​万能に​直すものでは​ありません。

 また,compile_commands.json を​再生成した​場合は,​再度パッチを​当てる​必要が​あります。​ make clean を​した​あとなどに​「あれ,​また​真っ赤だな」と​なったら,​大抵​これです。

 な​お,​CLion 側の​表示で​以下のような​エラーが​残る​ことがあります。

Cannot determine compiler type by executable file: 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\Hostx64\x64\ml64.exe'

 ​これは​ ml64.exe 周りの​表示なので,​C/C++ の​コードを​読む上では​一旦​無視して​構いません。​ src/java.base/share/native/launcher/main.c や​ src/hotspot/share/prims/jni.cpp を​開き,​インクルード周りが​赤くなっていなければ,​概ね勝ちです。

参考文献#