Add more flexibility to abi checking.
1) Marking a field "required" robs us of flexibility. Make fields optional allows us to update the message format without needing to necessarily update the reference abi-dumps. 2) Allow local warnings with the invocation of header-abi-diff. Test: Added a function to libjpeg, got a warning claiming abi extended. 3) Introduce a flag which allows us to not filter any abi. This is useful for cases when libraries do not include what they export. eg : libsqlite. Test: abi-dump size of libsqlite: without no-filter : 0 with no-filter : ~9M Change-Id: I6cfeacc8711f6df7a4136c2a27b5638988a2c54b
This commit is contained in:
@@ -294,6 +294,7 @@ DiffWrapper<FunctionDecl, FunctionDeclDiff>::Get() {
|
|||||||
google::protobuf::RepeatedPtrField<ParamDeclDiff> *pdiffs =
|
google::protobuf::RepeatedPtrField<ParamDeclDiff> *pdiffs =
|
||||||
func_diff->mutable_param_diffs();
|
func_diff->mutable_param_diffs();
|
||||||
assert(func_diff->mutable_return_type_diffs() != nullptr);
|
assert(func_diff->mutable_return_type_diffs() != nullptr);
|
||||||
|
func_diff->set_name(oldp_->basic_abi().linker_set_key());
|
||||||
if (DiffBasicNamedAndTypedDecl(
|
if (DiffBasicNamedAndTypedDecl(
|
||||||
func_diff->mutable_return_type_diffs()->mutable_old(),
|
func_diff->mutable_return_type_diffs()->mutable_old(),
|
||||||
func_diff->mutable_return_type_diffs()->mutable_new_(),
|
func_diff->mutable_return_type_diffs()->mutable_new_(),
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ static llvm::cl::opt<bool> advice_only(
|
|||||||
"advice-only", llvm::cl::desc("Advisory mode only"), llvm::cl::Optional,
|
"advice-only", llvm::cl::desc("Advisory mode only"), llvm::cl::Optional,
|
||||||
llvm::cl::cat(header_checker_category));
|
llvm::cl::cat(header_checker_category));
|
||||||
|
|
||||||
|
static llvm::cl::opt<bool> suppress_local_warnings(
|
||||||
|
"suppress_local_warnings", llvm::cl::desc("suppress local warnings"),
|
||||||
|
llvm::cl::Optional, llvm::cl::cat(header_checker_category));
|
||||||
|
|
||||||
static llvm::cl::opt<bool> allow_extensions(
|
static llvm::cl::opt<bool> allow_extensions(
|
||||||
"allow-extensions",
|
"allow-extensions",
|
||||||
llvm::cl::desc("Do not return a non zero status on extensions"),
|
llvm::cl::desc("Do not return a non zero status on extensions"),
|
||||||
@@ -80,6 +84,28 @@ int main(int argc, const char **argv) {
|
|||||||
|
|
||||||
CompatibilityStatus status = judge.GenerateCompatibilityReport();
|
CompatibilityStatus status = judge.GenerateCompatibilityReport();
|
||||||
|
|
||||||
|
std::string status_str = "";
|
||||||
|
switch (status) {
|
||||||
|
case CompatibilityStatus::INCOMPATIBLE:
|
||||||
|
status_str = "broken";
|
||||||
|
break;
|
||||||
|
case CompatibilityStatus::EXTENSION:
|
||||||
|
status_str = "extended";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!suppress_local_warnings && status) {
|
||||||
|
llvm::errs() << "******************************************************\n"
|
||||||
|
<< "VNDK Abi "
|
||||||
|
<< status_str
|
||||||
|
<< ":"
|
||||||
|
<< " Please check compatiblity report at : "
|
||||||
|
<< compatibility_report << "\n"
|
||||||
|
<< "*****************************************************\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (advice_only) {
|
if (advice_only) {
|
||||||
return CompatibilityStatus::COMPATIBLE;
|
return CompatibilityStatus::COMPATIBLE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,10 @@ static llvm::cl::list<std::string> exported_header_dirs(
|
|||||||
"I", llvm::cl::desc("<export_include_dirs>"), llvm::cl::Prefix,
|
"I", llvm::cl::desc("<export_include_dirs>"), llvm::cl::Prefix,
|
||||||
llvm::cl::ZeroOrMore, llvm::cl::cat(header_checker_category));
|
llvm::cl::ZeroOrMore, llvm::cl::cat(header_checker_category));
|
||||||
|
|
||||||
|
static llvm::cl::opt<bool> no_filter(
|
||||||
|
"no-filter", llvm::cl::desc("Do not filter any abi"), llvm::cl::Optional,
|
||||||
|
llvm::cl::cat(header_checker_category));
|
||||||
|
|
||||||
// Hide irrelevant command line options defined in LLVM libraries.
|
// Hide irrelevant command line options defined in LLVM libraries.
|
||||||
static void HideIrrelevantCommandLineOptions() {
|
static void HideIrrelevantCommandLineOptions() {
|
||||||
llvm::StringMap<llvm::cl::Option *> &map = llvm::cl::getRegisteredOptions();
|
llvm::StringMap<llvm::cl::Option *> &map = llvm::cl::getRegisteredOptions();
|
||||||
@@ -92,6 +96,10 @@ int main(int argc, const char **argv) {
|
|||||||
::exit(1);
|
::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (no_filter) {
|
||||||
|
static_cast<std::vector<std::string> &>(exported_header_dirs).clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize clang tools and run front-end action.
|
// Initialize clang tools and run front-end action.
|
||||||
std::vector<std::string> header_files{ header_file };
|
std::vector<std::string> header_files{ header_file };
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ static llvm::cl::opt<std::string> arch(
|
|||||||
"arch", llvm::cl::desc("<arch>"), llvm::cl::Optional,
|
"arch", llvm::cl::desc("<arch>"), llvm::cl::Optional,
|
||||||
llvm::cl::cat(header_linker_category));
|
llvm::cl::cat(header_linker_category));
|
||||||
|
|
||||||
|
static llvm::cl::opt<bool> no_filter(
|
||||||
|
"no-filter", llvm::cl::desc("Do not filter any abi"), llvm::cl::Optional,
|
||||||
|
llvm::cl::cat(header_linker_category));
|
||||||
|
|
||||||
class HeaderAbiLinker {
|
class HeaderAbiLinker {
|
||||||
public:
|
public:
|
||||||
HeaderAbiLinker(
|
HeaderAbiLinker(
|
||||||
@@ -301,6 +305,9 @@ bool HeaderAbiLinker::ParseVersionScriptFiles() {
|
|||||||
int main(int argc, const char **argv) {
|
int main(int argc, const char **argv) {
|
||||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||||
llvm::cl::ParseCommandLineOptions(argc, argv, "header-linker");
|
llvm::cl::ParseCommandLineOptions(argc, argv, "header-linker");
|
||||||
|
if (no_filter) {
|
||||||
|
static_cast<std::vector<std::string> &>(exported_header_dirs).clear();
|
||||||
|
}
|
||||||
HeaderAbiLinker Linker(dump_files, exported_header_dirs,
|
HeaderAbiLinker Linker(dump_files, exported_header_dirs,
|
||||||
version_script, linked_dump, arch, api);
|
version_script, linked_dump, arch, api);
|
||||||
if (!Linker.LinkAndDump()) {
|
if (!Linker.LinkAndDump()) {
|
||||||
|
|||||||
@@ -7,30 +7,30 @@ package abi_diff;
|
|||||||
message RecordFieldDeclDiff {
|
message RecordFieldDeclDiff {
|
||||||
optional abi_dump.RecordFieldDecl old = 1;
|
optional abi_dump.RecordFieldDecl old = 1;
|
||||||
optional abi_dump.RecordFieldDecl new = 2;
|
optional abi_dump.RecordFieldDecl new = 2;
|
||||||
required uint32 index = 3;
|
optional uint32 index = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message EnumFieldDeclDiff {
|
message EnumFieldDeclDiff {
|
||||||
optional abi_dump.EnumFieldDecl old = 1;
|
optional abi_dump.EnumFieldDecl old = 1;
|
||||||
optional abi_dump.EnumFieldDecl new = 2;
|
optional abi_dump.EnumFieldDecl new = 2;
|
||||||
required uint32 index = 3;
|
optional uint32 index = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CXXBaseSpecifierDiff {
|
message CXXBaseSpecifierDiff {
|
||||||
optional abi_dump.CXXBaseSpecifier old = 1;
|
optional abi_dump.CXXBaseSpecifier old = 1;
|
||||||
optional abi_dump.CXXBaseSpecifier new = 2;
|
optional abi_dump.CXXBaseSpecifier new = 2;
|
||||||
required uint32 index = 3;
|
optional uint32 index = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CXXVTableDiff {
|
message CXXVTableDiff {
|
||||||
optional abi_dump.VTableComponent old = 1;
|
optional abi_dump.VTableComponent old = 1;
|
||||||
optional abi_dump.VTableComponent new = 2;
|
optional abi_dump.VTableComponent new = 2;
|
||||||
required uint32 index = 3;
|
optional uint32 index = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BasicNamedAndTypedDeclDiff {
|
message BasicNamedAndTypedDeclDiff {
|
||||||
required abi_dump.BasicNamedAndTypedDecl old = 1;
|
optional abi_dump.BasicNamedAndTypedDecl old = 1;
|
||||||
required abi_dump.BasicNamedAndTypedDecl new = 2;
|
optional abi_dump.BasicNamedAndTypedDecl new = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RecordDeclDiff {
|
message RecordDeclDiff {
|
||||||
@@ -38,29 +38,30 @@ message RecordDeclDiff {
|
|||||||
repeated CXXBaseSpecifierDiff base_diffs = 2;
|
repeated CXXBaseSpecifierDiff base_diffs = 2;
|
||||||
repeated CXXVTableDiff vtable_diffs = 3;
|
repeated CXXVTableDiff vtable_diffs = 3;
|
||||||
optional BasicNamedAndTypedDeclDiff type_diff = 4;
|
optional BasicNamedAndTypedDeclDiff type_diff = 4;
|
||||||
required string name = 5;
|
optional string name = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message EnumDeclDiff {
|
message EnumDeclDiff {
|
||||||
repeated EnumFieldDeclDiff field_diffs = 1;
|
repeated EnumFieldDeclDiff field_diffs = 1;
|
||||||
optional BasicNamedAndTypedDeclDiff type_diff = 2;
|
optional BasicNamedAndTypedDeclDiff type_diff = 2;
|
||||||
required string name = 3;
|
optional string name = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ReturnTypeDiff {
|
message ReturnTypeDiff {
|
||||||
required abi_dump.BasicNamedAndTypedDecl old = 1;
|
optional abi_dump.BasicNamedAndTypedDecl old = 1;
|
||||||
required abi_dump.BasicNamedAndTypedDecl new = 2;
|
optional abi_dump.BasicNamedAndTypedDecl new = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ParamDeclDiff {
|
message ParamDeclDiff {
|
||||||
optional abi_dump.ParamDecl old = 1;
|
optional abi_dump.ParamDecl old = 1;
|
||||||
optional abi_dump.ParamDecl new = 2;
|
optional abi_dump.ParamDecl new = 2;
|
||||||
required uint32 index = 3;
|
optional uint32 index = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message FunctionDeclDiff {
|
message FunctionDeclDiff {
|
||||||
optional ReturnTypeDiff return_type_diffs = 1;
|
optional ReturnTypeDiff return_type_diffs = 1;
|
||||||
repeated ParamDeclDiff param_diffs = 2;
|
repeated ParamDeclDiff param_diffs = 2;
|
||||||
|
optional string name = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GlobalVarDeclDiff {
|
message GlobalVarDeclDiff {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ package abi_dump;
|
|||||||
|
|
||||||
message BasicTypeAbi {
|
message BasicTypeAbi {
|
||||||
// The type's name. for eg : a record field's type.
|
// The type's name. for eg : a record field's type.
|
||||||
required string name = 1;
|
optional string name = 1;
|
||||||
// Optional since templated types will not have this information.
|
// Optional since templated types will not have this information.
|
||||||
optional uint64 size = 2 [default = 0];
|
optional uint64 size = 2 [default = 0];
|
||||||
optional uint32 alignment = 3 [default = 0];
|
optional uint32 alignment = 3 [default = 0];
|
||||||
@@ -17,35 +17,35 @@ enum AccessSpecifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message BasicNamedAndTypedDecl {
|
message BasicNamedAndTypedDecl {
|
||||||
required BasicTypeAbi type_abi = 1;
|
optional BasicTypeAbi type_abi = 1;
|
||||||
// The TypedDecl's name.
|
// The TypedDecl's name.
|
||||||
required string name = 2;
|
optional string name = 2;
|
||||||
required AccessSpecifier access = 3;
|
optional AccessSpecifier access = 3;
|
||||||
optional string linker_set_key = 4;
|
optional string linker_set_key = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message FunctionDecl {
|
message FunctionDecl {
|
||||||
required BasicNamedAndTypedDecl basic_abi = 1;
|
optional BasicNamedAndTypedDecl basic_abi = 1;
|
||||||
// Mangled name.
|
// Mangled name.
|
||||||
required string mangled_function_name = 2;
|
optional string mangled_function_name = 2;
|
||||||
required string source_file = 3;
|
optional string source_file = 3;
|
||||||
repeated ParamDecl parameters = 4;
|
repeated ParamDecl parameters = 4;
|
||||||
optional TemplateInfo template_info = 5;
|
optional TemplateInfo template_info = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ParamDecl {
|
message ParamDecl {
|
||||||
required BasicNamedAndTypedDecl basic_abi = 1;
|
optional BasicNamedAndTypedDecl basic_abi = 1;
|
||||||
required bool default_arg = 2;
|
optional bool default_arg = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RecordFieldDecl {
|
message RecordFieldDecl {
|
||||||
// For future additions.
|
// For future additions.
|
||||||
required BasicNamedAndTypedDecl basic_abi = 1;
|
optional BasicNamedAndTypedDecl basic_abi = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message EnumFieldDecl {
|
message EnumFieldDecl {
|
||||||
required BasicNamedAndTypedDecl basic_abi = 1;
|
optional BasicNamedAndTypedDecl basic_abi = 1;
|
||||||
required int64 enum_field_value = 2; // assumption: fits int64
|
optional int64 enum_field_value = 2; // assumption: fits int64
|
||||||
}
|
}
|
||||||
|
|
||||||
message TemplateInfo {
|
message TemplateInfo {
|
||||||
@@ -53,17 +53,17 @@ message TemplateInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message TemplateElement {
|
message TemplateElement {
|
||||||
required BasicTemplateElementAbi basic_abi = 1;
|
optional BasicTemplateElementAbi basic_abi = 1;
|
||||||
message BasicTemplateElementAbi {
|
message BasicTemplateElementAbi {
|
||||||
optional BasicTypeAbi type_abi = 1;
|
optional BasicTypeAbi type_abi = 1;
|
||||||
optional string name = 2;
|
optional string name = 2;
|
||||||
required string linker_set_key = 3;
|
optional string linker_set_key = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message CXXBaseSpecifier {
|
message CXXBaseSpecifier {
|
||||||
required BasicNamedAndTypedDecl basic_abi = 1;
|
optional BasicNamedAndTypedDecl basic_abi = 1;
|
||||||
required bool is_virtual = 2;
|
optional bool is_virtual = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message VTableComponent {
|
message VTableComponent {
|
||||||
@@ -77,7 +77,7 @@ message VTableComponent {
|
|||||||
DeletingDtorPointer = 6;
|
DeletingDtorPointer = 6;
|
||||||
UnusedFunctionPointer = 7;
|
UnusedFunctionPointer = 7;
|
||||||
}
|
}
|
||||||
required Kind kind = 1;
|
optional Kind kind = 1;
|
||||||
optional string mangled_component_name = 2 [default = ""];
|
optional string mangled_component_name = 2 [default = ""];
|
||||||
optional uint64 value = 3 [default = 0];
|
optional uint64 value = 3 [default = 0];
|
||||||
}
|
}
|
||||||
@@ -87,24 +87,24 @@ message VTableLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message RecordDecl {
|
message RecordDecl {
|
||||||
required BasicNamedAndTypedDecl basic_abi = 1;
|
optional BasicNamedAndTypedDecl basic_abi = 1;
|
||||||
repeated RecordFieldDecl fields = 2;
|
repeated RecordFieldDecl fields = 2;
|
||||||
repeated CXXBaseSpecifier base_specifiers = 3;
|
repeated CXXBaseSpecifier base_specifiers = 3;
|
||||||
required string source_file = 4;
|
optional string source_file = 4;
|
||||||
optional TemplateInfo template_info = 5;
|
optional TemplateInfo template_info = 5;
|
||||||
required string mangled_record_name = 6;
|
optional string mangled_record_name = 6;
|
||||||
optional VTableLayout vtable_layout = 7;
|
optional VTableLayout vtable_layout = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message EnumDecl {
|
message EnumDecl {
|
||||||
required BasicNamedAndTypedDecl basic_abi = 1;
|
optional BasicNamedAndTypedDecl basic_abi = 1;
|
||||||
repeated EnumFieldDecl enum_fields = 2;
|
repeated EnumFieldDecl enum_fields = 2;
|
||||||
required string source_file = 3;
|
optional string source_file = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GlobalVarDecl {
|
message GlobalVarDecl {
|
||||||
required BasicNamedAndTypedDecl basic_abi = 1;
|
optional BasicNamedAndTypedDecl basic_abi = 1;
|
||||||
required string source_file = 2;
|
optional string source_file = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TranslationUnit {
|
message TranslationUnit {
|
||||||
|
|||||||
Reference in New Issue
Block a user