Özellikler

Sorun bildirin Kaynağı göster Gece · 7,4 , 7.3 · 7,2 · 7,1 · 7,0 · 6,5

Bu sayfada, Çevik yaklaşımın temellerini göz önünde bulundurur ve hem basit hem de örnekler.

Yönler, derleme bağımlılık graflarını ek bilgiler ve işlemlerle genişletmenize olanak tanır. Özelliklerin yararlı olabileceği bazı tipik senaryolar:

  • Bazel'i entegre eden entegre geliştirme ortamları, Google Haritalar'daki belirler.
  • 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ı protobuf kitaplığı tanımlarının hiyerarşisini belirtebilir ve dile özgü kurallar, belirli bir dil için protobuf destek kodu oluşturan işlemleri eklemek üzere yönleri kullanabilir.

En boy oranları hakkında temel bilgiler

BUILD dosyaları, bir projenin kaynak kodunun açıklamasını sağlar: Projenin parçası olan kaynak dosyalar, bu dosyalardan hangi yapıların (hedefler) oluşturulması gerektiği, bu dosyalar arasındaki bağımlılıklar vb. Bazel, derleme yapmak için bu bilgileri kullanır. Yani yapıları oluşturmak için gereken işlem grubunu (ör. derleyici veya bağlayıcı çalıştırma) belirler ve bu işlemleri yürütür. Bazel bunu, hedefler arasında bir bağlılık grafiği oluşturarak ve bu işlemleri toplamak için bu grafiği ziyaret ederek yapar.

Ş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:

Derleme grafiği

Şekil 1. BUILD dosya bağımlılık 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 güçleri bağımlılık grafiğinin onlar için oluşturulduğu şeydir. Bir görünümün bir uygulaması ve dağıttığı tüm özelliklerin listesi vardır. Projenin gidişatı boyunca "deps" adlı özellikler boyunca yayılır. Bu görünüm, X hedefi için uygulanarak A(X) görünümü uygulama düğümü oluşturulur. 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 yüzden, A niteliğini bir hedef X'e uygularken tek bir işlem bir "gölge grafiği" üretir / aşağıda gösterilen hedeflerin orijinal bağımlılık grafiğidir:

En boy oranıyla grafik oluşturma

Şekil 2. Boyutlarla grafik oluşturma.

Gölgelendirilen yalnızca kenarlar, yayılım seti olduğundan runtime_deps kenarı bu örneğine bakalım. Ardından, gölge grafiğin tüm düğümlerinde bir görünüm uygulama işlevi çağrılır. Bu, orijinal grafiğin düğümlerinde kural uygulamalarının çağrılmasına benzer.

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 sonuçta özellik uygulaması, en boy tanımı ve hususun nasıl çağrılacağı komutunu çalıştırın.

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 örnekte, boy oranıdeps tüm kuralları oluşturur.

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 []

Aspect uygulama işlevleri, kural uygulamasına benzer işlevlerine dahildir. Sağlayıcılar döndürürler, işlem yapın ve iki bağımsız değişken alın:

  • target: Özelliğin uygulandığı hedef.
  • ctx: Özelliklere erişmek, çıkışlar ve işlemler oluşturmak için kullanılabilen ctx 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, yön hiçbir şey sağlamadığından boş bir liste döndürülür.

Komut satırını kullanarak detayı çağırma

Bir özelliği uygulamanın en basit yolu, --aspects bağımsız değişkeninin önüne geçer. 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.

İleri düzey ö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. Bu örnekte, değerleri döndürmek için sağlayıcının nasıl kullanılacağı, bir bağımsız değişkeni bir özellik uygulamasına iletmek için parametrelerin nasıl kullanılacağı ve bir özelliği kuraldan nasıl çağıracağınız gösterilmektedir.

aksine kural tarafından dağıtılan özellikler olarak adlandırılır.

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 yönle ilgili özellik grubunu tanımlar. Herkese açık yön ö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.

Kural yayılımlı özellikler için parametre değerleri, istekte bulunan kuraldan alınır. kuralının aynı ada ve türe sahip özelliğini kullanarak en boy oranını girin. (file_count_rule kelimesinin 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ı.

En boyların label türünde gizli özelliklere de sahip olmasına izin verilir label_list. Özel etiket özellikleri, unsurlarla oluşturulan işlemler için gerekli araçlar veya kitaplıklar bulunur. 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 uygulamasının yaydığı sağlayıcılar öğeler uygulanmadan önce oluşturulur ve dondurulamaz ve emin olun. Bir hedef ve ona uygulanan bir unsur varsa bu bir hatadır aynı türden bir sağlayıcı sağlayabilirsiniz, OutputGroupInfo (birleştirildiği takdirde, kuralı ve en boy oranı farklı çıkış gruplarını belirtir) ve InstrumentedFilesInfo (görüntüyü dikkate alın). Bu, yön uygulamalarının hiçbir zaman DefaultInfo döndürmeyeceği anlamına gelir.

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, ctx.attr.deps üzerinden FileCountInfo'e nasıl erişileceği gösterilmektedir.

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 yönü ç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.

Referanslar