Độ ổn định của ABI

Tính ổn định của Giao diện nhị phân ứng dụng (ABI) là điều kiện tiên quyết của các bản cập nhật chỉ dành cho khung vì các mô-đun của nhà cung cấp có thể phụ thuộc vào các thư viện dùng chung Bộ công cụ phát triển gốc của nhà cung cấp (VNK) nằm trong phân vùng hệ thống. Trong bản phát hành Android, các thư viện chia sẻ VNĐK mới được xây dựng phải tương thích ABI với các thư viện chia sẻ VNĐK đã phát hành trước đó để các mô-đun của nhà cung cấp có thể hoạt động với các thư viện đó mà không cần biên dịch lại và không có lỗi thời gian chạy. Giữa các bản phát hành Android, thư viện VNĐK có thể được thay đổi và không có đảm bảo ABI.

Để giúp đảm bảo khả năng tương thích ABI, Android 9 bao gồm trình kiểm tra ABI tiêu đề, như được mô tả trong các phần sau.

Về việc tuân thủ VNDK và ABI

VNĐK là một bộ thư viện hạn chế mà các mô-đun của nhà cung cấp có thể liên kết tới và cho phép cập nhật chỉ dành cho khung. Tuân thủ ABI đề cập đến khả năng phiên bản mới hơn của thư viện dùng chung hoạt động như mong đợi với mô-đun được liên kết động với nó (tức là hoạt động như phiên bản cũ hơn của thư viện).

Giới thiệu về các biểu tượng đã xuất

Biểu tượng được xuất (còn được gọi là biểu tượng chung ) đề cập đến biểu tượng đáp ứng tất cả các điều sau:

  • Được xuất theo tiêu đề công khai của thư viện dùng chung.
  • Xuất hiện trong bảng .dynsym của file .so tương ứng với thư viện dùng chung.
  • Có ràng buộc YẾU hoặc TOÀN CẦU.
  • Khả năng hiển thị là MẶC ĐỊNH hoặc ĐƯỢC BẢO VỆ.
  • Chỉ mục phần không được xác định.
  • Loại là FUNC hoặc ĐỐI TƯỢNG.

Các tiêu đề công khai của thư viện dùng chung được định nghĩa là các tiêu đề có sẵn cho các thư viện/tệp nhị phân khác thông qua các export_include_dirs , export_header_lib_headers , export_static_lib_headers , export_shared_lib_headers export_generated_headers trong định nghĩa Android.bp của mô-đun tương ứng với thư viện dùng chung.

Giới thiệu về các loại có thể truy cập

Loại có thể truy cập là bất kỳ loại C/C++ tích hợp hoặc do người dùng xác định nào có thể truy cập trực tiếp hoặc gián tiếp thông qua biểu tượng được xuất VÀ được xuất thông qua các tiêu đề công khai. Ví dụ: libfoo.so có hàm Foo , là biểu tượng được xuất trong bảng .dynsym . Thư viện libfoo.so bao gồm:

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"
  ],
}
bảng .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

Nhìn vào Foo , các loại có thể truy cập trực tiếp/gián tiếp bao gồm:

Kiểu Sự miêu tả
bool Kiểu trả về của Foo .
int Loại tham số Foo đầu tiên.
bar_t * Loại tham số Foo thứ hai. Bằng cách bar_t * , bar_t được xuất qua foo_exported.h .

bar_t chứa thành viên mfoo , thuộc loại foo_t , được xuất qua foo_exported.h , dẫn đến nhiều loại được xuất hơn:
  • int : là loại m1 .
  • int * : là loại m2 .
  • foo_private_t * : là loại mPfoo .

Tuy nhiên, foo_private_t KHÔNG thể truy cập được vì nó không được xuất qua foo_exported.h . ( foo_private_t * không rõ ràng, do đó những thay đổi được thực hiện đối với foo_private_t được cho phép.)

Một lời giải thích tương tự cũng có thể được đưa ra cho các loại có thể truy cập thông qua các bộ xác định lớp cơ sở và các tham số mẫu.

Đảm bảo tuân thủ ABI

Phải đảm bảo tuân thủ ABI đối với các thư viện được đánh dấu là vendor_available: truevndk.enabled: true trong các tệp Android.bp tương ứng. Ví dụ:

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

