Bu eğitimde, C++'ın nasıl yapılandırılacağını açıklayan örnek bir senaryo kullanılmaktadır. araç zincirleri olarak düşünebilirsiniz.
Neler öğreneceksiniz?
Bu eğitimde şunları öğreneceksiniz:
- Derleme ortamını ayarlama
- Araç zinciri çözünürlüğünde hata ayıklamak için
--toolchain_resolution_debug
kullanın - C++ araç zincirini yapılandırma
- Etiket için ek yapılandırma sağlayan bir Starlark kuralı
Bazel'in uygulamayı
clang
ile derleyebilmesi içincc_toolchain
bazel build //main:hello-world
komutunu çalıştırarak Linux makinesibazel build //main:hello-world --platforms=//:android_x86_64
komutunu çalıştırarak Android için ikili programı çapraz derleyin
Başlamadan önce
Bu eğiticide, Linux kullandığınız ve C++ hizmetini başarıyla derlediğiniz varsayılmaktadır
doğru araçları ve kitaplıkları yüklemeniz gerekir. Eğitim
sisteminize yükleyebileceğiniz clang version 16
uygulamasını kullanır.
Derleme ortamını ayarlama
Derleme ortamınızı aşağıdaki gibi ayarlayın:
Henüz yapmadıysanız Bazel'i indirip yükleyin 7.0.2 veya sonraki sürümler.
Kök klasöre boş bir
MODULE.bazel
dosyası ekleyin.main/BUILD
dosyasına aşağıdakicc_binary
hedefini ekleyin:cc_binary( name = "hello-world", srcs = ["hello-world.cc"], )
Çünkü Bazel, derleme sırasında C++ dilinde yazılmış birçok dahili araç kullandığından,
process-wrapper
olarak ayarlanırsa önceden var olan varsayılan C++ araç zinciri belirtilir barındırma platformu için de geçerli. Böylece bu dahili araçlar, mevcut kaynaklarınızla araç zincirini kullanmaya devam edebilirsiniz. Dolayısıyla,cc_binary
hedefi varsayılan araç zinciriyle de derlenmiştir.Derlemeyi aşağıdaki komutla çalıştırın:
bazel build //main:hello-world
Derleme,
MODULE.bazel
içinde kayıtlı herhangi bir araç zinciri olmadan başarılı olur.Gelişmiş seçenekleri daha iyi 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
Bazel,
--platforms
belirtmeden@platforms//host
kullanıyor@bazel_tools+cc_configure_extension+local_config_cc//:cc-compiler-k8
.
C++ araç zincirini yapılandırma
C++ araç zincirini yapılandırmak için uygulamayı sürekli olarak derleyin ve her hatayı aşağıda açıklandığı gibi tek tek güncelleyin.
Ayrıca clang version 9.0.1
varsayılır, ancak ayrıntılar yalnızca değişmelidir
ve clang'ın farklı versiyonları arasında biraz daha
Ş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.bazel
bazel_dep(name = "platforms", version = "0.0.10") register_toolchains( "//toolchain:cc_toolchain_for_linux_x86_64" )
Bu adım bir
cc_toolchain
tanımlar ve bunu birtoolchain
hedefine bağlar. yapılandırdığınızdan emin olun.Derlemeyi tekrar çalıştırın. Çünkü
toolchain
paketi henüzlinux_x86_64_toolchain_config
hedefi belirlendiğinde, Bazel şu 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/BUILD
dosyasında boş bir dosya grubunu aşağıdaki gibi tanımlayın:package(default_visibility = ["//visibility:public"]) filegroup(name = "linux_x86_64_toolchain_config")
Derlemeyi tekrar çalıştırın. Bazel şu hatayı verir:
'//toolchain:linux_x86_64_toolchain_config' does not have mandatory providers: 'CcToolchainConfigInfo'.
CcToolchainConfigInfo
, C++ uygulamanızı yapılandırmak için kullandığınız bir sağlayıcıdır. araç zincirleri olarak düşünebilirsiniz. Bu hatayı düzeltmek için aşağıdakileri sağlayan bir Starlark kuralı oluşturun:CcToolchainConfigInfo
işlemini kullanarak Bazel'e Şu içeriğe sahiptoolchain/cc_toolchain_config.bzl
dosyası: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ştururCcToolchainConfigInfo
.cc_toolchain_config
kuralını kullanmak için bir yük ekleyin deyimini paket ekstresinin hemen altında bulunantoolchain/BUILD
olarak değiştirin:load(":cc_toolchain_config.bzl", "cc_toolchain_config")
"linux_x86_64_toolchain_config" ifadesini ise bildirim içeren dosya grubu
cc_toolchain_config
kuralının sayısı:cc_toolchain_config(name = "linux_x86_64_toolchain_config")
Derlemeyi tekrar çalıştırın. Bazel şu hatayı verir:
.../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 sahip ancak ancak gerekli derlemeyi tamamlamak için hangi araçların kullanılması gerektiğini işlemlerdir. Starlark kuralının uygulanmasını değiştirerek Bazel'a çeşitli araçlar vardır. Bunun için
tool_path()
oluşturucuya@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
ve/usr/bin/ld
yollarının en iyi uygulamaları paylaşacağız.Derlemeyi tekrar çalıştırın. Bazel şu hatayı verir:
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 eklenen başlıkları nerede arayacağını bilmesi gerekiyor. Birden fazla Örneğin
cc_binary
içinincludes
özelliğini kullanmak, Ancak burada bu, tek bir kodla araç zinciri düzeyindecxx_builtin_include_directories
parametresi içincc_common.create_cc_toolchain_config_info
değerini girin. Proje başlatma belgesindeclang
için farklı bir sürüm kullanıyorsanız dahil etme yolu yardımcı olur. Bu yollar ayrıca dağıtıma bağlı olarak farklı olabilir.toolchain/cc_toolchain_config.bzl
bölümündeki döndürülen değeri şu şekilde değiştirin: bu: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ırdığınızda şuna benzer bir hata gösterilir:
/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++ standardının eksik olmasıdır. simgelerini bulamıyor. Bunu çözmenin pek çok yolu var. örneğin
cc_binary
içinlinkopts
özelliğini kullanabilirsiniz. Bu örnekte araç zincirini kullanan herhangi bir hedefin bunu belirtmek zorunda tıklayın.Aşağıdaki kodu
toolchain/cc_toolchain_config.bzl
cihazına 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, nihayet ikili program derlenir işlemi başarıyla tamamlandı.toolchain/BUILD
bölümündekicc_toolchain_config
,cc_toolchain
vetoolchain
hedef velinux_x86_64
yerineandroid_x86_64
daha iyidir.MODULE.bazel
uygulamasında Android için araç zincirini kaydedinregister_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
komutunu çalıştırarak ikili programı derleyin Android
Pratikte, Linux ve Android'in farklı C++ araç zinciri yapılandırmaları olması gerekir. Siz
mevcut cc_toolchain_config
değerini farklar için değiştirebilir veya
farklı veri hizmetleri için ayrı kurallar (ör. CcToolchainConfigInfo
sağlayıcısı)
platformlar.
Çalışmanızı inceleyin
Bu eğiticide temel bir C++ araç zincirinin nasıl yapılandırılacağını öğrendiniz, araç zincirleri bu örnekten daha güçlüdür.
Ana fikirler:
- Şunun için komut satırında eşleşen bir
platforms
işareti belirtmeniz gerekir: platformu. Dokümanlar, dil ile ilgili daha fazla bilgi içerir. yapılandırma işaretleri dahil edilmiştir. - Araç zincirine araçların nerede bulunduğunu bildirmeniz gerekir. Bu eğiticide
araçlara sistemden erişebileceğiniz basitleştirilmiş bir sürümü vardır. Eğer
daha bağımsız bir yaklaşım istiyorsanız
dış bağımlılıklara yol açabilir. Araçlarınız nereden
ve bu modülün sonunda kendi dosyalarını,
Özelliklere hedef bağımlılıkları olan
cc_toolchain
compiler_files
.tool_paths
değerinin de değiştirilmesi gerekir. - Hangi işaretlerin iletileceğini özelleştirmek için özellikler oluşturabilirsiniz. işlemler (ör. bağlantı oluşturma veya başka türden işlemler)
Daha fazla bilgi
Daha fazla ayrıntı için C++ araç zincirine bakın yapılandırma