Tutorial ini menggunakan contoh skenario untuk menjelaskan cara mengonfigurasi C++ toolchain untuk sebuah project.
Yang akan Anda pelajari
Dalam tutorial ini, Anda akan mempelajari cara:
- Menyiapkan lingkungan build
- Menggunakan
--toolchain_resolution_debug
untuk men-debug resolusi toolchain - Mengonfigurasi toolchain C++
- Buat aturan Starlark yang menyediakan konfigurasi tambahan untuk
cc_toolchain
agar Bazel dapat membangun aplikasi denganclang
- Bangun biner C++ dengan menjalankan
bazel build //main:hello-world
pada Mesin Linux - Kompilasi silang biner untuk android dengan menjalankan
bazel build //main:hello-world --platforms=//:android_x86_64
Sebelum memulai
Tutorial ini mengasumsikan bahwa Anda menggunakan Linux dan telah berhasil membuat C++
aplikasi dan menginstal alat dan library yang sesuai. Tutorial
menggunakan clang version 16
, yang dapat Anda instal di sistem.
Menyiapkan lingkungan build
Siapkan lingkungan build Anda seperti berikut:
Jika Anda belum melakukannya, download dan instal Bazel 7.0.2 atau yang lebih baru.
Tambahkan file
MODULE.bazel
kosong di folder root.Tambahkan target
cc_binary
berikut ke filemain/BUILD
:cc_binary( name = "hello-world", srcs = ["hello-world.cc"], )
Karena Bazel menggunakan banyak {i>tool<i} internal yang ditulis dalam C++ selama {i>build<i}, seperti sebagai
process-wrapper
, toolchain C++ default yang sudah ada akan ditentukan untuk platform host. Hal ini memungkinkan alat internal ini membangun menggunakan toolchain dari yang dibuat dalam tutorial ini. Oleh karena itu, targetcc_binary
juga dibuat dengan toolchain default.Jalankan build dengan perintah berikut:
bazel build //main:hello-world
Build akan berhasil tanpa toolchain yang terdaftar di
MODULE.bazel
.Untuk melihat apa yang ada di balik layar, jalankan:
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
Tanpa menetapkan
--platforms
, Bazel membuat target untuk@platforms//host
menggunakan@bazel_tools+cc_configure_extension+local_config_cc//:cc-compiler-k8
.
Mengonfigurasi toolchain C++
Untuk mengonfigurasi toolchain C++, bangun aplikasi berulang kali dan hilangkan tiap {i>error<i} satu per satu seperti yang dijelaskan di bawah ini.
Tutorial ini juga mengasumsikan clang version 9.0.1
, meskipun detailnya hanya akan berubah.
sedikit di antara
versi {i>clang<i} yang berbeda.
Tambahkan
toolchain/BUILD
denganfilegroup(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", ], )
Kemudian tambahkan dependensi yang sesuai dan daftarkan toolchain dengan
MODULE.bazel
denganbazel_dep(name = "platforms", version = "0.0.10") register_toolchains( "//toolchain:cc_toolchain_for_linux_x86_64" )
Langkah ini menentukan
cc_toolchain
dan mengikatnya ke targettoolchain
untuk konfigurasi {i>host<i}.Jalankan build lagi. Karena paket
toolchain
belum menentukan Targetlinux_x86_64_toolchain_config
, Bazel akan menampilkan error berikut: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.
Di file
toolchain/BUILD
, tentukan grup file kosong sebagai berikut:package(default_visibility = ["//visibility:public"]) filegroup(name = "linux_x86_64_toolchain_config")
Jalankan build lagi. Bazel menampilkan error berikut:
'//toolchain:linux_x86_64_toolchain_config' does not have mandatory providers: 'CcToolchainConfigInfo'.
CcToolchainConfigInfo
adalah penyedia yang Anda gunakan untuk mengonfigurasi C++ toolchain. Untuk memperbaiki {i>error<i} ini, buat aturan Starlark yang memberikanCcToolchainConfigInfo
ke Bazel dengan membuattoolchain/cc_toolchain_config.bzl
dengan konten berikut: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()
membuat penyedia yang diperlukanCcToolchainConfigInfo
. Untuk menggunakan aturancc_toolchain_config
, tambahkan beban menjaditoolchain/BUILD
tepat di bawah pernyataan paket:load(":cc_toolchain_config.bzl", "cc_toolchain_config")
Dan ganti file "linux_x86_64_ toolchain_config" filegroup dengan deklarasi dari aturan
cc_toolchain_config
:cc_toolchain_config(name = "linux_x86_64_toolchain_config")
Jalankan build lagi. Bazel menampilkan error berikut:
.../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`
Pada titik ini, Bazel memiliki cukup informasi untuk mencoba membuat kode tetapi mereka masih belum tahu alat apa yang digunakan untuk menyelesaikan build yang dibutuhkan tindakan. Anda akan memodifikasi implementasi aturan Starlark untuk memberi tahu Bazel apa yang peralatan yang tepat untuk digunakan. Untuk itu, Anda memerlukan konstruktor
tool_path()
dari@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 )
Pastikan
/usr/bin/clang
dan/usr/bin/ld
adalah jalur yang benar untuk sistem Anda.Jalankan build lagi. Bazel menampilkan error berikut:
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 perlu tahu di mana harus mencari {i>header<i} yang disertakan. Ada beberapa cara untuk menyelesaikan masalah ini, seperti menggunakan atribut
includes
daricc_binary
, tapi di sini ini diselesaikan di level toolchain dengancxx_builtin_include_directories
daricc_common.create_cc_toolchain_config_info
. Berhati-hatilah jika Anda menggunakan versiclang
yang berbeda, jalur yang disertakan akan menjadi berbeda. Jalur ini mungkin juga berbeda tergantung pada distribusinya.Ubah nilai yang ditampilkan di
toolchain/cc_toolchain_config.bzl
agar terlihat seperti ini ini: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, )
Jalankan perintah build lagi, Anda akan melihat error seperti:
/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'
Alasannya adalah karena linker tidak memiliki standar C++ {i>library<i} dan tidak dapat menemukan simbolnya. Ada banyak cara untuk menyelesaikan ini, seperti menggunakan atribut
linkopts
daricc_binary
. Di sini masalah diselesaikan dengan memastikan bahwa setiap target yang menggunakan rantai alat tidak perlu menentukan penanda.Salin kode berikut ke
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], )
Menjalankan
bazel build //main:hello-world
, akhirnya harus membangun biner berhasil untuk {i>host<i}.Di
toolchain/BUILD
, salincc_toolchain_config
,cc_toolchain
, dantoolchain
target dan gantilinux_x86_64
denganandroid_x86_64
di nama target.Di
MODULE.bazel
, daftarkan toolchain untuk Androidregister_toolchains( "//toolchain:cc_toolchain_for_linux_x86_64", "//toolchain:cc_toolchain_for_android_x86_64" )
Jalankan
bazel build //main:hello-world --android_platforms=//toolchain:android_x86_64
untuk membangun biner Android.
Dalam praktiknya, Linux dan Android harus memiliki konfigurasi toolchain C++ yang berbeda. Anda
dapat memodifikasi cc_toolchain_config
yang ada untuk perbedaan atau
buat aturan terpisah (yaitu penyedia CcToolchainConfigInfo
) untuk aturan terpisah
di berbagai platform Google.
Tinjau tugas Anda
Dalam tutorial ini, Anda telah mempelajari cara mengonfigurasi toolchain C++ dasar, tetapi toolchain lebih canggih daripada contoh ini.
Poin-poin penting adalah:
- Anda perlu menentukan flag
platforms
yang cocok dalam command line untuk Bazel untuk me-resolve ke toolchain untuk nilai batasan yang sama di terkelola sepenuhnya. Dokumentasi ini menyimpan informasi selengkapnya tentang bahasa tertentu flag konfigurasi. - Anda harus memberi tahu toolchain terkait tempat alat tersebut berada. Dalam tutorial ini
terdapat versi sederhana di mana Anda
dapat mengakses alat dari sistem. Jika
Anda tertarik dengan pendekatan yang
lebih mandiri, Anda dapat membaca
dependensi eksternal. Alat Anda bisa berasal dari
modul yang berbeda dan Anda harus
membuat file mereka tersedia untuk
cc_toolchain
dengan dependensi target pada atribut, seperticompiler_files
.tool_paths
juga harus diubah. - Anda dapat membuat fitur untuk menyesuaikan tanda yang harus diteruskan tindakan yang berbeda, baik itu menautkan atau jenis tindakan lainnya.
Bacaan lebih lanjut
Untuk mengetahui detail selengkapnya, lihat Toolchain C++ konfigurasi