Stabilność ABI

Stabilność interfejsu binarnego aplikacji (ABI) jest warunkiem wstępnym tylko na potrzeby platformy, ponieważ moduły dostawcy mogą zależeć od reklamy natywnej Biblioteki udostępnione pakietu SDK (VNDK) znajdujące się w partycji systemowej. W wersji na Androida nowo utworzone biblioteki udostępnione VNDK muszą być Zgodność z interfejsem ABI z opublikowanymi wcześniej bibliotekami udostępnionymi VNDK, dzięki czemu moduły dostawców mogą działać z tymi bibliotekami bez ponownej kompilacji i bez błędów podczas działania. Między wersjami Androida można zmieniać biblioteki VNDK, nie ma też interfejsu ABI i gwarancjami.

Aby zapewnić zgodność z interfejsem ABI, Android 9 zawiera narzędzia do sprawdzania interfejsu ABI nagłówka, jak opisano w kolejnych sekcjach.

Informacje o zgodności VNDK i ABI

VNDK to ograniczony zestaw bibliotek, do których moduły dostawców mogą zamieszczać linki które umożliwiają aktualizacje tylko za pomocą platformy. Zgodność z ABI odnosi się do jest możliwe, że nowsza wersja biblioteki udostępnionej będzie działać zgodnie z oczekiwaniami który jest z nim dynamicznie połączony (tzn. działa jako starsza wersja modułu biblioteka).

Wyeksportowane symbole

Wyeksportowany symbol (nazywany też symbolem globalnym) odnosi się do symbol, który spełnia wszystkie poniższe warunki:

  • Wyeksportowane przez nagłówki publiczne biblioteki udostępnionej.
  • Pojawia się w tabeli .dynsym pliku .so odpowiadające zasobom wspólnych.
  • Ma wiązanie słabe lub GLOBALNE.
  • Widoczność to DEFAULT lub PROTECTED.
  • Indeks sekcji nie jest NIEDEFINED.
  • Typ to FUNC lub OBJECT.

Nagłówki publiczne biblioteki udostępnionej są zdefiniowane jako nagłówki. dostępnych dla innych bibliotek/plików binarnych za pośrednictwem export_include_dirs, export_header_lib_headers, export_static_lib_headers, export_shared_lib_headers i Atrybuty export_generated_headers w Android.bp definicje modułu odpowiadające zasobom wspólnych.

Typy osiągalne

Typ osiągalny to dowolny wbudowany lub zdefiniowany przez użytkownika typ w języku C/C++, który jest dostępne bezpośrednio lub pośrednio za pomocą wyeksportowanego symbolu ORAZ wyeksportowany za pomocą nagłówków publicznych. Na przykład libfoo.so ma funkcję Foo, który jest eksportowanym symbolem znalezionym w Tabela .dynsym. Biblioteka libfoo.so zawiera :

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"
  ],
}
tabela .dynsym
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

W kategorii Foo dostępne są następujące typy osiągalne bezpośrednio i pośrednio:

Typ Opis
bool Typ zwrotu: Foo.
int Typ pierwszego parametru Foo.
bar_t * Typ drugiego parametru Foo. W drodze bar_t *, Dane bar_t są eksportowane przez usługę foo_exported.h.

bar_t zawiera element mfoo typu foo_t, który jest eksportowany przez foo_exported.h, co powoduje eksport większej liczby typów:
  • int : to typ m1.
  • int * : to typ m2.
  • foo_private_t * : to typ mPfoo.
.
Jednak domena foo_private_t NIE jest dostępna, ponieważ nie jest wyeksportowane przez usługę foo_exported.h. (foo_private_t * jest nieprzezroczysty, więc zmiany w foo_private_t są dozwolone).

Podobne wyjaśnienie można podać dla typów osiągalnych przez klasę bazową specyfikatory i parametry szablonu.

Zadbaj o zgodność z ABI

Biblioteki oznaczone jako muszą być zgodne z ABI vendor_available: true i vndk.enabled: true w odpowiednich Android.bp plików. Na przykład:

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