Đối với các loại dữ liệu có thể truy cập trực tiếp hoặc gián tiếp bằng hàm xuất, những thay đổi sau đây đối với thư viện được phân loại là vi phạm ABI:

Loại dữ liệu Sự miêu tả
Cấu trúc và lớp học
  • Thay đổi kích thước của kiểu lớp hoặc kiểu cấu trúc.
  • Lớp cơ bản
    • Thêm hoặc loại bỏ các lớp cơ sở.
    • Thêm hoặc loại bỏ các lớp cơ sở hầu như được kế thừa.
    • Thay đổi thứ tự của các lớp cơ sở.
  • Hàm thành viên
    • Xóa các hàm thành viên*.
    • Thêm hoặc xóa đối số khỏi các hàm thành viên.
    • Thay đổi kiểu đối số hoặc kiểu trả về của hàm thành viên*.
    • Thay đổi cách bố trí bảng ảo.
  • Thành viên dữ liệu
    • Loại bỏ các thành viên dữ liệu tĩnh.
    • Thêm hoặc xóa thành viên dữ liệu không tĩnh.
    • Thay đổi các loại thành viên dữ liệu.
    • Thay đổi giá trị chênh lệch thành thành viên dữ liệu không tĩnh**.
    • Thay đổi các hạn const , volatile và/hoặc restricted của các thành viên dữ liệu***.
    • Hạ cấp các chỉ định truy cập của các thành viên dữ liệu***.
  • Thay đổi các đối số mẫu.
Công đoàn
  • Thêm hoặc xóa thành viên dữ liệu.
  • Thay đổi kích thước của loại kết hợp.
  • Thay đổi các loại thành viên dữ liệu.
Bảng liệt kê
  • Thay đổi loại cơ bản.
  • Thay đổi tên của điều tra viên.
  • Thay đổi giá trị của điều tra viên.
Biểu tượng toàn cầu
  • Xóa các ký hiệu được xuất bởi tiêu đề công khai.
  • Đối với các ký hiệu chung thuộc loại FUNC
    • Thêm hoặc xóa đối số.
    • Thay đổi các loại đối số.
    • Thay đổi kiểu trả về.
    • Hạ cấp bộ xác định quyền truy cập***.
  • Đối với các ký hiệu chung của loại ĐỐI TƯỢNG
    • Thay đổi loại C/C++ tương ứng.
    • Hạ cấp bộ xác định quyền truy cập***.

* Không được thay đổi hoặc xóa cả hàm thành viên công khai và riêng tư vì các hàm nội tuyến công khai có thể tham chiếu đến các hàm thành viên riêng tư. Tham chiếu biểu tượng đến các hàm thành viên riêng tư có thể được lưu giữ trong tệp nhị phân của người gọi. Việc thay đổi hoặc xóa các hàm thành viên riêng khỏi thư viện dùng chung có thể dẫn đến các tệp nhị phân không tương thích ngược.

** Không được thay đổi độ lệch đối với các thành viên dữ liệu công khai hoặc riêng tư vì các hàm nội tuyến có thể tham chiếu đến các thành viên dữ liệu này trong nội dung hàm của chúng. Việc thay đổi độ lệch thành viên dữ liệu có thể dẫn đến các tệp nhị phân không tương thích ngược.

*** Mặc dù những điều này không thay đổi bố cục bộ nhớ của loại nhưng có những khác biệt về ngữ nghĩa có thể dẫn đến các thư viện không hoạt động như mong đợi.

Sử dụng các công cụ tuân thủ ABI

Khi thư viện VNĐK được xây dựng, ABI của thư viện được so sánh với tham chiếu ABI tương ứng cho phiên bản VNĐK đang được xây dựng. Các bãi chứa ABI tham chiếu được đặt tại:

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

Ví dụ: khi xây dựng libfoo cho x86 ở API cấp 27, ABI suy ra của libfoo được so sánh với tham chiếu của nó tại:

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

Lỗi gãy ABI

Khi xảy ra sự cố ABI, nhật ký bản dựng hiển thị các cảnh báo có loại cảnh báo và đường dẫn đến báo cáo abi-diff. Ví dụ: nếu ABI của libbinder có thay đổi không tương thích, hệ thống xây dựng sẽ đưa ra lỗi với thông báo tương tự như sau:

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

