xref: /aosp_15_r20/build/make/tools/aconfig/aconfig/src/main.rs (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1*9e94795aSAndroid Build Coastguard Worker /*
2*9e94795aSAndroid Build Coastguard Worker  * Copyright (C) 2023 The Android Open Source Project
3*9e94795aSAndroid Build Coastguard Worker  *
4*9e94795aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*9e94795aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*9e94795aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*9e94795aSAndroid Build Coastguard Worker  *
8*9e94795aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*9e94795aSAndroid Build Coastguard Worker  *
10*9e94795aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*9e94795aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*9e94795aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9e94795aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*9e94795aSAndroid Build Coastguard Worker  * limitations under the License.
15*9e94795aSAndroid Build Coastguard Worker  */
16*9e94795aSAndroid Build Coastguard Worker 
17*9e94795aSAndroid Build Coastguard Worker //! `aconfig` is a build time tool to manage build time configurations, such as feature flags.
18*9e94795aSAndroid Build Coastguard Worker 
19*9e94795aSAndroid Build Coastguard Worker use aconfig_storage_file::DEFAULT_FILE_VERSION;
20*9e94795aSAndroid Build Coastguard Worker use aconfig_storage_file::MAX_SUPPORTED_FILE_VERSION;
21*9e94795aSAndroid Build Coastguard Worker use anyhow::{anyhow, bail, Context, Result};
22*9e94795aSAndroid Build Coastguard Worker use clap::{builder::ArgAction, builder::EnumValueParser, Arg, ArgMatches, Command};
23*9e94795aSAndroid Build Coastguard Worker use core::any::Any;
24*9e94795aSAndroid Build Coastguard Worker use std::fs;
25*9e94795aSAndroid Build Coastguard Worker use std::io;
26*9e94795aSAndroid Build Coastguard Worker use std::io::Write;
27*9e94795aSAndroid Build Coastguard Worker use std::path::{Path, PathBuf};
28*9e94795aSAndroid Build Coastguard Worker 
29*9e94795aSAndroid Build Coastguard Worker mod codegen;
30*9e94795aSAndroid Build Coastguard Worker mod commands;
31*9e94795aSAndroid Build Coastguard Worker mod dump;
32*9e94795aSAndroid Build Coastguard Worker mod storage;
33*9e94795aSAndroid Build Coastguard Worker 
34*9e94795aSAndroid Build Coastguard Worker use aconfig_storage_file::StorageFileType;
35*9e94795aSAndroid Build Coastguard Worker use codegen::CodegenMode;
36*9e94795aSAndroid Build Coastguard Worker use dump::DumpFormat;
37*9e94795aSAndroid Build Coastguard Worker 
38*9e94795aSAndroid Build Coastguard Worker #[cfg(test)]
39*9e94795aSAndroid Build Coastguard Worker mod test;
40*9e94795aSAndroid Build Coastguard Worker 
41*9e94795aSAndroid Build Coastguard Worker use commands::{Input, OutputFile};
42*9e94795aSAndroid Build Coastguard Worker 
43*9e94795aSAndroid Build Coastguard Worker const HELP_DUMP_FILTER: &str = r#"
44*9e94795aSAndroid Build Coastguard Worker Limit which flags to output. If multiple --filter arguments are provided, the output will be
45*9e94795aSAndroid Build Coastguard Worker limited to flags that match any of the filters.
46*9e94795aSAndroid Build Coastguard Worker "#;
47*9e94795aSAndroid Build Coastguard Worker 
cli() -> Command48*9e94795aSAndroid Build Coastguard Worker fn cli() -> Command {
49*9e94795aSAndroid Build Coastguard Worker     Command::new("aconfig")
50*9e94795aSAndroid Build Coastguard Worker         .subcommand_required(true)
51*9e94795aSAndroid Build Coastguard Worker         .subcommand(
52*9e94795aSAndroid Build Coastguard Worker             Command::new("create-cache")
53*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("package").long("package").required(true))
54*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("container").long("container").required(true))
55*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("declarations").long("declarations").action(ArgAction::Append))
56*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("values").long("values").action(ArgAction::Append))
57*9e94795aSAndroid Build Coastguard Worker                 .arg(
58*9e94795aSAndroid Build Coastguard Worker                     Arg::new("default-permission")
59*9e94795aSAndroid Build Coastguard Worker                         .long("default-permission")
60*9e94795aSAndroid Build Coastguard Worker                         .value_parser(aconfig_protos::flag_permission::parse_from_str)
61*9e94795aSAndroid Build Coastguard Worker                         .default_value(aconfig_protos::flag_permission::to_string(
62*9e94795aSAndroid Build Coastguard Worker                             &commands::DEFAULT_FLAG_PERMISSION,
63*9e94795aSAndroid Build Coastguard Worker                         )),
64*9e94795aSAndroid Build Coastguard Worker                 )
65*9e94795aSAndroid Build Coastguard Worker                 .arg(
66*9e94795aSAndroid Build Coastguard Worker                     Arg::new("allow-read-write")
67*9e94795aSAndroid Build Coastguard Worker                         .long("allow-read-write")
68*9e94795aSAndroid Build Coastguard Worker                         .value_parser(clap::value_parser!(bool))
69*9e94795aSAndroid Build Coastguard Worker                         .default_value("true"),
70*9e94795aSAndroid Build Coastguard Worker                 )
71*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("cache").long("cache").required(true)),
72*9e94795aSAndroid Build Coastguard Worker         )
73*9e94795aSAndroid Build Coastguard Worker         .subcommand(
74*9e94795aSAndroid Build Coastguard Worker             Command::new("create-java-lib")
75*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("cache").long("cache").required(true))
76*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("out").long("out").required(true))
77*9e94795aSAndroid Build Coastguard Worker                 .arg(
78*9e94795aSAndroid Build Coastguard Worker                     Arg::new("mode")
79*9e94795aSAndroid Build Coastguard Worker                         .long("mode")
80*9e94795aSAndroid Build Coastguard Worker                         .value_parser(EnumValueParser::<CodegenMode>::new())
81*9e94795aSAndroid Build Coastguard Worker                         .default_value("production"),
82*9e94795aSAndroid Build Coastguard Worker                 )
83*9e94795aSAndroid Build Coastguard Worker                 .arg(
84*9e94795aSAndroid Build Coastguard Worker                     Arg::new("allow-instrumentation")
85*9e94795aSAndroid Build Coastguard Worker                         .long("allow-instrumentation")
86*9e94795aSAndroid Build Coastguard Worker                         .value_parser(clap::value_parser!(bool))
87*9e94795aSAndroid Build Coastguard Worker                         .default_value("false"),
88*9e94795aSAndroid Build Coastguard Worker                 ),
89*9e94795aSAndroid Build Coastguard Worker         )
90*9e94795aSAndroid Build Coastguard Worker         .subcommand(
91*9e94795aSAndroid Build Coastguard Worker             Command::new("create-cpp-lib")
92*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("cache").long("cache").required(true))
93*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("out").long("out").required(true))
94*9e94795aSAndroid Build Coastguard Worker                 .arg(
95*9e94795aSAndroid Build Coastguard Worker                     Arg::new("mode")
96*9e94795aSAndroid Build Coastguard Worker                         .long("mode")
97*9e94795aSAndroid Build Coastguard Worker                         .value_parser(EnumValueParser::<CodegenMode>::new())
98*9e94795aSAndroid Build Coastguard Worker                         .default_value("production"),
99*9e94795aSAndroid Build Coastguard Worker                 )
100*9e94795aSAndroid Build Coastguard Worker                 .arg(
101*9e94795aSAndroid Build Coastguard Worker                     Arg::new("allow-instrumentation")
102*9e94795aSAndroid Build Coastguard Worker                         .long("allow-instrumentation")
103*9e94795aSAndroid Build Coastguard Worker                         .value_parser(clap::value_parser!(bool))
104*9e94795aSAndroid Build Coastguard Worker                         .default_value("false"),
105*9e94795aSAndroid Build Coastguard Worker                 ),
106*9e94795aSAndroid Build Coastguard Worker         )
107*9e94795aSAndroid Build Coastguard Worker         .subcommand(
108*9e94795aSAndroid Build Coastguard Worker             Command::new("create-rust-lib")
109*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("cache").long("cache").required(true))
110*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("out").long("out").required(true))
111*9e94795aSAndroid Build Coastguard Worker                 .arg(
112*9e94795aSAndroid Build Coastguard Worker                     Arg::new("allow-instrumentation")
113*9e94795aSAndroid Build Coastguard Worker                         .long("allow-instrumentation")
114*9e94795aSAndroid Build Coastguard Worker                         .value_parser(clap::value_parser!(bool))
115*9e94795aSAndroid Build Coastguard Worker                         .default_value("false"),
116*9e94795aSAndroid Build Coastguard Worker                 )
117*9e94795aSAndroid Build Coastguard Worker                 .arg(
118*9e94795aSAndroid Build Coastguard Worker                     Arg::new("mode")
119*9e94795aSAndroid Build Coastguard Worker                         .long("mode")
120*9e94795aSAndroid Build Coastguard Worker                         .value_parser(EnumValueParser::<CodegenMode>::new())
121*9e94795aSAndroid Build Coastguard Worker                         .default_value("production"),
122*9e94795aSAndroid Build Coastguard Worker                 ),
123*9e94795aSAndroid Build Coastguard Worker         )
124*9e94795aSAndroid Build Coastguard Worker         .subcommand(
125*9e94795aSAndroid Build Coastguard Worker             Command::new("create-device-config-defaults")
126*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("cache").long("cache").action(ArgAction::Append).required(true))
127*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("out").long("out").default_value("-")),
128*9e94795aSAndroid Build Coastguard Worker         )
129*9e94795aSAndroid Build Coastguard Worker         .subcommand(
130*9e94795aSAndroid Build Coastguard Worker             Command::new("create-device-config-sysprops")
131*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("cache").long("cache").action(ArgAction::Append).required(true))
132*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("out").long("out").default_value("-")),
133*9e94795aSAndroid Build Coastguard Worker         )
134*9e94795aSAndroid Build Coastguard Worker         .subcommand(
135*9e94795aSAndroid Build Coastguard Worker             Command::new("dump-cache")
136*9e94795aSAndroid Build Coastguard Worker                 .alias("dump")
137*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("cache").long("cache").action(ArgAction::Append))
138*9e94795aSAndroid Build Coastguard Worker                 .arg(
139*9e94795aSAndroid Build Coastguard Worker                     Arg::new("format")
140*9e94795aSAndroid Build Coastguard Worker                         .long("format")
141*9e94795aSAndroid Build Coastguard Worker                         .value_parser(|s: &str| DumpFormat::try_from(s))
142*9e94795aSAndroid Build Coastguard Worker                         .default_value(
143*9e94795aSAndroid Build Coastguard Worker                             "{fully_qualified_name} [{container}]: {permission} + {state}",
144*9e94795aSAndroid Build Coastguard Worker                         ),
145*9e94795aSAndroid Build Coastguard Worker                 )
146*9e94795aSAndroid Build Coastguard Worker                 .arg(
147*9e94795aSAndroid Build Coastguard Worker                     Arg::new("filter")
148*9e94795aSAndroid Build Coastguard Worker                         .long("filter")
149*9e94795aSAndroid Build Coastguard Worker                         .action(ArgAction::Append)
150*9e94795aSAndroid Build Coastguard Worker                         .help(HELP_DUMP_FILTER.trim()),
151*9e94795aSAndroid Build Coastguard Worker                 )
152*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("dedup").long("dedup").num_args(0).action(ArgAction::SetTrue))
153*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("out").long("out").default_value("-")),
154*9e94795aSAndroid Build Coastguard Worker         )
155*9e94795aSAndroid Build Coastguard Worker         .subcommand(
156*9e94795aSAndroid Build Coastguard Worker             Command::new("create-storage")
157*9e94795aSAndroid Build Coastguard Worker                 .arg(
158*9e94795aSAndroid Build Coastguard Worker                     Arg::new("container")
159*9e94795aSAndroid Build Coastguard Worker                         .long("container")
160*9e94795aSAndroid Build Coastguard Worker                         .required(true)
161*9e94795aSAndroid Build Coastguard Worker                         .help("The target container for the generated storage file."),
162*9e94795aSAndroid Build Coastguard Worker                 )
163*9e94795aSAndroid Build Coastguard Worker                 .arg(
164*9e94795aSAndroid Build Coastguard Worker                     Arg::new("file")
165*9e94795aSAndroid Build Coastguard Worker                         .long("file")
166*9e94795aSAndroid Build Coastguard Worker                         .value_parser(|s: &str| StorageFileType::try_from(s)),
167*9e94795aSAndroid Build Coastguard Worker                 )
168*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("cache").long("cache").action(ArgAction::Append).required(true))
169*9e94795aSAndroid Build Coastguard Worker                 .arg(Arg::new("out").long("out").required(true))
170*9e94795aSAndroid Build Coastguard Worker                 .arg(
171*9e94795aSAndroid Build Coastguard Worker                     Arg::new("version")
172*9e94795aSAndroid Build Coastguard Worker                         .long("version")
173*9e94795aSAndroid Build Coastguard Worker                         .required(false)
174*9e94795aSAndroid Build Coastguard Worker                         .value_parser(|s: &str| s.parse::<u32>()),
175*9e94795aSAndroid Build Coastguard Worker                 ),
176*9e94795aSAndroid Build Coastguard Worker         )
177*9e94795aSAndroid Build Coastguard Worker }
178*9e94795aSAndroid Build Coastguard Worker 
get_required_arg<'a, T>(matches: &'a ArgMatches, arg_name: &str) -> Result<&'a T> where T: Any + Clone + Send + Sync + 'static,179*9e94795aSAndroid Build Coastguard Worker fn get_required_arg<'a, T>(matches: &'a ArgMatches, arg_name: &str) -> Result<&'a T>
180*9e94795aSAndroid Build Coastguard Worker where
181*9e94795aSAndroid Build Coastguard Worker     T: Any + Clone + Send + Sync + 'static,
182*9e94795aSAndroid Build Coastguard Worker {
183*9e94795aSAndroid Build Coastguard Worker     matches
184*9e94795aSAndroid Build Coastguard Worker         .get_one::<T>(arg_name)
185*9e94795aSAndroid Build Coastguard Worker         .ok_or(anyhow!("internal error: required argument '{}' not found", arg_name))
186*9e94795aSAndroid Build Coastguard Worker }
187*9e94795aSAndroid Build Coastguard Worker 
get_optional_arg<'a, T>(matches: &'a ArgMatches, arg_name: &str) -> Option<&'a T> where T: Any + Clone + Send + Sync + 'static,188*9e94795aSAndroid Build Coastguard Worker fn get_optional_arg<'a, T>(matches: &'a ArgMatches, arg_name: &str) -> Option<&'a T>
189*9e94795aSAndroid Build Coastguard Worker where
190*9e94795aSAndroid Build Coastguard Worker     T: Any + Clone + Send + Sync + 'static,
191*9e94795aSAndroid Build Coastguard Worker {
192*9e94795aSAndroid Build Coastguard Worker     matches.get_one::<T>(arg_name)
193*9e94795aSAndroid Build Coastguard Worker }
194*9e94795aSAndroid Build Coastguard Worker 
open_zero_or_more_files(matches: &ArgMatches, arg_name: &str) -> Result<Vec<Input>>195*9e94795aSAndroid Build Coastguard Worker fn open_zero_or_more_files(matches: &ArgMatches, arg_name: &str) -> Result<Vec<Input>> {
196*9e94795aSAndroid Build Coastguard Worker     let mut opened_files = vec![];
197*9e94795aSAndroid Build Coastguard Worker     for path in matches.get_many::<String>(arg_name).unwrap_or_default() {
198*9e94795aSAndroid Build Coastguard Worker         let file = Box::new(fs::File::open(path)?);
199*9e94795aSAndroid Build Coastguard Worker         opened_files.push(Input { source: path.to_string(), reader: file });
200*9e94795aSAndroid Build Coastguard Worker     }
201*9e94795aSAndroid Build Coastguard Worker     Ok(opened_files)
202*9e94795aSAndroid Build Coastguard Worker }
203*9e94795aSAndroid Build Coastguard Worker 
open_single_file(matches: &ArgMatches, arg_name: &str) -> Result<Input>204*9e94795aSAndroid Build Coastguard Worker fn open_single_file(matches: &ArgMatches, arg_name: &str) -> Result<Input> {
205*9e94795aSAndroid Build Coastguard Worker     let Some(path) = matches.get_one::<String>(arg_name) else {
206*9e94795aSAndroid Build Coastguard Worker         bail!("missing argument {}", arg_name);
207*9e94795aSAndroid Build Coastguard Worker     };
208*9e94795aSAndroid Build Coastguard Worker     let file = Box::new(fs::File::open(path)?);
209*9e94795aSAndroid Build Coastguard Worker     Ok(Input { source: path.to_string(), reader: file })
210*9e94795aSAndroid Build Coastguard Worker }
211*9e94795aSAndroid Build Coastguard Worker 
write_output_file_realtive_to_dir(root: &Path, output_file: &OutputFile) -> Result<()>212*9e94795aSAndroid Build Coastguard Worker fn write_output_file_realtive_to_dir(root: &Path, output_file: &OutputFile) -> Result<()> {
213*9e94795aSAndroid Build Coastguard Worker     let path = root.join(&output_file.path);
214*9e94795aSAndroid Build Coastguard Worker     let parent = path
215*9e94795aSAndroid Build Coastguard Worker         .parent()
216*9e94795aSAndroid Build Coastguard Worker         .ok_or(anyhow!("unable to locate parent of output file {}", path.display()))?;
217*9e94795aSAndroid Build Coastguard Worker     fs::create_dir_all(parent)
218*9e94795aSAndroid Build Coastguard Worker         .with_context(|| format!("failed to create directory {}", parent.display()))?;
219*9e94795aSAndroid Build Coastguard Worker     let mut file =
220*9e94795aSAndroid Build Coastguard Worker         fs::File::create(&path).with_context(|| format!("failed to open {}", path.display()))?;
221*9e94795aSAndroid Build Coastguard Worker     file.write_all(&output_file.contents)
222*9e94795aSAndroid Build Coastguard Worker         .with_context(|| format!("failed to write to {}", path.display()))?;
223*9e94795aSAndroid Build Coastguard Worker     Ok(())
224*9e94795aSAndroid Build Coastguard Worker }
225*9e94795aSAndroid Build Coastguard Worker 
write_output_to_file_or_stdout(path: &str, data: &[u8]) -> Result<()>226*9e94795aSAndroid Build Coastguard Worker fn write_output_to_file_or_stdout(path: &str, data: &[u8]) -> Result<()> {
227*9e94795aSAndroid Build Coastguard Worker     if path == "-" {
228*9e94795aSAndroid Build Coastguard Worker         io::stdout().write_all(data).context("failed to write to stdout")?;
229*9e94795aSAndroid Build Coastguard Worker     } else {
230*9e94795aSAndroid Build Coastguard Worker         fs::File::create(path)
231*9e94795aSAndroid Build Coastguard Worker             .with_context(|| format!("failed to open {}", path))?
232*9e94795aSAndroid Build Coastguard Worker             .write_all(data)
233*9e94795aSAndroid Build Coastguard Worker             .with_context(|| format!("failed to write to {}", path))?;
234*9e94795aSAndroid Build Coastguard Worker     }
235*9e94795aSAndroid Build Coastguard Worker     Ok(())
236*9e94795aSAndroid Build Coastguard Worker }
237*9e94795aSAndroid Build Coastguard Worker 
main() -> Result<()>238*9e94795aSAndroid Build Coastguard Worker fn main() -> Result<()> {
239*9e94795aSAndroid Build Coastguard Worker     let matches = cli().get_matches();
240*9e94795aSAndroid Build Coastguard Worker     match matches.subcommand() {
241*9e94795aSAndroid Build Coastguard Worker         Some(("create-cache", sub_matches)) => {
242*9e94795aSAndroid Build Coastguard Worker             let package = get_required_arg::<String>(sub_matches, "package")?;
243*9e94795aSAndroid Build Coastguard Worker             let container =
244*9e94795aSAndroid Build Coastguard Worker                 get_optional_arg::<String>(sub_matches, "container").map(|c| c.as_str());
245*9e94795aSAndroid Build Coastguard Worker             let declarations = open_zero_or_more_files(sub_matches, "declarations")?;
246*9e94795aSAndroid Build Coastguard Worker             let values = open_zero_or_more_files(sub_matches, "values")?;
247*9e94795aSAndroid Build Coastguard Worker             let default_permission = get_required_arg::<aconfig_protos::ProtoFlagPermission>(
248*9e94795aSAndroid Build Coastguard Worker                 sub_matches,
249*9e94795aSAndroid Build Coastguard Worker                 "default-permission",
250*9e94795aSAndroid Build Coastguard Worker             )?;
251*9e94795aSAndroid Build Coastguard Worker             let allow_read_write = get_optional_arg::<bool>(sub_matches, "allow-read-write")
252*9e94795aSAndroid Build Coastguard Worker                 .expect("failed to parse allow-read-write");
253*9e94795aSAndroid Build Coastguard Worker             let output = commands::parse_flags(
254*9e94795aSAndroid Build Coastguard Worker                 package,
255*9e94795aSAndroid Build Coastguard Worker                 container,
256*9e94795aSAndroid Build Coastguard Worker                 declarations,
257*9e94795aSAndroid Build Coastguard Worker                 values,
258*9e94795aSAndroid Build Coastguard Worker                 *default_permission,
259*9e94795aSAndroid Build Coastguard Worker                 *allow_read_write,
260*9e94795aSAndroid Build Coastguard Worker             )
261*9e94795aSAndroid Build Coastguard Worker             .context("failed to create cache")?;
262*9e94795aSAndroid Build Coastguard Worker             let path = get_required_arg::<String>(sub_matches, "cache")?;
263*9e94795aSAndroid Build Coastguard Worker             write_output_to_file_or_stdout(path, &output)?;
264*9e94795aSAndroid Build Coastguard Worker         }
265*9e94795aSAndroid Build Coastguard Worker         Some(("create-java-lib", sub_matches)) => {
266*9e94795aSAndroid Build Coastguard Worker             let cache = open_single_file(sub_matches, "cache")?;
267*9e94795aSAndroid Build Coastguard Worker             let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
268*9e94795aSAndroid Build Coastguard Worker             let allow_instrumentation =
269*9e94795aSAndroid Build Coastguard Worker                 get_required_arg::<bool>(sub_matches, "allow-instrumentation")?;
270*9e94795aSAndroid Build Coastguard Worker             let generated_files = commands::create_java_lib(cache, *mode, *allow_instrumentation)
271*9e94795aSAndroid Build Coastguard Worker                 .context("failed to create java lib")?;
272*9e94795aSAndroid Build Coastguard Worker             let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
273*9e94795aSAndroid Build Coastguard Worker             generated_files
274*9e94795aSAndroid Build Coastguard Worker                 .iter()
275*9e94795aSAndroid Build Coastguard Worker                 .try_for_each(|file| write_output_file_realtive_to_dir(&dir, file))?;
276*9e94795aSAndroid Build Coastguard Worker         }
277*9e94795aSAndroid Build Coastguard Worker         Some(("create-cpp-lib", sub_matches)) => {
278*9e94795aSAndroid Build Coastguard Worker             let cache = open_single_file(sub_matches, "cache")?;
279*9e94795aSAndroid Build Coastguard Worker             let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
280*9e94795aSAndroid Build Coastguard Worker             let allow_instrumentation =
281*9e94795aSAndroid Build Coastguard Worker                 get_required_arg::<bool>(sub_matches, "allow-instrumentation")?;
282*9e94795aSAndroid Build Coastguard Worker             let generated_files = commands::create_cpp_lib(cache, *mode, *allow_instrumentation)
283*9e94795aSAndroid Build Coastguard Worker                 .context("failed to create cpp lib")?;
284*9e94795aSAndroid Build Coastguard Worker             let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
285*9e94795aSAndroid Build Coastguard Worker             generated_files
286*9e94795aSAndroid Build Coastguard Worker                 .iter()
287*9e94795aSAndroid Build Coastguard Worker                 .try_for_each(|file| write_output_file_realtive_to_dir(&dir, file))?;
288*9e94795aSAndroid Build Coastguard Worker         }
289*9e94795aSAndroid Build Coastguard Worker         Some(("create-rust-lib", sub_matches)) => {
290*9e94795aSAndroid Build Coastguard Worker             let cache = open_single_file(sub_matches, "cache")?;
291*9e94795aSAndroid Build Coastguard Worker             let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
292*9e94795aSAndroid Build Coastguard Worker             let allow_instrumentation =
293*9e94795aSAndroid Build Coastguard Worker                 get_required_arg::<bool>(sub_matches, "allow-instrumentation")?;
294*9e94795aSAndroid Build Coastguard Worker             let generated_file = commands::create_rust_lib(cache, *mode, *allow_instrumentation)
295*9e94795aSAndroid Build Coastguard Worker                 .context("failed to create rust lib")?;
296*9e94795aSAndroid Build Coastguard Worker             let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
297*9e94795aSAndroid Build Coastguard Worker             write_output_file_realtive_to_dir(&dir, &generated_file)?;
298*9e94795aSAndroid Build Coastguard Worker         }
299*9e94795aSAndroid Build Coastguard Worker         Some(("create-device-config-defaults", sub_matches)) => {
300*9e94795aSAndroid Build Coastguard Worker             let cache = open_single_file(sub_matches, "cache")?;
301*9e94795aSAndroid Build Coastguard Worker             let output = commands::create_device_config_defaults(cache)
302*9e94795aSAndroid Build Coastguard Worker                 .context("failed to create device config defaults")?;
303*9e94795aSAndroid Build Coastguard Worker             let path = get_required_arg::<String>(sub_matches, "out")?;
304*9e94795aSAndroid Build Coastguard Worker             write_output_to_file_or_stdout(path, &output)?;
305*9e94795aSAndroid Build Coastguard Worker         }
306*9e94795aSAndroid Build Coastguard Worker         Some(("create-device-config-sysprops", sub_matches)) => {
307*9e94795aSAndroid Build Coastguard Worker             let cache = open_single_file(sub_matches, "cache")?;
308*9e94795aSAndroid Build Coastguard Worker             let output = commands::create_device_config_sysprops(cache)
309*9e94795aSAndroid Build Coastguard Worker                 .context("failed to create device config sysprops")?;
310*9e94795aSAndroid Build Coastguard Worker             let path = get_required_arg::<String>(sub_matches, "out")?;
311*9e94795aSAndroid Build Coastguard Worker             write_output_to_file_or_stdout(path, &output)?;
312*9e94795aSAndroid Build Coastguard Worker         }
313*9e94795aSAndroid Build Coastguard Worker         Some(("dump-cache", sub_matches)) => {
314*9e94795aSAndroid Build Coastguard Worker             let input = open_zero_or_more_files(sub_matches, "cache")?;
315*9e94795aSAndroid Build Coastguard Worker             let format = get_required_arg::<DumpFormat>(sub_matches, "format")
316*9e94795aSAndroid Build Coastguard Worker                 .context("failed to dump previously parsed flags")?;
317*9e94795aSAndroid Build Coastguard Worker             let filters = sub_matches
318*9e94795aSAndroid Build Coastguard Worker                 .get_many::<String>("filter")
319*9e94795aSAndroid Build Coastguard Worker                 .unwrap_or_default()
320*9e94795aSAndroid Build Coastguard Worker                 .map(String::as_ref)
321*9e94795aSAndroid Build Coastguard Worker                 .collect::<Vec<_>>();
322*9e94795aSAndroid Build Coastguard Worker             let dedup = get_required_arg::<bool>(sub_matches, "dedup")?;
323*9e94795aSAndroid Build Coastguard Worker             let output = commands::dump_parsed_flags(input, format.clone(), &filters, *dedup)?;
324*9e94795aSAndroid Build Coastguard Worker             let path = get_required_arg::<String>(sub_matches, "out")?;
325*9e94795aSAndroid Build Coastguard Worker             write_output_to_file_or_stdout(path, &output)?;
326*9e94795aSAndroid Build Coastguard Worker         }
327*9e94795aSAndroid Build Coastguard Worker         Some(("create-storage", sub_matches)) => {
328*9e94795aSAndroid Build Coastguard Worker             let version =
329*9e94795aSAndroid Build Coastguard Worker                 get_optional_arg::<u32>(sub_matches, "version").unwrap_or(&DEFAULT_FILE_VERSION);
330*9e94795aSAndroid Build Coastguard Worker             if *version > MAX_SUPPORTED_FILE_VERSION {
331*9e94795aSAndroid Build Coastguard Worker                 bail!("Invalid version selected ({})", version);
332*9e94795aSAndroid Build Coastguard Worker             }
333*9e94795aSAndroid Build Coastguard Worker             let file = get_required_arg::<StorageFileType>(sub_matches, "file")
334*9e94795aSAndroid Build Coastguard Worker                 .context("Invalid storage file selection")?;
335*9e94795aSAndroid Build Coastguard Worker             let cache = open_zero_or_more_files(sub_matches, "cache")?;
336*9e94795aSAndroid Build Coastguard Worker             let container = get_required_arg::<String>(sub_matches, "container")?;
337*9e94795aSAndroid Build Coastguard Worker             let path = get_required_arg::<String>(sub_matches, "out")?;
338*9e94795aSAndroid Build Coastguard Worker 
339*9e94795aSAndroid Build Coastguard Worker             let output = commands::create_storage(cache, container, file, *version)
340*9e94795aSAndroid Build Coastguard Worker                 .context("failed to create storage files")?;
341*9e94795aSAndroid Build Coastguard Worker             write_output_to_file_or_stdout(path, &output)?;
342*9e94795aSAndroid Build Coastguard Worker         }
343*9e94795aSAndroid Build Coastguard Worker         _ => unreachable!(),
344*9e94795aSAndroid Build Coastguard Worker     }
345*9e94795aSAndroid Build Coastguard Worker     Ok(())
346*9e94795aSAndroid Build Coastguard Worker }
347