W przypadku typów danych, które są dostępne bezpośrednio lub pośrednio przez eksportowaną funkcję, następujące zmiany w bibliotece są klasyfikowane jako powodujące uszkodzenia w interfejsie ABI:

Typ danych Opis
Struktury i zajęcia
  • Zmień rozmiar typu klasy lub typu struct.
  • Klasy podstawowe
    • Dodawanie i usuwanie klas podstawowych.
    • Dodaj lub usuń wirtualnie dziedziczone klasy podstawowe.
    • Umożliwia zmianę kolejności klas podstawowych.
  • Funkcje składowe
    • Usuń funkcje składowe*.
    • Dodaj lub usuń argumenty z funkcji składowych.
    • Zmień typy argumentów lub zwracane typy składowych funkcji*.
    • Zmień układ tabeli wirtualnej.
  • Użytkownicy danych
    • usuwać statyczne elementy danych.
    • Dodawanie i usuwanie niestatycznych użytkowników danych.
    • Zmień typy użytkowników danych.
    • Zmień przesunięcia na niestatyczne elementy danych**.
    • Zmień const, volatile lub Kwalifikatory użytkowników danych (restricted)***.
    • Zmień na starszą wersję specyfikatorów dostępu użytkowników danych***.
  • Zmień argumenty szablonu.
Związki
  • dodawać i usuwać użytkowników danych;
  • Zmień rozmiar rodzaju sumy.
  • Zmień typy użytkowników danych.
Wyliczenia
  • Zmień typ źródła.
  • Zmień nazwy urządzeń wyliczających.
  • Zmień wartości parametrów wyliczających.
Symbole globalne
  • Usuń symbole wyeksportowane przez nagłówki publiczne.
  • Symbole globalne typu FUNC
    • Dodaj lub usuń argumenty.
    • Zmień typy argumentów.
    • Zmień typ zwrotu.
    • Zmień wersję specyfikatora dostępu na starszą wersję***.
  • Dla symboli globalnych typu OBJECT
    • Zmień odpowiedni typ C/C++.
    • Zmień wersję specyfikatora dostępu na starszą wersję***.

* Zarówno publiczne, jak i prywatne funkcje członka muszą nie można zmienić ani usunąć, ponieważ publiczne funkcje wbudowane mogą odnosić się do funkcji członków prywatnych. Odniesienia do symboli do funkcji członków prywatnych mogą w plikach binarnych rozmówcy. Zmienianie lub usuwanie funkcji członków prywatnych z bibliotek udostępnionych może spowodować brak zgodności wstecznej plików binarnych.

** Przesunięcia na elementy publicznych lub prywatnych danych nie mogą być została zmieniona, ponieważ funkcje wbudowane mogą odwoływać się do tych elementów danych w swoich treść funkcji. Zmiana przesunięcia składu danych może spowodować niezgodne wstecznie pliki binarne.

*** Bez zmian w układzie pamięci tego typu, występują różnice semantyczne, które mogą sprawić, że biblioteki więc działa zgodnie z oczekiwaniami.

Korzystanie z narzędzi zgodności z ABI

Po utworzeniu biblioteki VNDK jej interfejs ABI jest porównywany z odpowiednie odwołanie do interfejsu ABI dla tworzonej wersji VNDK. Źródła wiedzy Zrzuty interfejsu ABI znajdują się w:

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

Na przykład w kompilacji libfoo dla x86 na poziomie API 27: Przypuszczalny interfejs ABI użytkownika libfoo jest porównywany z jego plikiem referencyjnym pod adresem:

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

Błąd uszkodzenia interfejsu ABI

W przypadku awarii interfejsu ABI log kompilacji wyświetla ostrzeżenia z typem ostrzeżenia i do raportu abi-diff. Jeśli na przykład interfejs ABI interfejsu libbinder ma niezgodną zmianę, system kompilacji zwróci błąd z komunikatem podobnie jak poniżej:

*****************************************************
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 ----

Kompilowanie testów ABI biblioteki VNDK