Xây dựng thư viện VNĐK kiểm tra ABI

Khi thư viện VNĐK được xây dựng:

  1. header-abi-dumper xử lý các file nguồn được biên dịch để xây dựng thư viện VNĐK (các file nguồn riêng của thư viện cũng như các file nguồn được kế thừa thông qua các phụ thuộc bắc cầu tĩnh), để cho ra các file .sdump tương ứng với từng nguồn.
    sdump creation
    Hình 1. Tạo tệp .sdump
  2. header-abi-linker sau đó xử lý các tệp .sdump (sử dụng tập lệnh phiên bản được cung cấp cho nó hoặc tệp .so tương ứng với thư viện dùng chung) để tạo tệp .lsdump ghi lại tất cả thông tin ABI tương ứng với thư viện dùng chung.
    lsdump creation
    Hình 2. Tạo tệp .lsdump
  3. header-abi-diff so sánh tệp .lsdump với tệp .lsdump tham chiếu để tạo báo cáo khác biệt nêu rõ sự khác biệt trong ABI của hai thư viện.
    abi diff creation
    Hình 3. Tạo báo cáo khác biệt

tiêu đề-abi-dumper

Công cụ header-abi-dumper phân tích cú pháp tệp nguồn C/C++ và chuyển ABI được suy ra từ tệp nguồn đó vào một tệp trung gian. Hệ thống xây dựng chạy header-abi-dumper trên tất cả các tệp nguồn được biên dịch đồng thời xây dựng một thư viện bao gồm các tệp nguồn từ các phần phụ thuộc bắc cầu.

Đầu vào
  • Tệp nguồn AC/C++
  • Đã xuất các thư mục bao gồm
  • Cờ trình biên dịch
đầu ra Một tệp mô tả ABI của tệp nguồn (ví dụ: foo.sdump đại diện cho ABI của foo.cpp ).

Hiện tại, các tệp .sdump có định dạng JSON, không đảm bảo tính ổn định trong các bản phát hành trong tương lai. Do đó, định dạng tệp .sdump phải được coi là chi tiết triển khai hệ thống xây dựng.

Ví dụ: libfoo.so có tệp nguồn sau 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;
}

Bạn có thể sử dụng header-abi-dumper để tạo tệp .sdump trung gian đại diện cho ABI do tệp nguồn trình bày bằng cách sử dụng:

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

Lệnh này yêu cầu header-abi-dumper phân tích cú pháp foo.cpp bằng các cờ trình biên dịch theo sau -- và phát ra thông tin ABI được xuất bởi các tiêu đề công khai trong thư mục exported . Sau đây là foo.sdump được tạo bởi 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 chứa thông tin ABI được xuất bởi tệp nguồn foo.cpp và các tiêu đề công khai, ví dụ:

  • record_types . Tham khảo các cấu trúc, liên kết hoặc các lớp được xác định trong các tiêu đề chung. Mỗi loại bản ghi có thông tin về các trường, kích thước, bộ chỉ định truy cập, tệp tiêu đề được xác định và các thuộc tính khác.
  • pointer_types . Tham khảo các loại con trỏ được tham chiếu trực tiếp/gián tiếp bởi các bản ghi/hàm đã xuất trong tiêu đề chung, cùng với loại mà con trỏ trỏ tới (thông qua trường referenced_type trong type_info ). Thông tin tương tự được ghi vào tệp .sdump cho các loại đủ điều kiện, loại C/C++ tích hợp sẵn, loại mảng và các loại tham chiếu lvalue và rvalue. Thông tin như vậy cho phép khác biệt đệ quy.
  • functions . Đại diện cho các hàm được xuất bởi các tiêu đề công khai. Chúng cũng có thông tin về tên được đọc sai của hàm, kiểu trả về, kiểu tham số, bộ chỉ định truy cập và các thuộc tính khác.

tiêu đề-abi-liên kết

Công cụ header-abi-linker lấy các tệp trung gian do header-abi-dumper tạo ra làm đầu vào rồi liên kết các tệp đó:

Đầu vào
  • Các tệp trung gian được tạo bởi header-abi-dumper
  • Phiên bản tập lệnh/tệp bản đồ (tùy chọn)
  • Tệp .so của thư viện dùng chung
  • Đã xuất các thư mục bao gồm
