Merge "Implement the Cross-Version ABI diff configuration" am: 7b72a4f5f1

Original change: https://android-review.googlesource.com/c/platform/development/+/2182596

Change-Id: I037c48d8db6c80e343aae6b598c8c986820abb44
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Mu-Le Lee
2022-08-19 08:47:19 +00:00
committed by Automerger Merge Worker
4 changed files with 120 additions and 74 deletions

View File

@@ -30,6 +30,7 @@ using header_checker::repr::CompatibilityStatusIR;
using header_checker::repr::DiffPolicyOptions; using header_checker::repr::DiffPolicyOptions;
using header_checker::repr::TextFormatIR; using header_checker::repr::TextFormatIR;
using header_checker::utils::ConfigFile; using header_checker::utils::ConfigFile;
using header_checker::utils::ConfigSection;
static llvm::cl::OptionCategory header_checker_category( static llvm::cl::OptionCategory header_checker_category(
@@ -129,6 +130,15 @@ static llvm::cl::opt<bool> allow_adding_removing_weak_symbols(
llvm::cl::init(false), llvm::cl::Optional, llvm::cl::init(false), llvm::cl::Optional,
llvm::cl::cat(header_checker_category)); llvm::cl::cat(header_checker_category));
static llvm::cl::opt<std::string> target_version(
"target-version",
llvm::cl::desc(
"Load the flags for <target version> and <lib name> from config.json in "
"the old dump's parent directory."
),
llvm::cl::init("current"), llvm::cl::Optional,
llvm::cl::cat(header_checker_category));
static std::set<std::string> LoadIgnoredSymbols(std::string &symbol_list_path) { static std::set<std::string> LoadIgnoredSymbols(std::string &symbol_list_path) {
std::ifstream symbol_ifstream(symbol_list_path); std::ifstream symbol_ifstream(symbol_list_path);
std::set<std::string> ignored_symbols; std::set<std::string> ignored_symbols;
@@ -150,33 +160,40 @@ static std::string GetConfigFilePath(const std::string &dump_file_path) {
return std::string(config_file_path); return std::string(config_file_path);
} }
static void UpdateFlags(const ConfigSection &section) {
for (auto &&p : section) {
auto &&key = p.first;
bool value_bool = p.second;
if (key == "allow_adding_removing_weak_symbols") {
allow_adding_removing_weak_symbols = value_bool;
} else if (key == "advice_only") {
advice_only = value_bool;
} else if (key == "elf_unreferenced_symbol_errors") {
elf_unreferenced_symbol_errors = value_bool;
} else if (key == "check_all_apis") {
check_all_apis = value_bool;
} else if (key == "allow_extensions") {
allow_extensions = value_bool;
} else if (key == "allow_unreferenced_elf_symbol_changes") {
allow_unreferenced_elf_symbol_changes = value_bool;
} else if (key == "allow_unreferenced_changes") {
allow_unreferenced_changes = value_bool;
} else if (key == "consider_opaque_types_different") {
consider_opaque_types_different = value_bool;
}
}
}
static void ReadConfigFile(const std::string &config_file_path) { static void ReadConfigFile(const std::string &config_file_path) {
ConfigFile cfg; ConfigFile cfg;
if (!cfg.Load(config_file_path)) { if (!cfg.Load(config_file_path)) {
::exit(1); ::exit(1);
} }
if (cfg.HasSection("global")) { if (cfg.HasGlobalSection()) {
for (auto &&p : cfg.GetSection("global")) { UpdateFlags(cfg.GetGlobalSection());
auto &&key = p.first; }
bool value_bool = p.second; if (cfg.HasSection(lib_name, target_version)) {
if (key == "allow_adding_removing_weak_symbols") { UpdateFlags(cfg.GetSection(lib_name, target_version));
allow_adding_removing_weak_symbols = value_bool;
} else if (key == "advice_only") {
advice_only = value_bool;
} else if (key == "elf_unreferenced_symbol_errors") {
elf_unreferenced_symbol_errors = value_bool;
} else if (key == "check_all_apis") {
check_all_apis = value_bool;
} else if (key == "allow_extensions") {
allow_extensions = value_bool;
} else if (key == "allow_unreferenced_elf_symbol_changes") {
allow_unreferenced_elf_symbol_changes = value_bool;
} else if (key == "allow_unreferenced_changes") {
allow_unreferenced_changes = value_bool;
} else if (key == "consider_opaque_types_different") {
consider_opaque_types_different = value_bool;
}
}
} }
} }

View File

@@ -18,13 +18,35 @@
#include <llvm/Support/raw_ostream.h> #include <llvm/Support/raw_ostream.h>
#include <fstream> #include <fstream>
#include <map>
#include <string> #include <string>
static const std::string GLOBAL_SECTION_NAME = "global";
namespace header_checker { namespace header_checker {
namespace utils { namespace utils {
static std::map<std::string, bool> LoadFlags(const Json::Value &section) {
std::map<std::string, bool> map;
if (section.isMember("flags")) {
for (auto &flag_keys : section["flags"].getMemberNames()) {
map[flag_keys] = section["flags"][flag_keys].asBool();
}
}
return map;
}
bool ConfigFile::HasGlobalSection() {
return HasSection(GLOBAL_SECTION_NAME, "");
}
const ConfigSection &ConfigFile::GetGlobalSection() {
return GetSection(GLOBAL_SECTION_NAME, "");
}
bool ConfigFile::Load(std::istream &istream) { bool ConfigFile::Load(std::istream &istream) {
Json::Value root; Json::Value root;
Json::CharReaderBuilder builder; Json::CharReaderBuilder builder;
@@ -34,11 +56,15 @@ bool ConfigFile::Load(std::istream &istream) {
return false; return false;
} }
for (auto &key : root.getMemberNames()) { for (auto &key : root.getMemberNames()) {
map_[key] = ConfigSection(); if (key == GLOBAL_SECTION_NAME) {
if (root[key].isMember("flags")) { ConfigSection &config_section = map_[{GLOBAL_SECTION_NAME, ""}];
for (auto &flag_keys : root[key]["flags"].getMemberNames()) { config_section.map_ = LoadFlags(root[GLOBAL_SECTION_NAME]);
map_[key].map_[flag_keys] = root[key]["flags"][flag_keys].asBool(); continue;
} }
for (auto &section : root[key]) {
ConfigSection &config_section =
map_[{key, section["target_version"].asString()}];
config_section.map_ = LoadFlags(section);
} }
} }
return true; return true;
@@ -46,9 +72,11 @@ bool ConfigFile::Load(std::istream &istream) {
bool ConfigFile::Load(const std::string &path) { bool ConfigFile::Load(const std::string &path) {
std::ifstream stream(path); std::ifstream stream(path);
return Load(stream); if (stream.is_open()) {
return Load(stream);
}
return false;
} }
} // namespace utils } // namespace utils
} // namespace header_checker } // namespace header_checker

View File

@@ -48,18 +48,11 @@ class ConfigSection {
return it->second; return it->second;
} }
bool operator[](const std::string &name) const { bool operator[](const std::string &name) const { return GetProperty(name); }
return GetProperty(name);
}
const_iterator begin() const { const_iterator begin() const { return map_.begin(); }
return map_.begin();
}
const_iterator end() const {
return map_.end();
}
const_iterator end() const { return map_.end(); }
private: private:
ConfigSection(const ConfigSection &) = delete; ConfigSection(const ConfigSection &) = delete;
@@ -75,7 +68,7 @@ class ConfigSection {
class ConfigFile { class ConfigFile {
public: public:
using MapType = std::map<std::string, ConfigSection>; using MapType = std::map<std::pair<std::string, std::string>, ConfigSection>;
using const_iterator = MapType::const_iterator; using const_iterator = MapType::const_iterator;
@@ -87,46 +80,43 @@ class ConfigFile {
bool Load(const std::string &path); bool Load(const std::string &path);
bool Load(std::istream &istream); bool Load(std::istream &istream);
bool HasSection(const std::string &section_name) const { bool HasSection(const std::string &section_name,
return map_.find(section_name) != map_.end(); const std::string &version) const {
return map_.find({section_name, version}) != map_.end();
} }
const ConfigSection &GetSection(const std::string &section_name) const { const ConfigSection &GetSection(const std::string &section_name,
auto &&it = map_.find(section_name); const std::string &version) const {
auto &&it = map_.find({section_name, version});
assert(it != map_.end()); assert(it != map_.end());
return it->second; return it->second;
} }
const ConfigSection &operator[](const std::string &section_name) const { bool HasGlobalSection();
return GetSection(section_name);
}
bool HasProperty(const std::string &section_name, const ConfigSection &GetGlobalSection();
bool HasProperty(const std::string &section_name, const std::string &version,
const std::string &property_name) const { const std::string &property_name) const {
auto &&it = map_.find(section_name); auto &&it = map_.find({section_name, version});
if (it == map_.end()) { if (it == map_.end()) {
return false; return false;
} }
return it->second.HasProperty(property_name); return it->second.HasProperty(property_name);
} }
bool GetProperty(const std::string &section_name, bool GetProperty(const std::string &section_name, const std::string &version,
const std::string &property_name) const { const std::string &property_name) const {
auto &&it = map_.find(section_name); auto &&it = map_.find({section_name, version});
if (it == map_.end()) { if (it == map_.end()) {
return false; return false;
} }
return it->second.GetProperty(property_name); return it->second.GetProperty(property_name);
} }
const_iterator begin() const { const_iterator begin() const { return map_.begin(); }
return map_.begin();
}
const_iterator end() const {
return map_.end();
}
const_iterator end() const { return map_.end(); }
private: private:
ConfigFile(const ConfigFile &) = delete; ConfigFile(const ConfigFile &) = delete;

View File

@@ -28,28 +28,39 @@ TEST(ConfigFileTest, Parse) {
// Comment line starts with slash // Comment line starts with slash
/* embedded comment */ /* embedded comment */
{ {
"section1": { "global": {
"flags": { "flags": {
"key1": true, "key1": true,
"key2": false, "key2": false,
}, },
}, },
"section2": { "library1": [
"flags": { {
"key1": true, "target_version": "current",
"key2": false, "flags": {
"key1": true,
"key2": false,
},
}, },
}, {
"target_version": "34",
"flags": {
"key1": false,
"key2": true,
},
},
],
} }
)"); )");
ConfigFile cfg; ConfigFile cfg;
cfg.Load(stream); cfg.Load(stream);
EXPECT_TRUE(cfg.HasSection("section1")); EXPECT_TRUE(cfg.HasSection("global", ""));
EXPECT_TRUE(cfg.HasSection("section2")); EXPECT_TRUE(cfg.HasSection("library1", "current"));
EXPECT_FALSE(cfg.HasSection("section3")); EXPECT_FALSE(cfg.HasSection("library1", "35"));
EXPECT_FALSE(cfg.HasSection("library2", "current"));
auto &&section1 = cfg.GetSection("section1"); auto &&section1 = cfg.GetSection("global", "");
EXPECT_TRUE(section1.HasProperty("key1")); EXPECT_TRUE(section1.HasProperty("key1"));
EXPECT_TRUE(section1.GetProperty("key1")); EXPECT_TRUE(section1.GetProperty("key1"));
EXPECT_TRUE(section1.HasProperty("key2")); EXPECT_TRUE(section1.HasProperty("key2"));
@@ -58,17 +69,17 @@ TEST(ConfigFileTest, Parse) {
EXPECT_FALSE(section1.HasProperty("key3")); EXPECT_FALSE(section1.HasProperty("key3"));
EXPECT_FALSE(section1.GetProperty("key3")); EXPECT_FALSE(section1.GetProperty("key3"));
auto &&section2 = cfg.GetSection("section2"); auto &&section2 = cfg.GetSection("library1", "current");
EXPECT_TRUE(section2.HasProperty("key1")); EXPECT_TRUE(section2.HasProperty("key1"));
EXPECT_TRUE(section2.GetProperty("key1")); EXPECT_TRUE(section2.GetProperty("key1"));
EXPECT_TRUE(section2.HasProperty("key2")); EXPECT_TRUE(section2.HasProperty("key2"));
EXPECT_FALSE(section2.GetProperty("key2")); EXPECT_FALSE(section2.GetProperty("key2"));
EXPECT_TRUE(cfg.GetProperty("section1", "key1")); EXPECT_TRUE(cfg.GetProperty("global", "", "key1"));
EXPECT_FALSE(cfg.GetProperty("section1", "key2")); EXPECT_TRUE(cfg.GetProperty("library1", "34", "key2"));
EXPECT_TRUE(cfg["section1"]["key1"]); EXPECT_TRUE(section1["key1"]);
EXPECT_FALSE(cfg["section1"]["key2"]); EXPECT_FALSE(section2["key2"]);
} }
TEST(ConfigFileTest, BadJsonFormat) { TEST(ConfigFileTest, BadJsonFormat) {