C++ बिल्ड के इस्तेमाल के सामान्य उदाहरण

यहां आपको Bazel की मदद से C++ प्रोजेक्ट बनाने के कुछ सबसे सामान्य उदाहरण मिलेंगे. अगर आपने अब तक ऐसा नहीं किया है, तो Bazel की मदद से C++ प्रोजेक्ट बनाना शुरू करें. इसके लिए, Bazel के बारे में जानकारी: C++ प्रोजेक्ट बनाना ट्यूटोरियल पूरा करें .

cc_library और hdrs हेडर फ़ाइलों के बारे में जानकारी के लिए, cc_library देखें.

किसी टारगेट में एक से ज़्यादा फ़ाइलें शामिल करना

glob की मदद से, किसी एक टारगेट में एक से ज़्यादा फ़ाइलें शामिल की जा सकती हैं glob. उदाहरण के लिए:

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

इस टारगेट के साथ, Bazel, BUILD फ़ाइल वाली डायरेक्ट्री में मौजूद सभी .cc और .h फ़ाइलें बनाएगा. इसमें सब-डायरेक्ट्री शामिल नहीं होंगी.

ट्रांज़िटिव इन्क्लूड का इस्तेमाल करना

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

  • यह डायरेक्ट्री ("gtest/gtest.h") से जुड़े हेडर फ़ाइलों का इस्तेमाल करता है. इसलिए, आपको उस डायरेक्ट्री को इन्क्लूड पाथ में जोड़ना होगा.googletest-release-1.10.0/include/

  • इसे 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++ टारगेट, इस नियम पर निर्भर हो सकते हैं.