Bazel Eğitimi: C++ Projesi Oluşturma

Sorun bildirin Kaynağı göster

Giriş

Bazel'i kullanmaya yeni mi başladınız? Doğru yerdesiniz. Bazel'in kullanımına basitleştirilmiş bir giriş için bu İlk Derleme eğitimini izleyin. Bu eğitimde, Bazel'ın bağlamında kullanılan temel terimler tanımlanıp Bazel iş akışının temel özellikleri açıklanmaktadır. İhtiyacınız olan araçlardan başlayarak, karmaşıklık düzeyi gittikçe artan üç proje oluşturup yürütecek ve bunların nasıl ve neden daha karmaşık hale geldiğini öğreneceksiniz.

Bazel çok dilli derlemeleri destekleyen bir derleme sistemi olsa da bu eğitim, örnek olarak bir C++ projesini kullanır ve çoğu dil için geçerli olan genel yönergeleri ve akışı sağlar.

Tahmini tamamlanma süresi: 30 dakika.

Ön koşullar

Henüz yapmadıysanız Bazel'i yükleyerek başlayın. Bu eğiticide kaynak kontrolü için Git kullanıldığından en iyi sonuçlar için Git'i de yükleyin.

Ardından, istediğiniz komut satırı aracında aşağıdaki komutu çalıştırarak Bazel'ın GitHub deposundan örnek projeyi alın:

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

Bu eğitim için örnek proje examples/cpp-tutorial dizinindedir.

Nasıl yapılandırıldığına aşağıda göz atabilirsiniz:

examples
└── cpp-tutorial
    ├──stage1
    │  ├── main
    │  │   ├── BUILD
    │  │   └── hello-world.cc
    │  └── WORKSPACE
    ├──stage2
    │  ├── main
    │  │   ├── BUILD
    │  │   ├── hello-world.cc
    │  │   ├── hello-greet.cc
    │  │   └── hello-greet.h
    │  └── WORKSPACE
    └──stage3
       ├── main
       │   ├── BUILD
       │   ├── hello-world.cc
       │   ├── hello-greet.cc
       │   └── hello-greet.h
       ├── lib
       │   ├── BUILD
       │   ├── hello-time.cc
       │   └── hello-time.h
       └── WORKSPACE

Bu eğiticide, her biri bir aşamayı temsil eden üç dosya grubu vardır. İlk aşamada, tek bir paket içinde yer alan tek bir hedef oluşturacaksınız. İkinci aşamada tek bir paketten hem ikili program hem de kitaplık oluşturacaksınız. Üçüncü ve son aşamada birden çok pakete sahip bir proje geliştirecek ve projeyi birden çok hedef ile oluşturacaksınız.

Özet: Giriş

Bu eğitim için Bazel'ı (ve Git) yükleyip depoyu klonlayarak Bazel ile ilk derlemenizin temelini atmış oldunuz. Bazı terimleri tanımlamak ve çalışma alanınızı ayarlamak için sonraki bölüme geçin.

Başlarken

Çalışma alanını ayarlama

Bir proje oluşturmadan önce projenin çalışma alanını oluşturmanız gerekir. Çalışma alanı, projenizin kaynak dosyalarını ve Bazel'ın derleme çıkışlarını barındıran bir dizindir. Ayrıca, aşağıdaki önemli 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 WORKSPACE file .
  • Bazel'e projenin farklı bölümlerini nasıl oluşturacağını bildiren bir veya daha fazla BUILD files . Çalışma alanında bulunan ve BUILD dosyası içeren dizin bir pakettir. (Bu eğiticinin sonraki bölümlerinde paketlerle ilgili daha fazla bilgi bulabilirsiniz.)

Gelecekteki projelerde bir dizini Bazel çalışma alanı olarak belirlemek için o dizinde WORKSPACE adlı boş bir dosya oluşturun. Bu eğiticinin amaçları doğrultusunda, her aşamada bir WORKSPACE dosyası zaten mevcuttur.

NOT: Bazel projeyi oluşturduğunda tüm girişlerin aynı çalışma alanında olması gerekir. Farklı çalışma alanlarında bulunan dosyalar, bağlantılı olmadıkları sürece birbirinden bağımsızdır. Çalışma alanı kuralları hakkında daha ayrıntılı bilgiyi bu kılavuzda bulabilirsiniz.

BUILD dosyasını anlama

