Kasus Penggunaan Build C++ Umum

Laporkan masalah Lihat sumber Per Malam · 7,2 · 7,1 · 7,0 · 6,5 · 6,4

Di sini Anda akan menemukan beberapa kasus penggunaan paling umum untuk membangun project C++ bersama Bazel. Jika Anda belum melakukannya, mulailah membangun C++ proyek bersama Bazel dengan menyelesaikan tutorial Pengantar Bazel: Membangun Project C++.

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

Menyertakan beberapa file dalam target

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

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

Dengan target ini, Bazel akan membangun semua file .cc dan .h yang ditemukannya di direktori yang sama dengan file BUILD yang berisi target ini (tidak termasuk subdirektori).

Menggunakan penyertaan transitif

Jika file menyertakan header, maka aturan apa pun dengan file tersebut sebagai sumber (yaitu, memiliki file tersebut dalam atribut srcs, hdrs, atau textual_hdrs) harus bergantung pada aturan library header yang disertakan. Sebaliknya, hanya mengarahkan dependensi perlu ditentukan sebagai dependensi. Sebagai contoh, misalkan sandwich.h mencakup bread.h dan bread.h mencakup flour.h. sandwich.h tidak termasuk flour.h (yang ingin tepung dalam sandwich mereka?), jadi BUILD akan tampak 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 di library flour.

Menambahkan jalur penyertaan

Terkadang Anda tidak dapat (atau tidak ingin) jalur penyertaan root di ruang kerja {i>root<i}. {i>Library<i} yang ada mungkin sudah memiliki direktori {i>include<i} yang tidak cocok dengan jalurnya di ruang kerja Anda. Misalnya, Anda memiliki beberapa struktur direktori:

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

Bazel mengharapkan some_lib.h untuk disertakan sebagai legacy/some_lib/include/some_lib.h, tetapi anggap saja some_lib.cc menyertakan "some_lib.h". Untuk membuatnya valid, jalur yang disertakan legacy/some_lib/BUILD harus menentukan bahwa 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 header-nya jika tidak, harus disertakan dengan awalan /.

Menyertakan library eksternal

Misalkan Anda menggunakan Pengujian Google. Anda dapat menggunakan salah satu fungsi repositori di file WORKSPACE untuk download Google Test dan sediakan di repositori Anda:

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 Pengujian Google. Google Test memiliki beberapa "khusus" persyaratan yang membuat aturan cc_library-nya lebih rumit:

  • googletest-release-1.10.0/src/gtest-all.cc #include lainnya file di googletest-release-1.10.0/src/: kecualikan dari kompilasi untuk mencegah kesalahan tautan untuk simbol duplikat.

  • OpenVPN menggunakan file {i>header<i} yang relatif terhadap Direktori googletest-release-1.10.0/include/ ("gtest/gtest.h"), jadi Anda harus menambahkan direktori itu ke jalur penyertaan.

  • ID tersebut harus ditautkan di pthread, jadi tambahkan sebagai linkopt.

Oleh karena itu, aturan terakhir akan 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 strip http_archive 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",
)

Maka 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 ./test/hello-test.cc pengujian, seperti:

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

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

Kemudian, 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 dapat dilihat 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

Tindakan 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 Anda ingin menggunakan {i>library<i} yang Anda hanya memiliki versi kompilasi (untuk misalnya, header dan file .so) menggabungkannya dalam aturan cc_library:

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

Dengan demikian, target C++ lain di ruang kerja Anda dapat bergantung pada aturan ini.