以前の記事の内容を高速化してみた。
CONTENTS
ENVIRONMENTS
コードで
#!/bin/sh coverage_main() { if [ -z "$RUSTUP_HOME" ]; then RUSTUP_HOME="${HOME}/.rustup" fi local toolchain_dir local llvm_profdata local llvm_cov toolchain_dir="${RUSTUP_HOME}/toolchains" coverage_setup local target_dir local prof_dir local output_dir target_dir="target/debug/deps" prof_dir="target/coverage" output_dir="ui/public/dist/coverage/api" export RUSTFLAGS="-Zinstrument-coverage" export LLVM_PROFILE_FILE="${prof_dir}/prof-%p-%m.profraw" cargo +nightly test if [ "$?" != 0 ]; then coverage_cleanup exit 1 fi echo "generate coverage report..." rm -rf "${output_dir}" mkdir -p "${output_dir}" local prof_data prof_data="${prof_dir}/merged.prodata" find "${prof_dir}" -type f -name '*.profraw' | xargs $llvm_profdata merge -sparse -o "${prof_data}" if [ ! -f "${prof_data}" ]; then echo "failed to merge prof data" exit 1 fi local crate_name crate_name="$(cat Cargo.toml | grep name | head -1 | cut -d'"' -f2 | sed 's/-/_/g')" local ignore_regex ignore_regex='(\.cargo|rustc|^api/|/[xyz]_|/infra/|/(main|test|init|data|event|infra)\.rs)' local object_file local output_file for object_file in $(find "${target_dir}" -type f -perm -a+x -name "${crate_name}"'-*'); do output_file="${output_dir}/$(basename "${object_file}").info" $llvm_cov export "${object_file}" \ -Xdemangler=rustfilt \ -instr-profile="${prof_data}" \ --ignore-filename-regex="${ignore_regex}" \ --format=lcov >"${output_file}" if [ -z "$(cat "${output_file}")" ]; then rm -f "${output_file}" fi done grcov "${output_dir}" -t html -o "${output_dir}" coverage_cleanup coverage_check } coverage_setup() { llvm_profdata=$(find "${toolchain_dir}" -type f -name llvm-profdata | head -1) llvm_cov=$(find "${toolchain_dir}" -type f -name llvm-cov | head -1) if [ ! -x "${llvm_profdata}" ]; then echo "llvm-profdata not found" exit 1 fi if [ ! -x "${llvm_cov}" ]; then echo "llvm-cov not found" exit 1 fi } coverage_check() { local line_coverage line_coverage=$(grep abbr "${output_dir}/index.html" | head -1 | cut -d'>' -f 2 | cut -d'%' -f 1) case "${line_coverage}" in 100*) echo "OK; line coverage: ${line_coverage}" ;; *) echo "NG; line coverage: ${line_coverage} < 100%" exit 1 ;; esac } coverage_cleanup() { echo "clean up profile files" rm -rf "${prof_dir}" } coverage_main
カバレッジは、grcov
ではなく、この Qiita の記事を参考にして llvm-cov
で取ることにした。
llvm-cov
と llvm-profdata
にはパスが通っていないので、まずこのコマンドを見つけることから始まる。
テストをして llvm-profdata
でマージしたら、カバレッジレポートを作成する。
llvm-cov
が要求する object ファイルは target ディレクトリにクレート名のファイルとして作成されるので、これをとってくる。
カバレッジレポートは lcov 形式で生成し、これを grcov
で整形する。
grcov
でカバレッジレポートを作成すると妙に時間がかかる。
すべての object ファイルのカバレッジをとっている雰囲気を感じる。
grcov のインストール
下記スクリプトで grcov
の最新版をダウンロードする。
#!/bin/sh setup_grcov() { local version version=$( curl --silent "https://api.github.com/repos/mozilla/grcov/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/' ) curl -sSL https://github.com/mozilla/grcov/releases/download/v${version}/grcov-linux-x86_64.tar.bz2 > tmp/grcov.tar.bz2 tar -xvjf tmp/grcov.tar.bz2 mv grcov ${CARGO_HOME}/bin } setup_grcov
cargo install するとソースからコンパイルするので時間がかかる。 バイナリが手に入ればいいので、ダウンロードでいい。
まとめ
rust のカバレッジレポート作成を高速化してみた。
grcov
のコンパイルとカバレッジレポートの作成に特に時間がかかっていたので、ここを改善してみた。