यहां आपको Bazel की मदद से C++ प्रोजेक्ट बनाने के कुछ सबसे सामान्य उदाहरण मिलेंगे. अगर आपने अब तक ऐसा नहीं किया है, तो 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 लाइब्रेरी पर निर्भर है. वहीं, 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 को कंपाइल करने के लिए किया जाता है.
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 के लिए दिखाने के लिए, आपको ./main/BUILD में visibility एट्रिब्यूट की वैल्यू के तौर पर "//test:__pkg__", को जोड़ना होगा.
अब टेस्ट चलाने के लिए, 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++ टारगेट, इस नियम पर निर्भर हो सकते हैं.