Bekerja dengan Dependensi Eksternal

Laporkan masalah Lihat sumber Per Malam · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

Bazel dapat bergantung pada target dari project lain. Dependensi dari project disebut dependensi eksternal.

File WORKSPACE (atau file WORKSPACE.bazel) di direktori workspace memberi tahu Bazel cara mendapatkan proyek lain sumber. Proyek-proyek lain ini dapat berisi satu atau beberapa file BUILD dengan targetnya sendiri. BUILD file di dalam proyek utama dapat bergantung pada target eksternal ini dengan menggunakan namanya dari file WORKSPACE.

Misalnya, ada dua project pada sebuah sistem:

/
  home/
    user/
      project1/
        WORKSPACE
        BUILD
        srcs/
          ...
      project2/
        WORKSPACE
        BUILD
        my-libs/

Jika project1 ingin bergantung pada target, :foo, yang ditentukan di /home/user/project2/BUILD, dia bisa menentukan bahwa repositori bernama project2 dapat ditemukan di /home/user/project2. Kemudian menargetkan di /home/user/project1/BUILD dapat bergantung pada @project2//:foo.

File WORKSPACE memungkinkan pengguna bergantung pada target dari bagian lain dalam Google Cloud sistem file atau diunduh dari internet. Sintaksisnya sama dengan BUILD file, tetapi mengizinkan seperangkat aturan berbeda yang disebut aturan repositori (terkadang juga dikenal sebagai aturan ruang kerja). Bazel dilengkapi dengan beberapa repositori bawaan aturan dan serangkaian repositori Starlark yang disematkan aturan. Pengguna juga dapat menulis repositori kustom aturan untuk mendapatkan perilaku yang lebih kompleks.

Jenis dependensi eksternal yang didukung

Beberapa jenis dasar dependensi eksternal dapat digunakan:

Bergantung pada project Bazel lainnya

Jika ingin menggunakan target dari proyek Bazel kedua, Anda dapat penggunaan local_repository, git_repository atau http_archive untuk melakukan symlink dari sistem file lokal, mereferensikan repositori git (masing-masing).

Misalnya, Anda sedang mengerjakan sebuah project, my-project/, dan ingin untuk bergantung pada target dari project rekan kerja Anda, coworkers-project/. Keduanya proyek menggunakan Bazel, jadi Anda dapat menambahkan proyek rekan kerja Anda dependensi dan kemudian menggunakan target apa pun yang telah ditentukan rekan kerja Anda dari Anda sendiri BANGUN file. Anda akan menambahkan kode berikut ke my_project/WORKSPACE:

local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
)

Jika rekan kerja Anda memiliki target //foo:bar, project Anda dapat merujuknya sebagai @coworkers_project//foo:bar. Nama proyek eksternal harus nama ruang kerja yang valid.

Bergantung pada project non-Bazel

Aturan yang diawali dengan new_, seperti new_local_repository memungkinkan Anda membuat target dari project yang tidak menggunakan Bazel.

Misalnya, Anda sedang mengerjakan sebuah project, my-project/, dan ingin bergantung pada project rekan kerja Anda, coworkers-project/. Milik rekan kerja Anda project menggunakan make untuk membangun, tetapi Anda ingin bergantung pada salah satu file .so yang dihasilkannya. Untuk melakukannya, tambahkan kode berikut ke my_project/WORKSPACE:

new_local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
    build_file = "coworker.BUILD",
)

build_file menetapkan file BUILD untuk ditempatkan pada project yang ada, sebagai contoh:

cc_library(
    name = "some-lib",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)

Anda kemudian dapat bergantung pada @coworkers_project//:some-lib dari project BUILD file.

Bergantung pada paket eksternal

Artefak dan repositori Maven

Menggunakan kumpulan aturan rules_jvm_external untuk mendownload artefak dari repositori Maven dan menyediakannya sebagai Java dependensi.

Mengambil dependensi

Secara default, dependensi eksternal diambil sesuai kebutuhan selama bazel build. Jika Anda ingin mengambil dependensi yang diperlukan untuk kumpulan target tertentu, gunakan bazel fetch Untuk mengambil semua dependensi eksternal tanpa syarat, gunakan bazel sync Karena repositori yang diambil disimpan di basis output, pengambilan yang terjadi per ruang kerja.

