Starlark, Python'a benzer
İlk olarak Bazel'de kullanılmak üzere geliştirilen ve yaygın olarak kullanılan
başka araçlar tarafından da kullanılabilir. Bazel'in BUILD
ve .bzl
dosyaları şu lehçeyle yazılmıştır:
Starlark, "Derleme Dili" olarak bilinse de çoğu zaman
Örneğin, Starlark’tan bahsediyoruz. Özellikle bir özelliğin
yerleşik veya "yerel" olmak yerine Yapı Dilinde ifade edilir parça
elde etti. Bazel, derlemeyle ilgili çok sayıda işlevle temel dili zenginleştirir
glob
, genrule
, java_binary
gibi.
Bkz. Bazel ve Starlark belgelerinde daha fazla ayrıntı sağlar Kurallar SIG şablonu bir başlangıç noktası görevi görebilir.
Boş kural
İlk kuralınızı oluşturmak için foo.bzl
dosyasını oluşturun:
def _foo_binary_impl(ctx):
pass
foo_binary = rule(
implementation = _foo_binary_impl,
)
rule
işlevini çağırdığınızda
bir geri çağırma işlevi tanımlamalıdır. Mantık bunu sağlar, ama
fonksiyonu şu an için boş bırakabilirsiniz. ctx
bağımsız değişkeni
hedef hakkında bilgi sağlar.
Kuralı yükleyip bir BUILD
dosyasından kullanabilirsiniz.
Aynı dizinde bir BUILD
dosyası oluşturun:
load(":foo.bzl", "foo_binary")
foo_binary(name = "bin")
Artık hedef oluşturulabilir:
$ bazel build bin
INFO: Analyzed target //:bin (2 packages loaded, 17 targets configured).
INFO: Found 1 target...
Target //:bin up-to-date (nothing to build)
Kural hiçbir şey yapmasa da zaten diğer kurallar gibi davranır: Kurala sahip
zorunlu ad; visibility
, testonly
ve
tags
.
Değerlendirme modeli
Devam etmeden önce kodun nasıl değerlendirildiğini anlamanız önemlidir.
foo.bzl
öğesini bazı basılı ifadelerle güncelleyin:
def _foo_binary_impl(ctx):
print("analyzing", ctx.label)
foo_binary = rule(
implementation = _foo_binary_impl,
)
print("bzl file evaluation")
ve BUILD:
load(":foo.bzl", "foo_binary")
print("BUILD file")
foo_binary(name = "bin1")
foo_binary(name = "bin2")
ctx.label
analiz edilen hedefin etiketine karşılık gelir. ctx
nesnesi
birçok faydalı alan ve yöntem, ayrıntılı bir listeyi
API referansı.
Kodu sorgulayın:
$ bazel query :all
DEBUG: /usr/home/bazel-codelab/foo.bzl:8:1: bzl file evaluation
DEBUG: /usr/home/bazel-codelab/BUILD:2:1: BUILD file
//:bin2
//:bin1
Birkaç gözlem yapın:
- "bzl dosya değerlendirmesi" yazdırılır.
BUILD
dosyasını değerlendirmeden önce, Bazel, yüklediği tüm dosyaları değerlendirir. Birden fazlaBUILD
dosyası yükleniyorsa foo.bzl ise yalnızca bir "bzl dosya değerlendirmesi" örneği görürsünüz çünkü Bazel, değerlendirmenin sonucunu önbelleğe alır. _foo_binary_impl
geri çağırma işlevi çağrılmadı. Bazel sorgusu yüklenirBUILD
dosya, ancak hedefleri analiz etmez.
Hedefleri analiz etmek için cquery
("yapılandırılmış
sorgusu") veya build
komutunu girin:
$ bazel build :all
DEBUG: /usr/home/bazel-codelab/foo.bzl:8:1: bzl file evaluation
DEBUG: /usr/home/bazel-codelab/BUILD:2:1: BUILD file
DEBUG: /usr/home/bazel-codelab/foo.bzl:2:5: analyzing //:bin1
DEBUG: /usr/home/bazel-codelab/foo.bzl:2:5: analyzing //:bin2
INFO: Analyzed 2 targets (0 packages loaded, 0 targets configured).
INFO: Found 2 targets...
Gördüğünüz gibi _foo_binary_impl
artık her hedef için bir kez olmak üzere iki kez çağrılıyor.
Bazı okuyucular, "bzl dosyasının değerlendirilmesi"nin tekrar yazdırılır, ancak
foo.bzl değerlendirmesi, bazel query
çağrısından sonra önbelleğe alınır. Bazel
kodu yeniden değerlendirmez, yalnızca yazdırma etkinliklerini yeniden oynatır. Her ne olursa olsun
aynı çıkışı elde edersiniz.
Dosya oluşturma
Kuralınızı daha kullanışlı hale getirmek için, dosya oluşturacak şekilde güncelleyin. Öncelikle, dosyasına bir ad verin. Bu örnekte, hedef:
ctx.actions.declare_file(ctx.label.name)
bazel build :all
öğesini şimdi çalıştırırsanız bir hata alırsınız:
The following files have no generating action:
bin2
Her dosya bildirdiğinizde, Bazel'a
bir eylem oluşturabilirsiniz. ctx.actions.write
kullanın,
dosya oluşturabilirsiniz.
def _foo_binary_impl(ctx):
out = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(
output = out,
content = "Hello\n",
)
Kod geçerli olsa da hiçbir işlevi olmaz:
$ bazel build bin1
Target //:bin1 up-to-date (nothing to build)
ctx.actions.write
işlevi, Bazel'a öğrenen bir işlem kaydetti.
nasıl oluşturulacağını öğreneceksiniz. Ancak Bazel, yüklenene kadar
istemiş olabilir. Bu yüzden yapılacak son şey, Bazel'a dosyanın
kuralın bir çıkışıdır, kural içinde kullanılan geçici bir dosya değildir
hakkında bilgi edindiniz.
def _foo_binary_impl(ctx):
out = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(
output = out,
content = "Hello!\n",
)
return [DefaultInfo(files = depset([out]))]
DefaultInfo
ve depset
işlevlerine daha sonra göz atın. Şimdilik,
bir kuralın çıkışlarını seçmek için son satırın yöntem olduğunu varsayın.
Şimdi, Bazel'i çalıştırın:
$ bazel build bin1
INFO: Found 1 target...
Target //:bin1 up-to-date:
bazel-bin/bin1
$ cat bazel-bin/bin1
Hello!
Dosyayı başarıyla oluşturdunuz.
Özellikler
Kuralı daha yararlı hale getirmek için
attr
modülünü inceleyip kural tanımını güncelleyin.
username
adlı bir dize özelliği ekleyin:
foo_binary = rule(
implementation = _foo_binary_impl,
attrs = {
"username": attr.string(),
},
)
Daha sonra, BUILD
dosyasında ayarlayın:
foo_binary(
name = "bin",
username = "Alice",
)
Geri çağırma işlevindeki değere erişmek için ctx.attr.username
işlevini kullanın. Örneğin:
def _foo_binary_impl(ctx):
out = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(
output = out,
content = "Hello {}!\n".format(ctx.attr.username),
)
return [DefaultInfo(files = depset([out]))]
Özelliği zorunlu hale getirebileceğinizi veya varsayılan bir değer ayarlayabileceğinizi unutmayın. Dikkat
attr.string
belgelerine bakın.
boole gibi başka özellik türlerini de kullanabilirsiniz
veya tam sayı listesi.
Bağımlılıklar
attr.label
gibi bağımlılık özellikleri
ve attr.label_list
,
özelliğine sahip olan hedeften bir bağımlılığı tanımlamak
etiketi, özelliğin değerinde görünür. Bu tür özellikler, projenin
karar vermektir.
BUILD
dosyasında hedef etiket,
//pkg:name
. Uygulama işlevinde hedef,
Target
nesnesini tanımlayın. Örneğin, döndürülen dosyaları görüntüleyin
Target.files
kullanarak hedefe göre ayarlayın.
Birden fazla dosya
Varsayılan olarak, yalnızca kurallar tarafından oluşturulan hedefler bağımlılık olarak görünebilir (örneğin,
foo_library()
hedef). Özelliğin
depodaki kaynak dosyalar gibi dosya biçimleriyle değil,
allow_files
ve kabul edilen dosya uzantılarının listesini belirtin (veya True
herhangi bir dosya uzantısına izin verin):
"srcs": attr.label_list(allow_files = [".java"]),
Dosya listesine ctx.files.<attribute name>
ile erişilebilir. Örneğin,
örneğin, srcs
özelliğindeki dosya listesine
ctx.files.srcs
Tek dosya
Yalnızca bir dosyaya ihtiyacınız varsa allow_single_file
uzantısını kullanın:
"src": attr.label(allow_single_file = [".java"])
Daha sonra bu dosyaya ctx.file.<attribute name>
altından erişilebilir:
ctx.file.src
Şablon kullanarak dosya oluşturma
Şablona dayalı .cc dosyası oluşturan bir kural oluşturabilirsiniz. Ayrıca,
kuralda oluşturulan bir dizenin çıktısını almak için ctx.actions.write
öğesini kullanabilir
ancak burada iki sorun var. Şablon ilk olarak
bellek daha verimli hale gelirken, verileri ayrı bir dosyaya
yerleştirmek ve dosyaları
büyük dizeler oluşturmayı öğreneceksiniz. İkinci olarak,
dosyası, kullanıcı için daha kullanışlı hale geliyor. Bunun yerine
ctx.actions.expand_template
kullanan bir şablondur.
Şablona bağımlılığı bildirmek için bir template
özelliği oluşturun
dosya:
def _hello_world_impl(ctx):
out = ctx.actions.declare_file(ctx.label.name + ".cc")
ctx.actions.expand_template(
output = out,
template = ctx.file.template,
substitutions = {"{NAME}": ctx.attr.username},
)
return [DefaultInfo(files = depset([out]))]
hello_world = rule(
implementation = _hello_world_impl,
attrs = {
"username": attr.string(default = "unknown person"),
"template": attr.label(
allow_single_file = [".cc.tpl"],
mandatory = True,
),
},
)
Kullanıcılar, kuralı şu şekilde kullanabilir:
hello_world(
name = "hello",
username = "Alice",
template = "file.cc.tpl",
)
cc_binary(
name = "hello_bin",
srcs = [":hello"],
)
Şablonu son kullanıcıya göstermek istemiyorsanız her zaman isterseniz, varsayılan bir değer ayarlayıp özelliği gizli hale getirebilirsiniz:
"_template": attr.label(
allow_single_file = True,
default = "file.cc.tpl",
),
Alt çizgi ile başlayan özellikler gizlidir ve
BUILD
dosyası yükleyin. Şablon artık bir dolaylı bağımlılık oldu: Her hello_world
hedefin bu dosyaya bağımlılığı var. Bu dosyayı görünür hale getirmeyi unutmayın
BUILD
dosyasını güncelleyip
exports_files
:
exports_files(["file.cc.tpl"])
Daha ileri gidiyoruz
- Kurallarla ilgili referans belgelerine göz atın.
- Depsets hakkında bilgi edinin.
- Örnek veri deposuna göz atın. ek kural örnekleri içerir.