इस ट्यूटोरियल में उदाहरण के तौर पर, C++ को कॉन्फ़िगर करने का तरीका बताया गया है एक प्रोजेक्ट के लिए बनाया जाता है.
आपको क्या सीखने को मिलेगा
इस ट्यूटोरियल में आपको ये काम करने का तरीका पता चलेगा:
- बिल्ड एनवायरमेंट को सेट अप करें
- टूलचेन रिज़ॉल्यूशन को डीबग करने के लिए,
--toolchain_resolution_debug
का इस्तेमाल करना - C++ टूलचेन कॉन्फ़िगर करना
- एक ऐसा Starlark नियम बनाएं जो
cc_toolchain
ताकि Baज़र,clang
की मदद से ऐप्लिकेशन बना सके - किसी कंप्यूटर पर
bazel build //main:hello-world
चलाकर, C++ बाइनरी बनाएं Linux मशीन bazel build //main:hello-world --platforms=//:android_x86_64
चलाकर, Android के लिए बाइनरी को क्रॉस-कंपाइल करें
शुरू करने से पहले
यह ट्यूटोरियल मानता है कि आप Linux का इस्तेमाल कर रहे हैं और आपने C++ बना लिया है
ऐप्लिकेशन इस्तेमाल किए और उनमें ज़रूरी टूल और लाइब्रेरी इंस्टॉल कीं. ट्यूटोरियल
clang version 16
का इस्तेमाल करता है, जिसे अपने सिस्टम पर इंस्टॉल किया जा सकता है.
बिल्ड एनवायरमेंट को सेट अप करें
बिल्ड एनवायरमेंट को इस तरह सेट अप करें:
अगर आपने पहले से ऐसा नहीं किया है, तो Basel को डाउनलोड करके इंस्टॉल करें 7.0.2 या उसके बाद के वर्शन.
रूट फ़ोल्डर में कोई खाली
MODULE.bazel
फ़ाइल जोड़ें.main/BUILD
फ़ाइल में, यहcc_binary
टारगेट जोड़ें:cc_binary( name = "hello-world", srcs = ["hello-world.cc"], )
हालांकि, बिल्ड के दौरान Basel में C++ में लिखे गए कई इंटरनल टूल इस्तेमाल किए जाते हैं, जैसे कि
process-wrapper
के तौर पर, पहले से मौजूद डिफ़ॉल्ट C++ टूलचेन का इस्तेमाल होस्ट प्लैटफ़ॉर्म के लिए. इससे इन इंटरनल टूल को इस ट्यूटोरियल में बनाए गए टूल की चेन. इस वजह से,cc_binary
टारगेट को डिफ़ॉल्ट टूलचेन के साथ भी बनाया गया है.बिल्ड को नीचे दिए गए निर्देश के साथ चलाएं:
bazel build //main:hello-world
MODULE.bazel
में रजिस्टर किए गए किसी भी टूलचेन के बिना, बिल्ड सफल हो जाता है.यह देखने के लिए कि आगे क्या है, चलाएं:
bazel build //main:hello-world --toolchain_resolution_debug='@bazel_tools//tools/cpp:toolchain_type' INFO: ToolchainResolution: Target platform @@platforms//host:host: Selected execution platform @@platforms//host:host, type @@bazel_tools//tools/cpp:toolchain_type -> toolchain @@bazel_tools+cc_configure_extension+local_config_cc//:cc-compiler-k8
--platforms
तय किए बिना, Basel ने इसके लिए टारगेट बनाया@platforms//host
इसका इस्तेमाल कर रहे हैं@bazel_tools+cc_configure_extension+local_config_cc//:cc-compiler-k8
.
C++ टूलचेन कॉन्फ़िगर करना
C++ टूलचेन को कॉन्फ़िगर करने के लिए, बार-बार ऐप्लिकेशन बनाएं और उन्हें समस्या को एक-एक करके ठीक करना होगा, जैसा कि नीचे बताया गया है.
इसे clang version 9.0.1
भी माना जा सकता है, लेकिन जानकारी में सिर्फ़ बदलाव होना चाहिए
क्लैंग के अलग-अलग वर्शन के बीच थोड़ा-बहुत.
toolchain/BUILD
को इससे जोड़ेंfilegroup(name = "empty") cc_toolchain( name = "linux_x86_64_toolchain", toolchain_identifier = "linux_x86_64-toolchain", toolchain_config = ":linux_x86_64_toolchain_config", all_files = ":empty", compiler_files = ":empty", dwp_files = ":empty", linker_files = ":empty", objcopy_files = ":empty", strip_files = ":empty", supports_param_files = 0, ) toolchain( name = "cc_toolchain_for_linux_x86_64", toolchain = ":linux_x86_64_toolchain", toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", exec_compatible_with = [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], target_compatible_with = [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], )
इसके बाद, ज़रूरी डिपेंडेंसी जोड़ें और टूलचेन को
MODULE.bazel
के साथbazel_dep(name = "platforms", version = "0.0.10") register_toolchains( "//toolchain:cc_toolchain_for_linux_x86_64" )
यह चरण
cc_toolchain
तय करता है और इसेtoolchain
होस्ट कॉन्फ़िगरेशन.बिल्ड को फिर से चलाएं. क्योंकि
toolchain
पैकेज अभी तकlinux_x86_64_toolchain_config
टारगेट पर, बेज़ल यह गड़बड़ी दिखाता है:ERROR: toolchain/BUILD:4:13: in toolchain_config attribute of cc_toolchain rule //toolchain:linux_x86_64_toolchain: rule '//toolchain:linux_x86_64_toolchain_config' does not exist.
toolchain/BUILD
फ़ाइल में, किसी खाली फ़ाइलग्रुप को इस तरह तय करें:package(default_visibility = ["//visibility:public"]) filegroup(name = "linux_x86_64_toolchain_config")
बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
'//toolchain:linux_x86_64_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")
और "linux_x86_64_toolchain_config" को बदलें एलान वाला फ़ाइलग्रुप
cc_toolchain_config
नियम का:cc_toolchain_config(name = "linux_x86_64_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 नियम लागू करने के तरीके में बदलाव करना होगा का इस्तेमाल करना है. इसके लिए, आपको
tool_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
इसके लिए सही पाथ हैं आपका सिस्टम.बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
ERROR: main/BUILD:3:10: Compiling main/hello-world.cc failed: absolute path inclusion(s) found in rule '//main:hello-world': the source file 'main/hello-world.cc' includes the following non-builtin files with absolute paths (if these are builtin files, make sure these paths are in your toolchain): '/usr/include/c++/13/ctime' '/usr/include/x86_64-linux-gnu/c++/13/bits/c++config.h' '/usr/include/x86_64-linux-gnu/c++/13/bits/os_defines.h' ...
Basel को यह जानने की ज़रूरत है कि शामिल किए गए हेडर को कहां खोजना है. कई इसे हल करने के तरीके, जैसे कि
cc_binary
केincludes
एट्रिब्यूट का इस्तेमाल करना, यह समस्या, टूलचेन लेवल पर हल की जा सकती है.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-16/lib/clang/16/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
एट्रिब्यूट का इस्तेमाल करना. यहाँ इसे हल किया गया है: यह पक्का करना ज़रूरी है कि टूलचेन का इस्तेमाल करने वाले किसी भी टारगेट को यह फ़्लैग करें.इस कोड को
toolchain/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", # NEW "flag_group", # NEW "flag_set", # NEW "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 //main:hello-world
को चलाने पर, आखिर में बाइनरी बननी चाहिए होस्ट के लिए सफलतापूर्वक बनाया गया.toolchain/BUILD
में,cc_toolchain_config
,cc_toolchain
, औरtoolchain
लक्ष्य बनाएं औरlinux_x86_64
कोandroid_x86_64
से बदलें टारगेट के नाम.MODULE.bazel
में, Android के लिए टूलचेन को रजिस्टर करेंregister_toolchains( "//toolchain:cc_toolchain_for_linux_x86_64", "//toolchain:cc_toolchain_for_android_x86_64" )
इसके लिए बाइनरी बनाने के लिए
bazel build //main:hello-world --android_platforms=//toolchain:android_x86_64
चलाएं Android.
Linux और Android में C++ टूलचेन कॉन्फ़िगरेशन अलग-अलग होने चाहिए. आपने लोगों तक पहुंचाया मुफ़्त में
या तो अंतर के लिए मौजूदा cc_toolchain_config
में बदलाव कर सकता है या
अलग-अलग क्वेरी के लिए एक अलग नियम (जैसे, CcToolchainConfigInfo
प्रोवाइडर) बनाएं
प्लैटफ़ॉर्म.
अपने काम की समीक्षा करें
इस ट्यूटोरियल में आपने एक बुनियादी C++ टूलचेन को कॉन्फ़िगर करने का तरीका सीखा, लेकिन इस उदाहरण की तुलना में, टूलचेन ज़्यादा असरदार हैं.
सीखने वाली ज़रूरी बातें:
- आपको इसके लिए कमांड लाइन में मिलान करने वाला
platforms
फ़्लैग तय करना होगा Basel को टूलचेन में, प्लैटफ़ॉर्म. दस्तावेज़ में किसी खास भाषा के बारे में ज़्यादा जानकारी दी गई है कॉन्फ़िगरेशन के लिए फ़्लैग. - आपको टूलचेन को यह बताना होगा कि टूल कहां उपलब्ध हैं. इस ट्यूटोरियल में
एक सरल वर्शन है, जहां सिस्टम से टूल ऐक्सेस किए जाते हैं. अगर आपने
की है, तो ज़्यादा सुरक्षित तरीके से काम करने में आपकी दिलचस्पी है.
बाहरी डिपेंडेंसी. आपके टूल
अलग मॉड्यूल हो सकता है और आपको उनकी फ़ाइलें
cc_toolchain
, जो एट्रिब्यूट पर टारगेट डिपेंडेंसी के साथ काम करता है, जैसे किcompiler_files
.tool_paths
को भी बदलना होगा. - किन फ़्लैग को भेजना है, यह तय करने के लिए आप सुविधाएं बना सकते हैं चाहे वह लिंक करना हो या कोई अन्य कार्रवाई.
इसके बारे में और पढ़ें
ज़्यादा जानकारी के लिए, C++ टूलचेन देखें कॉन्फ़िगरेशन