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:
@@ -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 §ion) {
|
||||||
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 §ion) {
|
||||||
|
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 §ion : 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
|
||||||
|
|||||||
@@ -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 §ion_name) const {
|
bool HasSection(const std::string §ion_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 §ion_name) const {
|
const ConfigSection &GetSection(const std::string §ion_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 §ion_name) const {
|
bool HasGlobalSection();
|
||||||
return GetSection(section_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasProperty(const std::string §ion_name,
|
const ConfigSection &GetGlobalSection();
|
||||||
|
|
||||||
|
bool HasProperty(const std::string §ion_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 §ion_name,
|
bool GetProperty(const std::string §ion_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;
|
||||||
|
|||||||
@@ -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 &§ion1 = cfg.GetSection("section1");
|
auto &§ion1 = 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 &§ion2 = cfg.GetSection("section2");
|
auto &§ion2 = 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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user