Dependensi bayangan

Jika memungkinkan, sebaiknya miliki satu kebijakan versi di proyek. Ini diperlukan untuk dependensi yang Anda kompilasi dan pada akhirnya dalam biner akhir. Tetapi untuk kasus di mana hal ini tidak benar, Anda dapat dependensi shadow. Pertimbangkan skenario berikut:

project saya/Ruang Kerja

workspace(name = "myproject")

local_repository(
    name = "A",
    path = "../A",
)
local_repository(
    name = "B",
    path = "../B",
)

A/Ruang Kerja

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/Ruang Kerja

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 = "..."
)

Kedua dependensi A dan B bergantung pada testrunner, tetapi keduanya bergantung pada versi testrunner yang berbeda. Tidak ada alasan bagi {i>test runner<i} ini untuk tidak hidup berdampingan secara damai dalam myproject, namun mereka akan bentrok dengan masing-masing satu sama lain karena mereka memiliki nama yang sama. Untuk mendeklarasikan kedua dependensi, perbarui 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"}
)

Mekanisme ini juga bisa digunakan untuk menggabungkan berlian. Misalnya jika A dan B memiliki dependensi yang sama tetapi memanggilnya dengan nama yang berbeda, dependensi tersebut dapat bergabung di myproject/WORKSPACE.

Mengganti repositori dari command line

Untuk mengganti repositori yang dideklarasikan dengan repositori lokal dari command line, gunakan --override_repository penanda. Menggunakan flag ini akan mengubah konten repositori eksternal tanpa mengubah kode sumber.

Misalnya, untuk mengganti @foo ke direktori lokal /path/to/local/foo, teruskan flag --override_repository=foo=/path/to/local/foo.

Beberapa kasus penggunaan mencakup:

  • Masalah proses debug. Misalnya, Anda dapat mengganti repositori http_archive ke direktori lokal di mana Anda dapat membuat perubahan dengan lebih mudah.
  • Vendor. Jika Anda berada di lingkungan di mana Anda tidak dapat melakukan panggilan jaringan, mengganti aturan repositori berbasis jaringan untuk mengarah ke direktori lokal sebagai gantinya.

Menggunakan proxy

Bazel akan mengambil alamat proxy dari HTTPS_PROXY dan HTTP_PROXY variabel lingkungan dan gunakan untuk mendownload file HTTP/HTTPS (jika ditentukan).

Dukungan untuk IPv6

Pada komputer yang hanya menggunakan IPv6, Bazel akan dapat mengunduh dependensi dengan tidak ada perubahan. Pada mesin dual-stack IPv4/IPv6, Bazel mengikuti cara sebagai Java: jika IPv4 diaktifkan, IPv4 akan lebih disukai. Dalam beberapa situasi, misalnya ketika jaringan IPv4 tidak dapat menyelesaikan/menjangkau alamat eksternal, hal ini dapat menyebabkan pengecualian Network unreachable dan kegagalan build. Dalam kasus ini, Anda dapat mengganti perilaku Bazel untuk lebih memilih IPv6 menggunakan properti sistem java.net.preferIPv6Addresses=true. Khususnya:

  • Gunakan --host_jvm_args=-Djava.net.preferIPv6Addresses=true opsi startup, misalnya dengan menambahkan baris berikut ke File .bazelrc:

    startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true

  • Jika Anda menjalankan target build Java yang perlu terhubung ke internet pengujian integrasi terkadang juga diperlukan), gunakan juga --jvmopt=-Djava.net.preferIPv6Addresses=true flag alat, misalnya dengan memiliki baris berikut di file .bazelrc Anda:

    build --jvmopt=-Djava.net.preferIPv6Addresses

  • Jika Anda menggunakan rules_jvm_external, misalnya, untuk resolusi versi dependensi, tambahkan juga -Djava.net.preferIPv6Addresses=true menuju COURSIER_OPTS variabel lingkungan untuk menyediakan opsi JVM bagi Coursier

Dependensi transitif