BUILD dosyası, Bazel için farklı türde talimatları içerir. Her BUILD dosyası, bir dizi talimat olarak en az bir kural gerektirir. Bu kurallar, Bazel'a yürütülebilir ikili programlar veya kitaplıklar gibi istenen çıkışları nasıl derleyeceğini bildirir. BUILD dosyasındaki her derleme kuralının örneğine hedef adı verilir ve bunlar belirli bir kaynak dosyaları ile bağımlılıkları işaret eder. Bir hedef, başka hedefleri de gösterebilir.

cpp-tutorial/stage1/main dizinindeki BUILD dosyasına göz atın:

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
)

Örneğimizde hello-world hedefi, Bazel'in yerleşik cc_binary rule özelliğini örneklendirir. Kural, Bazel'a hello-world.cc kaynak dosyasından bağımlılık olmadan bağımsız yürütülebilir bir ikili program oluşturmasını söyler.

Özet: başlarken

Artık bazı anahtar terimleri ve bunların bu proje ve genel olarak Bazel bağlamında ne anlama geldiğini biliyorsunuz. Bir sonraki bölümde projenin 1. aşamasını oluşturup test edeceksiniz.

1. Aşama: tek hedef, tek paket

Projenin ilk bölümünü inşa etme zamanı geldi. Görsel bir referans olması açısından, projenin 1. Aşama bölümünün yapısı şöyledir:

examples
└── cpp-tutorial
    └──stage1
       ├── main
       │   ├── BUILD
       │   └── hello-world.cc
       └── WORKSPACE

cpp-tutorial/stage1 dizinine taşımak için aşağıdaki komutu çalıştırın:

cd cpp-tutorial/stage1

Ardından şu komutu çalıştırın:

bazel build //main:hello-world

Hedef etikette //main: bölümü, çalışma alanının köküne göre BUILD dosyasının konumu, hello-world ise BUILD dosyasındaki hedef addır.

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

INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 2.267s, Critical Path: 0.25s

İlk Bazel hedefinizi oluşturdunuz. Bazel, derleme çıkışlarını çalışma alanının köküne bazel-bin dizinine yerleştirir.

Şimdi, yeni derlenen ikili programınızı test edin:

bazel-bin/main/hello-world

Bu işlem, basılı bir "Hello world" iletisiyle sonuçlanır.

1. Aşamanın bağımlılık grafiği şöyle olabilir:

hello-world için bağımlılık grafiği, tek bir kaynak dosyası bulunan tek bir hedef gösteriyor.

Özet: 1. aşama

İlk derlemenizi tamamladığınıza göre, artık bir derlemenin nasıl yapılandırıldığına dair temel bir fikriniz var. Bir sonraki aşamada başka bir hedef ekleyerek karmaşıklığı ekleyeceksiniz.

2. Aşama: Birden fazla derleme hedefi

Küçük projeler için tek bir hedef yeterli olsa da daha büyük projeleri birden fazla hedefe ve pakete bölmek isteyebilirsiniz. Bu yöntem, artımlı derlemelerin hızlı olmasını sağlar. Yani, Bazel yalnızca değişiklikleri yeniden oluşturur. Ayrıca, projenin birden fazla parçasını tek seferde derleyerek derlemelerinizi hızlandırır. Eğiticinin bu aşaması bir hedef, sonraki aşama ise bir paket ekler.

2. Aşama için çalıştığınız dizin şu şekildedir:

    ├──stage2
    │  ├── main
    │  │   ├── BUILD
    │  │   ├── hello-world.cc
    │  │   ├── hello-greet.cc
    │  │   └── hello-greet.h
    │  └── WORKSPACE

cpp-tutorial/stage2/main dizinindeki BUILD dosyasına göz atın:

cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
    ],
)