Po utworzeniu biblioteki VNDK:

  1. header-abi-dumper przetwarza pliki źródłowe skompilowane do utworzyć bibliotekę VNDK (własne pliki źródłowe biblioteki, a także pliki źródłowe dziedziczone przez statyczne zależności przejściowe), aby wygenerować Liczba plików, które odpowiadają każdemu źródłom: .sdump.
    tworzenie zrzutu
    Rysunek 1. Tworzę .sdump pliki
  2. header-abi-linker następnie przetwarza .sdump (za pomocą udostępnionego skryptu wersji lub tagu .so odpowiadający bibliotece współdzielonej), aby wygenerować .lsdump który zawiera wszystkie informacje związane z interfejsem ABI powiązane z biblioteką współdzieloną.
    Tworzenie pliku lsdump
    Rysunek 2. Tworzę .lsdump plik
  3. header-abi-diff porównuje .lsdump plik zawierający odwołanie do pliku .lsdump w celu wygenerowania raportu różnic które pokazują różnice w interfejsach ABI tych 2 bibliotek.
    tworzenie abi diff
    Rysunek 3. Tworzenie raportu różnic

nagłówek-abi-dumper,

Narzędzie header-abi-dumper analizuje plik źródłowy w języku C/C++ i zrzuty interfejs ABI uzyskany z tego pliku źródłowego do pliku pośredniego. Kompilacja system uruchamia header-abi-dumper na wszystkich skompilowanych plikach źródłowych podczas stworzenie biblioteki zawierającej pliki źródłowe z przechodnich zależności.

Wejścia
  • Plik źródłowy w języku C/C++
  • Wyeksportowano katalogi uwzględniania
  • Flagi kompilacji
Wyjście Plik opisujący interfejs ABI pliku źródłowego (na przykład foo.sdump reprezentuje interfejs ABI interfejsu foo.cpp).

Obecnie .sdump pliki są w formacie JSON, który nie jest musi być stabilna we wszystkich przyszłych wersjach. Z tego powodu .sdump formatowanie plików należy uznać za szczegóły implementacji systemu kompilacji.

Na przykład plik libfoo.so ma następujący plik źródłowy foo.cpp:

#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;
}

Aby wygenerować poziom średniozaawansowany, możesz użyć atrybutu header-abi-dumper Plik .sdump reprezentujący interfejs ABI prezentowany w pliku źródłowym przy użyciu:

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

To polecenie informuje header-abi-dumper o konieczności przeanalizowania foo.cpp z flagami kompilatora zgodnymi z zasadą -- oraz wysyła informacje ABI eksportowane przez publiczne nagłówki w pliku katalogu exported. Oto foo.sdump wygenerowane przez header-abi-dumper:

