aconfig: use proto struct directly
Remove the hand-crafted wrappers around the structures auto-generated
from protos/aconfig.proto, and use the auto-generated structs directly
intead. This gets rid of a lot of manual repetition, and its inherent
risk.
Also unify how individual fields read from text proto are verified (e.g.
is the flag.name field a valid identifier).
Also change the intermediate cache format from JSON to binary protobuf.
The concept of a 'cache' as an intermediate internal format to represent
parsed input stays. The command line interface still refers to caches.
At the moment a cache file is identical to a parsed_file protbuf, and
the code exploits this internally.
A couple of points regarding the auto-generated structs:
- Vectors are named in the singular (e.g. parsed_flags.parsed_flag is
a Vec<ProtoParsedFlag>) because this improves ergonomics for all
devs working with aconfig input files
- The auto-generated structs have fields that are of type Option<T>
and convenience methods (named the same as the fields) to access T
Test: atest aconfig.test aconfig.test.java
Bug: 283910447
Change-Id: I512820cc4bc6c543dea9f6a4356f863120a10be3
diff --git a/tools/aconfig/src/main.rs b/tools/aconfig/src/main.rs
index 3a9a573..e6a325d 100644
--- a/tools/aconfig/src/main.rs
+++ b/tools/aconfig/src/main.rs
@@ -16,7 +16,7 @@
//! `aconfig` is a build time tool to manage build time configurations, such as feature flags.
-use anyhow::{anyhow, ensure, Result};
+use anyhow::{anyhow, bail, ensure, Result};
use clap::{builder::ArgAction, builder::EnumValueParser, Arg, ArgMatches, Command};
use core::any::Any;
use std::fs;
@@ -24,8 +24,6 @@
use std::io::Write;
use std::path::{Path, PathBuf};
-mod aconfig;
-mod cache;
mod codegen;
mod codegen_cpp;
mod codegen_java;
@@ -36,8 +34,7 @@
#[cfg(test)]
mod test;
-use crate::cache::Cache;
-use commands::{DumpFormat, Input, OutputFile, Source};
+use commands::{DumpFormat, Input, OutputFile};
fn cli() -> Command {
Command::new("aconfig")
@@ -100,11 +97,19 @@
let mut opened_files = vec![];
for path in matches.get_many::<String>(arg_name).unwrap_or_default() {
let file = Box::new(fs::File::open(path)?);
- opened_files.push(Input { source: Source::File(path.to_string()), reader: file });
+ opened_files.push(Input { source: path.to_string(), reader: file });
}
Ok(opened_files)
}
+fn open_single_file(matches: &ArgMatches, arg_name: &str) -> Result<Input> {
+ let Some(path) = matches.get_one::<String>(arg_name) else {
+ bail!("missing argument {}", arg_name);
+ };
+ let file = Box::new(fs::File::open(path)?);
+ Ok(Input { source: path.to_string(), reader: file })
+}
+
fn write_output_file_realtive_to_dir(root: &Path, output_file: &OutputFile) -> Result<()> {
ensure!(
root.is_dir(),
@@ -137,68 +142,46 @@
let package = get_required_arg::<String>(sub_matches, "package")?;
let declarations = open_zero_or_more_files(sub_matches, "declarations")?;
let values = open_zero_or_more_files(sub_matches, "values")?;
- let cache = commands::create_cache(package, declarations, values)?;
+ let output = commands::parse_flags(package, declarations, values)?;
let path = get_required_arg::<String>(sub_matches, "cache")?;
- let file = fs::File::create(path)?;
- cache.write_to_writer(file)?;
+ write_output_to_file_or_stdout(path, &output)?;
}
Some(("create-java-lib", sub_matches)) => {
- let path = get_required_arg::<String>(sub_matches, "cache")?;
- let file = fs::File::open(path)?;
- let cache = Cache::read_from_reader(file)?;
- let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
+ let cache = open_single_file(sub_matches, "cache")?;
let generated_files = commands::create_java_lib(cache)?;
+ let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
generated_files
.iter()
.try_for_each(|file| write_output_file_realtive_to_dir(&dir, file))?;
}
Some(("create-cpp-lib", sub_matches)) => {
- let path = get_required_arg::<String>(sub_matches, "cache")?;
- let file = fs::File::open(path)?;
- let cache = Cache::read_from_reader(file)?;
- let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
+ let cache = open_single_file(sub_matches, "cache")?;
let generated_file = commands::create_cpp_lib(cache)?;
+ let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
write_output_file_realtive_to_dir(&dir, &generated_file)?;
}
Some(("create-rust-lib", sub_matches)) => {
- let path = get_required_arg::<String>(sub_matches, "cache")?;
- let file = fs::File::open(path)?;
- let cache = Cache::read_from_reader(file)?;
- let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
+ let cache = open_single_file(sub_matches, "cache")?;
let generated_file = commands::create_rust_lib(cache)?;
+ let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
write_output_file_realtive_to_dir(&dir, &generated_file)?;
}
Some(("create-device-config-defaults", sub_matches)) => {
- let mut caches = Vec::new();
- for path in sub_matches.get_many::<String>("cache").unwrap_or_default() {
- let file = fs::File::open(path)?;
- let cache = Cache::read_from_reader(file)?;
- caches.push(cache);
- }
- let output = commands::create_device_config_defaults(caches)?;
+ let cache = open_single_file(sub_matches, "cache")?;
+ let output = commands::create_device_config_defaults(cache)?;
let path = get_required_arg::<String>(sub_matches, "out")?;
write_output_to_file_or_stdout(path, &output)?;
}
Some(("create-device-config-sysprops", sub_matches)) => {
- let mut caches = Vec::new();
- for path in sub_matches.get_many::<String>("cache").unwrap_or_default() {
- let file = fs::File::open(path)?;
- let cache = Cache::read_from_reader(file)?;
- caches.push(cache);
- }
- let output = commands::create_device_config_sysprops(caches)?;
+ let cache = open_single_file(sub_matches, "cache")?;
+ let output = commands::create_device_config_sysprops(cache)?;
let path = get_required_arg::<String>(sub_matches, "out")?;
write_output_to_file_or_stdout(path, &output)?;
}
Some(("dump", sub_matches)) => {
- let mut caches = Vec::new();
- for path in sub_matches.get_many::<String>("cache").unwrap_or_default() {
- let file = fs::File::open(path)?;
- let cache = Cache::read_from_reader(file)?;
- caches.push(cache);
- }
+ let input = open_zero_or_more_files(sub_matches, "cache")?;
let format = get_required_arg::<DumpFormat>(sub_matches, "format")?;
- let output = commands::dump_cache(caches, *format)?;
+ let output = commands::dump_parsed_flags(input, *format)?;
let path = get_required_arg::<String>(sub_matches, "out")?;
write_output_to_file_or_stdout(path, &output)?;
}