Giriş
Bazel, çeşitli donanımlarda, işletim sistemlerinde ve sistem yapılandırmalarında kod oluşturup test edebilir. Bu, bağlayıcılar ve derleyiciler gibi farklı derleme aracı sürümlerini içerebilir. Bazel, bu karmaşıklığı yönetmeye yardımcı olmak için kısıtlamalar ve platformlar kavramlarını kullanır.
Kısıtlama, bir derleme veya üretim makinesinin ayırt edici özelliğidir. Sık karşılaşılan kısıtlamalar arasında CPU mimarisi, GPU'nun varlığı veya yokluğu ya da yerel olarak yüklenen derleyicinin sürümü yer alır. Ancak kısıtlamalar, derleme işini düzenlerken makineleri anlamlı bir şekilde ayıran her şey olabilir.
Platform, eksiksiz bir makineyi belirten bir kısıtlamalar koleksiyonudur. Bazel, geliştiricilerin hangi makineler için derleme yapmak istediklerini, hangi makinelerin derleme ve test işlemlerini çalıştırması gerektiğini ve hangi toolchain derleme işlemlerinin derlenmesi gerektiğini seçmelerine olanak tanımak için bu kavramı kullanır.
Geliştiriciler, derleme kurallarında özel özellikleri veya bağımlılıkları seçmek için de kısıtlamaları kullanabilir. Örneğin: "Derleme bir Arm makinesini hedeflediğinde src_arm.cc kullanın".
Platform türleri
Bazel, bir platformun oynayabileceği üç rolü tanır:
- Ana makine: Bazel'in kendisinin üzerinde çalıştığı platform.
- Yürütme: Derleme işlemlerini çalıştırarak derleme çıktıları üreten bir platform.
- Hedef: Oluşturulan kodun üzerinde çalışması gereken platform.
Derlemeler genellikle platformlarla üç tür ilişkiye sahiptir:
Tek platformlu derlemeler: Barındırma, yürütme ve hedef platformlar aynıdır. Örneğin, uzaktan yürütme olmadan bir geliştirici makinesinde derleme yapıp aynı makinede derlenmiş ikiliyi çalıştırma.
Çapraz derleme yapıları: Ana makine ve yürütme platformları aynıdır ancak hedef platform farklıdır. Örneğin, uzak yürütme olmadan Macbook Pro'da iOS uygulaması oluşturma.
Çok platformlu derlemeler: Ana makine, yürütme ve hedef platformların tümü farklıdır. Örneğin, Macbook Pro'da iOS uygulaması oluşturma ve Xcode gerektirmeyen C++ işlemlerini derlemek için uzak Linux makinelerini kullanma.
Platformları belirtme
Geliştiricilerin platformları kullanmasının en yaygın yolu, istenen hedef makineleri --platforms işaretiyle belirtmektir:
$ bazel build //:my_linux_app --platforms=//myplatforms:linux_x86
Derleme makinesi kurulumları kuruluşlar arasında farklılık gösterdiğinden kuruluşlar genellikle kendi platform tanımlarını korur.
--platforms ayarlanmadığında varsayılan olarak @platforms//host olur. Bu, özellikle derlemelerin Bazel'in üzerinde çalıştığı makineyi hedeflemesi için ana makinenin işletim sistemi ve CPU özelliklerini otomatik olarak algılayacak şekilde tanımlanır. Derleme kuralları, @platforms/os ve @platforms/cpu kısıtlamalarıyla bu özellikler üzerinde seçim yapabilir.
Genel olarak faydalı kısıtlamalar ve platformlar
Ekosistemin tutarlılığını korumak için Bazel ekibi, en popüler CPU mimarileri ve işletim sistemleri için kısıtlama tanımlarının bulunduğu bir depo tutar. Bunların tümü https://github.com/bazelbuild/platforms adresinde tanımlanmıştır.
Bazel, aşağıdaki özel platform tanımıyla birlikte gelir:
@platforms//host (@bazel_tools//tools:host_platform olarak da bilinir). Bu, Bazel'in üzerinde çalıştığı makinenin işletim sistemi ve CPU özelliklerini otomatik olarak algılar.
Kısıtlamaları tanımlama
Kısıtlamalar, constraint_setting ve constraint_value oluşturma kurallarıyla modellenir.
constraint_setting bir mülk türü bildirir. Örneğin:
constraint_setting(name = "cpu")
constraint_value, söz konusu özellik için olası bir değer bildirir:
constraint_value(
name = "x86",
constraint_setting = ":cpu"
)
Bunlar, platformlar tanımlanırken veya derleme kuralları özelleştirilirken etiket olarak referans verilebilir. Yukarıdaki örnekler cpus/BUILD içinde tanımlanmışsa x86 kısıtlamasına //cpus:x86 olarak referans verebilirsiniz.
Görünürlük izin veriyorsa constraint_setting için kendi değerinizi tanımlayarak mevcut bir constraint_setting değerini uzatabilirsiniz.
Platformları tanımlama
platform derleme kuralı, bir platformu constraint_value'lerin bir koleksiyonu olarak tanımlar:
platform(
name = "linux_x86",
constraint_values = [
"//oses:linux",
"//cpus:x86",
],
)
Bu, hem //oses:linux hem de //cpus:x86 kısıtlamalarına sahip olması gereken bir makineyi modeller.
Platformlar, belirli bir constraint_setting için yalnızca bir constraint_value'ya sahip olabilir.
Örneğin, ikinci değeri modellemek için başka bir constraint_setting türü oluşturmadığınız sürece bir platformda iki CPU olamaz.
Uyumsuz hedefler atlanıyor
Belirli bir hedef platform için derleme yaparken, söz konusu platformda hiçbir zaman çalışmayacak hedefleri atlamak genellikle istenir. Örneğin, Windows cihaz sürücünüz //... ile Linux makinesinde derleme yaparken büyük olasılıkla çok sayıda derleyici hatası oluşturacaktır. Kodunuzun hangi hedef platform kısıtlamalarına sahip olduğunu Bazel'e bildirmek için
target_compatible_with
özelliğini kullanın.
Bu özelliğin en basit kullanımı, hedefi tek bir platformla sınırlar.
Hedef, tüm kısıtlamaları karşılamayan hiçbir platform için oluşturulmaz. Aşağıdaki örnekte win_driver_lib.cc, 64 bit Windows ile sınırlandırılmıştır.
cc_library(
name = "win_driver_lib",
srcs = ["win_driver_lib.cc"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
],
)
:win_driver_lib yalnızca 64 bit Windows ile oluşturmaya uygundur ve diğer tüm sistemlerle uyumsuzdur. Uyumsuzluk geçişlidir. Uyumsuz bir hedefe geçişli olarak bağlı olan tüm hedefler de uyumsuz kabul edilir.
Hedefler ne zaman atlanır?
Hedefler, uyumsuz olarak kabul edildiklerinde ve hedef kalıbı genişletme kapsamında derlemeye dahil edildiklerinde atlanır. Örneğin, aşağıdaki iki çağırma işlemi, hedef kalıp genişletmesinde bulunan tüm uyumsuz hedefleri atlar.
$ bazel build --platforms=//:myplatform //...
$ bazel build --platforms=//:myplatform //:all
test_suite içindeki uyumsuz testler, komut satırında test_suite --expand_test_suites ile belirtilirse benzer şekilde atlanır.
Diğer bir deyişle, komut satırındaki test_suite hedefleri :all ve ... gibi davranır. --noexpand_test_suites kullanmak genişletmeyi engeller ve uyumsuz testlere sahip test_suite hedeflerinin de uyumsuz olmasına neden olur.
Komut satırında açıkça uyumsuz bir hedef belirtmek hata mesajına ve başarısız bir derlemeye neden olur.
$ bazel build --platforms=//:myplatform //:target_incompatible_with_myplatform
...
ERROR: Target //:target_incompatible_with_myplatform is incompatible and cannot be built, but was explicitly requested.
...
FAILED: Build did NOT complete successfully
--skip_incompatible_explicit_targets etkinse uyumsuz açık hedefler sessizce atlanır.
Daha etkileyici kısıtlamalar
Kısıtlamaları ifade etmede daha fazla esneklik için hiçbir platformun karşılamadığı @platforms//:incompatible
constraint_value
kullanın.
Daha karmaşık kısıtlamaları ifade etmek için select() ile @platforms//:incompatible öğesini birlikte kullanın. Örneğin, temel VEYA mantığını uygulamak için kullanın. Aşağıdaki işaret, macOS ve Linux ile uyumlu olan ancak diğer platformlarla uyumlu olmayan bir kitaplığı gösterir.
cc_library(
name = "unixish_lib",
srcs = ["unixish_lib.cc"],
target_compatible_with = select({
"@platforms//os:osx": [],
"@platforms//os:linux": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
)
Yukarıdaki bilgiler şu şekilde yorumlanabilir:
- macOS hedeflenirken hedefte kısıtlama yoktur.
- Linux hedeflenirken hedefte kısıtlama yoktur.
- Aksi takdirde, hedefte
@platforms//:incompatiblekısıtlaması vardır.@platforms//:incompatibleherhangi bir platformun parçası olmadığı için hedef uyumsuz kabul edilir.
Kısıtlamalarınızı daha okunabilir hale getirmek için skylib'in selects.with_or() işlevini kullanın.
Ters uyumluluğu da benzer şekilde ifade edebilirsiniz. Aşağıdaki örnekte, ARM dışında her şeyle uyumlu bir kitaplık açıklanmaktadır.
cc_library(
name = "non_arm_lib",
srcs = ["non_arm_lib.cc"],
target_compatible_with = select({
"@platforms//cpu:arm": ["@platforms//:incompatible"],
"//conditions:default": [],
}),
)
bazel cquery kullanarak uyumsuz hedefleri tespit etme
Uyumsuz hedefleri uyumlu olanlardan ayırt etmek için bazel cquery'ın Starlark çıkış biçimindeki IncompatiblePlatformProvider özelliğini kullanabilirsiniz.
Bu, uyumsuz hedefleri filtrelemek için kullanılabilir. Aşağıdaki örnekte yalnızca uyumlu hedeflerin etiketleri yazdırılır. Uyumsuz hedefler yazdırılmaz.
$ cat example.cquery
def format(target):
if "IncompatiblePlatformProvider" not in providers(target):
return target.label
return ""
$ bazel cquery //... --output=starlark --starlark:file=example.cquery
Bilinen sorunlar
Uyumsuz hedefler görünürlük kısıtlamalarını yoksayar.