{
 "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 zawiera informacje o interfejsie ABI wyeksportowane przez plik źródłowy foo.cpp oraz nagłówki publiczne, na przykład

  • record_types Odwołaj się do zdefiniowanych elementów struct, sumów lub klas w nagłówkach publicznych. Każdy typ rekordu ma informacje o jego polach, rozmiar, specyfikator dostępu, plik nagłówka, w którym jest zdefiniowany, .
  • pointer_types Odwoływać się bezpośrednio lub pośrednio do typów wskaźników do których odwołują się wyeksportowane rekordy/funkcje w nagłówkach publicznych, z typem, na który wskazuje wskaźnik (za pomocą funkcji referenced_type w type_info). Podobne informacje są rejestrowane na stronie Plik .sdump dla kwalifikujących się typów, wbudowanych typów C/C++, tablica oraz odwołania do lvalue i rvalue. Takie informacje pozwalają różnicowanie rekurencyjne.
  • functions Reprezentuj funkcje wyeksportowane przez nagłówki publiczne. Zawierają również informacje o zniekształconej nazwie funkcji, zwracanego typu typy parametrów, specyfikator dostępu i inne atrybuty.
.

nagłówek-abi-linker,

Narzędzie header-abi-linker wykorzystuje utworzone pliki pośrednie przez header-abi-dumper jako dane wejściowe, a następnie łączy te pliki:

Wejścia
  • Pliki pośrednie utworzone w programie header-abi-dumper
  • Skrypt wersji/plik mapy (opcjonalnie)
  • .so plik z biblioteki udostępnionej
  • Wyeksportowano katalogi uwzględniania
Wyjście Plik opisujący interfejs ABI udostępnianej biblioteki (np. libfoo.so.lsdump reprezentuje interfejs ABI interfejsu libfoo).

Narzędzie scala wykresy typów we wszystkich przekazanych mu plikach pośrednich, biorąc pod uwagę jedną definicję (zdefiniowane przez użytkownika typy w różnych jednostek tłumaczeniowych o tej samej pełnej i jednoznacznej nazwie mogą być semantyczne różnych jednostek tłumaczeniowych. Następnie narzędzie analizuje skrypt wersji lub tabela .dynsym zasobów wspólnych; (.so), aby utworzyć listę wyeksportowanych symboli.

Na przykład libfoo składa się z foo.cpp i bar.cpp Funkcja header-abi-linker może zostać wywołana do utwórz pełny powiązany zrzut ABI libfoo w następujący sposób:

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

Przykładowe dane wyjściowe polecenia w libfoo.so.lsdump:

{
 "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" : []
}

Narzędzie header-abi-linker:

  • Zawiera link do pliku .sdump (foo.sdump) i bar.sdump), odfiltrowując informacje dotyczące interfejsu ABI, których nie ma w nagłówki znajdujące się w katalogu: exported.
  • Przetwarza element libfoo.so i zbiera informacje o symbolach wyeksportowane przez bibliotekę przy użyciu tabeli .dynsym.
  • Dodaje _Z3FooiP3bar i _Z6FooBadiP3foo.

libfoo.so.lsdump to ostateczny wygenerowany zrzut ABI libfoo.so

nagłówek-abi-diff

Narzędzie header-abi-diff porównuje 2 pliki .lsdump interfejsu ABI dwóch bibliotek i tworzy raport różnic zawierający różnic między tymi dwoma interfejsami ABI.

Wejścia
  • .lsdump plik reprezentujący interfejs ABI starego udostępnionego pliku bibliotece.
  • Plik .lsdump reprezentujący interfejs ABI nowej biblioteki udostępnionej.
Wyjście raport różnic zawierający różnice w interfejsach ABI oferowanych przez te 2 usługi; biblioteki udostępnione.

Plik diff ABI znajduje się w format tekstowy protobuf. Format może ulec zmianie. w kolejnych wersjach.

Na przykład masz 2 wersje libfoo: libfoo_old.so i libfoo_new.so Za libfoo_new.so, w: bar_t, zmieniasz typ elementu mfoo z foo_t do foo_t *. Ponieważ bar_t to typ osiągalny, powinien być oznaczony jako zmiana powodująca niezgodność interfejsu ABI przez header-abi-diff

Aby uruchomić header-abi-diff:

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

Przykładowe dane wyjściowe polecenia w libfoo.so.abidiff:

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 zawiera raport o wszystkich problemach z interfejsem ABI zmiany w miesiącu: libfoo. Wiadomość record_type_diffs wskazuje, że rekord został zmieniony, i wyświetla listę niezgodnych zmian, która uwzględnij:

  • Rozmiar rekordu zmienia się z 24 B na 8 B.
  • Typ pola mfoo zmienia się z foo na foo * (wszystkie definicje typów są usuwane).

Pole type_stack wskazuje, jak header-abi-diff osiągnięto typ, który uległ zmianie (bar). To pole może być interpretowana jako Foo to wyeksportowana funkcja, która przyjmuje bar * jako parametru, który wskazuje bar, która była wyeksportowany i zmieniony.

Wymuszaj interfejsy ABI i API

Aby egzekwować interfejsy ABI i API w bibliotekach udostępnionych VNDK, odwołania do ABI muszą zameldowany(a) w ${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/. Aby utworzyć te odwołania, uruchom następujące polecenie:

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

Po utworzeniu odwołań wszystkie zmiany wprowadzone w kodzie źródłowym, które prowadzą do niekompatybilna zmiana interfejsu ABI/API w bibliotece VNDK powoduje teraz błąd kompilacji.

Aby zaktualizować odwołania do ABI dla określonych bibliotek, uruchom to polecenie:

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

Aby na przykład zaktualizować odwołania do interfejsu ABI libbinder, uruchom polecenie:

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