ABI Kararlılığı

Uygulama İkili Arayüzü (ABI) kararlılığı, yalnızca çerçeve güncellemelerinin bir ön koşuludur çünkü satıcı modülleri, sistem bölümünde bulunan Satıcı Yerel Geliştirme Kiti (VNDK) paylaşılan kitaplıklarına bağlı olabilir. Bir Android sürümünde, yeni oluşturulan VNDK paylaşılan kitaplıklarının, daha önce yayımlanan VNDK paylaşılan kitaplıklarıyla ABI uyumlu olması gerekir; böylece satıcı modüller, yeniden derleme olmadan ve çalışma zamanı hataları olmadan bu kitaplıklarla çalışabilir. Android sürümleri arasında VNDK kitaplıkları değiştirilebilir ve ABI garantisi yoktur.

ABI uyumluluğunun sağlanmasına yardımcı olmak için Android 9, aşağıdaki bölümlerde açıklandığı gibi bir başlık ABI denetleyicisi içerir.

VNDK ve ABI uyumluluğu hakkında

VNDK, satıcı modüllerinin bağlanabileceği ve yalnızca çerçeve güncellemelerini etkinleştiren kısıtlayıcı bir kitaplıklar kümesidir. ABI uyumluluğu, paylaşılan bir kitaplığın daha yeni bir sürümünün, kendisine dinamik olarak bağlı bir modülle beklendiği gibi çalışabilme yeteneğini ifade eder (yani, kitaplığın eski bir sürümünün yapacağı gibi çalışır).

Dışa aktarılan semboller hakkında

Dışa aktarılan bir sembol (aynı zamanda global sembol olarak da bilinir), aşağıdakilerin tümünü karşılayan bir sembolü ifade eder:

  • Paylaşılan bir kitaplığın genel başlıkları tarafından dışa aktarılır.
  • Paylaşılan kitaplığa karşılık gelen .so dosyasının .dynsym tablosunda görünür.
  • ZAYIF veya GLOBAL bağlamaya sahiptir.
  • Görünürlük VARSAYILAN veya KORUNMALI'dır.
  • Bölüm dizini UNDEFINED değil.
  • Tür ya FUNC ya da OBJECT'tir.

Paylaşılan bir kitaplığın genel üstbilgileri, paylaşılan kitaplığa karşılık gelen modülün Android.bp tanımlarındaki export_include_dirs , export_header_lib_headers , export_static_lib_headers , export_shared_lib_headers ve export_generated_headers nitelikleri aracılığıyla diğer kitaplıklar/ikili dosyalar için kullanılabilen başlıklar olarak tanımlanır.

Ulaşılabilir türler hakkında

Ulaşılabilir tür, dışa aktarılan bir sembol aracılığıyla doğrudan veya dolaylı olarak erişilebilen VE genel başlıklar aracılığıyla dışa aktarılan herhangi bir C/C++ yerleşik veya kullanıcı tanımlı türdür. Örneğin, libfoo.so , .dynsym tablosunda bulunan, dışa aktarılan bir sembol olan Foo işlevine sahiptir. libfoo.so kütüphanesi aşağıdakileri içerir:

foo_exported.h foo.private.h
typedef struct foo_private foo_private_t;

typedef struct foo {
  int m1;
  int *m2;
  foo_private_t *mPfoo;
} foo_t;

typedef struct bar {
  foo_t mfoo;
} bar_t;

bool Foo(int id, bar_t *bar_ptr);
typedef struct foo_private {
  int m1;
  float mbar;
} foo_private_t;
Android.bp
cc_library {
  name : libfoo,
  vendor_available: true,
  vndk {
    enabled : true,
  }
  srcs : ["src/*.cpp"],
  export_include_dirs : [
    "exported"
  ],
}
.dynsym tablosu
Num Value Size Type Bind Vis Ndx Name
1 0 0 FUNC GLOB DEF UND dlerror@libc
2 1ce0 20 FUNC GLOB DEF 12 Foo

Foo bakıldığında, doğrudan/dolaylı ulaşılabilir türler şunları içerir:

Tip Tanım
bool Foo dönüş türü.
int İlk Foo parametresinin türü.
bar_t * İkinci Foo parametresinin türü. bar_t * aracılığıyla bar_t , foo_exported.h aracılığıyla dışa aktarılır.

