Trang này mô tả khung chuỗi công cụ, đây là cách để tác giả quy tắc tách rời logic quy tắc của họ khỏi việc chọn công cụ dựa trên nền tảng. Bạn nên đọc các trang quy tắc và nền tảng trước khi tiếp tục. Trang này trình bày lý do cần có chuỗi công cụ, cách để xác định và sử dụng chuỗi công cụ, cũng như cách Bazel chọn một chuỗi công cụ phù hợp dựa trên các ràng buộc về nền tảng.
Động lực
Trước tiên, hãy xem vấn đề mà chuỗi công cụ được thiết kế để giải quyết. Giả sử bạn
đang viết các quy tắc để hỗ trợ ngôn ngữ lập trình "bar". Quy tắc bar_binary
của bạn sẽ biên dịch các tệp *.bar bằng trình biên dịch barc, một công cụ mà bản thân nó
được xây dựng dưới dạng một mục tiêu khác trong không gian làm việc của bạn. Vì người dùng viết bar_binary
mục tiêu không cần phải chỉ định phần phụ thuộc vào trình biên dịch, nên bạn hãy tạo phần phụ thuộc
ngầm bằng cách thêm phần phụ thuộc đó vào định nghĩa quy tắc dưới dạng thuộc tính riêng tư.
bar_binary = rule(
implementation = _bar_binary_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
...
"_compiler": attr.label(
default = "//bar_tools:barc_linux", # the compiler running on linux
providers = [BarcInfo],
),
},
)
//bar_tools:barc_linux hiện là phần phụ thuộc của mọi mục tiêu bar_binary, vì vậy
phần phụ thuộc này sẽ được xây dựng trước bất kỳ mục tiêu bar_binary nào. Bạn có thể truy cập vào phần phụ thuộc này bằng hàm triển khai của quy tắc giống như bất kỳ thuộc tính nào khác:
BarcInfo = provider(
doc = "Information about how to invoke the barc compiler.",
# In the real world, compiler_path and system_lib might hold File objects,
# but for simplicity they are strings for this example. arch_flags is a list
# of strings.
fields = ["compiler_path", "system_lib", "arch_flags"],
)
def _bar_binary_impl(ctx):
...
info = ctx.attr._compiler[BarcInfo]
command = "%s -l %s %s" % (
info.compiler_path,
info.system_lib,
" ".join(info.arch_flags),
)
...
Vấn đề ở đây là nhãn của trình biên dịch được mã hoá cứng vào bar_binary, nhưng
các mục tiêu khác nhau có thể cần các trình biên dịch khác nhau tuỳ thuộc vào nền tảng mà chúng
đang được xây dựng và nền tảng mà chúng đang được xây dựng – lần lượt được gọi là
nền tảng mục tiêu và nền tảng thực thi. Hơn nữa, tác giả quy tắc không nhất thiết phải biết tất cả các công cụ và nền tảng có sẵn, vì vậy, không thể mã hoá cứng các công cụ và nền tảng này trong định nghĩa của quy tắc.
Một giải pháp không lý tưởng là chuyển gánh nặng sang người dùng bằng cách đặt
thuộc tính _compiler thành không riêng tư. Sau đó, các mục tiêu riêng lẻ có thể được
mã hoá cứng để xây dựng cho một nền tảng hoặc nền tảng khác.
bar_binary(
name = "myprog_on_linux",
srcs = ["mysrc.bar"],
compiler = "//bar_tools:barc_linux",
)
bar_binary(
name = "myprog_on_windows",
srcs = ["mysrc.bar"],
compiler = "//bar_tools:barc_windows",
)
Bạn có thể cải thiện giải pháp này bằng cách sử dụng select để chọn compiler
dựa trên nền tảng:
config_setting(
name = "on_linux",
constraint_values = [
"@platforms//os:linux",
],
)
config_setting(
name = "on_windows",
constraint_values = [
"@platforms//os:windows",
],
)
bar_binary(
name = "myprog",
srcs = ["mysrc.bar"],
compiler = select({
":on_linux": "//bar_tools:barc_linux",
":on_windows": "//bar_tools:barc_windows",
}),
)
Tuy nhiên, việc này tẻ nhạt và hơi quá đáng khi yêu cầu mọi người dùng bar_binary.
Nếu kiểu này không được sử dụng nhất quán trong toàn bộ không gian làm việc, thì kiểu này sẽ dẫn đến
các bản dựng hoạt động tốt trên một nền tảng nhưng không thành công khi mở rộng sang
các tình huống đa nền tảng. Kiểu này cũng không giải quyết được vấn đề thêm tính năng hỗ trợ
cho các nền tảng và trình biên dịch mới mà không cần sửa đổi các quy tắc hoặc mục tiêu hiện có.
Khung chuỗi công cụ giải quyết vấn đề này bằng cách thêm một cấp độ gián tiếp bổ sung. Về cơ bản, bạn khai báo rằng quy tắc của bạn có phần phụ thuộc trừu tượng vào một số thành viên của một họ mục tiêu (một loại chuỗi công cụ) và Bazel sẽ tự động phân giải phần phụ thuộc này thành một mục tiêu cụ thể (một chuỗi công cụ) dựa trên các ràng buộc về nền tảng áp dụng. Cả tác giả quy tắc lẫn tác giả mục tiêu đều không cần biết toàn bộ tập hợp các nền tảng và chuỗi công cụ có sẵn.
Viết các quy tắc sử dụng chuỗi công cụ
Trong khung chuỗi công cụ, thay vì các quy tắc phụ thuộc trực tiếp vào công cụ, các quy tắc này sẽ phụ thuộc vào các loại chuỗi công cụ. Loại chuỗi công cụ là một mục tiêu đơn giản đại diện cho một lớp công cụ đóng vai trò tương tự đối với các nền tảng khác nhau. Ví dụ: bạn có thể khai báo một loại đại diện cho trình biên dịch bar :
# By convention, toolchain_type targets are named "toolchain_type" and
# distinguished by their package path. So the full path for this would be
# //bar_tools:toolchain_type.
toolchain_type(name = "toolchain_type")
Định nghĩa quy tắc trong phần trước được sửa đổi để thay vì
nhận trình biên dịch làm thuộc tính, định nghĩa này sẽ khai báo rằng định nghĩa này sử dụng một
//bar_tools:toolchain_type chuỗi công cụ.
bar_binary = rule(
implementation = _bar_binary_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
...
# No `_compiler` attribute anymore.
},
toolchains = ["//bar_tools:toolchain_type"],
)
Hàm triển khai hiện truy cập vào phần phụ thuộc này trong ctx.toolchains
thay vì ctx.attr, sử dụng loại chuỗi công cụ làm khoá.
def _bar_binary_impl(ctx):
...
info = ctx.toolchains["//bar_tools:toolchain_type"].barcinfo
# The rest is unchanged.
command = "%s -l %s %s" % (
info.compiler_path,
info.system_lib,
" ".join(info.arch_flags),
)
...
ctx.toolchains["//bar_tools:toolchain_type"] trả về nhà cung cấp
ToolchainInfo
của bất kỳ mục tiêu nào mà Bazel đã phân giải phần phụ thuộc của chuỗi công cụ thành. Các trường của đối tượng
ToolchainInfo được thiết lập theo quy tắc của công cụ cơ bản; trong
phần tiếp theo, quy tắc này được xác định sao cho có một trường barcinfo bao bọc
đối tượng BarcInfo.
Quy trình của Bazel để phân giải chuỗi công cụ thành các mục tiêu được mô tả
bên dưới. Chỉ mục tiêu chuỗi công cụ đã phân giải mới thực sự
trở thành phần phụ thuộc của mục tiêu bar_binary, chứ không phải toàn bộ không gian của các chuỗi công cụ ứng cử.
Chuỗi công cụ bắt buộc và không bắt buộc
Theo mặc định, khi một quy tắc biểu thị phần phụ thuộc của loại chuỗi công cụ bằng nhãn trần (như minh hoạ ở trên), thì loại chuỗi công cụ được coi là bắt buộc. Nếu Bazel không tìm thấy chuỗi công cụ phù hợp (xem Phân giải chuỗi công cụ bên dưới) cho một loại chuỗi công cụ bắt buộc, thì đây là lỗi và quá trình phân tích sẽ dừng lại.
Thay vào đó, bạn có thể khai báo phần phụ thuộc của loại chuỗi công cụ không bắt buộc như sau:
bar_binary = rule(
...
toolchains = [
config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False),
],
)
Khi không thể phân giải loại chuỗi công cụ không bắt buộc, quá trình phân tích sẽ tiếp tục và kết tích của ctx.toolchains["//bar_tools:toolchain_type"] là None.
Hàm config_common.toolchain_type
mặc định là bắt buộc.
Bạn có thể sử dụng các biểu mẫu sau:
- Các loại chuỗi công cụ bắt buộc:
toolchains = ["//bar_tools:toolchain_type"]toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type")]toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = True)]
- Các loại chuỗi công cụ không bắt buộc:
toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False)]
bar_binary = rule(
...
toolchains = [
"//foo_tools:toolchain_type",
config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False),
],
)
Bạn cũng có thể kết hợp và đối sánh các biểu mẫu trong cùng một quy tắc. Tuy nhiên, nếu cùng một loại chuỗi công cụ được liệt kê nhiều lần, thì loại chuỗi công cụ đó sẽ lấy phiên bản nghiêm ngặt nhất, trong đó bắt buộc sẽ nghiêm ngặt hơn không bắt buộc.
Viết các khía cạnh sử dụng chuỗi công cụ
Các khía cạnh có quyền truy cập vào cùng một API chuỗi công cụ như các quy tắc: bạn có thể xác định các loại chuỗi công cụ bắt buộc , truy cập vào chuỗi công cụ thông qua ngữ cảnh và sử dụng các loại chuỗi công cụ này để tạo các hành động mới bằng chuỗi công cụ.
bar_aspect = aspect(
implementation = _bar_aspect_impl,
attrs = {},
toolchains = ['//bar_tools:toolchain_type'],
)
def _bar_aspect_impl(target, ctx):
toolchain = ctx.toolchains['//bar_tools:toolchain_type']
# Use the toolchain provider like in a rule.
return []
Xác định chuỗi công cụ
Để xác định một số chuỗi công cụ cho một loại chuỗi công cụ nhất định, bạn cần có 3 điều:
Một quy tắc dành riêng cho ngôn ngữ đại diện cho loại công cụ hoặc bộ công cụ. Theo quy ước, tên của quy tắc này có hậu tố "_toolchain".
- Lưu ý: Quy tắc
\_toolchainkhông thể tạo bất kỳ hành động xây dựng nào. Thay vào đó, quy tắc này thu thập các cấu phần phần mềm từ các quy tắc khác và chuyển tiếp các cấu phần phần mềm đó đến quy tắc sử dụng chuỗi công cụ. Quy tắc đó chịu trách nhiệm tạo tất cả các hành động xây dựng.
- Lưu ý: Quy tắc
Một số mục tiêu của loại quy tắc này, đại diện cho các phiên bản của công cụ hoặc bộ công cụ cho các nền tảng khác nhau.
Đối với mỗi mục tiêu như vậy, một mục tiêu được liên kết của quy tắc chung
toolchain, để cung cấp siêu dữ liệu mà khung chuỗi công cụ sử dụng. Mục tiêutoolchainnày cũng tham chiếu đếntoolchain_typeđược liên kết với chuỗi công cụ này. Điều này có nghĩa là một quy tắc_toolchainnhất định có thể được liên kết với bất kỳtoolchain_typenào và chỉ trong một thực thểtoolchainsử dụng quy tắc_toolchainnày thì quy tắc đó mới được liên kết vớitoolchain_type.
Đối với ví dụ đang chạy của chúng tôi, đây là định nghĩa cho quy tắc bar_toolchain. Ví dụ
của chúng tôi chỉ có một trình biên dịch, nhưng các công cụ khác như trình liên kết cũng có thể được
nhóm bên dưới trình biên dịch này.
def _bar_toolchain_impl(ctx):
toolchain_info = platform_common.ToolchainInfo(
barcinfo = BarcInfo(
compiler_path = ctx.attr.compiler_path,
system_lib = ctx.attr.system_lib,
arch_flags = ctx.attr.arch_flags,
),
)
return [toolchain_info]
bar_toolchain = rule(
implementation = _bar_toolchain_impl,
attrs = {
"compiler_path": attr.string(),
"system_lib": attr.string(),
"arch_flags": attr.string_list(),
},
)
Quy tắc phải trả về một ToolchainInfo nhà cung cấp, nhà cung cấp này sẽ trở thành đối tượng mà
quy tắc sử dụng truy xuất bằng ctx.toolchains và nhãn của loại
chuỗi công cụ. ToolchainInfo, giống như struct, có thể chứa các cặp trường-giá trị
tuỳ ý. Thông số kỹ thuật về chính xác những trường nào được thêm vào ToolchainInfo
phải được ghi lại rõ ràng ở loại chuỗi công cụ. Trong ví dụ này, các giá trị
trả về được gói trong một đối tượng BarcInfo để sử dụng lại lược đồ được xác định ở trên; kiểu
này có thể hữu ích cho việc xác thực và sử dụng lại mã.
Bây giờ, bạn có thể xác định các mục tiêu cho các trình biên dịch barc cụ thể.
bar_toolchain(
name = "barc_linux",
arch_flags = [
"--arch=Linux",
"--debug_everything",
],
compiler_path = "/path/to/barc/on/linux",
system_lib = "/usr/lib/libbarc.so",
)
bar_toolchain(
name = "barc_windows",
arch_flags = [
"--arch=Windows",
# Different flags, no debug support on windows.
],
compiler_path = "C:\\path\\on\\windows\\barc.exe",
system_lib = "C:\\path\\on\\windows\\barclib.dll",
)
Cuối cùng, bạn tạo toolchain định nghĩa cho 2 mục tiêu bar_toolchain.
Các định nghĩa này liên kết các mục tiêu dành riêng cho ngôn ngữ với loại chuỗi công cụ và
cung cấp thông tin ràng buộc cho Bazel biết khi nào chuỗi công cụ
phù hợp với một nền tảng nhất định.
toolchain(
name = "barc_linux_toolchain",
exec_compatible_with = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
target_compatible_with = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
toolchain = ":barc_linux",
toolchain_type = ":toolchain_type",
)
toolchain(
name = "barc_windows_toolchain",
exec_compatible_with = [
"@platforms//os:windows",
"@platforms//cpu:x86_64",
],
target_compatible_with = [
"@platforms//os:windows",
"@platforms//cpu:x86_64",
],
toolchain = ":barc_windows",
toolchain_type = ":toolchain_type",
)
Việc sử dụng cú pháp đường dẫn tương đối ở trên cho thấy tất cả các định nghĩa này đều nằm trong cùng một gói
, nhưng không có lý do gì khiến loại chuỗi công cụ, các mục tiêu chuỗi công cụ dành riêng cho ngôn ngữ
và các mục tiêu định nghĩa toolchain không thể nằm trong các gói riêng biệt.
Hãy xem go_toolchain
để biết ví dụ thực tế.
Chuỗi công cụ và cấu hình
Một câu hỏi quan trọng đối với tác giả quy tắc là khi một mục tiêu bar_toolchain được
phân tích, mục tiêu đó sẽ thấy cấu hình nào và những quá trình chuyển đổi
nào sẽ được sử dụng cho các phần phụ thuộc? Ví dụ ở trên sử dụng các thuộc tính chuỗi, nhưng
điều gì sẽ xảy ra đối với một chuỗi công cụ phức tạp hơn phụ thuộc vào các mục tiêu khác
trong kho lưu trữ Bazel?
Hãy xem phiên bản phức tạp hơn của bar_toolchain:
def _bar_toolchain_impl(ctx):
# The implementation is mostly the same as above, so skipping.
pass
bar_toolchain = rule(
implementation = _bar_toolchain_impl,
attrs = {
"compiler": attr.label(
executable = True,
mandatory = True,
cfg = "exec",
),
"system_lib": attr.label(
mandatory = True,
cfg = "target",
),
"arch_flags": attr.string_list(),
},
)
Việc sử dụng attr.label giống như đối với một quy tắc tiêu chuẩn,
nhưng ý nghĩa của tham số cfg hơi khác một chút.
Phần phụ thuộc từ một mục tiêu (gọi là "mẫu gốc") đến một chuỗi công cụ thông qua quá trình phân giải chuỗi công cụ
sử dụng một quá trình chuyển đổi cấu hình đặc biệt có tên là "quá trình chuyển đổi chuỗi công cụ". Quá trình chuyển đổi chuỗi công cụ giữ nguyên cấu hình, ngoại trừ
việc quá trình này buộc nền tảng thực thi phải giống nhau đối với chuỗi công cụ như đối với
mẫu gốc (nếu không, quá trình phân giải chuỗi công cụ cho chuỗi công cụ có thể chọn bất kỳ
nền tảng thực thi nào và không nhất thiết phải giống như đối với mẫu gốc). Điều này
cho phép mọi phần phụ thuộc exec của chuỗi công cụ cũng có thể thực thi cho các hành động xây dựng của
mẫu gốc. Mọi phần phụ thuộc của chuỗi công cụ sử dụng cfg =
"target" (hoặc không chỉ định cfg, vì "target" là giá trị mặc định) đều được
xây dựng cho cùng một nền tảng mục tiêu như mẫu gốc. Điều này cho phép các quy tắc chuỗi công cụ
đóng góp cả thư viện (thuộc tính system_lib ở trên) và công cụ (thuộc tính
compiler) cho các quy tắc xây dựng cần đến các quy tắc này. Các thư viện hệ thống
được liên kết vào cấu phần phần mềm cuối cùng, vì vậy, cần được xây dựng cho cùng một
nền tảng, trong khi trình biên dịch là một công cụ được gọi trong quá trình xây dựng và cần
có khả năng chạy trên nền tảng thực thi.
Đăng ký và xây dựng bằng chuỗi công cụ
Tại thời điểm này, tất cả các khối xây dựng đều được tập hợp và bạn chỉ cần cung cấp
các chuỗi công cụ cho quy trình phân giải của Bazel. Bạn có thể thực hiện việc này bằng cách
đăng ký chuỗi công cụ, trong tệp MODULE.bazel bằng
register_toolchains(), hoặc bằng cách truyền nhãn của chuỗi công cụ trên dòng
lệnh bằng cờ --extra_toolchains.
register_toolchains(
"//bar_tools:barc_linux_toolchain",
"//bar_tools:barc_windows_toolchain",
# Target patterns are also permitted, so you could have also written:
# "//bar_tools:all",
# or even
# "//bar_tools/...",
)
Khi sử dụng mẫu mục tiêu để đăng ký chuỗi công cụ, thứ tự đăng ký các chuỗi công cụ riêng lẻ được xác định theo các quy tắc sau:
- Các chuỗi công cụ được xác định trong một gói con của một gói được đăng ký trước các chuỗi công cụ được xác định trong chính gói đó.
- Trong một gói, các chuỗi công cụ được đăng ký theo thứ tự từ vựng của tên.
Bây giờ, khi bạn xây dựng một mục tiêu phụ thuộc vào một loại chuỗi công cụ, một chuỗi công cụ phù hợp sẽ được chọn dựa trên mục tiêu và nền tảng thực thi.
# my_pkg/BUILD
platform(
name = "my_target_platform",
constraint_values = [
"@platforms//os:linux",
],
)
bar_binary(
name = "my_bar_binary",
...
)
bazel build //my_pkg:my_bar_binary --platforms=//my_pkg:my_target_platform
Bazel sẽ thấy rằng //my_pkg:my_bar_binary đang được xây dựng bằng một nền tảng có @platforms//os:linux và do đó, phân giải tham chiếu //bar_tools:toolchain_type thành //bar_tools:barc_linux_toolchain.
Điều này sẽ dẫn đến việc xây dựng //bar_tools:barc_linux nhưng không xây dựng
//bar_tools:barc_windows.
Phân giải chuỗi công cụ
Đối với mỗi mục tiêu sử dụng chuỗi công cụ, quy trình phân giải chuỗi công cụ của Bazel sẽ xác định các phần phụ thuộc của chuỗi công cụ cụ thể của mục tiêu. Quy trình này nhận một tập hợp các loại chuỗi công cụ bắt buộc, nền tảng mục tiêu, danh sách các nền tảng thực thi có sẵn và danh sách các chuỗi công cụ có sẵn làm đầu vào. Đầu ra của quy trình này là một chuỗi công cụ được chọn cho mỗi loại chuỗi công cụ cũng như một nền tảng thực thi được chọn cho mục tiêu hiện tại.
Các nền tảng thực thi và chuỗi công cụ có sẵn được thu thập từ
biểu đồ phần phụ thuộc bên ngoài thông qua
register_execution_platforms
và
register_toolchains lệnh gọi trong
MODULE.bazelfiles.
Additional execution platforms and toolchains may also be specified on the
command line via
[--extra_execution_platforms](/versions/7.7.0/reference/command-line-reference#flag--extra_execution_platforms)
and
[--extra_toolchains`](/versions/7.7.0/reference/command-line-reference#flag--extra_toolchains).
Nền tảng máy chủ được tự động đưa vào làm nền tảng thực thi có sẵn.
Các nền tảng và chuỗi công cụ có sẵn được theo dõi dưới dạng danh sách có thứ tự để xác định,
ưu tiên các mục trước đó trong danh sách.
Tập hợp các chuỗi công cụ có sẵn, theo thứ tự ưu tiên, được tạo từ
--extra_toolchains và register_toolchains:
- Các chuỗi công cụ được đăng ký bằng
--extra_toolchainsđược thêm vào trước. (Trong số này, chuỗi công cụ cuối cùng có mức độ ưu tiên cao nhất.) - Các chuỗi công cụ được đăng ký bằng
register_toolchainstrong biểu đồ phần phụ thuộc bên ngoài bắc cầu, theo thứ tự sau: (Trong số này, chuỗi công cụ được đề cập đầu tiên có mức độ ưu tiên cao nhất.)- Các chuỗi công cụ được mô-đun gốc đăng ký (như trong
MODULE.bazelở gốc không gian làm việc); - Các chuỗi công cụ được đăng ký trong tệp
WORKSPACEcủa người dùng, bao gồm cả trong mọi macro được gọi từ đó; - Các chuỗi công cụ được đăng ký bởi các mô-đun không phải gốc (như trong các phần phụ thuộc do mô-đun gốc chỉ định và các phần phụ thuộc của chúng, v.v.);
- Các chuỗi công cụ được đăng ký trong "tiền tố WORKSPACE"; tiền tố này chỉ được một số quy tắc gốc đi kèm với bản cài đặt Bazel sử dụng.
- Các chuỗi công cụ được mô-đun gốc đăng ký (như trong
LƯU Ý: Các mục tiêu giả như :all, :* và
/... được sắp xếp theo cơ chế tải
gói của Bazel, sử dụng thứ tự từ vựng.
Các bước phân giải như sau.
Mệnh đề
target_compatible_withhoặcexec_compatible_withkhớp với một nền tảng nếu đối với mỗiconstraint_valuetrong danh sách, nền tảng đó cũng cóconstraint_valueđó (một cách rõ ràng hoặc dưới dạng mặc định).Nếu nền tảng có
constraint_valuetừconstraint_settingkhông được mệnh đề tham chiếu, thì các giá trị này sẽ không ảnh hưởng đến việc so khớp.Nếu mục tiêu đang được xây dựng chỉ định thuộc tính
exec_compatible_with(hoặc định nghĩa quy tắc của mục tiêu đó chỉ định đối sốexec_compatible_with), thì danh sách các nền tảng thực thi có sẵn sẽ được lọc để loại bỏ mọi nền tảng không khớp với các ràng buộc thực thi.Đối với mỗi nền tảng thực thi có sẵn, bạn sẽ liên kết mỗi loại chuỗi công cụ với chuỗi công cụ có sẵn đầu tiên (nếu có) tương thích với nền tảng thực thi này và nền tảng mục tiêu.
Mọi nền tảng thực thi không tìm thấy chuỗi công cụ bắt buộc tương thích cho một trong các loại chuỗi công cụ đều bị loại trừ. Trong số các nền tảng còn lại, nền tảng đầu tiên sẽ trở thành nền tảng thực thi của mục tiêu hiện tại và các chuỗi công cụ được liên kết của nền tảng đó (nếu có) sẽ trở thành phần phụ thuộc của mục tiêu.
Nền tảng thực thi đã chọn được dùng để chạy tất cả các hành động mà mục tiêu tạo ra.
Trong trường hợp cùng một mục tiêu có thể được xây dựng trong nhiều cấu hình (chẳng hạn như cho các CPU khác nhau) trong cùng một bản dựng, quy trình phân giải sẽ được áp dụng độc lập cho từng phiên bản của mục tiêu.
Nếu quy tắc sử dụng các nhóm thực thi, thì mỗi nhóm thực thi sẽ thực hiện quá trình phân giải chuỗi công cụ riêng biệt và mỗi nhóm có nền tảng thực thi và chuỗi công cụ riêng.
Gỡ lỗi chuỗi công cụ
Nếu bạn đang thêm tính năng hỗ trợ chuỗi công cụ vào một quy tắc hiện có, hãy sử dụng cờ
--toolchain_resolution_debug=regex. Trong quá trình phân giải chuỗi công cụ, cờ này
cung cấp đầu ra chi tiết cho các loại chuỗi công cụ hoặc tên mục tiêu khớp với biến regex. Bạn
có thể sử dụng .* để xuất tất cả thông tin. Bazel sẽ xuất tên của các chuỗi công cụ mà Bazel
kiểm tra và bỏ qua trong quá trình phân giải.
Nếu bạn muốn xem các phần phụ thuộc cquery nào là từ quá trình phân giải chuỗi công cụ, hãy sử dụng cquery's cờ --transitions:
# Find all direct dependencies of //cc:my_cc_lib. This includes explicitly
# declared dependencies, implicit dependencies, and toolchain dependencies.
$ bazel cquery 'deps(//cc:my_cc_lib, 1)'
//cc:my_cc_lib (96d6638)
@bazel_tools//tools/cpp:toolchain (96d6638)
@bazel_tools//tools/def_parser:def_parser (HOST)
//cc:my_cc_dep (96d6638)
@local_config_platform//:host (96d6638)
@bazel_tools//tools/cpp:toolchain_type (96d6638)
//:default_host_platform (96d6638)
@local_config_cc//:cc-compiler-k8 (HOST)
//cc:my_cc_lib.cc (null)
@bazel_tools//tools/cpp:grep-includes (HOST)
# Which of these are from toolchain resolution?
$ bazel cquery 'deps(//cc:my_cc_lib, 1)' --transitions=lite | grep "toolchain dependency"
[toolchain dependency]#@local_config_cc//:cc-compiler-k8#HostTransition -> b6df211