Platformlar

Sorun bildir Kaynağı göster

Bazel; bağlayıcılar ve derleyiciler gibi derleme araçlarının birçok farklı sürümünü kullanarak çeşitli donanımlar, işletim sistemleri ve sistem yapılandırmalarında kod oluşturup test edebilir. Bazel, bu karmaşıklığı yönetmeye yardımcı olmak için kısıtlamalar ve platformlar kavramlarını kullanır. Kısıtlama; CPU mimarisi, GPU'nun olup olmaması veya sistem tarafından yüklü derleyicinin sürümü gibi derleme veya üretim ortamlarının farklı olabileceği bir boyuttur. Platform, bazı ortamlarda kullanılabilir olan belirli kaynakları temsil eden bu kısıtlamalar için adlandırılmış bir seçenek koleksiyonudur.

Ortamın platform olarak modellenmesi, Bazel'ın 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, platformda hizmet verebilecek üç rolü tanır:

  • Ana makine - Bazel'ın kendisinin çalıştırıldığı platform.
  • Yürütme: Derleme araçlarının, ara ve nihai çıktılar üretmek için derleme işlemlerini yürüttüğü platform.
  • Hedef - Nihai çıkışın yer aldığı ve yürütüldüğü platform.

Bazel, platformlarla ilgili olarak aşağıdaki oluşturma senaryolarını destekler:

  • Tek platform derlemeleri (varsayılan): Ana makine, yürütme ve hedef platformlar aynıdır. Örneğin, Intel x64 CPU üzerinde çalışan Ubuntu'da yürütülebilir bir Linux oluşturma.

  • Çapraz derleme derlemeleri: Ana makine ve yürütme platformları aynı ancak hedef platform farklıdır. Örneğin, macOS'te MacBook Pro'da çalışan bir iOS uygulaması oluşturabilirsiniz.

  • Çoklu platform derlemeleri: Ana makine, yürütme ve hedef platformlar birbirinden farklıdır.

Kısıtlamaları ve platformları tanımlama

Platformlar için olası seçim 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. Birlikte bir enum ve olası değerlerini etkili bir şekilde tanımlarlar. Örneğin, bir BUILD dosyasının aşağıdaki snippet'i, sistemin glibc sürümü için iki olası değerle bir kısıtlama sunar.

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 etikete göre referans verilir ve bunlar genel görünürlük denetimlerine tabidir. Görünürlük izin veriyorsa mevcut bir kısıtlama ayarı için kendi değerinizi tanımlayarak bu ayarı genişletebilirsiniz.

platform kuralı, belirli kısıtlama değeri seçenekleriyle yeni bir platform sunar. Aşağıda linux_x86 adlı bir platform oluşturulmuştur ve bu platformun, 2.25 glibc sürümüyle bir x86_64 mimarisi üzerinde Linux işletim sistemi çalıştıran tüm ortamların açıklandığı belirtilmektedir. (Bazel'ın 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 faydalı kısıtlamalar ve platformlar

Ekosistem tutarlılığı sağlamak için Bazel ekibi en popüler CPU mimarileri ve işletim sistemleri için sınırlı tanımlar içeren bir depoya sahiptir. Bu platformların hepsi https://github.com/bazelbuild/platforms adresinde bulunmaktadır.

Bazel, aşağıdaki özel platform tanımıyla sunulur: @platforms//host (diğer adı @bazel_tools//tools:host_platform). Bu, otomatik olarak algılanan ana makine platformu değeridir ve Bazel'ın ç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 makine ve hedef platformları belirtebilirsiniz:

  • --host_platform - varsayılan olarak @bazel_tools//tools:host_platform değerine ayarlanır
    • Bu hedefin diğer adı @platforms//host olan ve ana makine işletim sistemi ile CPU'yu algılayıp platform hedefini yazan bir depo kuralı tarafından desteklenir.
    • Ayrıca, diğer BUILD ve Starlark dosyalarında kullanılabilecek HOST_CONSTRAINTS adlı bir diziyi açığa çıkaran @platforms//host:constraints.bzl vardır.
  • --platforms: Varsayılan olarak ana makine platformuna ayarlanır
    • Bu, başka işaret ayarlanmadığında hedef platformun @platforms//host olduğu anlamına gelir.
    • --platforms yerine --host_platform ayarlanırsa --host_platform hem ana makine hem de hedef platform olur.

Uyumsuz hedefler atlanıyor

Belirli bir hedef platform için geliştirme yaparken, o platformda hiçbir zaman çalışmayacak hedefleri atlamak genellikle tercih edilir. Örneğin, Windows cihaz sürücünüz //... ile bir Linux makinesinde derleme yaparken muhtemelen çok sayıda derleyici hatası oluşturacaktır. Bazel'a kodunuzda hangi hedef platform kısıtlamalarının 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 herhangi bir platform için oluşturulmaz. Aşağıdaki örnekte, win_driver_lib.cc değeri 64 bit Windows ile kısıtlanmış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 derlemeye uygundur ve başka hiçbir sistemle uyumlu değildir. Uyumsuzluk durumu geçişlidir. Geçişli olarak uyumsuz bir hedefe bağımlı olan hedeflerin kendileri uyumsuz olarak kabul edilir.

Hedefler ne zaman atlanır?

Hedefler, uyumsuz olduklarında atlanır ve hedef kalıbı genişletmesinin parçası olarak derlemeye dahil edilir. Örneğin, aşağıdaki iki çağrı, 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 --expand_test_suites ile birlikte test_suite belirtilmişse 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 uyumsuz bir hedefin açıkça belirtilmesi, hata mesajıyla ve başarısız derlemeyle sonuçlanır.

$ 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 etkinleştirilirse uyumsuz olan açık hedefler sessizce atlanır.

Daha etkili kısıtlamalar

Kısıtlamaları ifade etme konusunda daha fazla esneklik için hiçbir platformun karşılamadığı @platforms//:incompatible constraint_value yöntemini kullanın.

Daha karmaşık kısıtlamaları ifade etmek için select() etiketini @platforms//:incompatible ile birlikte kullanın. Örneğin, temel VEYA mantığını uygulamak için bunu kullanın. Aşağıda, macOS ve Linux ile uyumlu olan ancak başka platformlarla uyumlu olmayan bir kitaplık belirtilmiştir.

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 yorum şu şekilde yorumlanabilir:

  1. macOS hedeflenirken hedefte herhangi bir kısıtlama olmaz.
  2. Linux hedeflenirken hedefte hiçbir kısıtlama olmaz.
  3. Aksi takdirde, hedefin @platforms//:incompatible kısıtlaması olur. @platforms//:incompatible hiçbir platforma dahil olmadığından hedef uyumsuz olarak kabul edilir.

Kısıtlamalarınızı daha okunabilir hale getirmek için skylib selects.with_or() özelliğini kullanın.

Ters uyumluluğu benzer bir ş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 kullanılarak uyumsuz hedefler algılanıyor

Uyumsuz hedefleri uyumlulardan ayırt etmek için bazel cquery uygulamasının Starlark çıkış biçiminde IncompatiblePlatformProvider kullanabilirsiniz.

Bu özellik, uyumsuz hedefleri filtrelemek için kullanılabilir. Aşağıdaki örnekte yalnızca uyumlu hedeflere ilişkin etiketler yazdırılmaktadı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.