Bazel hanya membaca dependensi yang tercantum dalam file WORKSPACE Anda. Jika proyek Anda (A) bergantung pada project lain (B) yang mencantumkan dependensi pada project project (C) dalam file WORKSPACE-nya, Anda harus menambahkan B dan C ke file WORKSPACE project Anda. Persyaratan ini dapat menggelembungkan Ukuran file WORKSPACE, tetapi membatasi kemungkinan memiliki satu library menyertakan C di versi 1.0 dan lainnya menyertakan C pada versi 2.0.

Menyimpan cache dependensi eksternal

Secara {i>default<i}, Bazel hanya akan mengunduh ulang dependensi eksternal jika perubahan definisi. Perubahan pada file yang dirujuk dalam definisi (seperti patch atau file BUILD) juga dipertimbangkan oleh bazel.

Untuk memaksa download ulang, gunakan bazel sync.

Tata Letak

Dependensi eksternal semuanya didownload ke direktori di bawah subdirektori external dalam base output. Dalam kasus repositori lokal, symlink akan dibuat di sana daripada membuat direktori baru. Anda dapat melihat direktori external dengan menjalankan:

ls $(bazel info output_base)/external

Perlu diketahui bahwa menjalankan bazel clean tidak akan benar-benar menghapus saat ini. Untuk menghapus semua artefak eksternal, gunakan bazel clean --expunge.

Build offline

Terkadang, Anda perlu atau perlu menjalankan build secara offline. Sebagai kasus penggunaan sederhana, seperti bepergian di pesawat, prefetching yang diperlukan repositori dengan bazel fetch atau bazel sync sudah cukup; selain itu, menggunakan opsi --nofetch, pengambilan repositori lebih lanjut dapat dinonaktifkan selama proses build.

Untuk build offline yang sebenarnya, tempat penyediaan file yang diperlukan harus dilakukan oleh entitas yang berbeda dari bazel, bazel mendukung opsi --distdir. Setiap kali aturan repositori meminta bazel untuk mengambil file melalui ctx.download atau ctx.download_and_extract dan memberikan jumlah hash dari file diperlukan, bazel akan melihat terlebih dahulu direktori yang ditentukan oleh opsi itu untuk file yang cocok dengan nama dasar URL pertama yang diberikan, dan gunakan salinan lokal tersebut jika {i>hash <i}itu cocok.

Bazel sendiri menggunakan teknik ini untuk melakukan bootstrap secara offline dari distribusi artefak. Hal ini dilakukan dengan mengumpulkan semua kebutuhan eksternal dependensi dalam distdir_tar

Namun, bazel memungkinkan eksekusi perintah arbitrer dalam aturan repositori, tanpa mengetahui apakah mereka terhubung ke jaringan. Oleh karena itu, bazel tidak memiliki opsi untuk menerapkan build yang sepenuhnya offline. Jadi menguji apakah build berfungsi dengan benar secara offline memerlukan pemblokiran jaringan eksternal, seperti yang dilakukan bazel pengujian bootstrap.

Praktik terbaik

Aturan repositori

Aturan repositori umumnya harus bertanggung jawab untuk:

  • Mendeteksi setelan sistem dan menulisnya ke file.
  • Mencari resource di tempat lain pada sistem.
  • Mendownload resource dari URL.
  • Membuat atau membuat symlink file BUILD ke direktori repositori eksternal.

Hindari penggunaan repository_ctx.execute jika memungkinkan. Misalnya, saat menggunakan C++ non-Bazel library yang memiliki build menggunakan Make, sebaiknya gunakan repository_ctx.download() lalu menulis file BUILD yang membangunnya, alih-alih menjalankan ctx.execute(["make"]).

Lebih suka http_archive ke git_repository dan new_git_repository. Alasannya adalah:

  • Aturan repositori Git bergantung pada git(1) sistem, sedangkan downloader HTTP dibangun ke dalam Bazel dan tidak memiliki dependensi sistem.
  • http_archive mendukung daftar urls sebagai duplikat, dan git_repository hanya mendukung satu remote.
  • http_archive berfungsi dengan cache repositori, tetapi tidak git_repository. Lihat #5116 untuk informasi selengkapnya.

Jangan gunakan bind(). Lihat "Pertimbangkan menghapus pengikatan" untuk waktu yang lama diskusi tentang isu dan alternatifnya.