Bazel Eğitimi: Java Projesi Oluşturma

Sorun bildir Kaynağı görüntüleyin Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bu eğitimde, Bazel ile Java uygulamaları oluşturmanın temelleri ele alınmaktadır. Çalışma alanınızı oluşturup hedefler ve BUILD dosyaları gibi temel Bazel kavramlarını gösteren basit bir Java projesi oluşturacaksınız.

Tahmini tamamlama süresi: 30 dakika.

Neler öğreneceksiniz?

Bu eğitimde şunları öğreneceksiniz:

  • Hedef oluşturma
  • Projenin bağımlılıklarını görselleştirme
  • Projeyi birden fazla hedefe ve pakete ayırma
  • Paketler genelinde hedef görünürlüğünü kontrol etme
  • Etiketler aracılığıyla hedeflere başvurma
  • Hedef dağıtma

Başlamadan önce

Bazel'i yükleme

Eğitime hazırlanmak için, henüz yüklemediyseniz önce Bazel'i yükleyin.

JDK'yi yükleme

  1. Java JDK'yi yükleyin (tercih edilen sürüm 11'dir ancak 8 ile 15 arasındaki sürümler desteklenir).

  2. JAVA_HOME ortam değişkenini JDK'yi işaret edecek şekilde ayarlayın.

    • Linux/macOS'te:

      export JAVA_HOME="$(dirname $(dirname $(realpath $(which javac))))"
      
    • Windows'da:

      1. Denetim Masası'nı açın.
      2. "Sistem ve Güvenlik" > "Sistem" > "Gelişmiş Sistem Ayarları" > "Gelişmiş" sekmesi > "Ortam Değişkenleri..."ne gidin. .
      3. "Kullanıcı değişkenleri" listesinin (üstteki) altında "Yeni..."yi tıklayın.
      4. "Değişken adı" alanına JAVA_HOME yazın.
      5. "Dizine Göz At..." seçeneğini tıklayın.
      6. JDK dizinine (örneğin, C:\Program Files\Java\jdk1.8.0_152) gidin.
      7. Tüm iletişim pencerelerinde "Tamam"ı tıklayın.

Örnek projeyi alma

Bazel'in GitHub deposundan örnek projeyi alın:

git clone https://github.com/bazelbuild/examples

Bu eğitim için örnek proje examples/java-tutorial dizinindedir ve aşağıdaki gibi yapılandırılır:

java-tutorial
├── BUILD
├── src
│   └── main
│       └── java
│           └── com
│               └── example
│                   ├── cmdline
│                   │   ├── BUILD
│                   │   └── Runner.java
│                   ├── Greeting.java
│                   └── ProjectRunner.java
└── MODULE.bazel

Bazel ile geliştirin

Çalışma alanını ayarlama

Proje oluşturmadan önce projenin çalışma alanını ayarlamanız gerekir. Çalışma alanı, projenizin kaynak dosyalarını ve Bazel'in derleme çıkışlarını içeren bir dizindir. Bazel'in özel olarak tanıdığı dosyaları da içerir:

  • Dizini ve içeriğini Bazel çalışma alanı olarak tanımlayan ve projenin dizin yapısının kökünde bulunan MODULE.bazel dosyası,

  • Bazel'e projenin farklı bölümlerinin nasıl derleneceğini söyleyen bir veya daha fazla BUILD dosyası. (Çalışma alanında bulunan ve BUILD dosyası içeren dizin bir pakettir. Paketler hakkında bilgiyi bu eğiticinin ilerleyen bölümlerinde öğreneceksiniz.)

Bir dizini Bazel çalışma alanı olarak atamak için söz konusu dizinde MODULE.bazel adlı boş bir dosya oluşturun.

Bazel projeyi derlerken tüm giriş ve bağımlılıkların aynı çalışma alanında olması gerekir. Farklı çalışma alanlarında bulunan dosyalar, bağlanmadıkları sürece birbirinden bağımsızdır. Bu konu bu eğitim kapsamında değildir.

BUILD dosyasını anlama

BUILD dosyası, Bazel için birkaç farklı türde talimat içerir. En önemli tür, Bazel'e istenen çıkışları (ör. yürütülebilir ikili dosyalar veya kitaplıklar) nasıl oluşturacağını söyleyen derleme kuralı'dır. BUILD dosyasındaki her derleme kuralının örneği hedef olarak adlandırılır ve belirli bir kaynak dosya ve bağımlılık grubuna işaret eder. Hedefler diğer hedefleri de gösterebilir.

