Kasus Penggunaan Build C++ Umum

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.
Laporkan masalah Lihat sumber

Di sini, Anda akan menemukan beberapa kasus penggunaan paling umum untuk mem-build project C++ dengan Bazel. Jika Anda belum melakukannya, mulailah membuat project C++ dengan Bazel dengan menyelesaikan tutorial Pengantar Bazel: Membuat Project C++.

Untuk informasi tentang file header cc_library dan hdrs, lihat cc_library.

Menyertakan beberapa file dalam satu target

Anda dapat menyertakan beberapa file dalam satu target dengan glob. Contoh:

cc_library(
    name = "build-all-the-files",
    srcs = glob(["*.cc"]),
    hdrs = glob(["*.h"]),
)

Dengan target ini, Bazel akan mem-build semua file .cc dan .h yang ditemukan dalam direktori yang sama dengan file BUILD yang berisi target ini (tidak termasuk subdirektori).

Menggunakan transitif meliputi

Jika file menyertakan header, setiap aturan dengan file tersebut sebagai sumber (yaitu, memiliki file dalam atribut srcs, hdrs, atau textual_hdrs) harus bergantung pada aturan library header yang disertakan. Sebaliknya, hanya dependensi langsung yang harus ditentukan sebagai dependensi. Misalnya, sandwich.h menyertakan bread.h dan bread.h mencakup flour.h. sandwich.h tidak menyertakan flour.h (siapa yang ingin tepung di sandwichnya?), jadi file BUILD akan terlihat seperti ini:

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"],
)

Di sini, library sandwich bergantung pada library bread, yang bergantung pada library flour.

Menambahkan jalur penyertaan

Terkadang Anda tidak dapat (atau tidak ingin) menyertakan jalur di root ruang kerja. Library yang ada mungkin sudah memiliki direktori include yang tidak cocok dengan jalurnya di ruang kerja Anda. Misalnya, Anda memiliki struktur direktori berikut:

└── my-project
    ├── legacy
    │   └── some_lib
    │       ├── BUILD
    │       ├── include
    │       │   └── some_lib.h
    │       └── some_lib.cc
    └── WORKSPACE

Bazel mengharapkan some_lib.h disertakan sebagai legacy/some_lib/include/some_lib.h, tetapi anggaplah some_lib.cc menyertakan "some_lib.h". Untuk membuat jalur penyertaan tersebut valid, legacy/some_lib/BUILD harus menentukan bahwa direktori some_lib/include adalah direktori include:

cc_library(
    name = "some_lib",
    srcs = ["some_lib.cc"],
    hdrs = ["include/some_lib.h"],
    copts = ["-Ilegacy/some_lib/include"],
)

Hal ini sangat berguna untuk dependensi eksternal, karena file headernya harus disertakan dengan awalan /.

Menyertakan library eksternal

Misalnya Anda menggunakan Google Test. Anda dapat menggunakan salah satu fungsi repositori dalam file WORKSPACE untuk mendownload Google Test dan menyediakannya di repositori:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

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

Kemudian, buat gtest.BUILD, file BUILD yang digunakan untuk mengompilasi Google Test. Google Test memiliki beberapa persyaratan "khusus" yang membuat aturan cc_library-nya lebih rumit:

  • googletest-release-1.10.0/src/gtest-all.cc #include semua file lainnya di googletest-release-1.10.0/src/: mengecualikannya dari kompilasi untuk mencegah error link untuk simbol duplikat.

  • Opsi ini menggunakan file header yang relatif terhadap direktori googletest-release-1.10.0/include/ ("gtest/gtest.h"), sehingga Anda harus menambahkan direktori tersebut ke jalur yang disertakan.

  • Link harus ditautkan di pthread, jadi tambahkan sebagai linkopt.

Oleh karena itu, aturan akhir terlihat seperti ini:

cc_library(
    name = "main",
    srcs = glob(
        ["googletest-release-1.10.0/src/*.cc"],
        exclude = ["googletest-release-1.10.0/src/gtest-all.cc"]
    ),
    hdrs = glob([
        "googletest-release-1.10.0/include/**/*.h",
        "googletest-release-1.10.0/src/*.h"
    ]),
    copts = [
        "-Iexternal/gtest/googletest-release-1.10.0/include",
        "-Iexternal/gtest/googletest-release-1.10.0"
    ],
    linkopts = ["-pthread"],
    visibility = ["//visibility:public"],
)

Ini agak berantakan: semuanya diawali dengan googletest-release-1.10.0 sebagai produk sampingan dari struktur arsip. Anda dapat membuat http_archive menghapus awalan ini dengan menambahkan atribut 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.10.0.zip",
    sha256 = "94c634d499558a76fa649edb13721dce6e98fb1e7018dfaeba3cd7a083945e91",
    build_file = "@//:gtest.BUILD",
    strip_prefix = "googletest-release-1.10.0",
)

Kemudian, gtest.BUILD akan terlihat seperti ini:

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"],
)

Sekarang aturan cc_ dapat bergantung pada @gtest//:main.

Menulis dan menjalankan pengujian C++

Misalnya, Anda dapat membuat pengujian ./test/hello-test.cc, seperti:

#include "gtest/gtest.h"
#include "main/hello-greet.h"

TEST(HelloTest, GetGreet) {
  EXPECT_EQ(get_greet("Bazel"), "Hello Bazel");
}

Lalu buat file ./test/BUILD untuk pengujian Anda:

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

Agar hello-greet terlihat oleh hello-test, Anda harus menambahkan "//test:__pkg__", ke atribut visibility di ./main/BUILD.

Sekarang Anda dapat menggunakan bazel test untuk menjalankan pengujian.

bazel test test:hello-test

Perintah ini menghasilkan output berikut:

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.

Menambahkan dependensi pada library yang telah dikompilasi sebelumnya

Jika ingin menggunakan library yang hanya Anda miliki versi yang dikompilasi (misalnya, header dan file .so) gabungkan ke dalam aturan cc_library:

cc_library(
    name = "mylib",
    srcs = ["mylib.so"],
    hdrs = ["mylib.h"],
)

Dengan cara ini, target C++ lainnya di ruang kerja Anda dapat bergantung pada aturan ini.