Bu eğitimde, bir proje için C++ araç zincirlerinin nasıl yapılandırılacağını açıklamak üzere örnek bir senaryo kullanılmaktadır.
Neler öğreneceksiniz?
Bu eğitimde şunları öğreneceksiniz:
- Derleme ortamını ayarlama
- Araç zinciri çözümünde hata ayıklamak için --toolchain_resolution_debugkullanma
- C++ araç zincirini yapılandırma
- Bazel'in uygulamayı clangile oluşturabilmesi içincc_toolchainile ilgili ek yapılandırma sağlayan bir Starlark kuralı oluşturun.
- Linux makinesinde bazel build //main:hello-worldkomutunu çalıştırarak C++ ikilisini oluşturun.
- bazel build //main:hello-world --platforms=//:android_x86_64komutunu çalıştırarak Android için ikili dosyayı çapraz derleyin.
Başlamadan önce
Bu eğitimde, Linux kullandığınız ve C++ uygulamalarını başarıyla oluşturup uygun araçları ve kitaplıkları yüklediğiniz varsayılır. Eğitimde, sisteminize yükleyebileceğiniz clang version 16 kullanılıyor.
Derleme ortamını ayarlama
Derleme ortamınızı aşağıdaki gibi ayarlayın:
- Henüz yapmadıysanız Bazel 7.0.2 veya sonraki bir sürümü indirip yükleyin. 
- Kök klasöre boş bir - MODULE.bazeldosyası ekleyin.
- main/BUILDdosyasına aşağıdaki- cc_binaryhedefini ekleyin:- cc_binary( name = "hello-world", srcs = ["hello-world.cc"], )- Bazel, derleme sırasında - process-wrappergibi C++ ile yazılmış birçok dahili araç kullandığından, ana makine platformu için önceden var olan varsayılan C++ araç zinciri belirtilir. Bu sayede, bu dahili araçlar, bu eğiticide oluşturulan araç zincirini kullanarak geliştirme yapabilir. Bu nedenle,- cc_binaryhedefi de varsayılan araç zinciriyle oluşturulur.
- Aşağıdaki komutla derlemeyi çalıştırın: - bazel build //main:hello-world- Derleme, - MODULE.bazel'da kayıtlı herhangi bir araç zinciri olmadan başarılı olur.- İşleyişin ayrıntılarını görmek için şu komutu çalıştırın: - 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- --platformsbelirtilmeden Bazel,- @bazel_tools+cc_configure_extension+local_config_cc//:cc-compiler-k8kullanarak- @platforms//hostiçin hedefi oluşturur.
C++ araç zincirini yapılandırma
C++ araç zincirini yapılandırmak için uygulamayı tekrar tekrar oluşturun ve her hatayı tek tek giderin.
Ayrıca, ayrıntılar clang'in farklı sürümleri arasında yalnızca biraz değişse de clang version 9.0.1 olduğu varsayılır.
- Şunu ekle: - 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", ], )- Ardından uygun bağımlılıkları ekleyin ve araç zincirini - MODULE.bazelile kaydedin.- bazel_dep(name = "platforms", version = "0.0.10") register_toolchains( "//toolchain:cc_toolchain_for_linux_x86_64" )- Bu adım, bir - cc_toolchaintanımlar ve bunu ana makine yapılandırması için bir- toolchainhedefine bağlar.
- Derlemeyi tekrar çalıştırın. - toolchainpaketi henüz- linux_x86_64_toolchain_confighedefini tanımlamadığı için Bazel aşağıdaki hatayı verir:- 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/BUILDdosyasında boş bir dosya grubu tanımlayın:- package(default_visibility = ["//visibility:public"]) filegroup(name = "linux_x86_64_toolchain_config")
- Derlemeyi tekrar çalıştırın. Bazel aşağıdaki hatayı veriyor: - '//toolchain:linux_x86_64_toolchain_config' does not have mandatory providers: 'CcToolchainConfigInfo'.- CcToolchainConfigInfo, C++ araç zincirlerinizi yapılandırmak için kullandığınız bir sağlayıcıdır. Bu hatayı düzeltmek için aşağıdaki içeriğe sahip bir- toolchain/cc_toolchain_config.bzldosyası oluşturarak Bazel'e- CcToolchainConfigInfosağlayan bir Starlark kuralı oluşturun:- 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()gerekli sağlayıcıyı oluşturur- CcToolchainConfigInfo.- cc_toolchain_configkuralını kullanmak için paket ifadesinin hemen altına- toolchain/BUILDyükleme ifadesi ekleyin:- load(":cc_toolchain_config.bzl", "cc_toolchain_config")- Ayrıca "linux_x86_64_toolchain_config" filegroup'u - cc_toolchain_configkuralının bildirimiyle değiştirin:- cc_toolchain_config(name = "linux_x86_64_toolchain_config")
- Derlemeyi tekrar çalıştırın. Bazel aşağıdaki hatayı veriyor: - .../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`- Bu noktada Bazel, kodu oluşturmayı denemek için yeterli bilgiye sahiptir ancak gerekli derleme işlemlerini tamamlamak için hangi araçların kullanılacağını hâlâ bilmemektedir. Starlark kuralı uygulamasını, Bazel'e hangi araçların kullanılacağını söyleyecek şekilde değiştireceksiniz. Bunun için - @bazel_tools//tools/cpp:cc_toolchain_config_lib.bzlkaynağından- tool_path()oluşturucusu gerekir:- # 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/clangve- /usr/bin/ld'nin sisteminiz için doğru yollar olduğundan emin olun.
- Derlemeyi tekrar çalıştırın. Bazel aşağıdaki hatayı veriyor: - 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' ...- Bazel'in, dahil edilen üstbilgileri nerede arayacağını bilmesi gerekir. Bunu çözmenin birden fazla yolu vardır (ör. - cc_binaryöğesinin- includesözelliğini kullanma). Ancak burada bu sorun,- cc_common.create_cc_toolchain_config_infoöğesinin- cxx_builtin_include_directoriesparametresiyle araç zinciri düzeyinde çözülür.- clang'nın farklı bir sürümünü kullanıyorsanız ekleme yolunun farklı olacağını unutmayın. Bu yollar, dağıtıma bağlı olarak da farklılık gösterebilir.- toolchain/cc_toolchain_config.bzliçindeki dönüş değerini aşağıdaki gibi değiştirin:- 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, )
- Derleme komutunu tekrar çalıştırın. Şuna benzer bir hata görürsünüz: - /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'- Bunun nedeni, bağlayıcıda C++ standart kitaplığının olmaması ve sembollerinin bulunamamasıdır. Bu sorunu çözmenin birçok yolu vardır. Örneğin, - cc_binaryöğesinin- linkoptsözelliğini kullanabilirsiniz. Burada, araç zincirini kullanan herhangi bir hedefin bu işareti belirtmesi gerekmediğinden sorun çözülmüştür.- Aşağıdaki kodu - toolchain/cc_toolchain_config.bzlkonumuna kopyalayın:- # 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çalıştırıldığında, ana makine için ikili dosya başarıyla oluşturulmalıdır.
- toolchain/BUILDiçinde- cc_toolchain_config,- cc_toolchainve- toolchainhedeflerini kopyalayın ve hedef adlarında- linux_x86_64yerine- android_x86_64yazın.- MODULE.bazelbölümünde, Android için araç zincirini kaydedin.- register_toolchains( "//toolchain:cc_toolchain_for_linux_x86_64", "//toolchain:cc_toolchain_for_android_x86_64" )
- Android için ikili dosya oluşturmak üzere - bazel build //main:hello-world --android_platforms=//toolchain:android_x86_64komutunu çalıştırın.
Uygulamada, Linux ve Android'in farklı C++ araç zinciri yapılandırmaları olmalıdır. Farklılıklar için mevcut cc_toolchain_config öğesini değiştirebilir veya ayrı platformlar için ayrı kurallar (ör. CcToolchainConfigInfo sağlayıcı) oluşturabilirsiniz.
Çalışmanızı inceleme
Bu eğitimde, temel bir C++ araç zincirinin nasıl yapılandırılacağını öğrendiniz. Ancak araç zincirleri bu örnekten daha güçlüdür.
Önemli noktalar:
- Bazel'in platformdaki aynı kısıtlama değerlerine sahip araç zincirini çözebilmesi için komut satırında eşleşen bir platformsişareti belirtmeniz gerekir. Dokümanda dile özgü yapılandırma işaretleri hakkında daha fazla bilgi yer almaktadır.
- Araç zincirine araçların nerede bulunduğunu bildirmeniz gerekir. Bu eğitimin basitleştirilmiş bir sürümünde, araçlara sistemden erişebilirsiniz. Daha bağımsız bir yaklaşımla ilgileniyorsanız harici bağımlılıklar hakkında bilgi edinebilirsiniz. Araçlarınız farklı bir modülden gelebilir ve dosyalarını cc_toolchainiçin kullanılabilir hale getirmeniz gerekir. Bu araçlar,compiler_filesgibi özelliklere yönelik hedef bağımlılıklar içerir.tool_pathsde değiştirilmelidir.
- Bağlantı oluşturma veya başka bir işlem türü olsun, hangi işaretlerin farklı işlemlere iletileceğini özelleştirmek için özellikler oluşturabilirsiniz.
Daha fazla bilgi
Daha fazla bilgi için C++ toolchain yapılandırması başlıklı makaleyi inceleyin.