यहां आपको 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
लाइब्रेरी पर निर्भर करती है, जो 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 का इस्तेमाल किया जा रहा है.
Google टेस्ट को डाउनलोड करने और उसे अपनी रिपॉज़िटरी में उपलब्ध कराने के लिए, WORKSPACE
फ़ाइल में मौजूद रिपॉज़िटरी फ़ंक्शन में से किसी एक का इस्तेमाल किया जा सकता है:
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
का प्रीफ़िक्स जोड़ा गया है. strip_prefix
एट्रिब्यूट जोड़कर, http_archive
को इस प्रीफ़िक्स से हटाया जा सकता है:
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++ टारगेट इस नियम पर निर्भर हो सकते हैं.