Bazel có thể phụ thuộc vào mục tiêu của các dự án khác. Các phần phụ thuộc từ các thành phần khác các dự án đó được gọi là phần phụ thuộc bên ngoài.
Tệp WORKSPACE
(hoặc WORKSPACE.bazel
) trong
thư mục workspace
cho Bazel biết cách lấy các dự án khác nguồn. Các dự án khác này có thể
chứa một hoặc nhiều tệp BUILD
với mục tiêu riêng. BUILD
tệp trong
dự án chính có thể phụ thuộc vào các mục tiêu bên ngoài này
bằng cách sử dụng tên của chúng từ
tệp WORKSPACE
.
Ví dụ: giả sử có hai dự án trên một hệ thống:
/
home/
user/
project1/
WORKSPACE
BUILD
srcs/
...
project2/
WORKSPACE
BUILD
my-libs/
Nếu project1
muốn phụ thuộc vào một mục tiêu, :foo
, được xác định trong
/home/user/project2/BUILD
, thì lớp này có thể chỉ định rằng một kho lưu trữ có tên
Có thể tìm thấy project2
tại /home/user/project2
. Sau đó nhắm mục tiêu trong
/home/user/project1/BUILD
có thể phụ thuộc vào @project2//:foo
.
Tệp WORKSPACE
cho phép người dùng phụ thuộc vào mục tiêu từ các phần khác của
hệ thống tệp hoặc được tải xuống từ Internet. Hàm này sử dụng cú pháp giống như BUILD
nhưng cho phép một bộ quy tắc khác được gọi là quy tắc kho lưu trữ (đôi khi
còn gọi là quy tắc không gian làm việc). Bazel đi kèm với một vài kho lưu trữ tích hợp sẵn
các quy tắc và tập hợp kho lưu trữ Starlark được nhúng
. Người dùng cũng có thể ghi kho lưu trữ tuỳ chỉnh
để có được hành vi phức tạp hơn.
Các loại phần phụ thuộc bên ngoài được hỗ trợ
Bạn có thể sử dụng một số kiểu phần phụ thuộc bên ngoài cơ bản sau:
- Phần phụ thuộc vào các dự án Bazel khác
- Phần phụ thuộc vào các dự án không phải Bazel
- Phần phụ thuộc vào gói bên ngoài
Tuỳ thuộc vào các dự án khác của Bazel
Nếu muốn sử dụng các mục tiêu từ dự án Bazel thứ hai, bạn có thể
sử dụng
local_repository
!
git_repository
hoặc http_archive
để liên kết tượng trưng từ hệ thống tệp cục bộ, hãy tham khảo kho lưu trữ git hoặc tải xuống
video (tương ứng).
Ví dụ: giả sử bạn đang làm việc cho một dự án, my-project/
và bạn muốn
phụ thuộc vào các mục tiêu trong dự án coworkers-project/
của một đồng nghiệp. Cả hai
các dự án này đều sử dụng Bazel, vì vậy, bạn có thể thêm dự án của đồng nghiệp dưới dạng một dự án
rồi sử dụng bất kỳ mục tiêu nào mà đồng nghiệp của bạn đã tự xác định
XÂY DỰNG tệp. Bạn sẽ thêm đoạn mã sau vào my_project/WORKSPACE
:
local_repository(
name = "coworkers_project",
path = "/path/to/coworkers-project",
)
Nếu đồng nghiệp của bạn có một //foo:bar
mục tiêu, thì dự án của bạn có thể gọi mục tiêu đó là
@coworkers_project//foo:bar
Tên dự án bên ngoài phải là
tên không gian làm việc hợp lệ.
Tuỳ thuộc vào các dự án không phải Bazel
Các quy tắc có tiền tố new_
, chẳng hạn như
new_local_repository
,
cho phép bạn tạo mục tiêu từ các dự án không sử dụng Bazel.
Ví dụ: giả sử bạn đang làm việc cho một dự án, my-project/
và bạn muốn
phụ thuộc vào dự án của đồng nghiệp coworkers-project/
. Video của đồng nghiệp
dự án sẽ sử dụng make
để tạo, nhưng bạn muốn phụ thuộc vào một trong các tệp .so
mà nó tạo ra. Để thực hiện việc này, hãy thêm nội dung sau vào my_project/WORKSPACE
:
new_local_repository(
name = "coworkers_project",
path = "/path/to/coworkers-project",
build_file = "coworker.BUILD",
)
build_file
chỉ định một tệp BUILD
để phủ lên dự án hiện có, cho
ví dụ:
cc_library(
name = "some-lib",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)
Sau đó, bạn có thể phụ thuộc vào @coworkers_project//:some-lib
từ
BUILD
tệp.
Tuỳ thuộc vào các gói bên ngoài
Cấu phần phần mềm và kho lưu trữ Maven
Sử dụng bộ quy tắc rules_jvm_external
để tải cấu phần phần mềm xuống qua kho lưu trữ Maven và cung cấp dưới dạng Java
phần phụ thuộc.
Đang tìm nạp phần phụ thuộc
Theo mặc định, các phần phụ thuộc bên ngoài sẽ được tìm nạp khi cần trong bazel build
. Nếu
bạn muốn tìm nạp trước các phần phụ thuộc cần thiết cho một tập hợp mục tiêu cụ thể, hãy sử dụng
bazel fetch
.
Để tìm nạp vô điều kiện tất cả phần phụ thuộc bên ngoài, hãy sử dụng
bazel sync
.
Vì các kho lưu trữ đã tìm nạp được lưu trữ trong cơ sở dữ liệu đầu ra, việc tìm nạp
xảy ra trên mỗi không gian làm việc.
Các phần phụ thuộc đổ bóng
Bất cứ khi nào có thể, bạn nên có một chính sách phiên bản duy nhất trong dự án. Đây là yêu cầu bắt buộc đối với các phần phụ thuộc mà bạn biên dịch và cuối cùng trong tệp nhị phân cuối cùng. Nhưng đối với trường hợp không đúng, có thể phần phụ thuộc đổ bóng. Hãy xem xét trường hợp sau:
myproject/WORKSPACE
workspace(name = "myproject")
local_repository(
name = "A",
path = "../A",
)
local_repository(
name = "B",
path = "../B",
)
KHÔNG GIAN LÀM VIỆC
workspace(name = "A")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner",
urls = ["https://github.com/testrunner/v1.zip"],
sha256 = "...",
)
B/WORKSPACE
workspace(name = "B")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner",
urls = ["https://github.com/testrunner/v2.zip"],
sha256 = "..."
)
Cả hai phần phụ thuộc A
và B
đều phụ thuộc vào testrunner
, nhưng chúng lại phụ thuộc
các phiên bản khác nhau của testrunner
. Không có lý do gì để những trình chạy kiểm thử này phải
không cùng tồn tại một cách yên bình trong myproject
, tuy nhiên, chúng sẽ xung đột với nhau
khác vì chúng có cùng tên. Để khai báo cả hai phần phụ thuộc,
cập nhật myproject/WORKSPACE:
workspace(name = "myproject")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner-v1",
urls = ["https://github.com/testrunner/v1.zip"],
sha256 = "..."
)
http_archive(
name = "testrunner-v2",
urls = ["https://github.com/testrunner/v2.zip"],
sha256 = "..."
)
local_repository(
name = "A",
path = "../A",
repo_mapping = {"@testrunner" : "@testrunner-v1"}
)
local_repository(
name = "B",
path = "../B",
repo_mapping = {"@testrunner" : "@testrunner-v2"}
)
Cơ chế này cũng có thể dùng để kết hợp kim cương. Ví dụ: nếu A
và B
có cùng phần phụ thuộc nhưng gọi bằng tên khác, các phần phụ thuộc đó có thể
để tham gia myproject/WORKSPACE.
Ghi đè kho lưu trữ từ dòng lệnh
Để ghi đè một kho lưu trữ đã khai báo bằng một kho lưu trữ cục bộ từ dòng lệnh,
sử dụng
--override_repository
cờ. Việc sử dụng cờ này sẽ thay đổi nội dung của các kho lưu trữ bên ngoài mà không
thay đổi mã nguồn của mình.
Ví dụ: để ghi đè @foo
vào thư mục cục bộ /path/to/local/foo
,
truyền cờ --override_repository=foo=/path/to/local/foo
.
Sau đây là một số trường hợp sử dụng:
- Gỡ lỗi cho vấn đề. Ví dụ: bạn có thể ghi đè kho lưu trữ
http_archive
vào một thư mục cục bộ nơi bạn có thể thực hiện thay đổi dễ dàng hơn. - Nhà cung cấp. Nếu bạn đang ở trong một môi trường không thể thực hiện cuộc gọi mạng, ghi đè các quy tắc về kho lưu trữ dựa trên mạng để trỏ đến các thư mục cục bộ thay thế.
Sử dụng proxy
Bazel sẽ nhận địa chỉ proxy từ HTTPS_PROXY
và HTTP_PROXY
biến môi trường và sử dụng các biến này để tải các tệp HTTP/HTTPS xuống (nếu được chỉ định).
Hỗ trợ cho IPv6
Trên các máy chỉ hỗ trợ IPv6, Bazel sẽ có thể tải các phần phụ thuộc xuống bằng
không có thay đổi nào. Tuy nhiên, trên các máy IPv4/IPv6 ngăn xếp kép, Bazel tuân theo cùng một
quy ước là Java: nếu IPv4 được bật, IPv4 sẽ được ưu tiên. Trong một số trường hợp,
ví dụ: khi mạng IPv4 không thể phân giải/tiếp cận các địa chỉ bên ngoài,
điều này có thể gây ra các ngoại lệ Network unreachable
và lỗi bản dựng.
Trong những trường hợp này, bạn có thể ghi đè hành vi của Bazel để ưu tiên IPv6
bằng cách sử dụng thuộc tính hệ thống java.net.preferIPv6Addresses=true
.
Cụ thể:
Sử dụng
--host_jvm_args=-Djava.net.preferIPv6Addresses=true
tuỳ chọn khởi động, Ví dụ: bằng cách thêm dòng sau vào.bazelrc
tệp:startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true
Nếu bạn đang chạy các mục tiêu bản dựng Java cần kết nối Internet (đôi khi kiểm thử tích hợp cần điều đó), cũng sử dụng
--jvmopt=-Djava.net.preferIPv6Addresses=true
cờ công cụ, ví dụ: bằng cách đặt dòng sau trong tệp.bazelrc
:build --jvmopt=-Djava.net.preferIPv6Addresses
Nếu bạn đang sử dụng rules_jvm_external, ví dụ: để phân giải phiên bản phần phụ thuộc, hãy thêm
-Djava.net.preferIPv6Addresses=true
đếnCOURSIER_OPTS
biến môi trường để cung cấp các tuỳ chọn JVM cho Coursier
Phần phụ thuộc bắc cầu
Bazel chỉ đọc các phần phụ thuộc được liệt kê trong tệp WORKSPACE
. Nếu dự án của bạn
(A
) phụ thuộc vào một dự án khác (B
) liệt kê phần phụ thuộc trên một phần ba
dự án (C
) trong tệp WORKSPACE
, bạn sẽ phải thêm cả B
và C
vào tệp WORKSPACE
của dự án. Yêu cầu này có thể bao quát
Kích thước tệp là WORKSPACE
, nhưng hạn chế khả năng chỉ có một thư viện
bao gồm C
ở phiên bản 1.0 và một số khác bao gồm C
ở phiên bản 2.0.
Lưu các phần phụ thuộc bên ngoài vào bộ nhớ đệm
Theo mặc định, Bazel sẽ chỉ tải lại các phần phụ thuộc bên ngoài xuống nếu
các thay đổi về định nghĩa. Các thay đổi đối với tệp được tham chiếu trong định nghĩa (chẳng hạn như bản vá)
hoặc BUILD
) cũng được bazel xem xét.
Để buộc tải xuống lại, hãy sử dụng bazel sync
.
Bố cục
Tất cả các phần phụ thuộc bên ngoài đều được tải xuống một thư mục trong thư mục con
external
trong cơ sở đầu ra. Trong trường hợp có
kho lưu trữ cục bộ, một đường liên kết tượng trưng được tạo
vào đó thay vì tạo một thư mục mới.
Bạn có thể xem thư mục external
bằng cách chạy:
ls $(bazel info output_base)/external
Lưu ý rằng việc chạy bazel clean
sẽ không thực sự xoá các thành phần bên ngoài
thư mục. Để xoá tất cả cấu phần phần mềm bên ngoài, hãy dùng bazel clean --expunge
.
Bản dựng ngoại tuyến
Đôi khi, việc chạy một bản dựng theo cách ngoại tuyến là cần thiết hoặc mong muốn. Cho
các trường hợp sử dụng đơn giản, chẳng hạn như khi di chuyển trên máy bay,
prefetching các URL cần thiết
các kho lưu trữ có bazel fetch
hoặc bazel sync
là đủ; hơn nữa, việc
bằng cách sử dụng tuỳ chọn --nofetch
, bạn có thể tắt tính năng tìm nạp thêm kho lưu trữ
trong quá trình tạo bản dựng.
Đối với các bản dựng ngoại tuyến thực sự, cần phải cung cấp các tệp cần thiết
bởi một thực thể khác với bazel, bazel hỗ trợ tuỳ chọn
--distdir
. Bất cứ khi nào quy tắc kho lưu trữ yêu cầu bazel tìm nạp tệp thông qua
ctx.download
hoặc
ctx.download_and_extract
và cung cấp tổng băm của tệp
nếu cần, trước tiên bazel sẽ xem xét các thư mục được chỉ định bởi tuỳ chọn đó để
một tệp khớp với tên cơ sở của URL đầu tiên được cung cấp và sử dụng bản sao cục bộ đó
nếu hàm băm khớp.
Chính Bazel sử dụng kỹ thuật này để tự khởi động ngoại tuyến từ bản phân phối
cấu phần phần mềm.
Để thực hiện điều này, công cụ này thu thập tất cả dữ liệu bên ngoài cần thiết
phần phụ thuộc
trong một chiến dịch nội bộ
distdir_tar
.
Tuy nhiên, bazel cho phép thực thi các lệnh tuỳ ý trong các quy tắc kho lưu trữ, mà không biết liệu chúng có gọi đến mạng hay không. Do đó, bazel không có lựa chọn để thực thi chế độ ngoại tuyến hoàn toàn cho các bản dựng. Vì vậy, việc kiểm thử xem một bản dựng có hoạt động đúng cách hay không khi không có mạng đòi hỏi phải chặn mạng từ bên ngoài, như bazel đã làm trong thử nghiệm Tự thân khởi nghiệp.
Các phương pháp hay nhất
Quy tắc kho lưu trữ
Quy tắc kho lưu trữ thường phải chịu trách nhiệm về:
- Phát hiện chế độ cài đặt hệ thống và ghi vào tệp.
- Đang tìm tài nguyên ở nơi khác trong hệ thống.
- Đang tải tài nguyên xuống từ các URL.
- Tạo hoặc liên kết tệp BUILD trong thư mục kho lưu trữ bên ngoài.
Tránh sử dụng repository_ctx.execute
khi có thể. Ví dụ: khi sử dụng C++ không phải Bazel
thư viện có bản dựng sử dụng Make, bạn nên dùng repository_ctx.download()
sau đó
hãy viết tệp BUILD để tạo tệp đó, thay vì chạy ctx.execute(["make"])
.
Ưu tiên http_archive
đến git_repository
và
new_git_repository
. Lý do là:
- Quy tắc kho lưu trữ Git phụ thuộc vào hệ thống
git(1)
trong khi trình tải xuống HTTP được tạo vào Bazel và không có phần phụ thuộc hệ thống. http_archive
hỗ trợ danh sáchurls
dưới dạng bản sao vàgit_repository
chỉ hỗ trợ mộtremote
.http_archive
hoạt động với bộ nhớ đệm của kho lưu trữ, nhưng khônggit_repository
. Xem #5116 để biết thêm thông tin.
Đừng sử dụng bind()
. Hãy xem phần "Cân nhắc xóa
ràng buộc" trong một khoảng thời gian dài
thảo luận về các vấn đề và phương án thay thế.