bar_t foo_exported.h aracılığıyla dışa aktarılan foo_t türünde mfoo üyesini içerir, bu da daha fazla türün dışa aktarılmasına neden olur:
  • int : m1 türüdür.
  • int * : m2 türüdür.
  • foo_private_t * : mPfoo türüdür.

Ancak foo_private_t , foo_exported.h aracılığıyla dışa aktarılmadığından ulaşılamaz. ( foo_private_t * opaktır, bu nedenle foo_private_t üzerinde yapılan değişikliklere izin verilir.)

Temel sınıf belirticileri ve şablon parametreleri aracılığıyla ulaşılabilen türler için de benzer bir açıklama yapılabilir.

ABI uyumluluğunun sağlanması

İlgili Android.bp dosyalarında vendor_available: true ve vndk.enabled: true olarak işaretlenen kitaplıklar için ABI uyumluluğu sağlanmalıdır. Örneğin:

cc_library {
    name: "libvndk_example",
    vendor_available: true,
    vndk: {
        enabled: true,
    }
}

Dışa aktarılan bir işlev tarafından doğrudan veya dolaylı olarak erişilebilen veri türleri için, bir kitaplıkta yapılan aşağıdaki değişiklikler ABI'yi bozan değişiklikler olarak sınıflandırılır:

Veri tipi Tanım
Yapılar ve Sınıflar
  • Sınıf türünün veya yapı türünün boyutunu değiştirin.
  • Temel sınıflar
    • Temel sınıfları ekleyin veya kaldırın.
    • Neredeyse devralınan temel sınıfları ekleyin veya kaldırın.
    • Temel sınıfların sırasını değiştirin.
  • Üye işlevleri
    • Üye işlevlerini kaldırın*.
    • Üye işlevlerden bağımsız değişkenler ekleyin veya kaldırın.
    • Bağımsız değişken türlerini veya üye işlevlerin dönüş türlerini değiştirin*.
    • Sanal tablo düzenini değiştirin.
  • Veri üyeleri
    • Statik veri üyelerini kaldırın.
    • Statik olmayan veri üyelerini ekleyin veya kaldırın.
    • Veri üyelerinin türlerini değiştirin.
    • Uzaklıkları statik olmayan veri üyeleriyle değiştirin**.
    • Veri üyelerinin const , volatile ve/veya restricted niteleyicilerini değiştirin***.
    • Veri üyelerinin erişim belirticilerinin düzeyini düşürün***.
  • Şablon bağımsız değişkenlerini değiştirin.
Sendikalar
  • Veri üyelerini ekleyin veya kaldırın.
  • Birleşim türünün boyutunu değiştirin.
  • Veri üyelerinin türlerini değiştirin.
Numaralandırmalar
  • Temel türü değiştirin.
  • Numaralandırıcıların adlarını değiştirin.
  • Numaralandırıcıların değerlerini değiştirin.
Küresel Semboller
  • Genel başlıklar tarafından dışa aktarılan sembolleri kaldırın.
  • FUNC türündeki global semboller için
    • Bağımsız değişkenleri ekleyin veya kaldırın.
    • Argüman türlerini değiştirin.
    • Dönüş türünü değiştirin.
    • Erişim belirticisinin düzeyini düşürün***.
  • OBJECT türündeki global semboller için
    • İlgili C/C++ türünü değiştirin.
    • Erişim belirticisinin düzeyini düşürün***.

* Genel satır içi işlevler özel üye işlevlerine atıfta bulunabileceğinden, hem genel hem de özel üye işlevleri değiştirilmemeli veya kaldırılmamalıdır. Özel üye işlevlerine yönelik sembol referansları arayan ikili dosyalarda tutulabilir. Özel üye işlevlerinin paylaşılan kitaplıklardan değiştirilmesi veya kaldırılması, ikili dosyaların geriye dönük olarak uyumsuz olmasına neden olabilir.

** Satır içi işlevler, işlev gövdelerinde bu veri üyelerine başvurabildiğinden genel veya özel veri üyelerine ilişkin uzaklıklar değiştirilmemelidir. Veri üyesi uzaklıklarının değiştirilmesi, geriye dönük olarak uyumsuz ikili dosyalara neden olabilir.

*** Bunlar türün bellek düzenini değiştirmese de kitaplıkların beklendiği gibi çalışmamasına yol açabilecek anlamsal farklılıklar vardır.

