Bazel Eğitimi: Java Projesi Oluşturma

Sorun bildir Kaynağı görüntüle Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

Bu eğiticide, Bazel ile Java uygulamaları oluşturmanın temelleri açıklanmaktadır. Çalışma alanınızı ayarlayacak ve hedefler ile 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 bölme
  • Paketler genelinde hedef görünürlüğünü kontrol etme
  • Etiketler aracılığıyla hedeflere referans verme
  • Hedef dağıtma

Başlamadan önce

Bazel'i yükleme

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

JDK'yı yükleyin

  1. Java JDK'yı 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'yı 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..." seçeneğine gidin. .
      3. "Kullanıcı değişkenleri" listesinde (en üstteki) "Yeni..."yi tıklayın.
      4. "Değişken adı" alanına JAVA_HOME girin.
      5. "Dizine Göz At..."ı tıklayın.
      6. JDK dizinine gidin (örneğin, C:\Program Files\Java\jdk1.8.0_152).
      7. Tüm iletişim pencerelerinde "Tamam"ı tıklayın.

Örnek projeyi alma

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

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

Bu eğitimdeki örnek proje, examples/java-tutorial dizininde yer alır ve aşağıdaki gibi yapılandırılmıştır:

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

Bazel ile derleme

Çalışma alanını ayarlama

Proje oluşturabilmek için önce ç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. Ayrıca Bazel'in özel olarak tanıdığı dosyaları da içerir:

  • Dizini ve içeriklerini Bazel çalışma alanı olarak tanımlayan ve projenin dizin yapısının kök dizininde bulunan MODULE.bazel dosyası,

  • Projenin farklı bölümlerinin nasıl oluşturulacağını Bazel'e bildiren bir veya daha fazla BUILD dosyası. (Çalışma alanında BUILD dosyası içeren bir dizin paket olarak kabul edilir. Paketler hakkında daha fazla bilgiyi bu eğitimin ilerleyen bölümlerinde edineceksiniz.)

Bir dizini Bazel çalışma alanı olarak belirlemek için bu dizinde MODULE.bazel adlı boş bir dosya oluşturun.

Bazel projeyi oluşturduğunda tüm girişler ve bağımlılıklar aynı çalışma alanında olmalıdır. Farklı çalışma alanlarında bulunan dosyalar, bu eğitimin kapsamı dışında olan bağlantı oluşturma işlemi yapılmadığı sürece birbirinden bağımsızdır.

BUILD dosyasını anlama

Bir BUILD dosyası, Bazel için çeşitli talimat türleri içerir. En önemli tür, derleme kuralıdır. Bu kural, Bazel'e yürütülebilir ikili dosyalar veya kitaplıklar gibi istenen çıktıların nasıl oluşturulacağını söyler. BUILD dosyasındaki her derleme kuralı örneğine hedef denir ve belirli bir kaynak dosyaları ve bağımlılıkları kümesini gösterir. Bir hedef, diğer hedefleri de işaret edebilir.

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ı oluşturur. Kural, Bazel'e .jar dosyası ve sarmalayıcı kabuk komut dosyası (her ikisi de hedefle aynı ada sahip) oluşturmasını söyler.

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

Projeyi oluşturma

Örnek projenizi oluşturmak için java-tutorial dizinine gidin ve şu komutu çalıştırın:

bazel build //:ProjectRunner

Hedef etiketteki // bölümü, BUILD dosyasının çalışma alanının köküne (bu örnekte kök kendisidir) göre konumu, ProjectRunner ise BUILD dosyasındaki hedef adıdır. (Hedef etiketler hakkında daha ayrıntılı bilgiyi bu eğitimin sonunda bulabilirsiniz.)

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

   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.

Şimdi yeni oluşturduğunuz ikili dosyayı 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 kullanarak projenin bağımlılık grafiğini oluşturur. Bu grafik, doğru artımlı derlemeler yapılmasını sağlar.

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

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

Yukarıdaki komut, Bazel'e //:ProjectRunner hedefinin tüm bağımlılıklarını (ana makine ve örtülü 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ıklar olmadan iki kaynak dosyası oluşturan tek bir hedef var:

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

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

Bazel derlemenizi hassaslaştırma