Bazel, bu BUILD dosyasıyla önce hello-greet kitaplığını (Bazel'in yerleşik cc_library rule kitaplığını kullanarak) ve ardından hello-world ikili programını oluşturur. hello-world hedefindeki deps özelliği, Bazel'a hello-world ikili programını derlemek için hello-greet kitaplığının gerekli olduğunu bildirir.

Projenin bu yeni sürümünü oluşturabilmek için önce dizinleri değiştirmeniz ve aşağıdaki komutu çalıştırarak cpp-tutorial/stage2 dizinine geçmeniz gerekir:

cd ../stage2

Artık aşağıdaki bilinen komutu kullanarak yeni ikili programı derleyebilirsiniz:

bazel build //main:hello-world

Bir kez daha Bazel aşağıdaki gibi bir şey üretir:

INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 2.399s, Critical Path: 0.30s

Artık başka bir "Hello world" döndüren yeni derlenmiş ikili programınızı test edebilirsiniz:

bazel-bin/main/hello-world

Şimdi hello-greet.cc öğesini değiştirip projeyi yeniden derlerseniz Bazel yalnızca söz konusu dosyayı yeniden derler.

Bağımlılık grafiğine baktığınızda, hello-world'ün daha önce olduğu gibi girişlere bağlı olduğunu ancak derlemenin yapısının farklı olduğunu görebilirsiniz:

"hello-world"ün bağımlılık grafiği, dosyada değişiklik yapıldıktan sonra yapı değişikliklerini gösteriyor.

Özet: 2. aşama

Projeyi iki hedefle oluşturmuş oldunuz. hello-world hedefi, bir kaynak dosya oluşturur ve iki ek kaynak dosyası oluşturan başka bir hedefe (//main:hello-greet) bağlıdır. Bir sonraki bölümde, bunu bir adım öteye getirip başka bir paket ekleyin.

3. Aşama: Birden fazla paket

Bir sonraki aşama ise başka bir komplikasyon katmanı ekler ve birden fazla pakete sahip bir proje oluşturur. Aşağıda cpp-tutorial/stage3 dizininin yapısına ve içeriğine göz atabilirsiniz:

└──stage3
   ├── main
   │   ├── BUILD
   │   ├── hello-world.cc
   │   ├── hello-greet.cc
   │   └── hello-greet.h
   ├── lib
   │   ├── BUILD
   │   ├── hello-time.cc
   │   └── hello-time.h
   └── WORKSPACE

Gördüğünüz gibi, her biri bir BUILD dosyası içeren iki alt dizin vardır. Dolayısıyla, çalışma alanı Bazel'a göre artık iki paket içeriyor: lib ve main.

lib/BUILD dosyasına göz atın:

cc_library(
    name = "hello-time",
    srcs = ["hello-time.cc"],
    hdrs = ["hello-time.h"],
    visibility = ["//main:__pkg__"],
)

main/BUILD dosyasında:

cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
        "//lib:hello-time",
    ],
)

Ana paketteki hello-world hedefi, lib paketindeki hello-time hedefine (dolayısıyla hedef etiketi //lib:hello-time) bağlıdır. Bazel bunu deps özelliği aracılığıyla bilir. Bunun bağımlılık grafiğinde yansıdığını görebilirsiniz:

"hello-world"ün bağımlılık grafiği, ana paketteki hedefin "lib" paketindeki hedefe nasıl bağlı olduğunu gösterir.

Derlemenin başarılı olması için görünürlük özelliğini kullanarak lib/BUILD içindeki //lib:hello-time hedefini main/BUILD içindeki hedeflere açıkça görünür hale getirirsiniz. Bunun nedeni, hedeflerin varsayılan olarak yalnızca aynı BUILD dosyasındaki diğer hedefler tarafından görülebilmesidir. Bazel, herkese açık API'lere sızdırılan uygulama ayrıntılarını içeren kitaplıklar gibi sorunları önlemek için hedef görünürlük kullanır.

Şimdi projenin bu son sürümünü derleyin. Şu komutu çalıştırarak cpp-tutorial/stage3 dizinine geçin:

cd  ../stage3

Bir kez daha aşağıdaki komutu çalıştırın:

bazel build //main:hello-world

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

INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 0.167s, Critical Path: 0.00s

Şimdi, bu eğiticinin son ikili programındaki son Hello world mesajını test edin:

bazel-bin/main/hello-world

Özet: 3. aşama

Bu aşamada projeyi, üç hedefi olan iki paket halinde oluşturdunuz ve bunlar arasındaki bağımlılıkları anladınız. Bu sayede Bazel ile ilerlemek ve gelecek projeler oluşturmak için gereken araçları elde edebilirsiniz. Bir sonraki bölümde Bazel yolculuğunuza nasıl devam edeceğinize bakacağız.

Sonraki adımlar

Bazel ile ilk temel derlemenizi tamamladınız, ancak bu daha başlangıç. Bazel ile öğrenmeye devam etmek için aşağıdaki diğer kaynakları kullanabilirsiniz:

Mutlu binalar!