ABI uyumluluk araçlarını kullanma

Bir VNDK kitaplığı oluşturulduğunda, kitaplığın ABI'si, oluşturulmakta olan VNDK sürümüne karşılık gelen ABI referansıyla karşılaştırılır. Referans ABI dökümleri şurada bulunur:

${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/<PLATFORM_VNDK_VERSION>/<BINDER_BITNESS>/<ARCH>/source-based

Örneğin, API düzeyi 27'de x86 için libfoo derlenirken, libfoo çıkarılan ABI şu adresteki referansıyla karşılaştırılır:

${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/27/64/x86/source-based/libfoo.so.lsdump

ABI kırılma hatası

ABI kesintilerinde derleme günlüğü, uyarı türüyle birlikte uyarıları ve abi-diff raporuna giden yolu görüntüler. Örneğin, libbinder ABI'sinde uyumsuz bir değişiklik varsa derleme sistemi aşağıdakine benzer bir mesajla bir hata atar:

*****************************************************
error: VNDK library: libbinder.so's ABI has INCOMPATIBLE CHANGES
Please check compatibility report at:
out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm64_armv8-a_cortex-a73_vendor_shared/libbinder.so.abidiff
******************************************************
---- Please update abi references by running
platform/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l libbinder ----

VNDK kütüphanesi ABI kontrolleri oluşturma

Bir VNDK kütüphanesi oluşturulduğunda:

  1. header-abi-dumper her kaynağa karşılık gelen .sdump dosyalarını üretmek için VNDK kitaplığını (kitaplığın kendi kaynak dosyalarının yanı sıra statik geçişli bağımlılıklar yoluyla devralınan kaynak dosyaları) oluşturmak için derlenen kaynak dosyalarını işler.
    sdump creation
    Şekil 1. .sdump dosyalarını oluşturma
  2. header-abi-linker daha sonra .sdump dosyalarını işler (kendisine sağlanan bir sürüm komut dosyasını veya paylaşılan kitaplığa karşılık gelen .so dosyasını kullanarak), paylaşılan kitaplığa karşılık gelen tüm ABI bilgilerini günlüğe kaydeden bir .lsdump dosyası üretir.
    lsdump creation
    Şekil 2. .lsdump dosyasını oluşturma
  3. header-abi-diff iki kitaplığın ABI'lerindeki farklılıkları özetleyen bir diff raporu oluşturmak için .lsdump dosyasını bir referans .lsdump dosyasıyla karşılaştırır.
    abi diff creation
    Şekil 3. Fark raporunun oluşturulması

başlık-abi-damper

header-abi-dumper aracı bir C/C++ kaynak dosyasını ayrıştırır ve bu kaynak dosyadan çıkarılan ABI'yi bir ara dosyaya döker. Derleme sistemi, derlenmiş tüm kaynak dosyalar üzerinde header-abi-dumper çalıştırırken aynı zamanda geçişli bağımlılıklardan gelen kaynak dosyaları içeren bir kitaplık da oluşturur.

Girişler
  • AC/C++ kaynak dosyası
  • Dışa aktarılan dizinleri içerir
  • Derleyici bayrakları
Çıktı Kaynak dosyanın ABI'sini açıklayan bir dosya (örneğin foo.sdump , foo.cpp ABI'sini temsil eder).

Şu anda .sdump dosyaları JSON biçimindedir ve bu biçimin gelecek sürümlerde kararlı olacağı garanti edilmez. Bu nedenle, .sdump dosya biçimlendirmesinin bir derleme sistemi uygulama ayrıntısı olarak düşünülmesi gerekir.

Örneğin, libfoo.so aşağıdaki kaynak dosya foo.cpp sahiptir:

#include <stdio.h>
#include <foo_exported.h>

bool Foo(int id, bar_t *bar_ptr) {
    if (id > 0 && bar_ptr->mfoo.m1 > 0) {
        return true;
    }
    return false;
}

Aşağıdakileri kullanarak kaynak dosya tarafından sunulan ABI'yi temsil eden bir ara .sdump dosyası oluşturmak için header-abi-dumper kullanabilirsiniz:

$ header-abi-dumper foo.cpp -I exported -o foo.sdump -- -I exported -x c++

Bu komut header-abi-dumper foo.cpp -- izleyen derleyici bayraklarıyla ayrıştırmasını ve exported dizindeki genel başlıklar tarafından dışa aktarılan ABI bilgilerini yaymasını söyler. header-abi-dumper tarafından oluşturulan foo.sdump aşağıdadır:

{
 "array_types" : [],
 "builtin_types" :
 [
  {
   "alignment" : 4,
   "is_integral" : true,
   "linker_set_key" : "_ZTIi",
   "name" : "int",
   "referenced_type" : "_ZTIi",
   "self_type" : "_ZTIi",
   "size" : 4
  }
 ],
 "elf_functions" : [],
 "elf_objects" : [],
 "enum_types" : [],
 "function_types" : [],
 "functions" :
 [
  {
   "function_name" : "FooBad",
   "linker_set_key" : "_Z6FooBadiP3foo",
   "parameters" :
   [
    {
     "referenced_type" : "_ZTIi"
    },
    {
     "referenced_type" : "_ZTIP3foo"
    }
   ],
   "return_type" : "_ZTI3bar",
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "global_vars" : [],
 "lvalue_reference_types" : [],
 "pointer_types" :
 [
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIP11foo_private",
   "name" : "foo_private *",
   "referenced_type" : "_ZTI11foo_private",
   "self_type" : "_ZTIP11foo_private",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIP3foo",
   "name" : "foo *",
   "referenced_type" : "_ZTI3foo",
   "self_type" : "_ZTIP3foo",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIPi",
   "name" : "int *",
   "referenced_type" : "_ZTIi",
   "self_type" : "_ZTIPi",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "qualified_types" : [],
 "record_types" :
 [
  {
   "alignment" : 8,
   "fields" :
   [
    {
     "field_name" : "mfoo",
     "referenced_type" : "_ZTI3foo"
    }
   ],
   "linker_set_key" : "_ZTI3bar",
   "name" : "bar",
   "referenced_type" : "_ZTI3bar",
   "self_type" : "_ZTI3bar",
   "size" : 24,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "fields" :
   [
    {
     "field_name" : "m1",
     "referenced_type" : "_ZTIi"
    },
    {
     "field_name" : "m2",
     "field_offset" : 64,
     "referenced_type" : "_ZTIPi"
    },
    {
     "field_name" : "mPfoo",
     "field_offset" : 128,
     "referenced_type" : "_ZTIP11foo_private"
    }
   ],
   "linker_set_key" : "_ZTI3foo",
   "name" : "foo",
   "referenced_type" : "_ZTI3foo",
   "self_type" : "_ZTI3foo",
   "size" : 24,
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "rvalue_reference_types" : []
}

foo.sdump foo.cpp kaynak dosyası ve genel başlıklar tarafından dışa aktarılan ABI bilgilerini içerir; örneğin,

  • record_types . Genel başlıklarda tanımlanan yapılara, birleşimlere veya sınıflara bakın. Her kayıt türü; alanları, boyutu, erişim belirteci, içinde tanımlandığı başlık dosyası ve diğer nitelikler hakkında bilgi içerir.
  • pointer_types . Genel başlıklarda dışa aktarılan kayıtlar/işlevler tarafından doğrudan/dolaylı olarak başvurulan işaretçi türlerine ve işaretçinin işaret ettiği türe ( type_info içindeki referenced_type alanı aracılığıyla) bakın. Nitelikli türler, yerleşik C/C++ türleri, dizi türleri ve lvalue ve rvalue başvuru türleri için benzer bilgiler .sdump dosyasına kaydedilir. Bu tür bilgiler özyinelemeli farklılığa izin verir.
  • functions . Genel başlıklar tarafından dışarı aktarılan işlevleri temsil eder. Ayrıca işlevin değiştirilmiş adı, dönüş türü, parametre türleri, erişim belirtici ve diğer nitelikler hakkında da bilgi içerirler.

başlık-abi-bağlayıcı

header-abi-linker aracı, header-abi-dumper tarafından üretilen ara dosyaları girdi olarak alır ve ardından bu dosyaları bağlar:

Girişler
  • header-abi-dumper tarafından üretilen ara dosyalar
  • Sürüm komut dosyası/Harita dosyası (isteğe bağlı)
  • Paylaşılan kitaplığın .so dosyası
  • Dışa aktarılan dizinleri içerir
Çıktı Paylaşılan bir kitaplığın ABI'sini açıklayan bir dosya (örneğin, libfoo.so.lsdump libfoo ABI'sini temsil eder).

Araç, çeviri birimleri arasındaki tek tanımlı (aynı tam nitelikli ada sahip farklı çeviri birimlerindeki kullanıcı tanımlı türler, anlamsal olarak farklı olabilir) farklılıkları dikkate alarak kendisine verilen tüm ara dosyalardaki tür grafiklerini birleştirir. Araç daha sonra dışa aktarılan sembollerin bir listesini oluşturmak için bir sürüm komut dosyasını veya paylaşılan kitaplığın ( .so dosyası) .dynsym tablosunu ayrıştırır.

Örneğin libfoo , foo.cpp ve bar.cpp oluşur. libfoo tam bağlantılı ABI dökümünü oluşturmak için header-abi-linker şu şekilde çağrılabilir:

header-abi-linker -I exported foo.sdump bar.sdump \
                  -o libfoo.so.lsdump \
                  -so libfoo.so \
                  -arch arm64 -api current

libfoo.so.lsdump örnek komut çıktısı:

{
 "array_types" : [],
 "builtin_types" :
 [
  {
   "alignment" : 1,
   "is_integral" : true,
   "is_unsigned" : true,
   "linker_set_key" : "_ZTIb",
   "name" : "bool",
   "referenced_type" : "_ZTIb",
   "self_type" : "_ZTIb",
   "size" : 1
  },
  {
   "alignment" : 4,
   "is_integral" : true,
   "linker_set_key" : "_ZTIi",
   "name" : "int",
   "referenced_type" : "_ZTIi",
   "self_type" : "_ZTIi",
   "size" : 4
  }
 ],
 "elf_functions" :
 [
  {
   "name" : "_Z3FooiP3bar"
  },
  {
   "name" : "_Z6FooBadiP3foo"
  }
 ],
 "elf_objects" : [],
 "enum_types" : [],
 "function_types" : [],
 "functions" :
 [
  {
   "function_name" : "Foo",
   "linker_set_key" : "_Z3FooiP3bar",
   "parameters" :
   [
    {
     "referenced_type" : "_ZTIi"
    },
    {
     "referenced_type" : "_ZTIP3bar"
    }
   ],
   "return_type" : "_ZTIb",
   "source_file" : "exported/foo_exported.h"
  },
  {
   "function_name" : "FooBad",
   "linker_set_key" : "_Z6FooBadiP3foo",
   "parameters" :
   [
    {
     "referenced_type" : "_ZTIi"
    },
    {
     "referenced_type" : "_ZTIP3foo"
    }
   ],
   "return_type" : "_ZTI3bar",
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "global_vars" : [],
 "lvalue_reference_types" : [],
 "pointer_types" :
 [
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIP11foo_private",
   "name" : "foo_private *",
   "referenced_type" : "_ZTI11foo_private",
   "self_type" : "_ZTIP11foo_private",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIP3bar",
   "name" : "bar *",
   "referenced_type" : "_ZTI3bar",
   "self_type" : "_ZTIP3bar",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIP3foo",
   "name" : "foo *",
   "referenced_type" : "_ZTI3foo",
   "self_type" : "_ZTIP3foo",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "linker_set_key" : "_ZTIPi",
   "name" : "int *",
   "referenced_type" : "_ZTIi",
   "self_type" : "_ZTIPi",
   "size" : 8,
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "qualified_types" : [],
 "record_types" :
 [
  {
   "alignment" : 8,
   "fields" :
   [
    {
     "field_name" : "mfoo",
     "referenced_type" : "_ZTI3foo"
    }
   ],
   "linker_set_key" : "_ZTI3bar",
   "name" : "bar",
   "referenced_type" : "_ZTI3bar",
   "self_type" : "_ZTI3bar",
   "size" : 24,
   "source_file" : "exported/foo_exported.h"
  },
  {
   "alignment" : 8,
   "fields" :
   [
    {
     "field_name" : "m1",
     "referenced_type" : "_ZTIi"
    },
    {
     "field_name" : "m2",
     "field_offset" : 64,
     "referenced_type" : "_ZTIPi"
    },
    {
     "field_name" : "mPfoo",
     "field_offset" : 128,
     "referenced_type" : "_ZTIP11foo_private"
    }
   ],
   "linker_set_key" : "_ZTI3foo",
   "name" : "foo",
   "referenced_type" : "_ZTI3foo",
   "self_type" : "_ZTI3foo",
   "size" : 24,
   "source_file" : "exported/foo_exported.h"
  }
 ],
 "rvalue_reference_types" : []
}

header-abi-linker aracı:

  • Kendisine sağlanan .sdump dosyalarını ( foo.sdump ve bar.sdump ) bağlar ve şu dizinde bulunan başlıklarda bulunmayan ABI bilgilerini filtreler: exported .
  • libfoo.so dosyasını ayrıştırır ve .dynsym tablosu aracılığıyla kitaplık tarafından dışa aktarılan semboller hakkında bilgi toplar.
  • _Z3FooiP3bar ve _Z6FooBadiP3foo ekler.

libfoo.so.lsdump , libfoo.so oluşturulan son ABI dökümüdür.

başlık-abi-fark

header-abi-diff aracı, iki kitaplığın ABI'sini temsil eden iki .lsdump dosyasını karşılaştırır ve iki ABI arasındaki farkları belirten bir diff raporu üretir.

Girişler
  • Eski bir paylaşılan kitaplığın ABI'sini temsil eden .lsdump dosyası.
  • Yeni bir paylaşılan kitaplığın ABI'sini temsil eden .lsdump dosyası.
Çıktı Karşılaştırılan iki paylaşılan kitaplığın sunduğu ABI'lerdeki farklılıkları belirten bir fark raporu.

ABI fark dosyası protobuf metin formatındadır . Format gelecek sürümlerde değişebilir.

Örneğin, libfoo iki sürümü var: libfoo_old.so ve libfoo_new.so . libfoo_new.so , bar_t , mfoo türünü foo_t yerine foo_t * olarak değiştirirsiniz. bar_t erişilebilir bir tür olduğundan, bu header-abi-diff tarafından ABI'yi bozan bir değişiklik olarak işaretlenmelidir.

header-abi-diff çalıştırmak için:

header-abi-diff -old libfoo_old.so.lsdump \
                -new libfoo_new.so.lsdump \
                -arch arm64 \
                -o libfoo.so.abidiff \
                -lib libfoo

libfoo.so.abidiff örnek komut çıktısı:

lib_name: "libfoo"
arch: "arm64"
record_type_diffs {
  name: "bar"
  type_stack: "Foo-> bar *->bar "
  type_info_diff {
    old_type_info {
      size: 24
      alignment: 8
    }
    new_type_info {
      size: 8
      alignment: 8
    }
  }
  fields_diff {
    old_field {
      referenced_type: "foo"
      field_offset: 0
      field_name: "mfoo"
      access: public_access
    }
    new_field {
      referenced_type: "foo *"
      field_offset: 0
      field_name: "mfoo"
      access: public_access
    }
  }
}

libfoo.so.abidiff , libfoo tüm ABI değişikliklerinin raporunu içerir. record_type_diffs mesajı, bir kaydın değiştiğini belirtir ve aşağıdakileri içeren uyumsuz değişiklikleri listeler:

  • Kaydın boyutu 24 bayttan 8 bayta değişiyor.
  • mfoo alan türü foo foo * ya değişiyor (tüm typedef'ler çıkarılmıştır).

type_stack alanı header-abi-diff değişen türe ( bar ) nasıl ulaştığını gösterir. Bu alan, Foo parametre olarak bar * ı alan, dışa aktarılan ve değiştirilen bar işaret eden, dışa aktarılan bir işlev olduğu şeklinde yorumlanabilir.

ABI/API'yi zorunlu kılma

VNDK paylaşılan kitaplıklarının ABI/API'sini uygulamak için ABI referanslarının ${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/ içine kontrol edilmesi gerekir. Bu referansları oluşturmak için aşağıdaki komutu çalıştırın:

${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py

Referansları oluşturduktan sonra kaynak kodunda yapılan ve VNDK kitaplığında uyumsuz bir ABI/API değişikliğine yol açan herhangi bir değişiklik artık derleme hatasıyla sonuçlanıyor.

Belirli kitaplıkların ABI referanslarını güncellemek için aşağıdaki komutu çalıştırın:

${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l <lib1> -l <lib2>

Örneğin, libbinder ABI referanslarını güncellemek için şunu çalıştırın:

${ANDROID_BUILD_TOP}/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l libbinder