Bazel, bağlayıcılar ve derleyiciler gibi derleme araçlarının birçok farklı sürümünü kullanarak çeşitli donanımlarda, işletim sistemlerinde ve sistem yapılandırmalarında kod oluşturabilir ve test edebilir. Bazel, bu karmaşıklığı yönetmeye yardımcı olmak için sınırlamalar ve platformlar kavramına sahiptir. Kısıtlama; CPU mimarisi, GPU'nun olup olmaması veya sistem tarafından yüklenmiş derleyici sürümü gibi derleme ya da üretim ortamlarının farklılık gösterebileceği boyuttur. Platform, bazı ortamlarda mevcut olan belirli kaynakları temsil eden, bu kısıtlamalar için adlandırılmış bir seçenekler koleksiyonudur.
Ortamın platform olarak modellenmesi, Bazel'in derleme işlemleri için uygun araç zincirlerini otomatik olarak seçmesine yardımcı olur. Platformlar, yapılandırılabilir özellikler yazmak için config_setting kuralıyla birlikte de kullanılabilir.
Bazel, bir platformun işleyebileceği üç rolün farkındadır:
- Ana makine: Bazel'in çalıştığı platform.
- Yürütme: Derleme araçlarının ara ve nihai çıkışlar oluşturmak için derleme işlemlerini yürüttüğü bir platformdur.
- Hedef: Son çıktının bulunduğu ve çalıştırıldığı platform.
Bazel, platformlarla ilgili aşağıdaki derleme senaryolarını destekler:
Tek platformlu derlemeler (varsayılan): Ana makine, yürütme ve hedef platformlar aynıdır. Örneğin, Ubuntu'da Intel x64 CPU'da çalışan bir Linux yürütülebilir dosyası oluşturma.
Derlemeler arası derlemeler: Ana makine ve yürütme platformları aynıdır ancak hedef platform farklıdır. Örneğin, macOS'te MacBook Pro üzerinde bir iOS uygulaması derleyebiliriz.
Çok platformlu derlemeler: Barındırma, yürütme ve hedef platformların tümü farklıdır.
Kısıtlamaları ve platformları tanımlama
Platformlar için olası seçenekler alanı, BUILD
dosyalarındaki constraint_setting
ve constraint_value
kuralları kullanılarak tanımlanır.
constraint_setting
yeni bir boyut oluştururken constraint_value
belirli bir boyut için yeni bir değer oluşturur. Bu iki değer birlikte bir enum ve olası değerlerini etkili bir şekilde tanımlar. Örneğin, aşağıdaki BUILD
dosyası snippet'inde, sistemin glibc sürümü için iki olası değer içeren bir kısıtlama sunulmaktadır.
constraint_setting(name = "glibc_version")
constraint_value(
name = "glibc_2_25",
constraint_setting = ":glibc_version",
)
constraint_value(
name = "glibc_2_26",
constraint_setting = ":glibc_version",
)
Kısıtlamalar ve değerleri, çalışma alanındaki farklı paketlerde tanımlanabilir. Bunlara etiketle referans verilir ve normal görünürlük denetimlerine tabidir. Görünürlük izin veriyorsa mevcut bir kısıtlama ayarını kendi değerinizi tanımlayarak genişletebilirsiniz.
platform
kuralı, belirli kısıtlama değeri seçenekleri içeren yeni bir platform sunar. Aşağıdaki komut linux_x86
adında bir platform oluşturur ve bu platformun, 2.25 glibc sürümüne sahip x86_64 mimarisi üzerinde Linux işletim sistemi çalıştıran tüm ortamları tanımladığı belirtilmektedir. (Bazel'in yerleşik kısıtlamaları hakkında daha fazla bilgi için aşağıya bakın.)
platform(
name = "linux_x86",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
":glibc_2_25",
],
)
Genel olarak yararlı kısıtlamalar ve platformlar
Ekosistemin tutarlı kalması için Bazel ekibi, en popüler CPU mimarileri ve işletim sistemleri için kısıtlama tanımları içeren bir depo tutar. Bunların tümü https://github.com/bazelbuild/platforms adresinde yer alır.
Bazel, aşağıdaki özel platform tanımı ile birlikte gönderilir:
@platforms//host
(@bazel_tools//tools:host_platform
olarak adlandırılır). Bu, otomatik olarak algılanan ana makine platform değeridir. Bazel'in çalıştığı sistem için otomatik olarak algılanan platformu temsil eder.
Derleme için platform belirtme
Aşağıdaki komut satırı işaretlerini kullanarak bir derleme için ana makineyi ve hedef platformları belirtebilirsiniz:
--host_platform
: Varsayılan olarak@bazel_tools//tools:host_platform
değerine ayarlanır.- Bu hedefin takma adı
@platforms//host
olarak belirlenir. Bu hedef, ana makine işletim sistemini ve CPU'yu algılayıp platform hedefini yazan bir repo kuralı tarafından desteklenir. - Diğer BUILD ve Starlark dosyalarında kullanılabilecek
HOST_CONSTRAINTS
adlı bir diziyi gösteren@platforms//host:constraints.bzl
de vardır.
- Bu hedefin takma adı
--platforms
: Varsayılan olarak ana makine platformu kullanılır- Bu, başka işaret ayarlanmadığında hedef platformun
@platforms//host
olduğu anlamına gelir. --platforms
yerine--host_platform
ayarlandıysa--host_platform
değeri hem ana makine hem de hedef platformdur.
- Bu, başka işaret ayarlanmadığında hedef platformun
Uyumsuz hedefleri atlama
Belirli bir hedef platform için uygulama oluştururken genellikle söz konusu platformda hiçbir zaman çalışmayacak hedefleri atlamak istenir. Örneğin, Windows cihaz sürücünüz //...
ile Linux makinede derleme yaparken büyük olasılıkla çok sayıda derleyici hatası oluşturacaktır. Bazel'e, kodunuzun hangi hedef platform kısıtlamalarına sahip olduğunu bildirmek için target_compatible_with
özelliğini kullanın.
Bu özelliğin en basit kullanımı, hedefi tek bir platformla kısıtlar.
Hedef, tüm kısıtlamaları karşılamayan platformlar 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 derleme için uyumludur ve diğer tüm sistemlerle uyumlu değildir. Uyumsuzluk geçişlidir. Geçiş yoluyla uyumsuz bir hedefe bağlı olan tüm hedeflerin uyumsuz olduğu kabul edilir.
Hedefler ne zaman atlanır?
Hedefler, uyumlu olmadığı kabul edildiğinde ve hedef kalıp genişletmesinin bir parçası olarak derlemeye dahil edildiğinde atlanır. Örneğin, aşağıdaki iki çağrı, hedef kalıp genişletmesinde bulunan uyumsuz hedefleri atlar.
$ bazel build --platforms=//:myplatform //...
$ bazel build --platforms=//:myplatform //:all
test_suite
içindeki uyumlu olmayan testler de test_suite
, komut satırında --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
kullanılması, 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 belirlemek, hata mesajına ve başarısız 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 uyumlu olmayan açık hedefler sessizce atlanır.
Daha etkileyici kısıtlamalar
Kısıtlamaları ifade etme konusunda 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
birlikte kullanın. Örneğin, temel VEYA mantığını uygulamak için kullanın. Aşağıdaki işaret, macOS ve Linux ile uyumlu 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 ifade şu şekilde yorumlanabilir:
- macOS hedeflenirken hedefin herhangi bir kısıtlaması yoktur.
- Linux'u hedeflerken hedefte kısıtlama yoktur.
- Aksi takdirde hedefte
@platforms//:incompatible
kısıtlaması vardır.@platforms//:incompatible
herhangi bir platformun parçası olmadığı için hedef uyumlu değildir.
Kısıtlamalarınızı daha okunaklı hale getirmek için skylib'in selects.with_or()
aracını kullanın.
Ters uyumluluğu da benzer şekilde ifade edebilirsiniz. Aşağıdaki örnekte, ARM hariç 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 algılama
Uyumsuz hedefleri uyumlu olanlardan ayırt etmek için bazel cquery
'ın Starlark çıkış biçimindeki IncompatiblePlatformProvider
değerini kullanabilirsiniz.
Bu, uyumlu olmayan hedefleri filtrelemek için kullanılabilir. Aşağıdaki örnekte yalnızca uyumlu hedeflerin etiketleri yazdırılır. Uyumlu olmayan 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.