इस ट्यूटोरियल में उदाहरण के तौर पर, किसी प्रोजेक्ट के लिए C++ टूलचेन को कॉन्फ़िगर करने का तरीका बताया गया है.
आप इन चीज़ों के बारे में जानेंगे
इस ट्यूटोरियल में आपको ये काम करने का तरीका पता चलेगा:
- बिल्ड एनवायरमेंट को सेट अप करें
- टूलचेन रिज़ॉल्यूशन को डीबग करने के लिए,
--toolchain_resolution_debug
का इस्तेमाल करना - C++ टूलचेन कॉन्फ़िगर करना
- Starlark का ऐसा नियम बनाएं जो
cc_toolchain
के लिए अतिरिक्त कॉन्फ़िगरेशन उपलब्ध कराता हो, ताकि Ba हटाना,clang
का इस्तेमाल करके ऐप्लिकेशन बना सके - Linux मशीन पर
bazel build //main:hello-world
चलाकर, C++ बाइनरी बनाएं bazel build //main:hello-world --platforms=//:android_x86_64
चलाकर, Android के लिए बाइनरी को क्रॉस-कंपाइल करें
वेब कंटेनर इंस्टॉल करने से पहले
इस ट्यूटोरियल में यह मान लिया गया है कि आप Linux का इस्तेमाल कर रहे हैं और आपने C++ ऐप्लिकेशन बना लिए हैं और ज़रूरी टूल और लाइब्रेरी इंस्टॉल कर ली हैं.
ट्यूटोरियल में clang version 16
का इस्तेमाल किया गया है, जिसे अपने सिस्टम पर इंस्टॉल किया जा सकता है.
बिल्ड एनवायरमेंट को सेट अप करें
बिल्ड एनवायरमेंट को इस तरह सेट अप करें:
अगर आपने पहले से ऐसा नहीं किया है, तो Basel 7.0.2 या उसके बाद के वर्शन को डाउनलोड और इंस्टॉल करें.
रूट फ़ोल्डर में कोई खाली
WORKSPACE
फ़ाइल जोड़ें.main/BUILD
फ़ाइल में, यहcc_binary
टारगेट जोड़ें:load("@rules_cc//cc:defs.bzl", "cc_binary") cc_binary( name = "hello-world", srcs = ["hello-world.cc"], )
Basel, बिल्ड के दौरान C++ में लिखे गए कई इंटरनल टूल इस्तेमाल करता है, जैसे कि
process-wrapper
. इसलिए, होस्ट प्लैटफ़ॉर्म के लिए पहले से मौजूद डिफ़ॉल्ट C++ टूलचेन की जानकारी दी जाती है. इसकी मदद से, ये इंटरनल टूल, इस ट्यूटोरियल में बनाए गए टूलचेन के इस्तेमाल से बनाए जा सकते हैं. इसलिए,cc_binary
टारगेट को डिफ़ॉल्ट टूलचेन की मदद से भी बनाया गया है.बिल्ड को नीचे दिए गए निर्देश के साथ चलाएं:
bazel build //main:hello-world
WORKSPACE
में रजिस्टर किए गए किसी भी टूलचेन के बिना, बिल्ड सफल हो जाता है.यह देखने के लिए कि आगे क्या है, चलाएं:
bazel build //main:hello-world --toolchain_resolution_debug='@bazel_tools//tools/cpp:toolchain_type' INFO: ToolchainResolution: Target platform @@local_config_platform//:host: Selected execution platform @@local_config_platform//:host, type @@bazel_tools//tools/cpp:toolchain_type -> toolchain @@bazel_tools~cc_configure_extension~local_config_cc//:cc-compiler-k8
--platforms
तय किए बिना, Basel ने@bazel_tools//cc_configure_extension/local_config_cc//:cc-compiler-k8
का इस्तेमाल करके@local_config_platform//:host
के लिए टारगेट बनाया
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", ], )
इसके बाद,
WORKSPACE
के साथ टूलचेन को रजिस्टर करें. इसके लिए, इनकी मदद लें:register_toolchains( "//toolchain:cc_toolchain_for_linux_x86_64" )
यह चरण,
cc_toolchain
को तय करता है और इसे होस्ट कॉन्फ़िगरेशन के लिए,toolchain
टारगेट से बाइंड करता है.बिल्ड को फिर से चलाएं.
toolchain
पैकेज, अब तकlinux_x86_64_toolchain_config
टारगेट को तय नहीं कर सका. इसलिए, Basel को यह गड़बड़ी दिखती है: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 का नियम बनाएं. यह नियम इस कॉन्टेंट वाली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
नियम का इस्तेमाल करने के लिए, पैकेज स्टेटमेंट के ठीक नीचे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 नियम लागू करने के तरीके में बदलाव करना होगा. इसके लिए, आपको
@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
आपके सिस्टम के लिए सही पाथ हैं.बिल्ड को फिर से चलाएं. बेज़ल यह गड़बड़ी दिखाता है:
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
एट्रिब्यूट का इस्तेमाल करना. हालांकि, यहां इसे टूलचेन लेवल पर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-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
से बदल दें.WORKSPACE
में, Android के लिए टूलचेन को रजिस्टर करेंregister_toolchains( "//toolchain:cc_toolchain_for_linux_x86_64", "//toolchain:cc_toolchain_for_android_x86_64" )
Android के लिए बाइनरी बनाने के लिए,
bazel build //main:hello-world --android_platforms=//toolchain:android_x86_64
चलाएं.
Linux और Android में C++ टूलचेन कॉन्फ़िगरेशन अलग-अलग होने चाहिए. दोनों में अंतर के लिए, मौजूदा cc_toolchain_config
में बदलाव किया जा सकता है या अलग-अलग प्लैटफ़ॉर्म के लिए अलग नियम (जैसे, CcToolchainConfigInfo
प्रोवाइडर) बनाए जा सकते हैं.
अपने काम की समीक्षा करें
इस ट्यूटोरियल में आपने एक बुनियादी C++ टूलचेन को कॉन्फ़िगर करने का तरीका सीखा है, लेकिन टूलचेन इस आसान उदाहरण से ज़्यादा असरदार हैं.
सीखने लायक ज़रूरी बातें:
- आपको कमांड लाइन में, मेल खाने वाले
platforms
फ़्लैग की ज़रूरत होगी. ऐसा करने से, प्लैटफ़ॉर्म पर एक जैसी कंस्ट्रेंट वैल्यू के लिए टूलचेन को हल किया जा सकेगा. दस्तावेज़ में किसी खास भाषा के कॉन्फ़िगरेशन फ़्लैग के बारे में ज़्यादा जानकारी दी गई है. - आपको टूलचेन को यह बताना होगा कि टूल कहां उपलब्ध हैं. इस ट्यूटोरियल में, एक आसान वर्शन दिया गया है. इसमें सिस्टम से टूल ऐक्सेस किए जाते हैं. अगर
आपकी दिलचस्पी अपने-आप में पूरी जानकारी देने वाली है, तो
फ़ाइल फ़ोल्डर के बारे में पढ़ें. आपके टूल किसी अलग फ़ाइल फ़ोल्डर से आ सकते हैं और आपको
compiler_files
जैसे एट्रिब्यूट के आधार पर,cc_toolchain
में उनकी फ़ाइलें उपलब्ध करानी होंगी.tool_paths
को भी बदलना होगा. - आपके पास यह कस्टमाइज़ करने के लिए सुविधाएं बनाने का विकल्प होता है कि अलग-अलग कार्रवाइयों के लिए कौनसे फ़्लैग भेजे जाने चाहिए. जैसे, लिंक करना या कोई दूसरी कार्रवाई.
इसके बारे में और पढ़ें
ज़्यादा जानकारी के लिए, C++ टूलचेन कॉन्फ़िगरेशन पर जाएं