Bu sayfada, Çevik yaklaşımın temellerini göz önünde bulundurur ve hem basit hem de örnekler.
En boy oranları, ek bilgi içeren bağımlılık grafiklerinin artırılmasına olanak tanır ve işlemler. Özelliklerin yararlı olabileceği bazı tipik senaryolar:
- Bazel'i entegre eden IDE'ler, proje hakkında bilgi toplamak için yönleri kullanabilir.
- Kod oluşturma araçları, belli bir ekip üyesine ait girdileri
hedeften bağımsız bir şekilde sınırlayın. Örneğin,
BUILD
dosyaları bir hiyerarşi belirtebilir protobuf kitaplığının tanımlar ve dile özgü kurallar, Çevik ve Scrum’ın belirli bir dil için protobuf destek kodu oluşturan işlemler.
Aspect ile ilgili temel bilgiler
BUILD
dosyaları, bir projenin kaynak koduyla ilgili bir açıklama sağlar: Hangi kaynak?
hangi yapıların (hedefler) oluşturulması gerektiğine,
ve bu dosyalar arasındaki bağımlılıkların neler olduğu gibi konuları ele alacağız. Bazel,
yani bir derleme işlemi için gereken işlemleri
yapıları oluşturmak için gerekli olan (örneğin, derleyici veya bağlayıcı çalıştırma) ve
bu işlemleri yürütür. Bazel bunu başarmak için bir bağımlılık
grafiği ziyaret edin.
Şu BUILD
dosyasını göz önünde bulundurun:
java_library(name = 'W', ...)
java_library(name = 'Y', deps = [':W'], ...)
java_library(name = 'Z', deps = [':W'], ...)
java_library(name = 'Q', ...)
java_library(name = 'T', deps = [':Q'], ...)
java_library(name = 'X', deps = [':Y',':Z'], runtime_deps = [':T'], ...)
Bu BUILD
dosyası, aşağıdaki şekilde gösterilen bir bağımlılık grafiğini tanımlar:
Şekil 1. BUILD
dosya bağımlılığı grafiği.
Bazel, yukarıdaki örnekteki her hedef için ilgili kuralın (bu durumda "java_library") bir uygulama işlevini çağırarak bu bağımlılık grafiğini analiz eder. Kural uygulama işlevleri,
.jar
dosyaları gibi derleme yapıları ve konumlar gibi ilet bilgileri
bağımlılıklarıyla, bu hedeflerin ters bağımlılıklarına
sağlayıcılar.
Yönleri, işlemler oluşturan ve sağlayıcıları döndüren bir uygulama işlevine sahip olmaları açısından kurallara benzer. Ancak bu modellerin gücü, bağımlılıkları için oluşturulan bağımlılıklar grafiğinden gelir. Bir yöne göre uygulama mevcut ve yayıldığı tüm özelliklerin listesini içerir. Projenin gidişatı boyunca "deps" adlı özellikler boyunca yayılır. Bu özellik, bir hedef X oluşturduğundan, A(X) en boy uygulama düğümü elde edilir. Uygulaması sırasında A bileşeni, X'in "dep"lerinde atıfta bulunduğu tüm hedeflere yinelemeli olarak uygulanır. özelliği (A'nın yayılım listesindeki tüm özellikler).
Bu nedenle, A yönü X hedefine tek bir kez uygulandığında, aşağıdaki şekilde gösterilen hedeflerin orijinal bağımlılık grafiğinin "gölge grafiği" elde edilir:
Şekil 2. Yönleri olan bir grafik oluşturun.
Gölgelenen tek kenarlar, dağıtım grubundaki özellikler boyunca uzanan kenarlardır. Bu nedenle, bu örnekte runtime_deps
kenarı gölgelenmez. Ardından, tablodaki tüm düğümlerde bir en boy uygulama işlevi
Düğümlerde kural uygulamalarının çağrılmasına benzer şekilde gölge grafik
farklı olabilir.
Basit örnek
Bu örnekte, bir kuralın ve deps
özelliğine sahip tüm bağımlılarının kaynak dosyalarının nasıl yinelemeli olarak yazdırılacağını gösterilmektedir. Bu örnekte, bir özellik uygulaması, bir özellik tanımı ve Bazel komut satırından özelliğin nasıl çağrılacağı gösterilmektedir.
def _print_aspect_impl(target, ctx):
# Make sure the rule has a srcs attribute.
if hasattr(ctx.rule.attr, 'srcs'):
# Iterate through the files that make up the sources and
# print their paths.
for src in ctx.rule.attr.srcs:
for f in src.files.to_list():
print(f.path)
return []
print_aspect = aspect(
implementation = _print_aspect_impl,
attr_aspects = ['deps'],
)
Örneği parçalarına ayırıp her birini ayrı ayrı inceleyelim.
En boy tanımı
print_aspect = aspect(
implementation = _print_aspect_impl,
attr_aspects = ['deps'],
)
Yönetmelik tanımları, kural tanımlarına benzer ve aspect
işlevi kullanılarak tanımlanır.
Bir kural gibi, bir görünümün de bir uygulama işlevi vardır. Bu durumda bu işlev _print_aspect_impl
'tür.
attr_aspects
, görünümün yayıldığı kural özelliklerinin listesidir.
Bu durumda, görünüm uygulandığı kuralların deps
özelliği boyunca yayılır.
attr_aspects
için kullanılan diğer bir yaygın bağımsız değişken ['*']
'tır. Bu bağımsız değişken, yönü bir kuralın tüm özelliklerine dağıtır.
Aspect uygulaması
def _print_aspect_impl(target, ctx):
# Make sure the rule has a srcs attribute.
if hasattr(ctx.rule.attr, 'srcs'):
# Iterate through the files that make up the sources and
# print their paths.
for src in ctx.rule.attr.srcs:
for f in src.files.to_list():
print(f.path)
return []
Yön özellik uygulama işlevleri, kural uygulama işlevlerine benzer. Sağlayıcılar döndürür, işlemler oluşturabilir ve iki bağımsız değişken alır:
target
: Özelliğin uygulandığı hedef.ctx
: Özelliklere erişmek, çıkışlar ve işlemler oluşturmak için kullanılabilenctx
nesnesi.
Uygulama işlevi, şununla ilgili hedef kuralın özelliklerine erişebilir:
ctx.rule.attr
. Şu anda Google’da çalışan
uygulandığı hedef tarafından sağlanır (target
bağımsız değişkeni aracılığıyla).
Servis sağlayıcıların listesini döndürmek için yönler gereklidir. Bu örnekte, herhangi bir şey sağlamaz, bu nedenle boş bir liste döndürür.
Komut satırını kullanarak detayı çağırma
Bir yönü uygulamanın en kolay yolu, komut satırında --aspects
bağımsız değişkenini kullanmaktır. Yukarıdaki özelliğin print.bzl
adlı bir dosyada tanımlandığı varsayıldığında
bu:
bazel build //MyExample:example --aspects print.bzl%print_aspect
print_aspect
özelliğini, example
hedefine ve deps
özelliği aracılığıyla yinelemeli olarak erişilebilen tüm hedef kurallarına uygular.
--aspects
işareti, <extension file label>%<aspect top-level name>
biçiminde boyutun bir spesifikasyonu olan bir bağımsız değişken alır.
Gelişmiş örnek
Aşağıdaki örnekte, hedef kuraldaki bir özelliğin kullanımı gösterilmektedir , hedeflerdeki dosyaları sayan, potansiyel olarak uzantıları uzantıya göre filtreleyen bir programdır. Değer döndürmek için bir sağlayıcının nasıl kullanılacağını, bir bağımsız değişkeni özellik uygulamasına ve bir kuraldan bir özelliğin nasıl çağrılacağını öğreneceksiniz.
file_count.bzl
dosyası:
FileCountInfo = provider(
fields = {
'count' : 'number of files'
}
)
def _file_count_aspect_impl(target, ctx):
count = 0
# Make sure the rule has a srcs attribute.
if hasattr(ctx.rule.attr, 'srcs'):
# Iterate through the sources counting files
for src in ctx.rule.attr.srcs:
for f in src.files.to_list():
if ctx.attr.extension == '*' or ctx.attr.extension == f.extension:
count = count + 1
# Get the counts from our dependencies.
for dep in ctx.rule.attr.deps:
count = count + dep[FileCountInfo].count
return [FileCountInfo(count = count)]
file_count_aspect = aspect(
implementation = _file_count_aspect_impl,
attr_aspects = ['deps'],
attrs = {
'extension' : attr.string(values = ['*', 'h', 'cc']),
}
)
def _file_count_rule_impl(ctx):
for dep in ctx.attr.deps:
print(dep[FileCountInfo].count)
file_count_rule = rule(
implementation = _file_count_rule_impl,
attrs = {
'deps' : attr.label_list(aspects = [file_count_aspect]),
'extension' : attr.string(default = '*'),
},
)
BUILD.bazel
dosyası:
load('//:file_count.bzl', 'file_count_rule')
cc_library(
name = 'lib',
srcs = [
'lib.h',
'lib.cc',
],
)
cc_binary(
name = 'app',
srcs = [
'app.h',
'app.cc',
'main.cc',
],
deps = ['lib'],
)
file_count_rule(
name = 'file_count',
deps = ['app'],
extension = 'h',
)
Aspect tanımı
file_count_aspect = aspect(
implementation = _file_count_aspect_impl,
attr_aspects = ['deps'],
attrs = {
'extension' : attr.string(values = ['*', 'h', 'cc']),
}
)
Bu örnekte, görünümün deps
özelliği aracılığıyla nasıl dağıtıldığı gösterilmektedir.
attrs
, bir özellik için bir özellik grubu tanımlar. Herkese açık özellik özellikleri
parametreleri tanımlar ve yalnızca bool
, int
veya string
türünde olabilir.
Kural tarafından dağıtılan özellikler için int
ve string
parametrelerinde values
belirtilmelidir. Bu örnekte, değeri "*
", "h
" veya "cc
" olan extension
adlı bir parametre vardır.
Kuralla dağıtılan görünümler için parametre değerleri, görünümü isteyen kuraldan alınır. Bu işlemde, kuralın aynı ada ve türe sahip özelliği kullanılır.
(file_count_rule
tanımına bakın).
Komut satırı özellikleri için parametre değerleri, --aspects_parameters
işareti kullanılarak iletilebilir. int
ve string
parametreleri için values
kısıtlaması şu olabilir:
atlandı.
Ayrıca, label
veya label_list
türünde özel özelliklere sahip olmalarına da izin verilir. Özel etiket özellikleri, yönler tarafından oluşturulan işlemler için gereken araçlara veya kitaplıklara olan bağımlılıkları belirtmek için kullanılabilir. Bu örnekte özel bir özellik tanımlanmamıştır ancak aşağıdaki kod snippet'inde bir aracı bir görünüme nasıl iletebileceğiniz gösterilmektedir:
...
attrs = {
'_protoc' : attr.label(
default = Label('//tools:protoc'),
executable = True,
cfg = "exec"
)
}
...
Aspect uygulaması
FileCountInfo = provider(
fields = {
'count' : 'number of files'
}
)
def _file_count_aspect_impl(target, ctx):
count = 0
# Make sure the rule has a srcs attribute.
if hasattr(ctx.rule.attr, 'srcs'):
# Iterate through the sources counting files
for src in ctx.rule.attr.srcs:
for f in src.files.to_list():
if ctx.attr.extension == '*' or ctx.attr.extension == f.extension:
count = count + 1
# Get the counts from our dependencies.
for dep in ctx.rule.attr.deps:
count = count + dep[FileCountInfo].count
return [FileCountInfo(count = count)]
Tıpkı kural uygulama işlevi gibi, bir görünüm uygulama işlevi de bağımlılıkları tarafından erişilebilen bir sağlayıcı yapısını döndürür.
Bu örnekte FileCountInfo
, benzersiz bir hizmet sağlayıcısı olarak tanımlanmış bir sağlayıcı
count
alanı. En iyi uygulama olarak, bir reklamverenin alanlarını açıkça tanımlamak
fields
özelliğini kullanan bir sağlayıcıdır.
A(X) en boy uygulaması için sağlayıcı grubu, sağlayıcıların birleşimidir
hedefi X için bir kuralın uygulanmasından ve
uygulanır. Bir kural uygulamanın dağıttığı sağlayıcılar, yönler uygulanmadan önce oluşturulur ve dondurulur ve bir yönden değiştirilemez. Bir hedef ve ona uygulanan bir özellik, OutputGroupInfo
(kural ve özellik farklı çıkış grupları belirttiği sürece birleştirilir) ve InstrumentedFilesInfo
(özellikten alınır) hariç olmak üzere her biri aynı türde bir sağlayıcı sağlıyorsa bu bir hatadır. Bu, özellik uygulamalarının
hiçbir zaman DefaultInfo
değerini döndürmez.
Parametreler ve gizli özellikler, ctx
öğesinin özelliklerinde iletilir. Bu örnekte extension
parametresine referans verilerek hangi dosyaların sayılacağına karar verilir.
Geri dönen sağlayıcılar için,
en boy oranı (attr_aspects
listesinden) şununla değiştirilir:
uygulamanın sonuçlarını tanımlamasına yardımcı olur. Örneğin,
X'in noktalarında Y ve Z değerleri vardır. A(X) için ctx.rule.attr.deps
değeri [A(Y), A(Z)] olur.
Bu örnekte ctx.rule.attr.deps
, en iyi performans gösteren ve
“dep”lere uygulamanın sonuçları orijinal hedefin
en boy oranı uygulandı.
Bu örnekte, özellik, FileCountInfo
sağlayıcısına şuradan erişiyor:
toplam geçişli dosya sayısını toplamak için bağımlılıklarını
Bir kuraldan özellik çağrılıyor
def _file_count_rule_impl(ctx):
for dep in ctx.attr.deps:
print(dep[FileCountInfo].count)
file_count_rule = rule(
implementation = _file_count_rule_impl,
attrs = {
'deps' : attr.label_list(aspects = [file_count_aspect]),
'extension' : attr.string(default = '*'),
},
)
Kural uygulamasında, FileCountInfo
hedefine nasıl erişileceği gösterilmektedir
ctx.attr.deps
üzerinden.
Kural tanımı, bir parametrenin (extension
) nasıl tanımlanacağını gösterir.
ve varsayılan bir değer (*
) belirleyin. Projenin gidişatı boyunca
'cc
', 'h
' veya '*
' değerlerinden biri değildi
en boy tanımındaki parametreye uygulanan kısıtlamalar.
Hedef kuralı aracılığıyla bir özelliği çağırma
load('//:file_count.bzl', 'file_count_rule')
cc_binary(
name = 'app',
...
)
file_count_rule(
name = 'file_count',
deps = ['app'],
extension = 'h',
)
Bu görselde, extension
parametresinin özellik parametresine nasıl iletileceği gösterilmektedir
aracılığıyla iletişim kurabilirsiniz. extension
parametresi kural uygulamasında varsayılan bir değere sahip olduğundan extension
isteğe bağlı bir parametre olarak kabul edilir.
file_count
hedefi oluşturulduğunda, özelliğimiz şu yönde değerlendirilir:
kendisi ve deps
üzerinden yinelemeli olarak erişilebilen tüm hedefler.