इस ट्यूटोरियल में उदाहरण के तौर पर, C++ को कॉन्फ़िगर करने का तरीका बताया गया है
एक प्रोजेक्ट के लिए बनाया जाता है. यह इन पर आधारित है
C++ प्रोजेक्ट का उदाहरण
जो clang
का इस्तेमाल करके गड़बड़ी-रहित बनाता है.
आप इन चीज़ों के बारे में जानेंगे
इस ट्यूटोरियल में आपको ये काम करने का तरीका पता चलेगा:
- बिल्ड एनवायरमेंट को सेट अप करें
- C++ टूलचेन कॉन्फ़िगर करना
- Starlark का ऐसा नियम बनाएं जो ज़्यादा जानकारी देता हो
cc_toolchain
के लिए कॉन्फ़िगरेशन करें, ताकि Basel ऐप्लिकेशन बना सकेclang
के साथ - चलाकर अनुमानित नतीजों की पुष्टि करें
Linux मशीन पर
bazel build --config=clang_config //main:hello-world
- C++ ऐप्लिकेशन बनाएं
शुरू करने से पहले
बिल्ड एनवायरमेंट को सेट अप करें
यह ट्यूटोरियल मानता है कि आप Linux का इस्तेमाल कर रहे हैं और आपने इसे सफलतापूर्वक बना लिया है
C++ ऐप्लिकेशन इंस्टॉल किए और ज़रूरी टूल और लाइब्रेरी इंस्टॉल कीं.
ट्यूटोरियल में clang version 9.0.1
का इस्तेमाल किया गया है, जिसे अपने सिस्टम पर इंस्टॉल किया जा सकता है.
बिल्ड एनवायरमेंट को इस तरह सेट अप करें:
अगर आपने पहले से ऐसा नहीं किया है, तो Basel 0.23 या इसके बाद का वर्शन डाउनलोड और इंस्टॉल करें.
Google News ऐप्लिकेशन C++ प्रोजेक्ट का उदाहरण GitHub से कॉपी करें और उसे अपने कंप्यूटर पर किसी खाली डायरेक्ट्री में डालें.
main/BUILD
फ़ाइल में, यहcc_binary
टारगेट जोड़ें:cc_binary( name = "hello-world", srcs = ["hello-world.cc"], )
फ़ाइल फ़ोल्डर की डायरेक्ट्री के रूट में एक
.bazelrc
फ़ाइल बनाएं.--config
फ़्लैग का इस्तेमाल चालू करने के लिए कॉन्टेंट:# 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
झंडे से अलग-अलग दिखाया गया है.
क्योंकि Basel, बिल्ड के दौरान C++ में लिखे गए कई इंटरनल टूल इस्तेमाल करता है, जैसे कि प्रोसेस-रैपर, पहले से मौजूद डिफ़ॉल्ट C++ टूलचेन ताकि ये टूल उस टूलचेन का इस्तेमाल करके बनाए जाएं जिसका इस्तेमाल किया जा रहा है. इस ट्यूटोरियल में बनाया गया ऐप्लिकेशन.
C++ टूलचेन को कॉन्फ़िगर करना
C++ टूलचेन को कॉन्फ़िगर करने के लिए, बार-बार ऐप्लिकेशन बनाएं और उन्हें समस्या को एक-एक करके ठीक करें, जैसा कि नीचे बताया गया है.
बिल्ड को नीचे दिए गए निर्देश के साथ चलाएं:
bazel build --config=clang_config //main:hello-world
क्योंकि आपने
--crosstool_top=//toolchain:clang_suite
को.bazelrc
फ़ाइल का इस्तेमाल करने पर, Baze नीचे दी गई गड़बड़ी दिखाता है:No such package `toolchain`: BUILD file not found on package path.
वर्कस्पेस डायरेक्ट्री में, पैकेज के लिए
toolchain
डायरेक्ट्री बनाएं औरtoolchain
डायरेक्ट्री में एक खालीBUILD
फ़ाइल है.बिल्ड को फिर से चलाएं. क्योंकि
toolchain
पैकेज अभी तकclang_suite
टारगेट पर, बेज़ल यह गड़बड़ी दिखाता है: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
टारगेट तय किया है और बेज़ल इसके बारे में शिकायत करेंगे जल्द ही.बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
Rule '//toolchain:k8_toolchain' does not exist
अब आपको यहां दी गई हर वैल्यू के लिए
cc_toolchain
टारगेट तय करने होंगेcc_toolchain_suite.toolchains
एट्रिब्यूट की वैल्यू सबमिट करें. निम्न को इसमें जोड़ें: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
इसके बाद, ":k8_toolchain_config" जोड़ें
toolchain/BUILD
फ़ाइल को टारगेट करें:filegroup(name = "k8_toolchain_config")
बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
'//toolchain:k8_toolchain_config' does not have mandatory providers: 'CcToolchainConfigInfo'
CcToolchainConfigInfo
ऐसी सेवा देने वाली कंपनी है जिसका इस्तेमाल आप कॉन्फ़िगर करने के लिए करते हैं आपके C++ टूलचेन का इस्तेमाल कर सकते हैं. इस गड़बड़ी को ठीक करने के लिए, Starlark नियम बनाएं जो बेज़ल कोCcToolchainConfigInfo
उपलब्ध कराता है,toolchain/cc_toolchain_config.bzl
फ़ाइल में यह कॉन्टेंट है: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
नियम का इस्तेमाल करने के लिए, एक लोड जोड़ें पैकेज विवरण के ठीक नीचेtoolchain/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 नियम लागू करने के तरीके में बदलाव करना होगा का इस्तेमाल करना है. इसके लिए, आपको इस प्रॉपर्टी से Tools_path() कंस्ट्रक्टर की ज़रूरत पड़ेगी
@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl
:# 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 को यह जानने की ज़रूरत है कि शामिल किए गए हेडर को कहां खोजना है. यहां हैं इसे हल करने के कई तरीके हैं, जैसे कि
includes
एट्रिब्यूट का इस्तेमाल करनाcc_binary
, लेकिन यहां इसे हल करने के लिए टूलचेन लेवल परcxx_builtin_include_directories
cc_common.create_cc_toolchain_config_info
का पैरामीटर. ध्यान रहे कि अगर आप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
जैसे कमांड लाइन फ़्लैग का इस्तेमाल किया जा सकता है.
- आपको टूलचेन को यह बताना होगा कि टूल कहां उपलब्ध हैं. इस ट्यूटोरियल में
एक सरल वर्शन है, जहां सिस्टम से टूल ऐक्सेस किए जाते हैं. अगर आपने
की है, तो ज़्यादा सुरक्षित तरीके से काम करने में आपकी दिलचस्पी है.
फ़ाइल फ़ोल्डर यहां देखें. आपके टूल
और आपको उनकी फ़ाइलें उपलब्ध करानी होंगी
cc_toolchain
तक, टारगेट डिपेंडेंसी के साथ एट्रिब्यूट पर निर्भर करता है. जैसे
compiler_files
. tool_paths
को भी बदलना होगा.
- आपके पास यह तय करने के लिए सुविधाएं बनाने का विकल्प है कि कौनसे फ़्लैग को फ़्लैग किया जाना चाहिए
चाहे वह लिंक करना हो या कोई अन्य कार्रवाई.
इसके बारे में और पढ़ें
ज़्यादा जानकारी के लिए, यह देखें C++ टूलचेन कॉन्फ़िगरेशन