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
- Ek özellikler sağlayan bir Starlark kuralı
Bazel'in uygulamayı derleyebilmesi için
cc_toolchain
yapılandırmasıclang
ile - Şu komutu çalıştırarak C++ ikili programını derleyin:
Bir Linux makinesinde
bazel build //main:hello-world
bazel 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 başarıyla geliştirdiğiniz varsayılmaktadır.
C++ uygulamalarını yükleyebilir ve uygun araçlar ile kitaplıkları yükleyebilirsiniz.
Eğitimde, sisteminize yükleyebileceğiniz clang version 16
kullanılır.
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ünü indirip yüklemeniz gerekir.
Kök klasöre boş bir
WORKSPACE
dosyası ekleyin.main/BUILD
dosyasına aşağıdakicc_binary
hedefini ekleyin:load("@rules_cc//cc:defs.bzl", "cc_binary") 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, barındırma platformu. Böylece bu dahili araçlar, mevcut kaynaklarınızla araç zincirini kullanmaya devam edebilirsiniz. Bu nedenle,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,
WORKSPACE
içinde kayıtlı herhangi bir araç zinciri olmadan başarılı olur.Gelişmiş seçenekleri daha fazla 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 @@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
Bazel,
--platforms
belirtmeden@local_config_platform//: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
clang'ın farklı versiyonları arasında
biraz fark var.
Ş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 araç zincirini
WORKSPACE
öğesine kaydedin.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
, yapılandırmak için kullandığınız bir sağlayıcıdır çok önemlidir. Bu hatayı düzeltmek için bir Starlark kuralı oluşturun oluşturarak Bazel'eCcToolchainConfigInfo
sağlayan bir Ş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
@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 doğru olduğundan emin olun bir uygulamadır.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. Her biri 100'den az gösterim alan bunu çözmek için
includes
cc_binary
, ancak burada bu,cxx_builtin_include_directories
parametresi içincc_common.create_cc_toolchain_config_info
değerini girin. Bu nedenle, farklı birclang
sürümünü 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 değiştirerek aşağıdaki gibidir: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, belirli bir 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 ana makine için ikili programın başarıyla derlenmesi gerekir.toolchain/BUILD
bölümündekicc_toolchain_config
,cc_toolchain
vetoolchain
hedef velinux_x86_64
yerineandroid_x86_64
değerini hedefle gösterir.WORKSPACE
uygulamasında Android için araç zincirini kaydedinregister_toolchains( "//toolchain:cc_toolchain_for_linux_x86_64", "//toolchain:cc_toolchain_for_android_x86_64" )
Android için ikili programı derlemek üzere
bazel build //main:hello-world --android_platforms=//toolchain:android_x86_64
komutunu çalıştırın.
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 basit örnekten daha güçlüdür.
Ana fikirler:
- Bazel'ın şunları yapması için komut satırında eşleşen bir
platforms
işareti belirtmeniz gerekir: platformdaki aynı kısıtlama değerleri için araç zincirine çözümlenir. Dokümanlarda, 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ğ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
çalışma alanları gibi diğer işlevler de dahildir. Araçlarınız nereden
ve onlara ait dosyaları kullanılabilir hale getirmeniz,
cc_toolchain
ilecompiler_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 bilgi için bkz. C++ araç zinciri yapılandırması