`(blog ,garaemon)

ポップカルチャーを摂取して、コードを吐き出す機械

catkin toolsでcompile_commands.jsonを生成する

ROSのパッケージをビルドするときにcatkin tools (catkin_makeではなくてcatkinコマンド)を利用してcompile_commands.jsonを生成するために、シェル関数を~/.bashrcとか~/.zshrcに定義しておくと便利。

開発時は定期的に気が向いたら実行する。

compile_commands.jsonはclang-tidy走らせたり, cqueryのようなソースコード編集時にエディタで補完を助けてくれるlspサーバが利用するファイル。 コンパイル時に実行されるコマンドなどが入っている.

このシェル関数でやっていることは以下の3点

  1. catkinのcmakeの引数に-DCMAKE_EXPORT_COMPILE_COMMANDS=ONが入っていなかったら追加する
  2. catkin buildの実行
  3. catkin workspaceのbuildディレクトリ以下にできたcompile_commands.jsonソースコード側のパッケージのトップディレクトリにシンボリックリンクを貼る.
function catkin-compile-commands-json() {
    local catkin_ws=$(echo $CMAKE_PREFIX_PATH | cut -d: -f1)/..
    # Verify catkin cmake args contains -DCMAKE_EXPORT_COMPILE_COMMANDS=ON.
    # If the arguments does not include the option, add to cmake args.
    (cd "${catkin_ws}" && catkin config | grep -- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON >/dev/null)
    local catkin_config_contains_compile_commands=$?
    if [ $catkin_config_contains_compile_commands -ne 0 ]; then
        echo catkin config does not include -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
        (
            cd "${catkin_ws}" &&
                catkin config -a --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
        )
    fi
    # Run catkin build in order to run cmake and generate compile_commands.json
    (cd "${catkin_ws}" && catkin build)
    # Find compile_commands.json in build directory and create symlink to the top of the package
    # directories.
    local package_directories=$(find "${catkin_ws}/src" -name package.xml | xargs -n 1 dirname)
    for package_dir in $(echo $package_directories); do
        local package=$(echo $package_dir | xargs -n 1 basename)
        (
            cd "${catkin_ws}"
            if [ -e ${catkin_ws}/build/$package/compile_commands.json ]; then
                ln -sf ${catkin_ws}/build/$package/compile_commands.json \
                    $(rospack find $package)/compile_commands.json
            fi
        )
    done
}

compile_commands.jsonシンボリックリンクがパッケージのトップディレクトリにできてしまうので, .gitignoreなどでgitの対象から外してあげるのとセットで運用している。