• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use anyhow::{anyhow, Result};
2 use std::env;
3 use std::fs;
4 use std::fs::File;
5 use std::io::Write;
6 use std::path::{Path, PathBuf};
7 
8 use convert_finalized_flags::read_files_to_map_using_path;
9 use convert_finalized_flags::FinalizedFlagMap;
10 
11 // This fn makes assumptions about the working directory which we should not rely
12 // on for actual (Soong) builds. It is reasonable to assume that this is being
13 // called from the aconfig directory as cargo is used for local development and
14 // the cargo workspace for our project is build/make/tools/aconfig.
15 // This is meant to get the list of finalized flag
16 // files provided by the filegroup + "locations" in soong.
17 // Cargo-only usage is asserted via implementation of
18 // read_files_to_map_using_env, the only public cargo-only fn.
read_files_to_map_using_env() -> Result<FinalizedFlagMap>19 fn read_files_to_map_using_env() -> Result<FinalizedFlagMap> {
20     let mut current_dir = std::env::current_dir()?;
21 
22     // Path of aconfig from the top of tree.
23     let aconfig_path = PathBuf::from("build/make/tools/aconfig");
24 
25     // Path of SDK files from the top of tree.
26     let sdk_dir_path = PathBuf::from("prebuilts/sdk");
27 
28     // Iterate up the directory structure until we have the base aconfig dir.
29     while !current_dir.canonicalize()?.ends_with(&aconfig_path) {
30         if let Some(parent) = current_dir.parent() {
31             current_dir = parent.to_path_buf();
32         } else {
33             return Err(anyhow!("Cannot execute outside of aconfig."));
34         }
35     }
36 
37     // Remove the aconfig path, leaving the top of the tree.
38     for _ in 0..aconfig_path.components().count() {
39         current_dir.pop();
40     }
41 
42     // Get the absolute path of the sdk files.
43     current_dir.push(sdk_dir_path);
44 
45     let mut flag_files = Vec::new();
46 
47     // Search all sub-dirs in prebuilts/sdk for finalized-flags.txt files.
48     // The files are in prebuilts/sdk/<api level>/finalized-flags.txt.
49     let api_level_dirs = fs::read_dir(current_dir)?;
50     for api_level_dir in api_level_dirs {
51         if api_level_dir.is_err() {
52             eprintln!("Error opening directory: {}", api_level_dir.err().unwrap());
53             continue;
54         }
55 
56         // Skip non-directories.
57         let api_level_dir_path = api_level_dir.unwrap().path();
58         if !api_level_dir_path.is_dir() {
59             continue;
60         }
61 
62         // Some directories were created before trunk stable and don't have
63         // flags, or aren't api level directories at all.
64         let flag_file_path = api_level_dir_path.join("finalized-flags.txt");
65         if !flag_file_path.exists() {
66             continue;
67         }
68 
69         if let Some(path) = flag_file_path.to_str() {
70             flag_files.push(path.to_string());
71         } else {
72             eprintln!("Error converting path to string: {:?}", flag_file_path);
73         }
74     }
75 
76     read_files_to_map_using_path(flag_files)
77 }
78 
main()79 fn main() {
80     let out_dir = env::var_os("OUT_DIR").unwrap();
81     let dest_path = Path::new(&out_dir).join("finalized_flags_record.json");
82 
83     let finalized_flags_map: Result<FinalizedFlagMap> = read_files_to_map_using_env();
84     if finalized_flags_map.is_err() {
85         return;
86     }
87     let json_str = serde_json::to_string(&finalized_flags_map.unwrap()).unwrap();
88 
89     let mut f = File::create(&dest_path).unwrap();
90     f.write_all(json_str.as_bytes()).unwrap();
91 
92     //println!("cargo:rerun-if-changed=input.txt");
93 }
94