本文を読み飛ばす

LSPにclangdを使ってPocketSDRのソースを読む

動機

VSCodeでPocketSDRのコードを読んでいる。 MSのC/C++拡張 (cpptools) は変数や関数のジャンプがやたらと遅い。 そこで、clangdを使うことにした。

手順

makefileの変更

makefileに直に書かれている make$(MAKE) に変更する。 サブモジュールのライブラリのmakefileも。

compile_commands.json の生成

PATHに C:msys64mingw64bin がある状態で、PowerShellやcmdで mingw32-make > build.log 2>&1 でmakefileを実行する。 (makeのログにあるパスがcygpathを経由せず、素のWindowsのパスとして出力されるようにする) 念のため -j は付けず、 make clean して実行するのが良いかもしれない (考えればわかる)。

compiledb --parse build.log --full-pathcompile_commands.json を生成する。

この際、コンパイラのフルパスはPATHで最初に解決されたものになることに注意。 実際に使ったコンパイラと一致しているか確認。

VSCodeのclasgd拡張で読み込み

settings.json--query-driver を指定する。 compiledbが出力するコンパイラのフルパスではgccやg++の拡張子が .EXE と大文字になることがある。 --query-driver に書いたパスが小文字だと検出されない(?)ようで、いろいろ考えるのが面倒だったためワイルドカードを用いた。 もしかしたら勘違いかもしれない。 また、余計なものが入る可能性があるため、地道に列挙しても良い。

"clangd.arguments": [
    "--query-driver=C:\\msys64\\mingw64\\bin\\g*",
    "--clang-tidy",
    "--log=verbose"
],

clangdが mingw64/bin をPATHに持つ環境で起動するようにする。 色々と方法はあるが、ここではGoでラッパーを書いてそれを呼び出すようにした (Goは未経験だがAIに頼んだらGoで出してきた) 。 なお、実行ファイルでないとエラーが出る。

ラッパーのスクリプト

package main

import (
    "os"
    "os/exec"
    "strings"
)

func main() {
    clangd := `C:\Program Files\LLVM\bin\clangd.exe`
    path := os.Getenv("PATH")
    add := `C:\msys64\mingw64\bin`
    if !strings.Contains(strings.ToLower(`;`+path+`;`), `;`+strings.ToLower(add)+`;`) {
        path = add + `;` + path
    }
    cmd := exec.Command(clangd, os.Args[1:]...)
    cmd.Env = append(os.Environ(), "PATH="+path)
    cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
    if err := cmd.Run(); err != nil {
        os.Exit(1)
    }
}

コンパイルコマンド

mkdir clangd_env
cd clangd_env
# コードを書いたら
go mod init example.com/claangd_env
go build -o clangd_env.exe clangd_env.go

settings.json

"clangd.path": "${workspaceFolder}/clangd_env/clangd_env.exe",

.clangd を書く。 必須なのは CompilationDatabase で、 compile_commands.json があるディレクトリを指定する。

CompileFlags:
  CompilationDatabase: PocketSDR/lib/build
  # BuiltinHeaders: QueryDriver
Index:
  Background: Build
Completion:
  HeaderInsertion: IWYU

補遺

各手順の理由は大部分を省略。 かなりclangd, clangd拡張, gccに (今回、筆者にとって) 都合の悪い仕様があったため、余裕があるとき [いつ?] に追加する。

感想

非常に大変だった。 ここまでたどり着くまでに10時間くらいかかってしまった。


そういえば、みちびき5号機が来月打ち上げられるそう。 成功を祈ります。