Kural, Bazel'in gerçekleştirdiği bir dizi işlemi tanımlar Bir dizi çıkış üretmek için kullanılan girişler, Kuralın tarafından döndürülen sağlayıcılar uygulama işlevi hakkında daha fazla bilgi edinin. Örneğin, bir C++ ikili kuralı şunları yapabilir:
.cpp
kaynak dosyası (giriş) alın.- Kaynak dosyalarda
g++
komutunu çalıştırın (işlem). - Yürütülebilir çıktıyı ve diğer dosyaları içeren
DefaultInfo
sağlayıcısını iade edin kullanılabilir hale getirmektir. CcInfo
sağlayıcısını, ve bağımlılıklarını konuşacağız.
Bazel açısından bakıldığında g++
ve standart C++ kitaplıkları da
ekleyin. Kural yazarı olarak, yalnızca kullanıcı tarafından sağlanan
aynı zamanda yürütülmesi için gereken tüm araçlar ve kitaplıkların
işlemlerdir.
Herhangi bir kural oluşturmadan veya değiştirmeden önce Bazel'in geliştirme aşamalarına göz atın. Üç noktayı anlamanız önemlidir, aşamalarından (yükleme, analiz ve yürütme) oluşur. Proje zaman çizelgesini kurallar ve makrolar arasındaki farkı anlamak için makrolar hakkında bilgi edinin makrolarında da yer alır. Başlamak için önce Kurallar Eğitimi'ni inceleyin. Ardından, bu sayfayı referans olarak kullanın.
Bazel'in kendisinde birkaç kural oluşturulmuştur. Bu yerel kurallar, örneğin
cc_library
ve java_binary
, belirli diller için temel destek sağlar.
Kendi kurallarınızı tanımlayarak dil ve araçlar için de benzer destek özellikleri ekleyebilirsiniz.
temel olarak desteklemediğini unutmayın.
Bazel,
Starlark'ın dili. Bu kurallar .bzl
dosyalarına yazılır. Bu dosyalar
BUILD
dosyadan doğrudan yüklenebilir.
Kendi kuralınızı tanımlarken kuralınızın hangi özellikleri desteklediğine ve ve çıktılarını nasıl ürettiğini konuştuk.
Kuralın implementation
işlevi,
analiz aşamasından erişilebilir. Bu işlev,
harici komutlar verebilirsiniz. Bunun yerine, bu araçtan yararlanmak için işlemleri
sonraki aşamalarda devreye girerek kuralın çıktılarını
gerekir.
Kural oluşturma
Bir .bzl
dosyasında yeni bir kural tanımlamak için rule işlevini kullanın
kuralına ekleyin ve sonucu genel bir değişkende depolayın. rule
çağrısı,
özellikler ve
uygulama işlevi:
example_library = rule(
implementation = _example_library_impl,
attrs = {
"deps": attr.label_list(),
...
},
)
Bu, example_library
adlı bir kural türünü tanımlar.
rule
çağrısı, kuralın
yürütülebilir çıkış (executable=True
ile) veya özel olarak
yürütülebilir bir test (test=True
ile). İkincisi ise kural bir test kuralı ise
ve kuralın adı _test
ile bitmelidir.
Hedef örneklendirme
Kurallar yüklenebilir ve BUILD
dosyalarında çağrılabilir:
load('//some/pkg:rules.bzl', 'example_library')
example_library(
name = "example_target",
deps = [":another_target"],
...
)
Bir derleme kuralına yapılan her çağrı, hiçbir değer döndürmez ancak belirir. Buna, kuralın tetiklenmesi denir. Bu, Hedefin özellikleri için yeni hedef ve değerler girin.
Kurallar, Starlark işlevlerinden de çağrılabilir ve .bzl
dosyalarına yüklenebilir.
Kuralları çağıran Starlark işlevleri Starlark makroları olarak adlandırılır.
Starlark makroları sonuçta BUILD
dosyalarından çağrılmalıdır ve yalnızca
BUILD
olduğunda yükleme aşamasında çağrılır
dosyaları, hedefleri örneklendirmek için değerlendirilir.
Özellikler
Özellik, bir kural bağımsız değişkenidir. Özellikler, bir uygulamasına yönlendirmediği takdirde bağımlılıklarını gösteren bir grafik oluşturuyorsunuz.
srcs
veya deps
gibi kurala özgü özellikler, haritadan geçilerek tanımlanır
özellik adlarından şemalara (attr
modülü) rule
öğesinin attrs
parametresine ekleyin.
Şunlar gibi ortak özellikler
name
ve visibility
, tüm kurallara dolaylı olarak eklenir. Ek bilgiler
özelliklerinin dolaylı olarak
yürütülebilir ve test kurallarını uygulayın. Şu özellikte olan özellikler:
bir kurala dolaylı olarak eklendiğinde,
attrs
Bağımlılık özellikleri
Kaynak kodunu işleyen kurallar, genellikle işlenecek aşağıdaki özellikleri tanımlar bağımlılık türlerini görebilirsiniz:
srcs
, hedefin işlemleri tarafından işlenen kaynak dosyaları belirtir. Çoğu zaman özellik şeması, sıralama için hangi dosya uzantılarının beklendiğini belirtir kuralının işlediği kaynak dosyayı oluşturur. Başlık dosyaları olan dil kuralları tarafından işlenen başlıklar için genellikle ayrı birhdrs
özelliği belirtir. ve tüketicilerini hedefler.deps
, bir hedef için kod bağımlılıklarını belirtir. Özellik şeması Bu bağımlıların hangi sağlayıcıları sağlaması gerektiğini belirtin. ( Örneğin,cc_library
,CcInfo
sağlar.)data
, çalışma zamanında yürütülebilir herhangi bir dosya için kullanıma sunulacak dosyaları belirtir Bu da hedefe bağlıdır. Bu, rastgele dosyaların belirtiliyor.
example_library = rule(
implementation = _example_library_impl,
attrs = {
"srcs": attr.label_list(allow_files = [".example"]),
"hdrs": attr.label_list(allow_files = [".header"]),
"deps": attr.label_list(providers = [ExampleInfo]),
"data": attr.label_list(allow_files = True),
...
},
)
Bunlar, bağımlılık özelliklerine örnektir. Belirttiği herhangi bir özellik:
giriş etiketi (
attr.label_list
attr.label
veya
attr.label_keyed_string_dict
)
belirli bir türdeki bağımlılıkları belirtir
arasında bir hedef ile etiketleri (veya ilgili
Label
nesne) söz konusu özellikte listelenir.
tanımlanmıştır. Bu etiketlerin depo ve muhtemelen yolu çözümlendi
ve tanımlanan hedefe göre belirlenir.
example_library(
name = "my_target",
deps = [":other_target"],
)
example_library(
name = "other_target",
...
)
Bu örnekte other_target
, my_target
bağımlılığıdır ve dolayısıyla
Önce other_target
analiz edilir. Zaman çizelgesinde döngü varsa
bağımlılık grafiğini görebilirsiniz.
Özel özellikler ve örtülü bağımlılıklar
Varsayılan değere sahip bir bağımlılık özelliği dolaylı bağımlılık oluşturur. Google
dolaylı bir hedeftir çünkü kullanıcının aramadığı hedef grafiğin bir parçası olduğu için,
BUILD
dosyasında belirtin. Örtülü bağımlılıklar, bir projeniz için
bir kural ile araç arasındaki ilişki (ör.
(derleyici) içerir. Kullanıcılar çoğu zaman
aracını kullanın. Kuralın uygulama işlevinde bu
aynı olduğunu göreceksiniz.
Kullanıcının çalıştırmasına izin vermeden bir örtülü bağımlılık sağlamak
bu değeri geçersiz kılarsanız, özelliğe bir ad vererek özelliği gizli hale getirebilirsiniz
bir alt çizgi (_
) ile başlayan reklamlar gösterilir. Özel özelliklerin varsayılan değeri olmalıdır
değerler. Gizli özellikleri kullanmak genellikle
ve bildirmeyi konuştuk.
example_library = rule(
implementation = _example_library_impl,
attrs = {
...
"_compiler": attr.label(
default = Label("//tools:example_compiler"),
allow_single_file = True,
executable = True,
cfg = "exec",
),
},
)
Bu örnekte, example_library
türündeki her hedefin
şu derleyicide bağımlılık: //tools:example_compiler
. Bu da
example_library
öğesinin uygulama işlevini kullanarak
kullanıcı etiketini giriş olarak aktarmamış olsa bile derleyici tarafından görüntülenebilir. Başlangıç
_compiler
gizli bir özellik olduğu için ctx.attr._compiler
bu kuralın tüm hedeflerinde her zaman //tools:example_compiler
değerini gösterir
türü. Alternatif olarak, compiler
özelliğini
alt çizgi çizin ve varsayılan değeri koruyun. Bu, kullanıcıların farklı bir yerine
farklı bir derleyici kullanabilir, ancak derleyicinin kodu ile ilgili bilgi sahibi değildir
etiket.
Dolaylı bağımlılıklar genellikle aynı modelde bulunan araçlar için depoyu etkinleştirmelisiniz. Araç yürütme platformuna veya farklı bir depoya kuralının söz konusu aracı bir araç zincirinden edinmesi gerekir.
Çıkış özellikleri
Çıkış özellikleri, örneğin attr.output
ve
attr.output_list
ise bir çıkış dosyası bildirin.
anlamına gelir. Bunlar bağımlılık özelliklerinden iki şekilde ayrılır:
- Tanımlanan hedeflere başvurmak yerine çıkış dosyası hedeflerini tanımlarlar olduğunu anlayabilir.
- Çıkış dosyası hedefleri, şunun yerine örneklenen kural hedefine dayanır: tam tersi de geçerlidir.
Genellikle çıkış özellikleri yalnızca bir kuralın çıkış oluşturması gerektiğinde kullanılır
hedef ada dayalı olamayan kullanıcı tanımlı adlara sahip olmalıdır. Bir kural
bir çıktı özelliği olduğundan bu genellikle out
veya outs
olarak adlandırılır.
Önceden beyan edilmiş çıkışları oluşturmanın tercih edilen yöntemi çıkış özellikleridir. projenin başarısına komut satırında istendiğinde.
Uygulama işlevi
Her kural için bir implementation
işlevi gerekir. Bu işlevler
yalnızca analiz aşamasında olması ve
yükleme aşamasında oluşturulan hedeflerin grafik
eylemlerin belirlenmesine yardımcı olur. Dolayısıyla,
uygulama işlevleri dosya okuyamaz veya yazamaz.
Kural uygulama işlevleri genellikle gizlidir (baştaki
alt çizgi) ekleyin. Geleneksel olarak, kurallarıyla aynı şekilde adlandırılırlar ancak
_impl
ile birlikte.
Uygulama işlevleri tam olarak bir parametre alır:
kural bağlamı, geleneksel olarak ctx
olarak adlandırılır. Bunlar,
providers için de geçerli olacaktır.
Hedefler
Bağımlılıklar analiz zamanında Target
olarak gösterilir
nesneler'i tıklayın. Bu nesneler,
hedefin uygulama işlevi yürütüldü.
ctx.attr
her bir kullanıcının adına karşılık gelen alanlar içeriyor
Her bir doğrudan temsil eden Target
nesneyi içeren bağımlılık özelliği
bu özellik üzerinden gelen
bağımlılığı ifade eder. label_list
özellikleri için bu liste
Targets
. label
özellikleri için bu, tek bir Target
veya None
değeridir.
Bir hedefin uygulama işlevi, sağlayıcı nesnelerinin bir listesini döndürür:
return [ExampleInfo(headers = depset(...))]
Bunlara dizin gösterimi ([]
) kullanılarak erişilebilir. Sağlayıcı türü şu şekildedir:
kullanabilirsiniz. Bunlar özel sağlayıcılar Starlark veya
Starlark olarak kullanılabilen yerel kural sağlayıcıları
kullanabilirsiniz.
Örneğin bir kural, başlık dosyalarını hdrs
özelliği aracılığıyla alıyor ve
derleme işlemleri ile bağlantılı olarak, hedefin ve tüketicilerinin
toplayabilirsiniz:
def _example_library_impl(ctx):
...
transitive_headers = [hdr[ExampleInfo].headers for hdr in ctx.attr.hdrs]
Bir struct
öğesinin
hedefin uygulama işlevini çağırın:
return struct(example_info = struct(headers = depset(...)))
Sağlayıcılar, Target
nesnesinin ilgili alanından alınabilir:
transitive_headers = [hdr.example_info.headers for hdr in ctx.attr.hdrs]
Bu stil kesinlikle önerilmez ve kurallar taşınması gerekir.
Dosyalar
Dosyalar File
nesneleriyle temsil edilir. Bazel
sırasında dosya G/Ç işlemleri gerçekleştirdiğinde, bu nesneler
doğrudan okuma veya yazma imkanı sunar. Bunun yerine, geri bildirim veren
(bkz. ctx.actions
) işlevlerini kullanarak
ve Eylem grafiği.
File
, bir kaynak dosya veya oluşturulmuş bir dosya olabilir. Oluşturulan her dosya
tam olarak bir işlemin sonucu olmalıdır. Kaynak dosyalar şunun çıktısı olamaz:
herhangi bir işlem.
Her bir bağımlılık özelliği için, karşılık gelen
ctx.files
, tüm varsayılan çıkışların listesini içerir
bağımlılıklarını görebilirsiniz:
def _example_library_impl(ctx):
...
headers = depset(ctx.files.hdrs, transitive=transitive_headers)
srcs = ctx.files.srcs
...
ctx.file
, şunlar için tek bir File
veya None
içerir:
özellikleri allow_single_file=True
olarak ayarlanmış bağımlılık özellikleri.
ctx.executable
, ctx.file
ile aynı şekilde davranır ancak yalnızca
özellikleri executable=True
olarak ayarlanmış bağımlılık özelliklerine ilişkin alanları içerir.
Çıkışları bildirme
Analiz aşamasında, bir kuralın uygulama işlevi çıktılar oluşturabilir.
Yükleme aşamasında tüm etiketlerin bilinmesi gerektiğinden, bu ek etiketler
çıkışların etiketi yok. Çıkışlar için File
nesne aşağıdakileri kullanarak oluşturulabilir:
ctx.actions.declare_file
ve
ctx.actions.declare_directory
. Çoğu zaman
Çıkışların adları hedefin adına göre belirlenir.
ctx.label.name
:
def _example_library_impl(ctx):
...
output_file = ctx.actions.declare_file(ctx.label.name + ".output")
...
Önceden beyan edilmiş çıkışlar için (ör. şunun için oluşturulanlar)
çıkış özellikleri, bunun yerine File
nesneleri alınabilir
ctx.outputs
öğesinin ilgili alanlarından kaldırın.
İşlemler
Eylemde, kontrol grubu için bir dizi girdiden bir dizi çıkışın nasıl oluşturulacağını örnek: "hello.c'de gcc'yi çalıştır ve hello.o'yu al". Bir eylem oluşturulduğunda Bazel komutu hemen çalıştırmaz. Projeyi bir bağımlılık grafiğine kaydeder, Çünkü bir eylem, bir başka işlemin sonucuna bağlı olabilir. Örneğin, C'de, bağlayıcı, derleyiciden sonra çağrılmalıdır.
Eylem oluşturan genel amaçlı işlevler şurada tanımlanmıştır:
ctx.actions
:
- Yürütülebilir bir dosyayı çalıştırmak için
ctx.actions.run
. ctx.actions.run_shell
, kabuk çalıştırmak için komutuna ekleyin.ctx.actions.write
: Dosyaya dize yazmak için.ctx.actions.expand_template
, - şablondan dosya oluşturabilirsiniz.
ctx.actions.args
, verimli bir şekilde kullanılabilir.
işlemler için bağımsız değişkenleri biriktirme. Yok sayılana kadar
yürütme süresi:
def _example_library_impl(ctx):
...
transitive_headers = [dep[ExampleInfo].headers for dep in ctx.attr.deps]
headers = depset(ctx.files.hdrs, transitive=transitive_headers)
srcs = ctx.files.srcs
inputs = depset(srcs, transitive=[headers])
output_file = ctx.actions.declare_file(ctx.label.name + ".output")
args = ctx.actions.args()
args.add_joined("-h", headers, join_with=",")
args.add_joined("-s", srcs, join_with=",")
args.add("-o", output_file)
ctx.actions.run(
mnemonic = "ExampleCompile",
executable = ctx.executable._compiler,
arguments = [args],
inputs = inputs,
outputs = [output_file],
)
...
İşlemler, giriş dosyalarının bir listesini veya alt kümesini alır ve şunları içeren (boş olmayan) bir liste oluşturur: çıkış dosyası olarak da kullanabilirsiniz. Giriş ve çıkış dosyaları grubu, analiz aşamasından geçti. Projenin değerine göre bağımlılıklarından gelen sağlayıcılar dahil olmak üzere bir sonucudur. Örneğin, işleminiz sıkıştırılmış dosya açma komutunu çalıştırıyorsa hangi dosyaların şişirilmesini beklediğinizi belirtmelidir (sıkıştırmayı açmadan önce). Dahili olarak değişken sayıda dosya oluşturan işlemler, bunları bir tek dosya (zip, tar veya başka bir arşiv biçimi gibi) desteklemez.
İşlemlerde tüm girişler listelenmelidir. Kullanılmayan girişlerin girilmesi ancak verimsizdir.
İşlemler tüm çıkışlarını oluşturmalıdır. Başka dosyalar yazabilirler ama Çıktılarda olmayan hiçbir şey tüketicilere sunulmayacak. Beyan edilen tüm çıkışlar bir işlem yapılarak yazılmalıdır.
Eylemler yalın işlevlerle karşılaştırılabilir: Yalnızca giriş yapmalı ve bilgisayar bilgilerine, kullanıcı adı, saat ve ağ veya G/Ç cihazları (okuma girişleri ve yazma çıkışları hariç) Bu önemlidir. Çünkü çıktı, önbelleğe alınıp yeniden kullanılır.
Bağımlılıklar Bazel tarafından çözülür ve hangi işlemlerin yürütüldü. Bağımlılık grafiğinde bir döngü varsa bu bir hatadır. Oluşturuluyor bir eylem, yürütüleceğini garanti etmez. Bu, ilgili kararın proje için gereken unsurlardır.
Sağlayıcılar
Sağlayıcılar, bir kuralın diğer kurallara açıkladığı ona güvenmeniz gerekir. Bu veriler; çıkış dosyaları, kitaplıklar, aktarılacak parametreler içerebilir bir aracın komut satırında veya hedef tüketicilerinin bilmesi gereken herhangi bir şey konu.
Bir kuralın uygulama işlevi yalnızca
örneklenmiş hedefin acil bağımlılıklarını
tarafından bilinmesi gereken, hedefin bağımlılıklarından elde edilen
bir depset
şeklinde biriktirme yoluyla elde edilir.
Bir hedefin sağlayıcıları, tarafından döndürülen Provider
nesnelerin listesi ile belirtilir
işlevi görür.
Eski uygulama işlevleri,
uygulama işlevi struct
sağlayıcı nesneleridir. Bu stil kesinlikle önerilmez ve kurallar
taşınması gerekir.
Varsayılan çıkışlar
Bir hedefin varsayılan çıkışları, aşağıdaki durumlarda varsayılan olarak istenen çıkışlardır:
komut satırında derleme için hedef istenir. Örneğin,
java_library
hedefi //pkg:foo
için varsayılan çıkış olarak foo.jar
kullanılıyor.
bazel build //pkg:foo
komutu tarafından oluşturulur.
Varsayılan çıkışlar, şu öğenin files
parametresiyle belirtilir:
DefaultInfo
:
def _example_library_impl(ctx):
...
return [
DefaultInfo(files = depset([output_file]), ...),
...
]
DefaultInfo
, bir kural uygulaması veya files
tarafından döndürülmezse
parametresi belirtilmemiş, DefaultInfo.files
varsayılan olarak tümü
önceden bildirilmiş çıkışlar (genellikle çıkış
özellikleri).
İşlem gerçekleştiren kurallar, bu çıkışlar olsa bile varsayılan çıkışlar sağlamalıdır doğrudan kullanılmaları beklenmez. Grafikte bulunmayan işlemler istenen çıkışlar kısaltılır. Bir çıktı yalnızca hedefin tüketicileri tarafından kullanılıyorsa hedef bağımsız olarak oluşturulduğunda bu işlemler gerçekleştirilmez. Bu yalnızca başarısız olan hedefi yeniden oluşturmak, hata ayıklamayı zorlaştıracağından, yeniden üretmemelidir.
Çalıştırma dosyaları
Çalıştırma dosyaları, bir hedef tarafından çalışma zamanında kullanılan bir dosya kümesidir. süre) ekleyebilirsiniz. Yürütme aşamasında Bazel, çalıştırma dosyalarını işaret eden sembolik bağlantılar içeren bir dizin ağacı. Bu aşama ortamına ekleyebilirsiniz.
Çalıştırma dosyaları, kural oluşturulurken manuel olarak eklenebilir.
runfiles
yöntemi ile runfiles
nesne oluşturulabilir
ctx.runfiles
olarak ayarlanmış ve
DefaultInfo
için runfiles
parametresi. Yürütülebilir çıktısı:
executable rules (yürütülebilir kurallar), çalıştırma dosyalarına dolaylı olarak eklenir.
Bazı kurallar, genellikle
data
; çıkışları
bir hedef çalıştırmanız gerekir. Ayrıca, çalıştırma dosyaları data
ve
genellikle nihai yürütme işlemine kod sağlayabilecek özelliklerden
srcs
(ilişkilendirilmiş data
ile filegroup
hedef içerebilir) ve
deps
.
def _example_library_impl(ctx):
...
runfiles = ctx.runfiles(files = ctx.files.data)
transitive_runfiles = []
for runfiles_attr in (
ctx.attr.srcs,
ctx.attr.hdrs,
ctx.attr.deps,
ctx.attr.data,
):
for target in runfiles_attr:
transitive_runfiles.append(target[DefaultInfo].default_runfiles)
runfiles = runfiles.merge_all(transitive_runfiles)
return [
DefaultInfo(..., runfiles = runfiles),
...
]
Özel sağlayıcılar
Sağlayıcılar, provider
kullanılarak tanımlanabilir.
işlevini kullanın:
ExampleInfo = provider(
"Info needed to compile/link Example code.",
fields={
"headers": "depset of header Files from transitive dependencies.",
"files_to_link": "depset of Files from compilation.",
})
Daha sonra kural uygulama işlevleri, sağlayıcı örneklerini oluşturup döndürebilir:
def _example_library_impl(ctx):
...
return [
...
ExampleInfo(
headers = headers,
files_to_link = depset(
[output_file],
transitive = [
dep[ExampleInfo].files_to_link for dep in ctx.attr.deps
],
),
)
]
Sağlayıcıların özel başlatılması
Bir sağlayıcının örneklendirmesini özel mantığıyla başlayalım. Bu, tüm iletişim türlerinin belirli değişkenliklere uyum sağlar veya kullanıcılara örnek alınıyor.
Bu,init
provider
işlevini kullanın. Bu geri çağırma yapılırsa
provider()
değişikliklerinin döndürme türü, iki değerin toplamı olacak şekilde değişir: provider
init
kullanılmadığında normal döndürülen değer olan "ham" sembolü
oluşturucu"dur.
Bu durumda, sağlayıcı sembolü çağrıldığında, doğrudan
yeni bir örnek oluşturursa bağımsız değişkenleri init
geri çağırmasına yönlendirir. İlgili içeriği oluşturmak için kullanılan
geri çağırmanın döndürülen değeri, değerler ile alan adları (dizeler) arasında bir dikt eşleme alanı olmalıdır;
bu, yeni örneğin alanlarını başlatmak için kullanılır. Lütfen
geri çağırmanın herhangi bir imzası olabilir ve bağımsız değişkenler imzayla eşleşmiyorsa
doğrudan geri çağırma işlemi çağrılmış gibi bir hata bildirilir.
Buna karşılık, ham oluşturucu init
geri çağırmasını atlar.
Aşağıdaki örnekte, bağımsız değişkenlerini önceden işlemek ve doğrulamak için init
kullanılmaktadır:
# //pkg:exampleinfo.bzl
_core_headers = [...] # private constant representing standard library files
# It's possible to define an init accepting positional arguments, but
# keyword-only arguments are preferred.
def _exampleinfo_init(*, files_to_link, headers = None, allow_empty_files_to_link = False):
if not files_to_link and not allow_empty_files_to_link:
fail("files_to_link may not be empty")
all_headers = depset(_core_headers, transitive = headers)
return {'files_to_link': files_to_link, 'headers': all_headers}
ExampleInfo, _new_exampleinfo = provider(
...
init = _exampleinfo_init)
export ExampleInfo
Daha sonra bir kural uygulaması, sağlayıcıyı şu şekilde örneklendirebilir:
ExampleInfo(
files_to_link=my_files_to_link, # may not be empty
headers = my_headers, # will automatically include the core headers
)
Ham oluşturucu, alternatif kamu fabrikası işlevlerini tanımlamak için kullanılabilir
init
mantığına uygun değildir. Örneğin, exampleinfo.bzl'de
tanımlanabilir:
def make_barebones_exampleinfo(headers):
"""Returns an ExampleInfo with no files_to_link and only the specified headers."""
return _new_exampleinfo(files_to_link = depset(), headers = all_headers)
Genellikle, ham kurucu, adı
alt çizgi (yukarıda _new_exampleinfo
) olduğundan kullanıcı kodu yüklenemez ve
rastgele sağlayıcı örnekleri oluşturabilirsiniz.
init
için başka bir kullanım da kullanıcının sağlayıcıyı aramasını engellemektir.
ve bunun yerine bir fabrika işlevi kullanmaya zorlama:
def _exampleinfo_init_banned(*args, **kwargs):
fail("Do not call ExampleInfo(). Use make_exampleinfo() instead.")
ExampleInfo, _new_exampleinfo = provider(
...
init = _exampleinfo_init_banned)
def make_exampleinfo(...):
...
return _new_exampleinfo(...)
Yürütülebilir kurallar ve test kuralları
Yürütülebilir kurallar, bir bazel run
komutu tarafından çağrılabilecek hedefleri tanımlar.
Test kuralları, yürütülebilir özel bir tür yürütülebilir kuraldır. Yürütülebilir kurallar; hedefler de
bazel test
komutuyla çağrılır. Yürütülebilir ve test kuralları,
ilgili executable
veya
rule
çağrısında True
adlı kullanıcıya yönelik test
bağımsız değişkeni:
example_binary = rule(
implementation = _example_binary_impl,
executable = True,
...
)
example_test = rule(
implementation = _example_binary_impl,
test = True,
...
)
Test kurallarının adları _test
ile biten adlara sahip olmalıdır. (Hedef adlarını da sık sık test edin
kurallara göre _test
ile biter, ancak bu zorunlu değildir.) Test dışı kurallar
kullanabilirsiniz.
Her iki kural türü de yürütülebilir bir çıktı dosyası oluşturmalıdır (bu dosya,
önceden beyan edilmesi gerekir.) run
veya test
komutları tarafından çağrılacaktır. Anlatmak için
Bir kural çıkışlarından hangisinin bu yürütülebilir olarak kullanılacağını Bazel, bunu
Döndürülen DefaultInfo
işlevinin executable
bağımsız değişkeni
sağlar. Bu executable
, kuralın varsayılan çıkışlarına eklenir (böylece
hem executable
hem de files
adlı cihaza iletmesi gerekmez). Aynı zamanda,
runfiles eklenir:
def _example_binary_impl(ctx):
executable = ctx.actions.declare_file(ctx.label.name)
...
return [
DefaultInfo(executable = executable, ...),
...
]
Bu dosyayı oluşturan işlem, dosyadaki yürütülebilir biti ayarlamalıdır. Örneğin,
ctx.actions.run
veya
Bunun yapılması gereken ctx.actions.run_shell
işlemi
işlem tarafından çağrılan temel araç tarafından uygulanır. Örneğin,
ctx.actions.write
işlemi, is_executable=True
geçin.
Eski davranış olarak, yürütülebilir kurallarda
önceden tanımlanmış özel ctx.outputs.executable
çıkışı. Bu dosya,
DefaultInfo
kullanarak bir uygulama belirtmezseniz varsayılan olarak yürütülebilir; olmaması gerekir
geri alınamaz. Bu çıkış mekanizması şunları desteklemediği için kullanımdan kaldırıldı:
yürütülebilir dosyanın adını analiz sırasında özelleştirme.
Örneklere bakın yürütülebilir kural ve test kuralını inceleyin.
Yürütülebilir kurallar ve test kurallarının doğrudan tanımlanmış özellikleri vardır. tüm kurallara uymalıdır. Varsayılan dolaylı yoldan eklenen özellikler değiştirilemez ancak özel bir kuralı Starlark makrosu içine sarmalayarak varsayılan:
def example_test(size="small", **kwargs):
_example_test(size=size, **kwargs)
_example_test = rule(
...
)
Runfiles konumu
Yürütülebilir bir hedef bazel run
(veya test
) ile çalıştırıldığında,
Runfiles dizini yürütülebilir dosyanın bitişiğindedir. Yollar aşağıdaki gibi ilişkilidir:
# Given launcher_path and runfile_file:
runfiles_root = launcher_path.path + ".runfiles"
workspace_name = ctx.workspace_name
runfile_path = runfile_file.short_path
execution_root_relative_path = "%s/%s/%s" % (
runfiles_root, workspace_name, runfile_path)
Runfiles dizininin altındaki File
yolu şuna karşılık gelir:
File.short_path
Doğrudan bazel
tarafından yürütülen ikili program, kök dizesine bitişik
runfiles
dizini. Ancak, çalıştırma dosyalarından from olarak adlandırılan ikili programlar
aynı varsayıma sahiptir. Her ikili, bu sorunun etkilerini azaltmak için
bir ortam veya komut satırı kullanarak runfiles kökünü parametre olarak kabul edin
bağımsız değişken/bayrak. Bu, ikili programların doğru standart çalıştırma dosyası kökünü iletmesine olanak tanır
çağrılmasını sağlar. Bu ayar belirtilmezse ikili program, bunun
çağırın ve bitişikteki runfiles dizinini arayın.
İleri düzey konular
Çıkış dosyalarını isteme
Tek bir hedefin birden fazla çıkış dosyası olabilir. bazel build
komutu
çalıştırıldığında, komuta verilen hedeflerin bazı çıktılarının, makine öğreniminin
istenebilir. Bazel, yalnızca istenen bu dosyaları ve bunların
bağımlılığın doğrudan veya dolaylı olarak değişmesidir. (Eylem grafiği olarak yalnızca Bazel,
öğesinin geçişli bağımlıları olarak erişilebilen işlemleri
istenen dosyalar.)
Varsayılan çıkışlara ek olarak önceden bildirilmiş tüm çıkışlar
komut satırında açıkça istenmesine izin verilmez. Kurallar, önceden tanımlanmış
çıkış özellikleri aracılığıyla çıkışlar sağlar. Böyle bir durumda, kullanıcı
kuralı örneklendirirken çıkışlar için etiketler açık bir şekilde seçer. Elde etmek için
Çıkış özellikleri için File
nesneleri; karşılık gelen
özelliği ctx.outputs
. Kurallar
önceden beyan edilmiş çıkışları dolaylı yoldan tanımlayabilirsiniz.
eklemiştir; ancak bu özellik kullanımdan kaldırılmıştır.
Varsayılan çıkışların yanı sıra koleksiyonlar olan çıkış grupları da vardır.
bir dizi çıkış dosyası ekleyebilirsiniz. Bu istekler
--output_groups
. Örneğin,
Örneğin, //pkg:mytarget
hedefi debug_files
içeren bir kural türündeyse
bu dosyalar bazel build //pkg:mytarget
--output_groups=debug_files
çalıştırılarak oluşturulabilir. Önceden bildirilmemiş çıkışların etiketi olmadığından
yalnızca varsayılan çıkışlarda veya çıkışta görünerek istenebilir.
grubu.
Çıkış grupları
OutputGroupInfo
sağlayıcısı. Çoğu modelin aksine
yerleşik sağlayıcılar, OutputGroupInfo
rastgele adlara sahip parametreler alabilir
şu ada sahip çıkış grupları tanımlamak için kullanılır:
def _example_library_impl(ctx):
...
debug_file = ctx.actions.declare_file(name + ".pdb")
...
return [
DefaultInfo(files = depset([output_file]), ...),
OutputGroupInfo(
debug_files = depset([debug_file]),
all_files = depset([output_file, debug_file]),
),
...
]
Ayrıca çoğu sağlayıcının aksine OutputGroupInfo
, hem
aspect ve bu özelliğin uygulandığı kural hedefi,
ancak aynı çıkış gruplarını tanımlamazlar. Böyle bir durumda,
sağlayıcı birleştirilir.
OutputGroupInfo
işlevinin genellikle belirli sıralamaları aktarmak için kullanılmaması gerektiğini unutmayın.
tüketicilerin eylemlerine kadar çeşitli dosyalar sunar. Tanımla
kurallara özel sağlayıcılar kullanabilirsiniz.
Yapılandırmalar
Farklı bir mimari için C++ ikili programı derlemek istediğinizi düşünün. İlgili içeriği oluşturmak için kullanılan karmaşık bir yapıda olabilir ve birkaç adım içerebilir. Bazı orta düzey derleyici ve kod oluşturucu gibi ikili programların yürütme platformu (barındırıcınız, veya uzaktaki bir yürütücü). Nihai çıkış gibi bazı ikili programlar hedef mimari.
Bu nedenle, Bazel'in "yapılandırmalar" daha fazla bilgi edineceksiniz. İlgili içeriği oluşturmak için kullanılan en üstteki hedefler (komut satırında istenenler) "hedef" yürütme platformunda çalışması gereken araçlar ise "yönlendirerek" yapılandırma. Kurallar, uygulamanıza bağlı olarak (ör. iletilen CPU mimarisini değiştirmek için) ekler. Bazı durumlarda, farklı cihazlar için aynı kitaplık yapılandırmanın üç yolu vardır. Böyle bir durumda analiz edilir ve birden fazla kez.
Varsayılan olarak Bazel, hedefin kendisi, başka bir deyişle geçişler olmadan. Bağımlılık hedefin oluşturulması için gereken özel bir araç varsa, exec yapılandırmasına geçiş olduğunu belirtir. Bu, aracın ve onun tüm özelliklerini bağımlılıkları belirlemenize yardımcı olur.
Her bir bağımlılık özelliğinde, bağımlılıkların olup olmadığına karar vermek için cfg
kullanabilirsiniz.
aynı yapılandırmada derlemesi veya bir yönetici yapılandırmasına geçiş yapması gerekir.
Bir bağımlılık özelliği executable=True
bayrağına sahipse cfg
ayarlanmalıdır
açık bir şekilde belirtmelisiniz. Bu, hatalı kullanım için yanlışlıkla bir araç oluşturulmasını önlemek amacıyla
yapılandırma.
Örneği inceleyin
Genel olarak, aynı yapılandırmayı kullanabilir.
Derlemenin bir parçası olarak yürütülen araçlar (derleyiciler veya kod oluşturucular gibi)
yürütülmelidir. Bu durumda, cfg="exec"
değerini
belirtir.
Aksi takdirde, çalışma zamanında kullanılan yürütülebilir dosyalar (örneğin bir testin parçası olarak)
oluşturulmalıdır. Bu durumda, cfg="target"
değerini
belirtir.
cfg="target"
aslında herhangi bir şey yapmaz. Tam anlamıyla kullanıcıların
kural tasarımcılarının amaçlarını
açıkça belirtmelerine yardımcı olur. executable=False
olduğunda,
Yani cfg
isteğe bağlıdır. Yalnızca okunabilirliğe gerçekten yardımcı olduğu durumlarda bunu ayarlayın.
Ayrıca, şunu kullanmak için cfg=my_transition
kullanabilirsiniz:
geçişlere izin veren kullanıcı tanımlı geçişleri
yapılandırma değiştirme konusunda çok daha fazla esneklikle
dezavantajı
yapı grafiğini daha geniş ve daha az anlaşılır hale getirir.
Not: Geçmişte Bazel'in yürütme platformu kavramı yoktu. Bunun yerine tüm derleme işlemlerinin ana makinede çalıştırıldığı kabul ediliyordu. Bazel 6.0'dan önceki sürümler ayrı bir "ana makine" oluşturuyordu yapılandıracağım. "Ana makine" ifadeleri görüyorsanız ya da eski belgelerden biri, bahsetmek istiyorum. Kavramsal olan bu ekstradan kaçınmak için Bazel 6.0 veya daha yeni bir sürüm kullanmanızı öneririz. yardımcı olabilir.
Yapılandırma parçaları
Kurallar erişebilir
yapılandırma parçalarını
cpp
, java
ve jvm
. Ancak, gerekli tüm parçalar şurada tanımlanmalıdır:
için şu adımları izleyin:
def _impl(ctx):
# Using ctx.fragments.cpp leads to an error since it was not declared.
x = ctx.fragments.java
...
my_rule = rule(
implementation = _impl,
fragments = ["java"], # Required fragments of the target configuration
host_fragments = ["java"], # Required fragments of the host configuration
...
)
Runfiles sembolik bağlantıları
Normalde, çalıştırma dosyaları ağacındaki bir dosyanın göreli yolu
dosyanın göreli yolunu gösterir. Bu
bir nedenden dolayı farklı olması gerekiyorsa, root_symlinks
veya
symlinks
bağımsız değişken. root_symlinks
,
dosyalarını içermelidir. Bu dizindeki yollar, runfiles dizininin köküne göre belirlenir. İlgili içeriği oluşturmak için kullanılan
symlinks
sözlüğü aynı ancak yolların başında dolaylı olarak
depolandığı yerin adını değil, depolandığı yerin adını
hedef) ekleyebilirsiniz.
...
runfiles = ctx.runfiles(
root_symlinks = {"some/path/here.foo": ctx.file.some_data_file2}
symlinks = {"some/path/here.bar": ctx.file.some_data_file3}
)
# Creates something like:
# sometarget.runfiles/
# some/
# path/
# here.foo -> some_data_file2
# <workspace_name>/
# some/
# path/
# here.bar -> some_data_file3
symlinks
veya root_symlinks
kullanılıyorsa iki farklı eşleme yapmamaya dikkat edin
dosyalarını çalıştırma ağacında aynı yola yönlendirir. Bu, derlemenin başarısız olmasına neden olur
bir hata mesajı alır. Bu sorunu düzeltmek için
Çakışmayı kaldırmak için ctx.runfiles
bağımsız değişken. Bu kontrol,
kuralınızı kullanan tüm hedeflerin yanı sıra bu kurallara bağlı olan her türlü hedef
belirler. Bu durum, özellikle aracınızın geçişli olarak kullanılması ihtimali varsa risklidir.
başka bir araçla; sembolik bağlantı adları bir aracın çalışma dosyalarında benzersiz olmalıdır ve
tüm bağımlılıklarını
fark edebilirsiniz.
Kod kapsamı
coverage
komutu çalıştırıldığında,
derlemenin belirli hedefler için kapsam araçları eklemesi gerekebilir. İlgili içeriği oluşturmak için kullanılan
derleme, gerekli araçları içeren kaynak dosyaların listesini de toplar. Alt kümesi
bayrakla kontrol edilen, ancak bayrakla kontrol edilen
--instrumentation_filter
.
Test hedefleri hariç tutulmadığı sürece
--instrument_test_targets
belirtilir.
Bir kural uygulaması, derleme sırasında kapsam araçları eklerse bunu uygulama işlevinde hesaba katmalıdır. ctx.coverage_instrumented, "true" değerini döndürür. kapsam modunu uygular:
# Are this rule's sources instrumented?
if ctx.coverage_instrumented():
# Do something to turn on coverage for this compile action
Kapsam modunda her zaman açık olması gereken mantık (hedefin kaynaklarının gerekli olup olmadığına) bağlı olarak, ctx.configuration.coverage_enabled.
Kural, derlemeden önce bağımlılıklarından gelen kaynakları doğrudan içeriyorsa (başlık dosyaları gibi) kullanıyorsanız, ve bağımlılıkların hangi kaynaklara yer verilmelidir:
# Are this rule's sources or any of the sources for its direct dependencies
# in deps instrumented?
if (ctx.configuration.coverage_enabled and
(ctx.coverage_instrumented() or
any([ctx.coverage_instrumented(dep) for dep in ctx.attr.deps]))):
# Do something to turn on coverage for this compile action
Kurallar, aynı zamanda hangi özelliklerin
InstrumentedFilesInfo
sağlayıcısıyla oluşturulan kapsam,
coverage_common.instrumented_files_info
instrumented_files_info
öğesinin dependency_attributes
parametresi şunları içermelidir:
deps
ve benzeri kod bağımlılıkları dahil tüm çalışma zamanı bağımlılık özellikleri
bağımlılıklarını (ör. data
) sağlar. source_attributes
parametresi,
kuralın kaynak dosya özellikleri:
def _example_library_impl(ctx):
...
return [
...
coverage_common.instrumented_files_info(
ctx,
dependency_attributes = ["deps", "data"],
# Omitted if coverage is not supported for this rule:
source_attributes = ["srcs", "hdrs"],
)
...
]
InstrumentedFilesInfo
döndürülmezse her biri için varsayılan bir tane oluşturulur
araç dışı bağımlılık özelliğinin ayarlanmamış olması
cfg
yerine "host"
veya "exec"
olarak değiştirin)
dependency_attributes
(Bu ideal bir davranış değildir çünkü
Örneğin, source_attributes
yerine dependency_attributes
içinde srcs
, ancak bu
tüm kurallar için açık kapsam yapılandırılması ihtiyacını ortadan kaldırır.
bağımlılık zinciri olabilir.)
Doğrulama İşlemleri
Bazen derleme hakkında bir şeyler doğrulamanız gerekir bu doğrulamayı yapmak için gereken bilgiler yalnızca yapılarda mevcuttur (kaynak dosyalar veya oluşturulan dosyalar). Bu bilgiler yapılarda bulunduğundan kurallar analiz sırasında bu doğrulamayı yapamaz, çünkü kurallar dosyası olarak da kaydedebilir. Bunun yerine, yürütme sırasında bu doğrulamayı yapması gerekir. Zaman işlem başarısız olursa işlem ve dolayısıyla derleme de başarısız olur.
Çalıştırılabilecek doğrulamalara örnek olarak statik analiz, hata analizi, bağımlılık ve tutarlılık kontrolleri ile stil kontrolleri.
Doğrulama işlemleri, parçaları hareket ettirerek derleme performansının iyileştirilmesine de yardımcı olabilir birçok işlem bulunur. Örneğin, derleme ve hata analizi yapan tek bir işlem işlemi, derleme işlemi ve linting işlemi olarak ayrılmış bir listedir. işlemi, doğrulama işlemi olarak ve diğer işlemlerle paralel olarak çalıştırılabilir.
Bu "doğrulama işlemleri" genellikle başka bir yerde kullanılan hiçbir şey üretmez. çünkü yalnızca girdileriyle ilgili birtakım iddialarda bulunmaları gerekiyor. Bu bir soruna işaret eder: Doğrulama işlemi gerçekten bir kural, derlemenin başka bir yerinde kullanılırsa işlemin çalıştırılmasını nasıl sağlar? Önceden yaklaşım, doğrulama işlemi çıktısının boş bir değer ve bu çıktıyı başka önemli bilgilerin girişlerine yapay olarak şu işlemi yapabilirsiniz:
Bu yöntem işe yarar çünkü Bazel, derleme işlemi sırasında her zaman doğrulama işlemini ancak bunun önemli dezavantajları vardır:
Doğrulama işlemi, derlemenin kritik yolundadır. Çünkü Bazel derleme işlemini çalıştırmak için boş çıkış gerektiğini düşünürse önce doğrulama işlemine tabi tutulur. Ancak, derleme işlemi girişi yoksayar. Bu, paralelliği azaltır ve derlemeleri yavaşlatır.
Derlemedeki diğer işlemler derleme işlemini seçerseniz doğrulama işlemlerinin boş çıkışlarının bu işlemleri de yapabilirsiniz (örneğin,
java_library
kaynak jar çıkışı). Bu derleme işlemi yerine çalıştırılabilecek yeni eylemlerin sonradan eklenir ve boş doğrulama çıkışı yanlışlıkla bırakılır.
Bu sorunların çözümü Doğrulamalar Çıktı Grubu'nu kullanmaktır.
Doğrulamalar Çıkış Grubu
Doğrulamalar Çıkış Grubu, diğer doğrulama işlemleri için kullanılmayan çıktıları oluşturur. Böylece bunların yapay olarak girişlerine eklenir.
Bu grup, ne olursa olsun çıkışları her zaman istenmesi açısından
--output_groups
işaretinin değerine ve hedefin nasıl
(örneğin, komut satırında, bağımlılık olarak veya
(hedefin örtülü çıktıları). Normal önbelleğe alma ve artımlılığın
hâlâ geçerlidir: doğrulama işlemine yapılan girişler değişmediyse ve
doğrulama işlemi başarıyla tamamlandıysa doğrulama işlemi
gerekir.
Bu çıkış grubunun kullanılması için doğrulama işlemlerinin bazı dosyalar üretmesi gerekir. boş bir alan olabilir. Bu, normal koşullarda çalışmayan bazı araçların çıkışlar oluşturacaksınız.
Bir hedefin doğrulama işlemleri üç durumda çalıştırılmaz:
- Hedefe bir araç olarak ihtiyaç duyulduğunda
- Hedefe dolaylı bir bağımlılık olarak dayanıldığında (örneğin, "_" ile başlayan özellik)
- Hedef, ana makine veya yönetici yapılandırmasında oluşturulduğunda.
Bu hedeflerin kendine ait olduğu varsayılır. doğrulama hatalarını ortaya çıkaracak ayrı derlemeler ve testler oluşturun.
Doğrulamalar Çıkış Grubunu Kullanma
Doğrulamalar Çıktı Grubu _validation
olarak adlandırılır ve diğer herhangi bir grup gibi kullanılır.
çıkış grubu:
def _rule_with_validation_impl(ctx):
ctx.actions.write(ctx.outputs.main, "main output\n")
ctx.actions.write(ctx.outputs.implicit, "implicit output\n")
validation_output = ctx.actions.declare_file(ctx.attr.name + ".validation")
ctx.actions.run(
outputs = [validation_output],
executable = ctx.executable._validation_tool,
arguments = [validation_output.path])
return [
DefaultInfo(files = depset([ctx.outputs.main])),
OutputGroupInfo(_validation = depset([validation_output])),
]
rule_with_validation = rule(
implementation = _rule_with_validation_impl,
outputs = {
"main": "%{name}.main",
"implicit": "%{name}.implicit",
},
attrs = {
"_validation_tool": attr.label(
default = Label("//validation_actions:validation_tool"),
executable = True,
cfg = "exec"),
}
)
Doğrulama çıkış dosyasının DefaultInfo
veya
girdiler. Bu kural türündeki bir hedef için doğrulama işlemi
çalışmaya devam edecektir. Hedef, etikete veya hedefin
örtülü çıkışlara doğrudan veya dolaylı olarak
bağlıdırlar.
Genellikle doğrulama işlemlerinin sonuçlarının yalnızca emin olun ve diğer işlemlerin girişlerine eklenmez. paralellik kazançlarını ortadan kaldırabilir. Ancak, Bazel'in şu anda bu özelliği uygulanacak özel denetimler vardır. Bu nedenle, doğrulama işlemi çıkışlarının testlerinden yararlanırız. Örneğin:
load("@bazel_skylib//lib:unittest.bzl", "analysistest")
def _validation_outputs_test_impl(ctx):
env = analysistest.begin(ctx)
actions = analysistest.target_actions(env)
target = analysistest.target_under_test(env)
validation_outputs = target.output_groups._validation.to_list()
for action in actions:
for validation_output in validation_outputs:
if validation_output in action.inputs.to_list():
analysistest.fail(env,
"%s is a validation action output, but is an input to action %s" % (
validation_output, action))
return analysistest.end(env)
validation_outputs_test = analysistest.make(_validation_outputs_test_impl)
Doğrulama İşlemleri İşareti
Doğrulama işlemlerinin çalıştırılması --run_validations
komut satırı tarafından kontrol edilir
işaretidir. Bu değer varsayılan olarak "true" (doğru) değerine ayarlanır.
Kullanımdan kaldırılan özellikler
Desteği sonlandırılan önceden beyan edilmiş çıkışlar
Önceden beyan edilmiş çıkışları kullanmanın desteği sonlandırılmış iki yöntemi vardır:
rule
öğesininoutputs
parametresi, Veri oluşturmak için çıkış özelliği adları ile dize şablonları arasında önceden beyan edilmiş çıkış etiketlerinden oluşur. Önceden bildirilmemiş çıkışları ve çıkışları açıkçaDefaultInfo.files
projesine ekliyor. Kural hedefinin önceden beyan edilmiş yerine çıkışı tüketen kurallar için giriş olarak etiketle çıkışının etiketine daha yakın olabilir.Yürütülebilir kurallar için
ctx.outputs.executable
şunu belirtir: dönüştürülebilir. Sonucu açıkça belirtmeyi tercih edin, örneğinctx.actions.declare_file(ctx.label.name)
ve komutun , yürütülebilir dosyayı yürütülmesine izin verecek şekilde ayarlar. Açıkça yürütülebilir çıktıyıDefaultInfo
executable
parametresine iletin.
Kaçınılması gereken Runfiles özellikleri
ctx.runfiles
ve runfiles
türü, çoğu eski nedenlerle saklanan karmaşık bir özellik grubuna sahiptir.
Aşağıdaki öneriler karmaşıklığı azaltmaya yardımcı olur:
Şu
collect_data
vecollect_default
modlarını kullanmaktan kaçının:ctx.runfiles
. Bu modlar, dosyaları kafa karıştırıcı şekillerde, sabit kodlu belirli bağımlılık kenarlarında çalıştırmasına yardımcı olur. Bunun yerine, dosyayı şu öğeninfiles
veyatransitive_files
parametrelerini kullanarak ekleyin:ctx.runfiles
kullanarak veya bağımlılıklardan gelen çalıştırma dosyalarınırunfiles = runfiles.merge(dep[DefaultInfo].default_runfiles)
.Şunlardan kaçının:
data_runfiles
vedefault_runfiles
DefaultInfo
oluşturucu. Bunun yerineDefaultInfo(runfiles = ...)
değerini belirtin. "Varsayılan" arasındaki fark ve "data" Runfiles'i yalnızca eski nedenler. Örneğin, bazı kurallar varsayılan çıkışlarınıdata_runfiles
, ancakdefault_runfiles
değil. Bunun yerinedata_runfiles
, kurallar her ikisi de varsayılan çıkışları içermeli ve Çalıştırma dosyaları sağlayan özelliklerdendefault_runfiles
(genellikledata
).DefaultInfo
kaynağındanrunfiles
alınırken (genellikle yalnızca birleştirme içindir) çalıştırmanız için kullanılan dosyayı kullanıyorsanız,DefaultInfo.default_runfiles
,DefaultInfo.data_runfiles
değil.
Eski sağlayıcılardan taşıma
Geçmişte Bazel sağlayıcıları Target
nesnesindeki basit alanlardı. Onlar
noktaları, nokta operatörü kullanılarak erişildi ve
işlevi tarafından döndürülen bir struct'a dönüştürülür.
Bu stil kullanımdan kaldırıldı ve yeni kodda kullanılmamalıdır; için aşağıdaki bilgilere bakın bazı ek bilgilere ulaşabilirsiniz. Yeni sağlayıcı mekanizması, addan kaçınıyor oluşturur. Ayrıca, bir sunucuya herhangi bir koda erişilmesini zorunlu kılarak sağlayıcı sembolü kullanarak almak için sağlayıcı örneği kullanabilirsiniz.
Şu an için, eski sağlayıcılar desteklenmektedir. Bir kural, aşağıdaki gibi eski ve modern sağlayıcılar:
def _old_rule_impl(ctx):
...
legacy_data = struct(x="foo", ...)
modern_data = MyInfo(y="bar", ...)
# When any legacy providers are returned, the top-level returned value is a
# struct.
return struct(
# One key = value entry for each legacy provider.
legacy_info = legacy_data,
...
# Additional modern providers:
providers = [modern_data, ...])
dep
, bu kuralın bir örneği için sonuçta elde edilen Target
nesnesiyse
sağlayıcılar ve içerikleri dep.legacy_info.x
ve
dep[MyInfo].y
.
Döndürülen struct, providers
'e ek olarak birkaç tane daha alabilir
alanları veya bu alanlara karşılık gelen bir miras teşkil etmez
sağlayıcı):
files
,runfiles
,data_runfiles
,default_runfiles
veexecutable
, aynı adlandırılmış alanlara karşılık gelirDefaultInfo
. Herhangi birDefaultInfo
sağlayıcısı döndürecek.output_groups
alanı bir struct değeri alır veOutputGroupInfo
provides
kural bildirimlerinde ve
providers
bağımlılık bildirimleri
özellikleri ile birlikte eski sağlayıcılar dize olarak aktarılır ve modern sağlayıcılar
*Info
sembolü ile geçilebilir. Dize yerine semboller kullanmayı unutmayın
göz önünde bulundurun. Güncellemenin zor olduğu karmaşık veya büyük kural kümeleri için
atomik bir yapıya sahip olduğunu fark ederseniz, bu diziyi takip etmeniz durumunda
için şu adımları izleyin:
Eski sağlayıcıyı oluşturan kuralları, hem eski sağlayıcıyı hem de eski sağlayıcıyı oluşturacak şekilde değiştirin ve modern sağlayıcılar için geçerlidir. Bunu belirten kurallar için eski sağlayıcıyı döndürmek için bu beyanı hem hem de eski ve modern sağlayıcılar için geçerli.
Eski sağlayıcıyı kullanan kuralları, bunun yerine modern bir sağlayıcı. Herhangi bir özellik bildirimleri için eski sağlayıcı gerekiyorsa modern sağlayıcıyı gerektirecek şekilde de güncellenecektir. İsteğe bağlı olarak: bu çalışmayı, tüketicilerin aşağıdakilerden birini kabul etmesini/zorunlu kılmasını sağlayarak 1. adıma provider: Alan adını kullanarak eski sağlayıcının varlığını test etme
hasattr(target, 'foo')
veyaFooInfo in target
kullanan yeni sağlayıcıEski sağlayıcıyı tüm kurallardan tamamen kaldırın.