BazelとGoogleTestの連携

2020/03/07

BAZEL C/C++ Googleサービス Linux RandomGrid Ubuntu 技術

t f B! P L

お楽しみ!BazelとGoogleTestの連携

や〜、や〜っとたどりついた〜

長かった、いや、サンプルプログラムとか途中で社内向けに作っていたので、今日はあまり作業時間が取れていないのですよ。
とはいえ来週からサーバの再構築を行わなければならないので、この辺の内容も今日中には社内マニュアルに載せないといけません。サンプルコード付きで。

というわけでその一部。

マニュアルをDa★Boが独断と偏見と根性と必中と魂と閃きと熱血で翻訳した記事に入っていきましょう。

ご利用は計画的に

外部のライブラリを利用する 

自分のワークスペース内の関数を抜き出しテスト実施するために、GoogleTestをダウンロードして実行可能にしてみましょう。
まず WORKSPACE ファイルに以下のような記述を追加します。
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "gtest",
    url = "https://github.com/google/googletest/archive/release-1.7.0.zip",
    sha256 = "b58cb7547a28b2c718d1e38aee18a3659c9e3ff52440297e965f5edffe34b6d0",
    build_file = "@//:gtest.BUILD",
)
テスト対象のパッケージにBUILDファイルを配置してある場合は build_file 属性の設定は省略できます。
GoogleTestをコンパイルするためのBUILDファイルを作成する場合、GoogleTestは cc_library ルールに記載すべき特別な要件がいくつか必要になります。

  • googletest-release-1.7.0/src/gtest-all.cc ファイルをコンパイル対象から除外する必要があります。除外せずにコンパイルを実行すると、シンボルの重複が発生しリンクエラーを起こします。 
  • GoogleTest関連のヘッダが必要ですので、googletest-release-1.7.0/include/ 下をインクルードディレクトリに追加します。(gtest/gtest.hのことね)
  • GoogleTestには pthread オプションが必要であるため、linkopt属性にこれを追加します。←copt に -lpthread ではだめぽ。
これらの条件を記載すると、最終的に以下のようなルールが出来ます。
cc_library(
    name = "main",
    srcs = glob(
        ["googletest-release-1.7.0/src/*.cc"],
        exclude = ["googletest-release-1.7.0/src/gtest-all.cc"]
    ),
    hdrs = glob([
        "googletest-release-1.7.0/include/**/*.h",
        "googletest-release-1.7.0/src/*.h"
    ]),
    copts = [
        "-Iexternal/gtest/googletest-release-1.7.0/include"
    ],
    linkopts = ["-pthread"],
    visibility = ["//visibility:public"],
)

ただし構文にいちいち googletest-release-1.7.0 という構文がつくと読みにくいので、 http_archive ルールの strip_prefix 属性を使って取り除きます。
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "gtest",
    url = "https://github.com/google/googletest/archive/release-1.7.0.zip",
    sha256 = "b58cb7547a28b2c718d1e38aee18a3659c9e3ff52440297e965f5edffe34b6d0",
    build_file = "@//:gtest.BUILD",
    strip_prefix = "googletest-release-1.7.0",
)

これを行うことで、gtest.BUILDは以下のように書き直すことが出来ます。
cc_library(
    name = "main",
    srcs = glob(
        ["src/*.cc"],
        exclude = ["src/gtest-all.cc"]
    ),
    hdrs = glob([
        "include/**/*.h",
        "src/*.h"
    ]),
    copts = ["-Iexternal/gtest/include"],
    linkopts = ["-pthread"],
    visibility = ["//visibility:public"],
)
これにより、各cc_ルールは、@gtest//:main への依存関係を持つことが出来ます。

実際にテストを書いて実行する 

例として、プロジェクト内にソースファイル、 ./test/hello-test.cc を作成して、以下の内容を記述してみましょう。

#include "gtest/gtest.h"
#include "lib/hello-greet.h"
TEST(HelloTest, GetGreet) {
  EXPECT_EQ(get_greet("Bazel"), "Hello Bazel");
}
cc_test(
    name = "hello-test",
    srcs = ["hello-test.cc"],
    copts = ["-Iexternal/gtest/include"],
    deps = [
        "@gtest//:main",
        "//main:hello-greet",
    ],
)

このテストをビルドする際には、.main/BUILD のルールの
 visibility 
属性に、//test:__pkg__ を設定して依存関係を持てるようにしておきましょう。 

これにより、bazel test が実行できるようになります。
bazel test test:hello-test

実行結果はこのようになります。
INFO: Found 1 test target...
Target //test:hello-test up-to-date:
  bazel-bin/test/hello-test
INFO: Elapsed time: 4.497s, Critical Path: 2.53s
//test:hello-test PASSED in 0.3s

Executed 1 out of 1 tests: 1 test passes.

Translate

ページビューの合計

注意書き

基本的にごった煮ブログですので、カテゴリから記事を参照していただけると読みやすいかと存じます。

ADBlocker等を使用していると、Twitterやアクセスカウンタが表示されません。

記事を読むには差し支えませんが、情報を参照したい場合には一時例外にしていただけると全てご参照いただけます。

Featured Post

ボイドラDICEの攻略法

QooQ