Make aconfig c++ generate only one header and only one .cc file

Bug: 283479529
Test: m aconfig_hello_world_cc && adb push $TOP/out/target/product/panther/system/bin/aconfig_hello_world_cc /system/bin && adb shell aconfig_hello_world_cc
Change-Id: I1890aff70262343e18a62fb2efb2fd0e13a48fb2
This commit is contained in:
Joe Onorato
2023-07-18 17:29:14 -07:00
parent 7859cc45f7
commit ac692c5eae
9 changed files with 305 additions and 344 deletions

View File

@@ -57,26 +57,6 @@ where
template: include_str!("../templates/cpp_source_file.template"), template: include_str!("../templates/cpp_source_file.template"),
dir: "", dir: "",
}, },
FileSpec {
name: &format!("{}_flag_provider.h", header),
template: match codegen_mode {
CodegenMode::Production => {
include_str!("../templates/cpp_prod_flag_provider.template")
}
CodegenMode::Test => include_str!("../templates/cpp_test_flag_provider.template"),
},
dir: "",
},
FileSpec {
name: &format!("{}_c.h", header),
template: include_str!("../templates/c_exported_header.template"),
dir: "include",
},
FileSpec {
name: &format!("{}_c.cc", header),
template: include_str!("../templates/c_source_file.template"),
dir: "",
},
]; ];
files.iter().map(|file| generate_file(file, &context)).collect() files.iter().map(|file| generate_file(file, &context)).collect()
} }
@@ -138,12 +118,13 @@ mod tests {
const EXPORTED_PROD_HEADER_EXPECTED: &str = r#" const EXPORTED_PROD_HEADER_EXPECTED: &str = r#"
#pragma once #pragma once
#ifdef __cplusplus
#include <memory> #include <memory>
namespace com::android::aconfig::test { namespace com::android::aconfig::test {
class flag_provider_interface { class flag_provider_interface {
public: public:
virtual ~flag_provider_interface() = default; virtual ~flag_provider_interface() = default;
virtual bool disabled_ro() = 0; virtual bool disabled_ro() = 0;
@@ -174,14 +155,32 @@ inline bool enabled_rw() {
} }
} }
extern "C" {
#endif // __cplusplus
bool com_android_aconfig_test_disabled_ro();
bool com_android_aconfig_test_disabled_rw();
bool com_android_aconfig_test_enabled_ro();
bool com_android_aconfig_test_enabled_rw();
#ifdef __cplusplus
} // extern "C"
#endif
"#; "#;
const EXPORTED_TEST_HEADER_EXPECTED: &str = r#" const EXPORTED_TEST_HEADER_EXPECTED: &str = r#"
#pragma once #pragma once
#ifdef __cplusplus
#include <memory> #include <memory>
namespace com::android::aconfig::test { namespace com::android::aconfig::test {
class flag_provider_interface { class flag_provider_interface {
public: public:
@@ -245,17 +244,44 @@ inline void reset_flags() {
} }
} }
extern "C" {
#endif // __cplusplus
bool com_android_aconfig_test_disabled_ro();
void set_com_android_aconfig_test_disabled_ro(bool val);
bool com_android_aconfig_test_disabled_rw();
void set_com_android_aconfig_test_disabled_rw(bool val);
bool com_android_aconfig_test_enabled_ro();
void set_com_android_aconfig_test_enabled_ro(bool val);
bool com_android_aconfig_test_enabled_rw();
void set_com_android_aconfig_test_enabled_rw(bool val);
void com_android_aconfig_test_reset_flags();
#ifdef __cplusplus
} // extern "C"
#endif
"#; "#;
const PROD_FLAG_PROVIDER_HEADER_EXPECTED: &str = r#" const PROD_SOURCE_FILE_EXPECTED: &str = r#"
#pragma once
#include "com_android_aconfig_test.h" #include "com_android_aconfig_test.h"
#include <server_configurable_flags/get_flags.h> #include <server_configurable_flags/get_flags.h>
namespace com::android::aconfig::test { namespace com::android::aconfig::test {
class flag_provider : public flag_provider_interface {
public: class flag_provider : public flag_provider_interface {
public:
virtual bool disabled_ro() override { virtual bool disabled_ro() override {
return false; return false;
@@ -278,26 +304,42 @@ public:
"com.android.aconfig.test.enabled_rw", "com.android.aconfig.test.enabled_rw",
"true") == "true"; "true") == "true";
} }
};
};
std::unique_ptr<flag_provider_interface> provider_ =
std::make_unique<flag_provider>();
} }
bool com_android_aconfig_test_disabled_ro() {
return false;
}
bool com_android_aconfig_test_disabled_rw() {
return com::android::aconfig::test::disabled_rw();
}
bool com_android_aconfig_test_enabled_ro() {
return true;
}
bool com_android_aconfig_test_enabled_rw() {
return com::android::aconfig::test::enabled_rw();
}
"#; "#;
const TEST_FLAG_PROVIDER_HEADER_EXPECTED: &str = r#" const TEST_SOURCE_FILE_EXPECTED: &str = r#"
#pragma once
#include "com_android_aconfig_test.h" #include "com_android_aconfig_test.h"
#include <server_configurable_flags/get_flags.h> #include <server_configurable_flags/get_flags.h>
#include <unordered_map>
#include <string>
namespace com::android::aconfig::test { namespace com::android::aconfig::test {
class flag_provider : public flag_provider_interface {
private: class flag_provider : public flag_provider_interface {
private:
std::unordered_map<std::string, bool> overrides_; std::unordered_map<std::string, bool> overrides_;
public: public:
flag_provider() flag_provider()
: overrides_() : overrides_()
{} {}
@@ -360,102 +402,21 @@ public:
overrides_["enabled_rw"] = val; overrides_["enabled_rw"] = val;
} }
virtual void reset_flags() override { virtual void reset_flags() override {
overrides_.clear(); overrides_.clear();
} }
}; };
}
"#;
const SOURCE_FILE_EXPECTED: &str = r#"
#include "com_android_aconfig_test.h"
#include "com_android_aconfig_test_flag_provider.h"
namespace com::android::aconfig::test {
std::unique_ptr<flag_provider_interface> provider_ = std::unique_ptr<flag_provider_interface> provider_ =
std::make_unique<flag_provider>(); std::make_unique<flag_provider>();
} }
"#;
const C_EXPORTED_PROD_HEADER_EXPECTED: &str = r#"
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
bool com_android_aconfig_test_disabled_ro();
bool com_android_aconfig_test_disabled_rw();
bool com_android_aconfig_test_enabled_ro();
bool com_android_aconfig_test_enabled_rw();
#ifdef __cplusplus
}
#endif
"#;
const C_EXPORTED_TEST_HEADER_EXPECTED: &str = r#"
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
bool com_android_aconfig_test_disabled_ro();
void set_com_android_aconfig_test_disabled_ro(bool val);
bool com_android_aconfig_test_disabled_rw();
void set_com_android_aconfig_test_disabled_rw(bool val);
bool com_android_aconfig_test_enabled_ro();
void set_com_android_aconfig_test_enabled_ro(bool val);
bool com_android_aconfig_test_enabled_rw();
void set_com_android_aconfig_test_enabled_rw(bool val);
void com_android_aconfig_test_reset_flags();
#ifdef __cplusplus
}
#endif
"#;
const C_PROD_SOURCE_FILE_EXPECTED: &str = r#"
#include "com_android_aconfig_test_c.h"
#include "com_android_aconfig_test.h"
bool com_android_aconfig_test_disabled_ro() {
return false;
}
bool com_android_aconfig_test_disabled_rw() {
return com::android::aconfig::test::disabled_rw();
}
bool com_android_aconfig_test_enabled_ro() {
return true;
}
bool com_android_aconfig_test_enabled_rw() {
return com::android::aconfig::test::enabled_rw();
}
"#;
const C_TEST_SOURCE_FILE_EXPECTED: &str = r#"
#include "com_android_aconfig_test_c.h"
#include "com_android_aconfig_test.h"
bool com_android_aconfig_test_disabled_ro() { bool com_android_aconfig_test_disabled_ro() {
return com::android::aconfig::test::disabled_ro(); return com::android::aconfig::test::disabled_ro();
} }
void set_com_android_aconfig_test_disabled_ro(bool val) { void set_com_android_aconfig_test_disabled_ro(bool val) {
com::android::aconfig::test::disabled_ro(val); com::android::aconfig::test::disabled_ro(val);
} }
@@ -464,6 +425,7 @@ bool com_android_aconfig_test_disabled_rw() {
return com::android::aconfig::test::disabled_rw(); return com::android::aconfig::test::disabled_rw();
} }
void set_com_android_aconfig_test_disabled_rw(bool val) { void set_com_android_aconfig_test_disabled_rw(bool val) {
com::android::aconfig::test::disabled_rw(val); com::android::aconfig::test::disabled_rw(val);
} }
@@ -472,6 +434,7 @@ bool com_android_aconfig_test_enabled_ro() {
return com::android::aconfig::test::enabled_ro(); return com::android::aconfig::test::enabled_ro();
} }
void set_com_android_aconfig_test_enabled_ro(bool val) { void set_com_android_aconfig_test_enabled_ro(bool val) {
com::android::aconfig::test::enabled_ro(val); com::android::aconfig::test::enabled_ro(val);
} }
@@ -480,6 +443,7 @@ bool com_android_aconfig_test_enabled_rw() {
return com::android::aconfig::test::enabled_rw(); return com::android::aconfig::test::enabled_rw();
} }
void set_com_android_aconfig_test_enabled_rw(bool val) { void set_com_android_aconfig_test_enabled_rw(bool val) {
com::android::aconfig::test::enabled_rw(val); com::android::aconfig::test::enabled_rw(val);
} }
@@ -487,7 +451,9 @@ void set_com_android_aconfig_test_enabled_rw(bool val) {
void com_android_aconfig_test_reset_flags() { void com_android_aconfig_test_reset_flags() {
com::android::aconfig::test::reset_flags(); com::android::aconfig::test::reset_flags();
} }
"#; "#;
fn test_generate_cpp_code(mode: CodegenMode) { fn test_generate_cpp_code(mode: CodegenMode) {
let parsed_flags = crate::test::parse_test_flags(); let parsed_flags = crate::test::parse_test_flags();
let generated = let generated =
@@ -514,50 +480,14 @@ void com_android_aconfig_test_reset_flags() {
) )
); );
target_file_path = String::from("com_android_aconfig_test_flag_provider.h");
assert!(generated_files_map.contains_key(&target_file_path));
assert_eq!(
None,
crate::test::first_significant_code_diff(
match mode {
CodegenMode::Production => PROD_FLAG_PROVIDER_HEADER_EXPECTED,
CodegenMode::Test => TEST_FLAG_PROVIDER_HEADER_EXPECTED,
},
generated_files_map.get(&target_file_path).unwrap()
)
);
target_file_path = String::from("com_android_aconfig_test.cc"); target_file_path = String::from("com_android_aconfig_test.cc");
assert!(generated_files_map.contains_key(&target_file_path)); assert!(generated_files_map.contains_key(&target_file_path));
assert_eq!(
None,
crate::test::first_significant_code_diff(
SOURCE_FILE_EXPECTED,
generated_files_map.get(&target_file_path).unwrap()
)
);
target_file_path = String::from("include/com_android_aconfig_test_c.h");
assert!(generated_files_map.contains_key(&target_file_path));
assert_eq!( assert_eq!(
None, None,
crate::test::first_significant_code_diff( crate::test::first_significant_code_diff(
match mode { match mode {
CodegenMode::Production => C_EXPORTED_PROD_HEADER_EXPECTED, CodegenMode::Production => PROD_SOURCE_FILE_EXPECTED,
CodegenMode::Test => C_EXPORTED_TEST_HEADER_EXPECTED, CodegenMode::Test => TEST_SOURCE_FILE_EXPECTED,
},
generated_files_map.get(&target_file_path).unwrap()
)
);
target_file_path = String::from("com_android_aconfig_test_c.cc");
assert!(generated_files_map.contains_key(&target_file_path));
assert_eq!(
None,
crate::test::first_significant_code_diff(
match mode {
CodegenMode::Production => C_PROD_SOURCE_FILE_EXPECTED,
CodegenMode::Test => C_TEST_SOURCE_FILE_EXPECTED,
}, },
generated_files_map.get(&target_file_path).unwrap() generated_files_map.get(&target_file_path).unwrap()
) )

View File

@@ -1,21 +0,0 @@
#pragma once
#ifdef __cplusplus
extern "C" \{
#endif
{{ for item in class_elements }}
bool {header}_{item.flag_name}();
{{ if for_test }}
void set_{header}_{item.flag_name}(bool val);
{{ -endif }}
{{ endfor - }}
{{ if for_test }}
void {header}_reset_flags();
{{ -endif }}
#ifdef __cplusplus
}
#endif

View File

@@ -1,28 +0,0 @@
#include "{header}_c.h"
#include "{header}.h"
{{ for item in class_elements}}
bool {header}_{item.flag_name}() \{
{{ if for_test }}
return {cpp_namespace}::{item.flag_name}();
{{ -else- }}
{{ if not item.readwrite- }}
return {item.default_value};
{{ -else- }}
return {cpp_namespace}::{item.flag_name}();
{{ -endif }}
{{ -endif }}
}
{{ if for_test }}
void set_{header}_{item.flag_name}(bool val) \{
{cpp_namespace}::{item.flag_name}(val);
}
{{ -endif }}
{{ endfor -}}
{{ if for_test }}
void {header}_reset_flags() \{
{cpp_namespace}::reset_flags();
}
{{ -endif }}

View File

@@ -1,5 +1,7 @@
#pragma once #pragma once
#ifdef __cplusplus
#include <memory> #include <memory>
namespace {cpp_namespace} \{ namespace {cpp_namespace} \{
@@ -47,4 +49,25 @@ inline void reset_flags() \{
return provider_->reset_flags(); return provider_->reset_flags();
} }
{{ -endif }} {{ -endif }}
} }
extern "C" \{
#endif // __cplusplus
{{ for item in class_elements }}
bool {header}_{item.flag_name}();
{{ if for_test }}
void set_{header}_{item.flag_name}(bool val);
{{ -endif }}
{{ endfor - }}
{{ if for_test }}
void {header}_reset_flags();
{{ -endif }}
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,24 +0,0 @@
#pragma once
#include "{header}.h"
{{ if readwrite }}
#include <server_configurable_flags/get_flags.h>
{{ endif }}
namespace {cpp_namespace} \{
class flag_provider : public flag_provider_interface \{
public:
{{ for item in class_elements}}
virtual bool {item.flag_name}() override \{
{{ if item.readwrite- }}
return server_configurable_flags::GetServerConfigurableFlag(
"{item.device_config_namespace}",
"{item.device_config_flag}",
"{item.default_value}") == "true";
{{ -else- }}
return {item.default_value};
{{ -endif }}
}
{{ endfor }}
};
}

View File

@@ -1,8 +1,98 @@
#include "{header}.h" #include "{header}.h"
#include "{header}_flag_provider.h" {{ if readwrite }}
#include <server_configurable_flags/get_flags.h>
{{ endif }}
namespace {cpp_namespace} \{ namespace {cpp_namespace} \{
{{ if for_test }}
class flag_provider : public flag_provider_interface \{
private:
std::unordered_map<std::string, bool> overrides_;
public:
flag_provider()
: overrides_()
\{}
{{ for item in class_elements}}
virtual bool {item.flag_name}() override \{
auto it = overrides_.find("{item.flag_name}");
if (it != overrides_.end()) \{
return it->second;
} else \{
{{ if item.readwrite- }}
return server_configurable_flags::GetServerConfigurableFlag(
"{item.device_config_namespace}",
"{item.device_config_flag}",
"{item.default_value}") == "true";
{{ -else- }}
return {item.default_value};
{{ -endif }}
}
}
virtual void {item.flag_name}(bool val) override \{
overrides_["{item.flag_name}"] = val;
}
{{ endfor }}
virtual void reset_flags() override \{
overrides_.clear();
}
};
{{ -else- }}
class flag_provider : public flag_provider_interface \{
public:
{{ for item in class_elements}}
virtual bool {item.flag_name}() override \{
{{ if item.readwrite- }}
return server_configurable_flags::GetServerConfigurableFlag(
"{item.device_config_namespace}",
"{item.device_config_flag}",
"{item.default_value}") == "true";
{{ -else- }}
return {item.default_value};
{{ -endif }}
}
{{ endfor }}
};
{{ -endif }}
std::unique_ptr<flag_provider_interface> provider_ = std::unique_ptr<flag_provider_interface> provider_ =
std::make_unique<flag_provider>(); std::make_unique<flag_provider>();
} }
{{ for item in class_elements}}
bool {header}_{item.flag_name}() \{
{{ if for_test }}
return {cpp_namespace}::{item.flag_name}();
{{ -else- }}
{{ if not item.readwrite- }}
return {item.default_value};
{{ -else- }}
return {cpp_namespace}::{item.flag_name}();
{{ -endif }}
{{ -endif }}
}
{{ if for_test }}
void set_{header}_{item.flag_name}(bool val) \{
{cpp_namespace}::{item.flag_name}(val);
}
{{ -endif }}
{{ endfor -}}
{{ if for_test }}
void {header}_reset_flags() \{
{cpp_namespace}::reset_flags();
}
{{ -endif }}

View File

@@ -1,48 +0,0 @@
#pragma once
#include "{header}.h"
{{ if readwrite }}
#include <server_configurable_flags/get_flags.h>
{{ endif }}
#include <unordered_map>
#include <string>
namespace {cpp_namespace} \{
class flag_provider : public flag_provider_interface \{
private:
std::unordered_map<std::string, bool> overrides_;
public:
flag_provider()
: overrides_()
\{}
{{ for item in class_elements}}
virtual bool {item.flag_name}() override \{
auto it = overrides_.find("{item.flag_name}");
if (it != overrides_.end()) \{
return it->second;
} else \{
{{ if item.readwrite- }}
return server_configurable_flags::GetServerConfigurableFlag(
"{item.device_config_namespace}",
"{item.device_config_flag}",
"{item.default_value}") == "true";
{{ -else- }}
return {item.default_value};
{{ -endif }}
}
}
virtual void {item.flag_name}(bool val) override \{
overrides_["{item.flag_name}"] = val;
}
{{ endfor }}
virtual void reset_flags() override \{
overrides_.clear();
}
};
}

View File

@@ -0,0 +1,17 @@
cc_aconfig_library {
name: "aconfig_test_cc_library",
aconfig_declarations: "aconfig.test.flags",
}
cc_binary {
name: "aconfig_hello_world_cc",
srcs: [
"aconfig_hello_world.cpp",
],
static_libs: [
"aconfig_test_cc_library",
],
shared_libs: [
"server_configurable_flags",
],
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "com_android_aconfig_test.h"
int main() {
printf("hello flag %d\n", com_android_aconfig_test_disabled_rw());
}