در اینجا تعدادی از رایج ترین موارد استفاده برای ساخت پروژه های C++ با Bazel را خواهید دید. اگر قبلاً این کار را انجام ندادهاید، با تکمیل آموزش مقدمه Bazel: ساخت پروژه C++ با Bazel شروع به ساخت پروژههای C++ کنید.
برای اطلاعات در مورد فایلهای هدر cc_library و hdrs، به cc_library مراجعه کنید.
شامل چندین فایل در یک هدف
شما می توانید چندین فایل را در یک هدف واحد با glob قرار دهید. مثلا:
cc_library(
name = "build-all-the-files",
srcs = glob(["*.cc"]),
hdrs = glob(["*.h"]),
)
با این هدف، Bazel تمام فایلهای .cc
و .h
را که پیدا میکند در همان فهرستی که فایل BUILD
حاوی این هدف است (به استثنای زیر شاخهها) میسازد.
استفاده از متعدی شامل
اگر فایلی شامل سرصفحه باشد، هر قانون با آن فایل به عنوان منبع (یعنی داشتن آن فایل در ویژگی srcs
، hdrs
یا textual_hdrs
) باید به قانون کتابخانه هدر موجود بستگی داشته باشد. برعکس، فقط وابستگی های مستقیم باید به عنوان وابستگی مشخص شوند. برای مثال، فرض کنید sandwich.h
شامل bread.h
و bread.h
شامل flour.h
است. sandwich.h
شامل flour.h
نیست (چه کسی در ساندویچ خود آرد می خواهد؟)، بنابراین فایل BUILD
به شکل زیر است:
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"],
)
در اینجا کتابخانه sandwich
به کتابخانه bread
بستگی دارد که به کتابخانه flour
بستگی دارد.
اضافه کردن شامل مسیرها
گاهی اوقات نمیتوانید (یا نمیخواهید) مسیرها را در ریشه فضای کاری روت کنید. ممکن است کتابخانههای موجود از قبل دارای یک فهرست شامل باشد که با مسیر آن در فضای کاری شما مطابقت ندارد. برای مثال، فرض کنید ساختار دایرکتوری زیر را دارید:
└── 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
شامل "some_lib.h"
باشد. برای معتبر ساختن مسیر شامل، legacy/some_lib/BUILD
باید مشخص کند که some_lib/include
یک فهرست شامل است:
cc_library(
name = "some_lib",
srcs = ["some_lib.cc"],
hdrs = ["include/some_lib.h"],
copts = ["-Ilegacy/some_lib/include"],
)
این به ویژه برای وابستگی های خارجی مفید است، زیرا در غیر این صورت فایل های سرصفحه آنها باید با یک پیشوند /
اضافه شوند.
از جمله کتابخانه های خارجی
فرض کنید از Google Test استفاده می کنید. می توانید از یکی از توابع مخزن در فایل WORKSPACE
برای دانلود Google Test و در دسترس قرار دادن آن در مخزن خود استفاده کنید:
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",
)
سپس gtest.BUILD
ایجاد کنید، یک فایل BUILD
که برای کامپایل تست گوگل استفاده می شود. Google Test چندین الزام "ویژه" دارد که قانون cc_library
آن را پیچیده تر می کند:
googletest-release-1.10.0/src/gtest-all.cc
#include
s تمام فایل های دیگر درgoogletest-release-1.10.0/src/
: برای جلوگیری از خطاهای پیوند برای نمادهای تکراری، آن را از کامپایل حذف کنید.از فایلهای سرصفحهای استفاده میکند که مربوط به
googletest-release-1.10.0/include/
("gtest/gtest.h"
) هستند، بنابراین باید آن دایرکتوری را به مسیرهای شامل اضافه کنید.نیاز به پیوند در
pthread
دارد، پس آن را به عنوانlinkopt
اضافه کنید.
بنابراین قانون نهایی به این صورت است:
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"],
)
این تا حدودی نامرتب است: همه چیز با پیشوند googletest-release-1.10.0
به عنوان محصول فرعی ساختار آرشیو است. می توانید با افزودن ویژگی strip_prefix
، http_archive
strip این پیشوند را ایجاد کنید:
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",
)
سپس 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
بستگی داشته باشند.
نوشتن و اجرای تست های ++C
به عنوان مثال، می توانید یک تست ./test/hello-test.cc
ایجاد کنید، مانند:
#include "gtest/gtest.h"
#include "main/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",
"//main:hello-greet",
],
)
برای قابل مشاهده کردن hello-greet
سلام برای hello-test
، باید "//test:__pkg__",
را به ویژگی visibility
در ./main/BUILD
کنید.
اکنون می توانید از 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.
افزودن وابستگی به کتابخانه های از پیش کامپایل شده
اگر می خواهید از کتابخانه ای استفاده کنید که فقط نسخه کامپایل شده آن را دارید (به عنوان مثال سرصفحه ها و فایل .so
) آن را در یک قانون cc_library
:
cc_library(
name = "mylib",
srcs = ["mylib.so"],
hdrs = ["mylib.h"],
)
به این ترتیب، سایر اهداف C++ در فضای کاری شما می توانند به این قانون وابسته باشند.