đầu ra Một tệp mô tả ABI của thư viện dùng chung (ví dụ: libfoo.so.lsdump đại diện cho ABI của libfoo ).

Công cụ này hợp nhất các biểu đồ loại trong tất cả các tệp trung gian được cung cấp cho nó, có tính đến sự khác biệt về một định nghĩa (loại do người dùng xác định trong các đơn vị dịch khác nhau có cùng tên đủ điều kiện, có thể khác nhau về mặt ngữ nghĩa) giữa các đơn vị dịch. Sau đó, công cụ này phân tích tập lệnh phiên bản hoặc bảng .dynsym của thư viện dùng chung (tệp .so ) để tạo danh sách các ký hiệu được xuất.

Ví dụ: libfoo bao gồm foo.cppbar.cpp . header-abi-linker có thể được gọi để tạo kết xuất ABI được liên kết hoàn chỉnh của libfoo như sau:

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

Đầu ra lệnh ví dụ trong 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" : []
}

Công cụ header-abi-linker :

  • Liên kết các tệp .sdump được cung cấp cho nó ( foo.sdumpbar.sdump ), lọc ra thông tin ABI không có trong các tiêu đề nằm trong thư mục: exported .
  • Phân tích libfoo.so và thu thập thông tin về các ký hiệu được thư viện xuất thông qua bảng .dynsym của nó.
  • Thêm _Z3FooiP3bar_Z6FooBadiP3foo .

libfoo.so.lsdump là kết xuất ABI được tạo cuối cùng của libfoo.so .

tiêu đề-abi-diff

Công cụ header-abi-diff so sánh hai tệp .lsdump đại diện cho ABI của hai thư viện và tạo ra một báo cáo khác biệt nêu rõ sự khác biệt giữa hai ABI.

Đầu vào
  • Tệp .lsdump đại diện cho ABI của thư viện dùng chung cũ.
  • Tệp .lsdump đại diện cho ABI của thư viện dùng chung mới.
đầu ra Một báo cáo khác nêu rõ sự khác biệt trong ABI do hai thư viện dùng chung cung cấp được so sánh.

Tệp khác biệt ABI có định dạng văn bản protobuf . Định dạng này có thể thay đổi trong các phiên bản tương lai.

Ví dụ: bạn có hai phiên bản libfoo : libfoo_old.solibfoo_new.so . Trong libfoo_new.so , trong bar_t , bạn thay đổi loại mfoo từ foo_t thành foo_t * . Vì bar_t là loại có thể truy cập nên điều này phải được gắn cờ là thay đổi vi phạm ABI bởi header-abi-diff .

Để chạy header-abi-diff :

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

Đầu ra lệnh ví dụ trong 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 chứa báo cáo về tất cả các thay đổi vi phạm ABI trong libfoo . Thông báo record_type_diffs cho biết một bản ghi đã thay đổi và liệt kê những thay đổi không tương thích, bao gồm:

  • Kích thước của bản ghi thay đổi từ 24 byte thành 8 byte.
  • Loại trường mfoo thay đổi từ foo thành foo * (tất cả các typedef đều bị loại bỏ).

Trường type_stack cho biết cách header-abi-diff tiếp cận loại đã thay đổi ( bar ). Trường này có thể được hiểu là Foo là một hàm được xuất lấy bar * làm tham số, trỏ đến bar , đã được xuất và thay đổi.

Thực thi ABI/API

Để thực thi ABI/API của thư viện chia sẻ VNDK, các tham chiếu ABI phải được kiểm tra trong ${ANDROID_BUILD_TOP}/prebuilts/abi-dumps/vndk/ . Để tạo các tài liệu tham khảo này, hãy chạy lệnh sau:

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

Sau khi tạo tham chiếu, bất kỳ thay đổi nào được thực hiện đối với mã nguồn dẫn đến thay đổi ABI/API không tương thích trong thư viện VNDK hiện dẫn đến lỗi xây dựng.

Để cập nhật tham chiếu ABI cho các thư viện cụ thể, hãy chạy lệnh sau:

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

Ví dụ: để cập nhật các tham chiếu ABI libbinder , hãy chạy:

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