bazel C++構文入門

9350 ワード

bazelのすべてのコードは現在のエンジニアリングで、各エンジニアリングはWORKSPACEです.各WORKSPACEの下に複数のBUILDファイルがあります.BUILD内には複数のtargetsがあり、これらのtargetsはstarlark言語で宣言されています.
Starlark言語
  • pythonに似ています.
  • スレッドセキュリティ
  • データ型None,bool,dict,function,int,list,string,depset,struct
  • 可変データ構造はlistsとdicts
  • コマンドライン
    ルール#ルール#
    bazel []  []
    

    または
    bazel []  [] -- []
    

    コマンドラインパラメータドキュメント
    さぎょうげんり
  • targetに関するBUILDファイルのロード
  • inputsとdependenciesを解析し、action graphを生成
  • graph実行、outputs産出
  • Actiongraph:bazelはこの図に依存してファイルの変化を追跡し、再コンパイルが必要かどうかを追跡し、ユーザーにコード間の依存関係図を提供することもできます.
    依存宣言
  • 同一ファイルBUILD内
  • cc_library(
        name = "hello-greet",
        srcs = ["hello-greet.cc"],
        hdrs = ["hello-greet.h"],
    )
    
    cc_binary(
        name = "hello-world",
        srcs = ["hello-world.cc"],
        deps = [
            ":hello-greet",
        ],
    )
    
  • 異なるBUILDファイル間
  • cc_library(
        name = "hello-greet",
        srcs = ["hello-greet.cc"],
        hdrs = ["hello-greet.h"],
    )
    
    cc_binary(
        name = "hello-world",
        srcs = ["hello-world.cc"],
        deps = [
            ":hello-greet",
            "//lib:hello-time",
        ],
    )
    

    :hello-time定義libディレクトリの異なるディレクトリBUILD bazelでは異なるパッケージと呼ばれます
  • 可視性同一パッケージ内のtargetsデフォルトで互いに見える異なるパッケージ間のtargetsの可視性は手動で定義する必要がある
  • cc_library(
        name = "hello-time",
        srcs = ["hello-time.cc"],
        hdrs = ["hello-time.h"],
        visibility = ["//main:__pkg__"],
    )
    

    各パッケージのBUILDファイルの上部にtargetsの他のパッケージのデフォルトの表示を宣言できます.
    package(
        default_visibility = [
            "//tensorflow_serving:internal",
        ],
        features = ["-layering_check"],
    )
    

    すべてのパッケージについて次のように表示されます.
    cc_proto_library(
        name = "cc_echo_c++_proto",
        deps = [
            ":echo_c++_proto",
        ],
        visibility = [
            "//visibility:public",
        ],
    )
    

    target
    2種類あります
  • rule target、例えばcc_library
  • file target

  • C++ベストプラクティス
    BUILDファイル
  • BUILDファイルごとにcc_を1個含むlibraryルールターゲット
  • なるべく細粒度C++ライブラリで並列速度を向上させ、インクリメンタルコンパイルを低減
  • srcにファイルが1つしかない場合はcc_libraryの名前はこのファイル名と同じです.例えば、
  •    cc_library(
           name = "mylib",
           srcs = ["mylib.cc"],
           hdrs = ["mylib.h"],
           deps = [":lower-level-lib"]
       )
    
  • libraryごとに個別のtest targetがあり、testの最後にこのtargetとテストファイル名を付けます.例えば
  •    cc_test(
           name = "mylib_test",
           srcs = ["mylib_test.cc"],
           deps = [":mylib"]
       )
    

    义齿
  • すべてのincludeパスがWORKSPACEディレクトリに対して
  • 非システムディレクトリ用#include "foo/bar/baz.h"、システムディレクトリ用#include
  • 使用しない...
  • サードパーティライブラリに使用可能include_prefixおよびstrip_include_prefix
  • サードパーティ製ライブラリに依存している場合、これらのライブラリのファイルに既存のinclude pathが現在のディレクトリに格納されている場合、workspace rootからファイルを参照するルールに合致しないため、次のディレクトリなどのディレクトリを追加する必要があります.
    └── my-project
        ├── legacy
        │   └── some_lib
        │       ├── BUILD
        │       ├── include
        │       │   └── some_lib.h
        │       └── some_lib.cc
        └── WORKSPACE
    

    以上、bazel要求some_lib.h・必ずlegacy/some_lib/include/some_lib.hという形で含まなければならないがsome_lib.cc現在は"include/some_lib.h"このように含まれるので、このinclude pathを有効にするには、以下のように経路を指定する必要がある(検証対象):
    cc_library(
        name = "some_lib",
        srcs = ["some_lib.cc"],
        hdrs = ["include/some_lib.h"],
        copts = ["-Ilegacy/some_lib/include"],
    )
    

    複数のファイルを含む
    globの使用
    cc_library(
        name = "build-all-the-files",
        srcs = glob(["*.cc"]),
        hdrs = glob(["*.h"]),
    )
    

    依存処理
  • bazelでの依存非伝達解析
  • 他のヘッダファイルが含まれている場合は、このヘッダファイルのtargetを含めます.このヘッダファイルの内部のincludeは管理しません.たとえば
    sandwichはbreadに依存し、breadはflourに依存するが、sandwichはflourに依存しない.
    cc_library(
        name = "sandwich",
        srcs = ["sandwich.cc"],
        hdrs = ["sandwich.h"],
        deps = [":bread"],
    )
    
    cc_library(
        name = "bread",
        srcs = ["bread.cc"],
        hdrs = ["bread.h"],
        deps = [":flour"],
    )
    
    cc_library(
        name = "flour",
        srcs = ["flour.cc"],
        hdrs = ["flour.h"],
    )
    
  • 単一ヘッダファイル、実装されていない場合はtargetも定義する必要がある、例えば
  • cc_library(
        name = "source_adapter",
        hdrs = ["source_adapter.h"],
        visibility = [
            "//visibility:public",
        ],
        deps = [
            ":loader",
            ":servable_data",
            ":source",
            ":storage_path",
            ":target",
            "//tensorflow_serving/util:class_registration",
            "@org_tensorflow//tensorflow/core:lib",
        ],
    )
    

    外部ライブラリを含める
    Google Testを使用する場合は、WORKSPACEで次のように指定できます.
    new_http_archive(
        name = "gtest",
        url = "https://github.com/google/googletest/archive/release-1.7.0.zip",
        sha256 = "b58cb7547a28b2c718d1e38aee18a3659c9e3ff52440297e965f5edffe34b6d0",
        build_file = "gtest.BUILD",
    )
    

    【注】ライブラリにBUILDファイルが含まれている場合は、non-new_関数を使用できます.ファイルを作成するgtest.BUILDGoogle Testをコンパイルするためのファイルです.Google testは特殊なニーズがあるため、コンパイルルールが複雑になります.特殊性は、次のとおりです.
  • googletest-release-1.7.0/src/gtest-all.cc#includegoogletest-release-1.7.0/src/下のすべてのファイルがあるので、このファイルを排除する必要がある
  • そのヘッダファイルはすべてこのディレクトリに対するgoogletest-release-1.7.0/include/例えば"gtest/gtest.h"なので、このディレクトリをcoptsの-Iオプションに追加する必要がある
  • pthreadへのリンクが必要
  • したがって、最終的なコンパイルルールは次のとおりです.
    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"],
    )
    

    これは少し乱れているように見えますが、そのバージョンのディレクトリ名が含まれているので、この名前はnew_http_archiveで使用できますstrip_prefix削除:
    new_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_ rules依存できる@gtest//:main.
    より詳細なcc rule説明はcc rulesを参照
    テストケースの作成
    ファイル作成./test/hello-test.cc
    #include "gtest/gtest.h"
    #include "lib/hello-greet.h"
    
    TEST(HelloTest, GetGreet) {
      EXPECT_EQ(get_greet("Bazel"), "Hello Bazel");
    }
    

    作成./test/BUILD
    cc_test(
        name = "hello-test",
        srcs = ["hello-test.cc"],
        copts = ["-Iexternal/gtest/include"],
        deps = [
            "@gtest//:main",
            "//lib:hello-greet",
        ],
    )
    

    注意hello-greethello-testを表示するには./lib/BUILDファイルに属性を追加する必要がありますvisibility値は//test:__pkg__です.
    テストの実行例:
    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.
    

    このセクションはbazel C++use caseから
    プリコンパイルされたライブラリを含む
  • 動的ライブラリ
  • cc_library(
        name = "mylib",
        srcs = ["mylib.so"],
        hdrs = ["mylib.h"],
    )
    

    外部依存の処理
    Working with external dependencies
    bazelエンジニアリングに依存
  • local_repository
  • git_repository
  • http_archive

  • 非bazelエンジニアリングに依存
  • new_local_repository
  • new_git_repository
  • new_http_archive

  • BUILDファイルの作成が必要
    依存非表示(Shadowing)
  • 同じパッケージの異なるバージョンに依存
  • その他
    getting started bazel C++