Trang này mô tả khung chuỗi công cụ, là một cách để các tác giả quy tắc tách logic quy tắc khỏi việc lựa chọn công cụ dựa trên nền tảng. Đó là bạn nên đọc các quy tắc và nền tảng trang 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 định nghĩa và sử dụng chúng, cũng như cách Bazel chọn một chuỗi công cụ phù hợp dựa trên các hạn chế của nền tảng.
Động lực
Trước tiên, hãy xem các chuỗi công cụ giải quyết vấn đề. Giả sử bạn
đang viết các quy tắc để hỗ trợ "thanh" ngôn ngữ lập trình. bar_binary
của bạn
quy tắc sẽ biên dịch các tệp *.bar
bằng cách sử dụng trình biên dịch barc
. Đây là một công cụ mà chính nó
được tạo làm một mục tiêu khác trong không gian làm việc của bạn. Vì những người dùng viết bar_binary
các mục tiêu không cần phải chỉ định một phần phụ thuộc cho trình biên dịch, bạn sẽ biến nó thành một
phần phụ thuộc ngầm ẩn bằng cách thêm nó 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
mã này sẽ được tạo trước mọi mục tiêu bar_binary
. Bạn có thể truy cập quy tắc này bằng
giống như mọi thuộc tính 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
, tuy nhiên
các mục tiêu khác nhau có thể cần trình biên dịch khác nhau tuỳ thuộc vào nền tảng mà chúng
đang được tạo cho mục đích gì và nền tảng nào họ đang được xây dựng – được gọi là
nền tảng mục tiêu và nền tảng thực thi tương ứng. Ngoài ra, quy tắc
tác giả 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 chúng trong định nghĩa của quy tắc.
Một giải pháp kém lý tưởng hơn là chuyển gánh nặng lên người dùng bằng cách tạo ra
thuộc tính _compiler
không ở chế độ riêng tư. Sau đó, các mục tiêu riêng lẻ có thể là
được cố định giá trị trong mã để tạo cho một nền tảng.
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à đòi hỏi hơi nhiều đối với mỗi người dùng bar_binary
.
Nếu kiểu này không được sử dụng một cách nhất quán trong toàn bộ không gian làm việc, sẽ dẫn đến
các bản dựng hoạt động tốt trên một nền tảng duy nhất nhưng không thành công khi được mở rộng tới
trong nhiều nền tảng. Thao tác này cũng không giải quyết được vấn đề khi thêm dịch vụ 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 hay 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. Về cơ bản, bạn khai báo rằng quy tắc của mình có phần phụ thuộc trừu tượng trên một số thành viên của nhóm mục tiêu (loại chuỗi công cụ) và Bazel tự động giải quyết vấn đề này thành một mục tiêu cụ thể (chuỗi công cụ) dựa trên các hạn chế nền tảng hiện hành. Không phải tác giả quy tắc lẫn tác giả đích cần biết toàn bộ các nền tảng và chuỗi công cụ có sẵn.
Quy tắc viết sử dụng chuỗi công cụ
Trong khung chuỗi công cụ, thay vì có các quy tắc phụ thuộc trực tiếp vào công cụ, mà thay vào đó chúng 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ụ có cùng vai trò cho các nền tảng. Ví dụ: bạn có thể khai báo một kiểu đại diện cho thanh trình biên dịch:
# 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ì
lấy trình biên dịch làm thuộc tính, nó khai báo rằng trình biên dịch sử dụng một thuộc tính
Chuỗi công cụ //bar_tools:toolchain_type
.
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ề
ToolchainInfo
nhà cung cấp
bất kỳ mục tiêu nào mà Bazel đã giải quyết phần phụ thuộc của chuỗi công cụ. Các trường của
Đối tượng ToolchainInfo
được đặt theo quy tắc của công cụ cơ bản; tiếp theo
, quy tắc này được định nghĩa để có một trường barcinfo
gói
đối tượng BarcInfo
.
Quy trình phân giải chuỗi công cụ cho các mục tiêu của Bazel được mô tả
bên dưới. Chỉ có mục tiêu chuỗi công cụ được phân giải mới thực sự
tạo ra 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 ứng cử viên
chuỗi 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 loại chuỗi công cụ bằng cách sử dụng nhãn trống (như trình bày ở trên), loại chuỗi công cụ được coi là bắt buộc. Nếu Bazel không thể tìm thấy chuỗi công cụ phù hợp (xem Giải pháp cho chuỗi công cụ ở bên dưới) cho một chuỗi công cụ bắt buộc loại, đây là một lỗi và quá trình phân tích sẽ tạm dừng.
Thay vào đó, bạn có thể khai báo phần phụ thuộc 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 một 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 quả của ctx.toolchains["//bar_tools:toolchain_type"]
là None
config_common.toolchain_type
mặc định của hàm 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à khớp các biểu mẫu trong cùng một quy tắc. Tuy nhiên, nếu cùng chuỗi công cụ được liệt kê nhiều lần thì sẽ lấy phiên bản nghiêm ngặt nhất, trong đó bắt buộc nghiêm ngặt hơn không bắt buộc.
Các khía cạnh viết có sử dụng chuỗi công cụ
Các khung hì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 quy tắc bắt buộc các loại chuỗi công cụ, truy cập chuỗi công cụ thông qua ngữ cảnh và sử dụng chúng để tạo mới các thao tác 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 sau:
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ố là "_toolchain".
- Lưu ý: Quy tắc
\_toolchain
không thể tạo bất kỳ thao tác nào cho bản dựng. Thay vào đó, công cụ này thu thập cấu phần phần mềm từ các quy tắc khác và chuyển tiếp chúng đế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ả tạo hành động.
- Lưu ý: Quy tắc
Một số mục tiêu của loại quy tắc này, thể hiện các phiên bản của công cụ hoặc công cụ này cho các nền tảng khác nhau.
Đối với mỗi mục tiêu như vậy, mục tiêu được liên kết của thuộc tính chung
toolchain
để cung cấp siêu dữ liệu mà khung chuỗi công cụ sử dụng.toolchain
này đích cũng tham chiếu đếntoolchain_type
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_toolchain
nhất định có thể được liên kết với bất kỳ quy tắc nàotoolchain_type
và chỉ thực hiện trong một thực thểtoolchain
sử dụng_toolchain
quy tắc này rằng quy tắc đó sẽ được liên kết vớitoolchain_type
.
Trong ví dụ về cách chạy, sau đây là định nghĩa cho quy tắc bar_toolchain
.
ví dụ này 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 nó.
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 này phải trả về trình cung cấp ToolchainInfo
, trình cung cấp này sẽ trở thành đối tượng
quy tắc tiêu thụ truy xuất bằng cách sử dụng ctx.toolchains
và nhãn của
chuỗi công cụ. ToolchainInfo
, chẳng hạn như struct
, có thể lưu giữ giá trị trường tuỳ ý
cặp. Thông số kỹ thuật cho biết chính xác những trường nào được thêm vào ToolchainInfo
phải được ghi chép rõ ràng theo loại chuỗi công cụ. Trong ví dụ này, giá trị
trả về được gói trong đối tượng BarcInfo
để sử dụng lại giản đồ được xác định ở trên; này
kiểu 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 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 định nghĩa toolchain
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 theo ngôn ngữ cụ thể với loại chuỗi công cụ và
cung cấp thông tin về quy tắc ràng buộc để cho Bazel biết khi nào chuỗi công cụ đượ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 những định nghĩa này đều nằm trong
cùng một gói, nhưng không có lý do gì
là loại chuỗi công cụ, theo ngôn ngữ cụ thể
mục tiêu chuỗi công cụ và mục tiêu định nghĩa toolchain
không thể tách riêng
.
Xem go_toolchain
để xem 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 các tác giả quy tắc là khi mục tiêu bar_toolchain
là
phân tích, nó sẽ nhìn thấy cấu hình nào và chuyển đổi nào
sẽ được dùng cho các phần phụ thuộc không? Ví dụ trên sử dụng thuộc tính chuỗi, nhưng
điều gì sẽ xảy ra 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 một 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ư quy tắc chuẩn,
nhưng ý nghĩa của tham số cfg
hơi khác.
Sự phụ thuộc từ một mục tiêu (gọi là "mẹ") thành một chuỗi công cụ thông qua chuỗi công cụ
sử dụng quá trình chuyển đổi cấu hình đặc biệt được gọi là "chuỗi công cụ"
chuyển đổi". Quá trình chuyển đổi chuỗi công cụ giúp giữ nguyên cấu hình, ngoại trừ
nó buộc nền tảng thực thi phải giống nhau cho chuỗi công cụ
phần tử mẹ (nếu không, độ 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 và không nhất thiết phải giống với nền tảng gốc). Chiến dịch này
cho phép mọi phần phụ thuộc exec
của chuỗi công cụ đều có thể thực thi cho
của phần tử mẹ. 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à mặc định) đều là
được tạo cho cùng một nền tảng mục tiêu với nền tảng mẹ. Đ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
) vào các quy tắc bản dựng cần các thuộc tính này. Thư viện hệ thống
được liên kết với cấu phần phần mềm cuối cùng nên 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 tạo và cần phải
có thể chạy trên nền tảng thực thi.
Đăng ký và tạo bằng chuỗi công cụ
Tại thời điểm này, tất cả các yếu tố nền tảng đã được lắp ráp và bạn chỉ cần thực hiện
các chuỗi công cụ có sẵn cho quy trình giải quyết của Bazel. Việc này được thực hiện bằng
đăng ký chuỗi công cụ, trong một tệp WORKSPACE
sử dụng
register_toolchains()
hoặc bằng cách truyền các chuỗi công cụ nhãn trong lệnh
bằng cách sử dụ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 các mẫu mục tiêu để đăng ký chuỗi công cụ, thứ tự mà chuỗi công cụ riêng lẻ được đăng ký đượ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 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ừ điển học là tên của họ.
Giờ đây, khi bạn tạo một mục tiêu phụ thuộc vào một loại chuỗi công cụ, thì chuỗi công cụ sẽ được chọn dựa trên nền tảng mục tiêu và 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 //my_pkg:my_bar_binary
đang được xây dựng bằng một nền tảng
có @platforms//os:linux
, do đó sẽ giải quyết
Tham chiếu //bar_tools:toolchain_type
đến //bar_tools:barc_linux_toolchain
.
Thao tác này sẽ tạo //bar_tools:barc_linux
nhưng khô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 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 đóng vai trò là dữ liệu đầu vào 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 loại chuỗi công cụ có sẵn nền tảng thực thi và danh sách chuỗi công cụ có sẵn. Kết quả của lớp này là chuỗi công cụ được chọn cho từng loại chuỗi công cụ cũng như một lượt thực thi đã 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ừ
WORKSPACE
tệp qua
register_execution_platforms
và
register_toolchains
.
Các chuỗi công cụ và nền tảng thực thi khác cũng có thể được chỉ định trên
dòng lệnh qua
--extra_execution_platforms
và
--extra_toolchains
.
Nền tảng lưu trữ sẽ tự động được thêm vào dưới dạng một 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ự cho thuật toán tất định,
với lựa chọn ưu tiên cho 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
:
- Những chuỗi công cụ được đăng ký bằng
--extra_toolchains
sẽ được thêm trước.- Trong những chuỗi công cụ này, chuỗi công cụ cuối cùng có mức độ ưu tiên cao nhất.
- Chuỗi công cụ được đăng ký bằng
register_toolchains
- Trong những chuỗi công cụ này, chuỗi công cụ đầu tiên được đề cập có mức độ ưu tiên cao nhất.
LƯU Ý: Mục tiêu giả như :all
, :*
và
/...
được đặt theo gói của Bazel
cơ chế tải, sử dụng thứ tự từ điển.
Các bước giải quyết như sau.
Mệnh đề
target_compatible_with
hoặcexec_compatible_with
khớp với nếu đối với mỗiconstraint_value
trong danh sách, nền tảng cũng cóconstraint_value
(một cách rõ ràng hoặc mặc định).Nếu nền tảng có
constraint_value
từconstraint_setting
thì không được tham chiếu theo mệnh đề, nên việc so khớp sẽ không bị ảnh hưởng.Nếu mục tiêu đang được tạo sẽ chỉ định Thuộc tính
exec_compatible_with
(hoặc định nghĩa quy tắc của quy tắc này chỉ định đối sốexec_compatible_with
), danh sách nền tảng thực thi có sẵn được lọc để loại bỏ bất kỳ mục nào không phù hợp với giới hạn thực thi.Đối với mỗi nền tảng thực thi có sẵn, bạn liên kết từng loại chuỗi công cụ với chuỗi công cụ đầu tiên hiện có (nếu có) tương thích với phương thức 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 đối với một trong các loại chuỗi công cụ của mình sẽ bị loại trừ. Trong số các nền tảng còn lại, đầu tiên trở thành nền tảng thực thi của mục tiêu hiện tại và nền tảng được liên kết chuỗi công cụ (nếu có) 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ả thao tác 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 ở 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 thì 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 nhóm thực thi, thì mỗi lần thực thi group thực hiện phân giải chuỗi công cụ một cách riêng biệt và mỗi chuỗi có quy trình thực thi riêng nền tảng và chuỗi công cụ.
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 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ờ
cung cấp kết quả 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 biểu thức chính quy. 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
và bỏ qua trong quá trình giải quyết.
Nếu bạn muốn biết những phần phụ thuộc cquery
nào đến từ chuỗi công cụ
hãy sử dụng cờ --transitions
của cquery
:
# 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