في ما يلي بعض حالات الاستخدام الأكثر شيوعًا لإنشاء مشاريع C++ باستخدام Bazel. في حال لم يسبق لك البدء، يمكنك البدء في إنشاء مشاريع C++ مع Bazel من خلال إكمال البرنامج التعليمي. مقدمة عن 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
يتوقع البازيل تضمين 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.
يمكنك استخدام إحدى وظائف المستودع في ملف 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.
هناك عدة متطلبات "خاصة" لـ Google Test تجعل قاعدة cc_library
أكثر تعقيدًا:
googletest-release-1.10.0/src/gtest-all.cc
#include
جميع الملفات الأخرى في النطاق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
كنتيجة ثانوية لبنية الأرشيف. يمكنك جعل هذه البادئة 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.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++ أخرى في مساحة العمل على هذه القاعدة.