इस ट्यूटोरियल में उदाहरण के तौर पर, किसी प्रोजेक्ट के लिए C++ टूलचेन को कॉन्फ़िगर करने का तरीका बताया गया है. यह C++ प्रोजेक्ट के उदाहरण पर आधारित है. इसमें clang
का इस्तेमाल करके, कोई गड़बड़ी नहीं बनाई जाती है.
आप इन चीज़ों के बारे में जानेंगे
इस ट्यूटोरियल में आपको ये काम करने का तरीका पता चलेगा:
- बिल्ड एनवायरमेंट को सेट अप करें
- C++ टूलचेन कॉन्फ़िगर करना
- Starlark का ऐसा नियम बनाएं जो
cc_toolchain
के लिए अतिरिक्त कॉन्फ़िगरेशन उपलब्ध कराता हो, ताकि Ba हटाना,clang
का इस्तेमाल करके ऐप्लिकेशन बना सके - Linux मशीन पर
bazel build --config=clang_config //main:hello-world
चलाकर, अनुमानित नतीजों की पुष्टि करें - C++ ऐप्लिकेशन बनाएं
वेब कंटेनर इंस्टॉल करने से पहले
बिल्ड एनवायरमेंट को सेट अप करें
इस ट्यूटोरियल में यह मान लिया गया है कि आप Linux का इस्तेमाल कर रहे हैं और आपने C++ ऐप्लिकेशन बना लिए हैं और ज़रूरी टूल और लाइब्रेरी इंस्टॉल कर ली हैं.
ट्यूटोरियल में clang version 9.0.1
का इस्तेमाल किया गया है, जिसे अपने सिस्टम पर इंस्टॉल किया जा सकता है.
बिल्ड एनवायरमेंट को इस तरह सेट अप करें:
अगर आपने पहले से ऐसा नहीं किया है, तो Bazel 0.23 या इसके बाद के वर्शन को डाउनलोड और इंस्टॉल करें.
GitHub से C++ प्रोजेक्ट का उदाहरण डाउनलोड करें और उसे अपने कंप्यूटर पर मौजूद खाली डायरेक्ट्री में रखें.
main/BUILD
फ़ाइल में, यहcc_binary
टारगेट जोड़ें:cc_binary( name = "hello-world", srcs = ["hello-world.cc"], )
--config
फ़्लैग का इस्तेमाल चालू करने के लिए, यहां दिए गए कॉन्टेंट के साथ वर्कस्पेस डायरेक्ट्री के रूट में एक.bazelrc
फ़ाइल बनाएं:# Use our custom-configured c++ toolchain. build:clang_config --crosstool_top=//toolchain:clang_suite # Use --cpu as a differentiator. build:clang_config --cpu=k8 # Use the default Bazel C++ toolchain to build the tools used during the # build. build:clang_config --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
build:{config_name} --flag=value
एंट्री के लिए, कमांड लाइन फ़्लैग
--config={config_name}
उस खास फ़्लैग से जुड़ा होता है. इस्तेमाल किए गए फ़्लैग से जुड़े दस्तावेज़ देखें:
crosstool_top
,
cpu
, और
host_crosstool_top
.
जब bazel build --config=clang_config //main:hello-world
के साथ टारगेट
बनाया जाता है, तो Basel, cc_toolchain_suite
से मिले आपके कस्टम टूलचेन का इस्तेमाल
//toolchain:clang_suite
करता है. सुइट में अलग-अलग सीपीयू के लिए, अलग-अलग टूलचेन शामिल हो सकते हैं. इसलिए, इन्हें --cpu=k8
फ़्लैग के हिसाब से अलग-अलग दिखाया जाता है.
Baज़ल, बिल्ड के दौरान C++ में लिखे कई इंटरनल टूल, जैसे कि प्रोसेस-रैपर का इस्तेमाल करता है. इसलिए, होस्ट प्लैटफ़ॉर्म के लिए पहले से मौजूद डिफ़ॉल्ट C++ टूलचेन के बारे में बताया जाता है. इससे, ये टूल इस ट्यूटोरियल में बनाए गए टूलचेन के बजाय, उस टूलचेन का इस्तेमाल करके बनाए जाते हैं.
C++ टूलचेन को कॉन्फ़िगर करना
C++ टूलचेन को कॉन्फ़िगर करने के लिए, बार-बार ऐप्लिकेशन बनाएं और नीचे बताए गए तरीके से हर गड़बड़ी को एक-एक करके ठीक करें.
बिल्ड को नीचे दिए गए निर्देश के साथ चलाएं:
bazel build --config=clang_config //main:hello-world
आपने
.bazelrc
फ़ाइल में--crosstool_top=//toolchain:clang_suite
को शामिल किया है, इसलिए Basel को यह गड़बड़ी दिखती है:No such package `toolchain`: BUILD file not found on package path.
वर्कस्पेस डायरेक्ट्री में, पैकेज के लिए
toolchain
डायरेक्ट्री औरtoolchain
डायरेक्ट्री में मौजूद एक खालीBUILD
फ़ाइल बनाएं.बिल्ड को फिर से चलाएं.
toolchain
पैकेज, अब तकclang_suite
टारगेट को तय नहीं करता है. इसलिए, Basel को यह गड़बड़ी दिखती है:No such target '//toolchain:clang_suite': target 'clang_suite' not declared in package 'toolchain' defined by .../toolchain/BUILD
toolchain/BUILD
फ़ाइल में, किसी खाली फ़ाइलग्रुप को इस तरह तय करें:package(default_visibility = ["//visibility:public"]) filegroup(name = "clang_suite")
बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
'//toolchain:clang_suite' does not have mandatory providers: 'ToolchainInfo'
बेज़ल ने पाया कि
--crosstool_top
फ़्लैग एक ऐसे नियम की ओर इशारा करता है जो ज़रूरीToolchainInfo
सेवा देने वाली कंपनी की जानकारी नहीं देता. इसलिए, आपको--crosstool_top
को एक ऐसे नियम पर ले जाना होगा जोToolchainInfo
देता है - जो किcc_toolchain_suite
नियम है.toolchain/BUILD
फ़ाइल में, खाली फ़ाइलग्रुप को इनसे बदलें:cc_toolchain_suite( name = "clang_suite", toolchains = { "k8": ":k8_toolchain", }, )
toolchains
एट्रिब्यूट,--cpu
(और तय किए जाने पर--compiler
) वैल्यू कोcc_toolchain
पर अपने-आप मैप करता है. आपने अभी तक कोई भीcc_toolchain
टारगेट तय नहीं किया है और Ba बैंक इसके बारे में जल्द ही शिकायत करेगा.बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
Rule '//toolchain:k8_toolchain' does not exist
अब आपको
cc_toolchain_suite.toolchains
एट्रिब्यूट में मौजूद हर वैल्यू के लिए,cc_toolchain
टारगेट तय करने होंगे.toolchain/BUILD
फ़ाइल में यह जानकारी जोड़ें:filegroup(name = "empty") cc_toolchain( name = "k8_toolchain", toolchain_identifier = "k8-toolchain", toolchain_config = ":k8_toolchain_config", all_files = ":empty", compiler_files = ":empty", dwp_files = ":empty", linker_files = ":empty", objcopy_files = ":empty", strip_files = ":empty", supports_param_files = 0, )
बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
Rule '//toolchain:k8_toolchain_config' does not exist
इसके बाद,
toolchain/BUILD
फ़ाइल में ":k8_toolchain_config" टारगेट जोड़ें:filegroup(name = "k8_toolchain_config")
बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
'//toolchain:k8_toolchain_config' does not have mandatory providers: 'CcToolchainConfigInfo'
CcToolchainConfigInfo
सेवा देने वाली कंपनी है. इसका इस्तेमाल C++ टूलचेन कॉन्फ़िगर करने के लिए किया जाता है. इस गड़बड़ी को ठीक करने के लिए, Starlark का नियम बनाएं. यह नियम इस कॉन्टेंट वालीtoolchain/cc_toolchain_config.bzl
फ़ाइल बनाकर, Basel कोCcToolchainConfigInfo
देता है:def _impl(ctx): return cc_common.create_cc_toolchain_config_info( ctx = ctx, toolchain_identifier = "k8-toolchain", host_system_name = "local", target_system_name = "local", target_cpu = "k8", target_libc = "unknown", compiler = "clang", abi_version = "unknown", abi_libc_version = "unknown", ) cc_toolchain_config = rule( implementation = _impl, attrs = {}, provides = [CcToolchainConfigInfo], )
cc_common.create_cc_toolchain_config_info()
, ज़रूरी कंपनीCcToolchainConfigInfo
बनाता है.cc_toolchain_config
नियम का इस्तेमाल करने के लिए,toolchains/BUILD
में लोड स्टेटमेंट जोड़ें:load(":cc_toolchain_config.bzl", "cc_toolchain_config")
इसके अलावा, "k8_toolchain_config" फ़ाइलग्रुप को
cc_toolchain_config
नियम के एलान से बदलें:cc_toolchain_config(name = "k8_toolchain_config")
बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
.../BUILD:1:1: C++ compilation of rule '//:hello-world' failed (Exit 1) src/main/tools/linux-sandbox-pid1.cc:421: "execvp(toolchain/DUMMY_GCC_TOOL, 0x11f20e0)": No such file or directory Target //:hello-world failed to build`
इस समय, Basel के पास कोड बनाने की कोशिश करने के लिए काफ़ी जानकारी है, लेकिन उसे अब भी यह नहीं पता है कि ज़रूरी बिल्ड ऐक्शन को पूरा करने के लिए कौनसे टूल इस्तेमाल करने चाहिए. बेज़ेल को यह बताने के लिए कि कौनसे टूल इस्तेमाल करने हैं, आपको Starlark नियम लागू करने के तरीके में बदलाव करना होगा. इसके लिए, आपको
@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl
से device_path() कंस्ट्रक्टर की ज़रूरत होगी:# toolchain/cc_toolchain_config.bzl: # NEW load("@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", "tool_path") def _impl(ctx): tool_paths = [ # NEW tool_path( name = "gcc", path = "/usr/bin/clang", ), tool_path( name = "ld", path = "/usr/bin/ld", ), tool_path( name = "ar", path = "/usr/bin/ar", ), tool_path( name = "cpp", path = "/bin/false", ), tool_path( name = "gcov", path = "/bin/false", ), tool_path( name = "nm", path = "/bin/false", ), tool_path( name = "objdump", path = "/bin/false", ), tool_path( name = "strip", path = "/bin/false", ), ] return cc_common.create_cc_toolchain_config_info( ctx = ctx, toolchain_identifier = "local", host_system_name = "local", target_system_name = "local", target_cpu = "k8", target_libc = "unknown", compiler = "clang", abi_version = "unknown", abi_libc_version = "unknown", tool_paths = tool_paths, # NEW )
पक्का करें कि
/usr/bin/clang
और/usr/bin/ld
आपके सिस्टम के लिए सही पाथ हैं.बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
..../BUILD:3:1: undeclared inclusion(s) in rule '//main:hello-world': this rule is missing dependency declarations for the following files included by 'main/hello-world.cc': '/usr/include/c++/9/ctime' '/usr/include/x86_64-linux-gnu/c++/9/bits/c++config.h' '/usr/include/x86_64-linux-gnu/c++/9/bits/os_defines.h' ....
Basel को यह जानने की ज़रूरत है कि शामिल किए गए हेडर को कहां खोजना है. इसे ठीक करने के कई तरीके हैं, जैसे कि
cc_binary
केincludes
एट्रिब्यूट का इस्तेमाल करना. हालांकि, यहां इसेcc_common.create_cc_toolchain_config_info
के पैरामीटर की मदद से, टूलचेन लेवल पर हल किया जा सकता है.cxx_builtin_include_directories
ध्यान रखें कि अगरclang
का कोई दूसरा वर्शन इस्तेमाल किया जा रहा है, तो शामिल करने का पाथ अलग होगा. डिस्ट्रिब्यूशन के हिसाब से, ये पाथ अलग-अलग भी हो सकते हैं.toolchain/cc_toolchain_config.bzl
की रिटर्न वैल्यू में बदलाव करें, ताकि वह कुछ ऐसा दिखे:return cc_common.create_cc_toolchain_config_info( ctx = ctx, cxx_builtin_include_directories = [ # NEW "/usr/lib/llvm-9/lib/clang/9.0.1/include", "/usr/include", ], toolchain_identifier = "local", host_system_name = "local", target_system_name = "local", target_cpu = "k8", target_libc = "unknown", compiler = "clang", abi_version = "unknown", abi_libc_version = "unknown", tool_paths = tool_paths, )
बिल्ड कमांड को फिर से चलाएं, आपको इस तरह की गड़बड़ी दिखेगी:
/usr/bin/ld: bazel-out/k8-fastbuild/bin/main/_objs/hello-world/hello-world.o: in function `print_localtime()': hello-world.cc:(.text+0x68): undefined reference to `std::cout'
इसकी वजह यह है कि लिंकर में C++ स्टैंडर्ड लाइब्रेरी मौजूद नहीं है और उसे इसके सिंबल नहीं मिलते. इसे ठीक करने के कई तरीके हैं, जैसे कि
cc_binary
केlinkopts
एट्रिब्यूट का इस्तेमाल करना. यहां इसे यह पक्का करके हल किया जाता है कि टूलचेन का इस्तेमाल करने वाले किसी भी टारगेट को इस फ़्लैग के बारे में बताने की ज़रूरत न हो.इस कोड को
cc_toolchain_config.bzl
में कॉपी करें:# NEW load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") # NEW load( "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", "feature", "flag_group", "flag_set", "tool_path", ) all_link_actions = [ # NEW ACTION_NAMES.cpp_link_executable, ACTION_NAMES.cpp_link_dynamic_library, ACTION_NAMES.cpp_link_nodeps_dynamic_library, ] def _impl(ctx): tool_paths = [ tool_path( name = "gcc", path = "/usr/bin/clang", ), tool_path( name = "ld", path = "/usr/bin/ld", ), tool_path( name = "ar", path = "/bin/false", ), tool_path( name = "cpp", path = "/bin/false", ), tool_path( name = "gcov", path = "/bin/false", ), tool_path( name = "nm", path = "/bin/false", ), tool_path( name = "objdump", path = "/bin/false", ), tool_path( name = "strip", path = "/bin/false", ), ] features = [ # NEW feature( name = "default_linker_flags", enabled = True, flag_sets = [ flag_set( actions = all_link_actions, flag_groups = ([ flag_group( flags = [ "-lstdc++", ], ), ]), ), ], ), ] return cc_common.create_cc_toolchain_config_info( ctx = ctx, features = features, # NEW cxx_builtin_include_directories = [ "/usr/lib/llvm-9/lib/clang/9.0.1/include", "/usr/include", ], toolchain_identifier = "local", host_system_name = "local", target_system_name = "local", target_cpu = "k8", target_libc = "unknown", compiler = "clang", abi_version = "unknown", abi_libc_version = "unknown", tool_paths = tool_paths, ) cc_toolchain_config = rule( implementation = _impl, attrs = {}, provides = [CcToolchainConfigInfo], )
अगर
bazel build --config=clang_config //main:hello-world
चलाया जाता है, तो यह पूरी तरह से तैयार होना चाहिए.
अपने काम की समीक्षा करें
इस ट्यूटोरियल में आपने एक बुनियादी C++ टूलचेन को कॉन्फ़िगर करने का तरीका सीखा है, लेकिन टूलचेन इस आसान उदाहरण से ज़्यादा असरदार हैं.
ज़रूरी बातें:
- आपको कमांड लाइन में --crosstool_top
फ़्लैग तय करना होगा, जो
cc_toolchain_suite
पर ले जाता हो
- .bazelrc
फ़ाइल का इस्तेमाल करके, किसी खास कॉन्फ़िगरेशन के लिए शॉर्टकट बनाया जा सकता है
- cc_toolchain_suite में अलग-अलग सीपीयू और कंपाइलर के लिए, cc_toolchains
शामिल किया जा सकता है. फ़र्क़ करने के लिए, --cpu
जैसे कमांड लाइन फ़्लैग का इस्तेमाल किया जा सकता है.
- आपको टूलचेन को यह बताना होगा कि टूल कहां उपलब्ध हैं. इस ट्यूटोरियल में,
एक आसान वर्शन दिया गया है. इसमें सिस्टम से टूल ऐक्सेस किए जा सकते हैं. अगर
आपको अपने कारोबार के बारे में ज़्यादा जानकारी चाहिए, तो
फ़ाइल फ़ोल्डर के बारे में यहां पढ़ें. आपके टूल किसी अन्य फ़ाइल फ़ोल्डर से आ सकते हैं और आपको compiler_files
जैसे एट्रिब्यूट के आधार पर, cc_toolchain
में उनकी फ़ाइलें उपलब्ध करानी होंगी. tool_paths
को भी बदलना होगा.
- आपके पास यह तय करने की सुविधा है कि अलग-अलग कार्रवाइयों के लिए कौनसे फ़्लैग भेजे जाने चाहिए.
जैसे, लिंक करना या कोई दूसरी कार्रवाई करना.
इसके बारे में और पढ़ें
ज़्यादा जानकारी के लिए, C++ टूलचेन कॉन्फ़िगरेशन पर जाएं