Küçük projeler için tek bir hedef yeterli olsa da daha büyük projeleri birden fazla hedef ve pakete bölmek isteyebilirsiniz. Böylece hızlı artımlı derlemeler (yani yalnızca değişenleri yeniden derleme) yapabilir ve bir projenin birden fazla bölümünü aynı anda derleyerek derleme işlemlerinizi hızlandırabilirsiniz.

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ırmada Bazel önce greeter kitaplığını, ardından ProjectRunner ikili dosyasını oluşturur. java_binary içindeki deps özelliği, Bazel'e ProjectRunner ikilisinin oluşturulması için greeter kitaplığının gerekli olduğunu bildirir.

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

bazel build //:ProjectRunner

Bazel, aşağıdakine benzer bir çıktı ü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

Şimdi yeni oluşturduğunuz ikili dosyayı test edin:

bazel-bin/ProjectRunner

Şimdi ProjectRunner.java dosyasını değiştirip projeyi yeniden oluşturursanız Bazel yalnızca bu dosyayı yeniden derler.

Bağımlılık grafiğine baktığınızda ProjectRunner öğesinin, daha önce olduğu gibi aynı girişlere bağlı olduğunu ancak derlemenin yapısının farklı olduğunu görebilirsiniz:

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

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

Birden fazla paket kullanma

Şimdi projeyi birden fazla pakete bölelim. src/main/java/com/example/cmdline dizinine baktığınızda, bu dizinde BUILD dosyasının yanı sıra bazı kaynak dosyalarının da bulunduğunu görebilirsiniz. Bu nedenle, Bazel için çalışma alanı artık //src/main/java/com/example/cmdline ve // olmak üzere iki paket içeriyor (çünkü çalışma alanının kök dizininde BUILD dosyası var).

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 bağlıdır (bu nedenle hedef etiketi //:greeter). 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 runner hedefinin//src/main/java/com/example/cmdline/BUILD, visibility özelliğini kullanarak //BUILD içindeki hedeflere görünürlüğünü açıkça vermeniz gerekir. Bunun nedeni, varsayılan olarak hedeflerin yalnızca aynı BUILD dosyasındaki diğer hedeflere görünür olmasıdır. (Bazel, hedef görünürlüğünü kullanarak kitaplıkların herkese açık API'lere sızan uygulama ayrıntılarını içermesi gibi sorunları önler.)

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

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

Şimdi, çalışma alanının kök dizininde 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ı üretir:

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

Şimdi yeni oluşturduğunuz ikili dosyayı test edin:

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

Artık projeyi, her biri bir hedef içeren iki paket olarak oluşturacak şekilde değiştirdiniz ve aralarındaki bağımlılıkları anlıyorsunuz.

Hedeflere referans vermek için etiketleri kullanma

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

//path/to/package:target-name

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

Depo kökündeki hedeflere referans verirken paket yolu boş olur. Bu durumda yalnızca //:target-name kullanın. Aynı BUILD dosyasındaki hedeflere referans verirken // çalışma alanı kök tanımlayıcısını atlayıp yalnızca :target-name kullanabilirsiniz.

Örneğin, java-tutorial/BUILD dosyasındaki hedefler için bir paket yolu belirtmeniz gerekmiyordu. Çünkü çalışma alanı kökü, kendisi bir paketti (//) ve iki hedef etiketiniz yalnızca //:ProjectRunner ve //:greeter idi.

Ancak //src/main/java/com/example/cmdline/BUILD dosyasındaki hedefler için //src/main/java/com/example/cmdline 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, tüm çalışma zamanı bağımlılıklarıyla ikili dosya oluşturarak dağıtım için bir Java hedefi paketleyelim. Bu, ikili dosyayı geliştirme ortamınızın dışında çalıştırmanıza olanak tanır.

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

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

İçerikler:

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 öğesini içeriyor ancak bağımlılığı olan Greeting.class öğesini içermiyor. Bazel'in oluşturduğu runner komut dosyası, sınıf yoluna greeter.jar ekler. Bu nedenle, 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ı, bağımsız ve dağıtılabilir bir ikili oluşturmanıza olanak tanır. Bunu oluşturmak için hedef adına _deploy.jar ekleyin:

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

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

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

Gerekli çalışma zamanı bağımlılıklarını içerdiğinden geliştirme ortamınızdan bağımsız olarak çalıştırabileceğiniz runner_deploy.jar adlı bir uygulama oluşturdunuz. Bu bağımsız JAR'ın içeriğine daha önce kullandığınız komutla göz atın:

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

İçerikler, aşağıdakileri çalıştırmak 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 inşa etmeler!