java-tutorial/BUILD dosyasına göz atın:

java_binary(
    name = "ProjectRunner",
    srcs = glob(["src/main/java/com/example/*.java"]),
)

Örneğimizde ProjectRunner hedefi, Bazel'in yerleşik java_binary kuralını örneklendirir. Kural, Bazel'e bir .jar dosyası ve sarmalayıcı kabuk komut dosyası (her ikisi de hedefin adıyla adlandırılır) oluşturmasını söyler.

Hedefteki özellikler, bağımlılıkları ve seçenekleri açıkça belirtir. name özelliği zorunludur ancak çoğu isteğe bağlıdır. Örneğin, ProjectRunner kural hedefinde name hedefin adıdır, srcs, hedefi oluşturmak için kullandığı kaynak dosyaları ve main_class, ana yöntemi içeren sınıfı belirtir. (Örneğimizde, bir grup kaynak dosyayı tek tek listelemek yerine Bazel'e iletmek için glob işlevinin kullanıldığını fark etmiş olabilirsiniz.)

Projeyi oluşturma

Örnek projenizi derlemek için java-tutorial dizinine gidin ve aşağıdaki komutu çalıştırın:

bazel build //:ProjectRunner

Hedef etiketinde // kısmı, BUILD dosyasının çalışma alanının köküne göre konumudur (bu durumda kökün kendisidir) ve ProjectRunner, BUILD dosyasındaki hedef addır. (Hedef etiketler hakkında daha fazla bilgiyi bu eğitim makalesinin sonunda bulabilirsiniz.)

Bazel, aşağıdakine benzer bir çıktı oluşturur:

   INFO: Found 1 target...
   Target //:ProjectRunner up-to-date:
      bazel-bin/ProjectRunner.jar
      bazel-bin/ProjectRunner
   INFO: Elapsed time: 1.021s, Critical Path: 0.83s

Tebrikler, ilk Bazel hedefinizi oluşturdunuz. Bazel, derleme çıkışlarını çalışma alanının kökündeki bazel-bin dizinine yerleştirir. Bazel'in çıkış yapısı hakkında fikir edinmek için içeriğine göz atın.

Ardından, yeni oluşturulan ikili dosyanızı test edin:

bazel-bin/ProjectRunner

Bağımlılık grafiğini inceleme

Bazel, derleme bağımlılıklarının BUILD dosyalarında açıkça belirtilmesini gerektirir. Bazel bu ifadeleri, projenin bağımlılık grafiğini oluşturmak için kullanır. Bu da doğru artımlı derlemeler sağlar.

Örnek projenin bağımlılıklarını görselleştirmek için çalışma alanı kökünde şu komutu çalıştırarak bağımlılık grafiğinin metin temsilini oluşturabilirsiniz:

bazel query  --notool_deps --noimplicit_deps "deps(//:ProjectRunner)" --output graph

Yukarıdaki komut, Bazel'e hedef //:ProjectRunner için tüm bağımlılıkları (ana makine ve gizli bağımlılıklar hariç) aramasını ve çıkışı grafik olarak biçimlendirmesini söyler.

Ardından metni GraphViz'e yapıştırın.

Gördüğünüz gibi, projede ek bağımlılık olmadan iki kaynak dosya oluşturan tek bir hedef vardır:

"ProjectRunner" hedefinin bağımlılık grafiği

Çalışma alanınızı ayarladıktan, projenizi oluşturduktan ve bağımlılıkları inceledikten sonra biraz karmaşıklık ekleyebilirsiniz.

Bazel derlemenizi hassaslaştırma

Küçük projeler için tek bir hedef yeterli olsa da hızlı artımlı derlemeler (yani yalnızca değişiklikleri yeniden derleme) sağlamak ve bir projenin birden fazla parçasını tek seferde oluşturarak derlemelerinizi hızlandırmak için daha büyük projeleri birden fazla hedefe ve pakete bölmek isteyebilirsiniz.

Birden fazla derleme hedefi belirtme

Örnek proje derlemesini iki hedefe bölebilirsiniz. java-tutorial/BUILD dosyasının içeriğini aşağıdakiyle değiştirin:

java_binary(
    name = "ProjectRunner",
    srcs = ["src/main/java/com/example/ProjectRunner.java"],
    main_class = "com.example.ProjectRunner",
    deps = [":greeter"],
)

java_library(
    name = "greeter",
    srcs = ["src/main/java/com/example/Greeting.java"],
)

Bu yapılandırmayla Bazel önce greeter kitaplığını, ardından ProjectRunner ikili programını oluşturur. java_binary öğesindeki deps özelliği, Bazel'a ProjectRunner ikili programını derlemek için greeter kitaplığının gerekli olduğunu bildirir.

Projenin bu yeni sürümünü derlemek için aşağıdaki komutu çalıştırın:

bazel build //:ProjectRunner

Bazel, aşağıdakine benzer çıktılar üretir:

INFO: Found 1 target...
Target //:ProjectRunner up-to-date:
  bazel-bin/ProjectRunner.jar
  bazel-bin/ProjectRunner
INFO: Elapsed time: 2.454s, Critical Path: 1.58s

Ardından, yeni oluşturulan ikili dosyanızı test edin:

bazel-bin/ProjectRunner

Artık ProjectRunner.java dosyasını değiştirip projeyi yeniden oluşturursanız Bazel yalnızca bu dosyayı yeniden derleyecektir.

Bağımlılık grafiğine baktığınızda ProjectRunner'ün öncekiyle aynı girişlere bağlı olduğunu ancak derlemenin yapısının farklı olduğunu görebilirsiniz:

Bağımlılık eklendikten sonra hedef "ProjectRunner"ın bağımlılık grafiği

Artık projeyi iki hedefle oluşturdunuz. ProjectRunner hedefi bir kaynak dosya oluşturur ve bir ek kaynak dosya oluşturan başka bir hedefe (:greeter) bağlıdır.

Birden fazla paket kullanma

Şimdi projeyi birden fazla pakete bölelim. src/main/java/com/example/cmdline dizinine göz atarsanız bir BUILD dosyasının yanı sıra bazı kaynak dosyaları da içerdiğini görebilirsiniz. Bu nedenle, Bazel'e göre çalışma alanı artık //src/main/java/com/example/cmdline ve // olmak üzere iki paket içeriyor (çalışma alanının kökünde bir BUILD dosyası bulunduğundan).

src/main/java/com/example/cmdline/BUILD dosyasına göz atın:

java_binary(
    name = "runner",
    srcs = ["Runner.java"],
    main_class = "com.example.cmdline.Runner",
    deps = ["//:greeter"],
)

runner hedefi, // paketindeki greeter hedefine (dolayısıyla hedef etiketi //:greeter) bağlıdır. Bazel bunu deps özelliği aracılığıyla bilir. Bağımlılık grafiğine göz atın:

Hedef "runner"ın bağımlılık grafiği

Ancak derlemenin başarılı olması için visibility özelliğini kullanarak //src/main/java/com/example/cmdline/BUILD'daki runner hedefine //BUILD'deki hedeflere yönelik açık bir görünürlük vermeniz gerekir. Bunun nedeni, hedeflerin varsayılan olarak yalnızca aynı BUILD dosyasındaki diğer hedefler tarafından görülebilmesidir. (Bazel, uygulama ayrıntılarını içeren kitaplıkların herkese açık API'lere sızması gibi sorunların önüne geçmek için hedef görünürlüğü kullanır.)

Bunu yapmak için visibility özelliğini java-tutorial/BUILD içindeki greeter hedefine aşağıdaki gibi ekleyin:

java_library(
    name = "greeter",
    srcs = ["src/main/java/com/example/Greeting.java"],
    visibility = ["//src/main/java/com/example/cmdline:__pkg__"],
)

Artık çalışma alanının kökünde aşağıdaki komutu çalıştırarak yeni paketi oluşturabilirsiniz:

bazel build //src/main/java/com/example/cmdline:runner

Bazel, aşağıdakine benzer bir çıktı oluşturur:

INFO: Found 1 target...
Target //src/main/java/com/example/cmdline:runner up-to-date:
  bazel-bin/src/main/java/com/example/cmdline/runner.jar
  bazel-bin/src/main/java/com/example/cmdline/runner
  INFO: Elapsed time: 1.576s, Critical Path: 0.81s

Ardından, yeni oluşturulan ikili dosyanızı test edin:

./bazel-bin/src/main/java/com/example/cmdline/runner

Bu aşamada projeyi, her biri birer hedef içeren iki paket halinde derleme yapacak şekilde değiştirdiniz ve bunlar arasındaki bağımlılıkları anladınız.

Hedeflere referans vermek için etiketleri kullanma

Bazel, BUILD dosyalarında ve komut satırında hedeflere referans vermek için hedef etiketleri kullanır (ör. //:ProjectRunner veya //src/main/java/com/example/cmdline:runner). Söz dizimi aşağıdaki gibidir:

//path/to/package:target-name

Hedef bir kural hedefiyse path/to/package, BUILD dosyasını içeren dizinin yoludur ve target-name, BUILD dosyasında hedefe verdiğiniz addır (name özelliği). Hedef bir dosya hedefiyse path/to/package, paketin kök yolunu, target-name ise tam yolu da dahil olmak üzere hedef dosyanın adını belirtir.

Depo kökündeki hedeflere referans verirken paket yolu boştur, yalnızca //:target-name kullanın. Aynı BUILDdosyasındaki hedeflere referans verirken // Workspace kök tanımlayıcısını atlayabilir ve yalnızca :target-name kullanabilirsiniz.

Örneğin, java-tutorial/BUILD dosyasındaki hedefler için bir paket yolu belirtmeniz gerekmez. Bunun nedeni, çalışma alanı kökünün de bir paket (//) olması ve iki hedef etiketinizin yalnızca //:ProjectRunner ve //:greeter olmasıdır.

Ancak //src/main/java/com/example/cmdline/BUILD dosyasındaki hedefler için //src/main/java/com/example/cmdline'un tam paket yolunu belirtmeniz gerekiyordu ve hedef etiketiniz //src/main/java/com/example/cmdline:runner idi.

Dağıtım için Java hedefini paketleme

Şimdi ikili dosyayı tüm çalışma zamanı bağımlılıkları ile derleyerek dağıtım için bir Java hedefi paketleyelim. Bu sayede, ikili dosyayı geliştirme ortamınızın dışında çalıştırabilirsiniz.

Hatırlayacağınız gibi, java_binary derleme kuralı bir .jar ve sarmalayıcı kabuk komut dosyası oluşturur. Şu komutu kullanarak runner.jar içeriğine göz atın:

jar tf bazel-bin/src/main/java/com/example/cmdline/runner.jar

İçeriklerin özellikleri:

META-INF/
META-INF/MANIFEST.MF
com/
com/example/
com/example/cmdline/
com/example/cmdline/Runner.class

Gördüğünüz gibi runner.jar, Runner.class'u içerir ancak bağımlılık öğesi Greeting.class'yi içermez. Bazel'in oluşturduğu runner komut dosyası, sınıf yoluna greeter.jar ekler. Bu nedenle, dosyayı bu şekilde bırakırsanız yerel olarak çalışır ancak başka bir makinede bağımsız olarak çalışmaz. Neyse ki java_binary kuralı, kendi kendine yeten, dağıtılabilir bir ikili oluşturmanıza olanak tanır. Oluşturmak için hedef adın sonuna _deploy.jar ekleyin:

bazel build //src/main/java/com/example/cmdline:runner_deploy.jar

Bazel, aşağıdakine benzer bir çıktı oluşturur:

INFO: Found 1 target...
Target //src/main/java/com/example/cmdline:runner_deploy.jar up-to-date:
  bazel-bin/src/main/java/com/example/cmdline/runner_deploy.jar
INFO: Elapsed time: 1.700s, Critical Path: 0.23s

runner_deploy.jar'ü derlediniz. Gerekli çalışma zamanı bağımlılıkları içerdiğinden, geliştirme ortamınızdan bağımsız olarak çalıştırabilirsiniz. Önceki komutu kullanarak bu bağımsız JAR dosyasının içeriğine göz atın:

jar tf bazel-bin/src/main/java/com/example/cmdline/runner_deploy.jar

İçerik, çalıştırılmak için gereken tüm sınıfları içerir:

META-INF/
META-INF/MANIFEST.MF
build-data.properties
com/
com/example/
com/example/cmdline/
com/example/cmdline/Runner.class
com/example/Greeting.class

Daha fazla bilgi

Daha fazla bilgi için:

İyi çalışmalar.