xref: /aosp_15_r20/development/tools/cargo_embargo/src/bp.rs (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1*90c8c64dSAndroid Build Coastguard Worker // Copyright (C) 2022 The Android Open Source Project
2*90c8c64dSAndroid Build Coastguard Worker //
3*90c8c64dSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*90c8c64dSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*90c8c64dSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*90c8c64dSAndroid Build Coastguard Worker //
7*90c8c64dSAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
8*90c8c64dSAndroid Build Coastguard Worker //
9*90c8c64dSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*90c8c64dSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*90c8c64dSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*90c8c64dSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*90c8c64dSAndroid Build Coastguard Worker // limitations under the License.
14*90c8c64dSAndroid Build Coastguard Worker 
15*90c8c64dSAndroid Build Coastguard Worker use anyhow::Result;
16*90c8c64dSAndroid Build Coastguard Worker use std::collections::BTreeMap;
17*90c8c64dSAndroid Build Coastguard Worker use std::path::PathBuf;
18*90c8c64dSAndroid Build Coastguard Worker 
19*90c8c64dSAndroid Build Coastguard Worker /// Build module.
20*90c8c64dSAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
21*90c8c64dSAndroid Build Coastguard Worker pub struct BpModule {
22*90c8c64dSAndroid Build Coastguard Worker     pub module_type: String,
23*90c8c64dSAndroid Build Coastguard Worker     pub props: BpProperties,
24*90c8c64dSAndroid Build Coastguard Worker }
25*90c8c64dSAndroid Build Coastguard Worker 
26*90c8c64dSAndroid Build Coastguard Worker /// Properties of a build module, or of a nested object value.
27*90c8c64dSAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
28*90c8c64dSAndroid Build Coastguard Worker pub struct BpProperties {
29*90c8c64dSAndroid Build Coastguard Worker     pub map: BTreeMap<String, BpValue>,
30*90c8c64dSAndroid Build Coastguard Worker     /// A raw block of text to append after the last key-value pair, but before the closing brace.
31*90c8c64dSAndroid Build Coastguard Worker     /// For example, if you have the properties
32*90c8c64dSAndroid Build Coastguard Worker     ///
33*90c8c64dSAndroid Build Coastguard Worker     ///     {
34*90c8c64dSAndroid Build Coastguard Worker     ///         name: "foo",
35*90c8c64dSAndroid Build Coastguard Worker     ///         srcs: ["main.rs"],
36*90c8c64dSAndroid Build Coastguard Worker     ///     }
37*90c8c64dSAndroid Build Coastguard Worker     ///
38*90c8c64dSAndroid Build Coastguard Worker     /// and add `raw_block = "some random text"`, you'll get
39*90c8c64dSAndroid Build Coastguard Worker     ///
40*90c8c64dSAndroid Build Coastguard Worker     ///     {
41*90c8c64dSAndroid Build Coastguard Worker     ///         name: "foo",
42*90c8c64dSAndroid Build Coastguard Worker     ///         srcs: ["main.rs"],
43*90c8c64dSAndroid Build Coastguard Worker     ///         some random text
44*90c8c64dSAndroid Build Coastguard Worker     ///     }
45*90c8c64dSAndroid Build Coastguard Worker     pub raw_block: Option<String>,
46*90c8c64dSAndroid Build Coastguard Worker }
47*90c8c64dSAndroid Build Coastguard Worker 
48*90c8c64dSAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
49*90c8c64dSAndroid Build Coastguard Worker pub enum BpValue {
50*90c8c64dSAndroid Build Coastguard Worker     Object(BpProperties),
51*90c8c64dSAndroid Build Coastguard Worker     Bool(bool),
52*90c8c64dSAndroid Build Coastguard Worker     String(String),
53*90c8c64dSAndroid Build Coastguard Worker     List(Vec<BpValue>),
54*90c8c64dSAndroid Build Coastguard Worker }
55*90c8c64dSAndroid Build Coastguard Worker 
56*90c8c64dSAndroid Build Coastguard Worker impl BpModule {
new(module_type: String) -> BpModule57*90c8c64dSAndroid Build Coastguard Worker     pub fn new(module_type: String) -> BpModule {
58*90c8c64dSAndroid Build Coastguard Worker         BpModule { module_type, props: BpProperties::new() }
59*90c8c64dSAndroid Build Coastguard Worker     }
60*90c8c64dSAndroid Build Coastguard Worker 
61*90c8c64dSAndroid Build Coastguard Worker     /// Serialize to Android.bp format.
write(&self, w: &mut impl std::fmt::Write) -> Result<()>62*90c8c64dSAndroid Build Coastguard Worker     pub fn write(&self, w: &mut impl std::fmt::Write) -> Result<()> {
63*90c8c64dSAndroid Build Coastguard Worker         w.write_str(&self.module_type)?;
64*90c8c64dSAndroid Build Coastguard Worker         w.write_str(" ")?;
65*90c8c64dSAndroid Build Coastguard Worker         self.props.write(w)?;
66*90c8c64dSAndroid Build Coastguard Worker         w.write_str("\n")?;
67*90c8c64dSAndroid Build Coastguard Worker         Ok(())
68*90c8c64dSAndroid Build Coastguard Worker     }
69*90c8c64dSAndroid Build Coastguard Worker }
70*90c8c64dSAndroid Build Coastguard Worker 
71*90c8c64dSAndroid Build Coastguard Worker impl BpProperties {
new() -> Self72*90c8c64dSAndroid Build Coastguard Worker     pub fn new() -> Self {
73*90c8c64dSAndroid Build Coastguard Worker         BpProperties { map: BTreeMap::new(), raw_block: None }
74*90c8c64dSAndroid Build Coastguard Worker     }
75*90c8c64dSAndroid Build Coastguard Worker 
get_string(&self, k: &str) -> Option<&str>76*90c8c64dSAndroid Build Coastguard Worker     pub fn get_string(&self, k: &str) -> Option<&str> {
77*90c8c64dSAndroid Build Coastguard Worker         match self.map.get(k)? {
78*90c8c64dSAndroid Build Coastguard Worker             BpValue::String(s) => Some(s),
79*90c8c64dSAndroid Build Coastguard Worker             _ => None,
80*90c8c64dSAndroid Build Coastguard Worker         }
81*90c8c64dSAndroid Build Coastguard Worker     }
82*90c8c64dSAndroid Build Coastguard Worker 
set<T: Into<BpValue>>(&mut self, k: &str, v: T)83*90c8c64dSAndroid Build Coastguard Worker     pub fn set<T: Into<BpValue>>(&mut self, k: &str, v: T) {
84*90c8c64dSAndroid Build Coastguard Worker         self.map.insert(k.to_string(), v.into());
85*90c8c64dSAndroid Build Coastguard Worker     }
86*90c8c64dSAndroid Build Coastguard Worker 
set_if_nonempty<T: Into<BpValue>>(&mut self, k: &str, v: Vec<T>)87*90c8c64dSAndroid Build Coastguard Worker     pub fn set_if_nonempty<T: Into<BpValue>>(&mut self, k: &str, v: Vec<T>) {
88*90c8c64dSAndroid Build Coastguard Worker         if !v.is_empty() {
89*90c8c64dSAndroid Build Coastguard Worker             self.set(k, v);
90*90c8c64dSAndroid Build Coastguard Worker         }
91*90c8c64dSAndroid Build Coastguard Worker     }
92*90c8c64dSAndroid Build Coastguard Worker 
object(&mut self, k: &str) -> &mut BpProperties93*90c8c64dSAndroid Build Coastguard Worker     pub fn object(&mut self, k: &str) -> &mut BpProperties {
94*90c8c64dSAndroid Build Coastguard Worker         let v =
95*90c8c64dSAndroid Build Coastguard Worker             self.map.entry(k.to_string()).or_insert_with(|| BpValue::Object(BpProperties::new()));
96*90c8c64dSAndroid Build Coastguard Worker         match v {
97*90c8c64dSAndroid Build Coastguard Worker             BpValue::Object(v) => v,
98*90c8c64dSAndroid Build Coastguard Worker             _ => panic!("key {k:?} already has non-object value"),
99*90c8c64dSAndroid Build Coastguard Worker         }
100*90c8c64dSAndroid Build Coastguard Worker     }
101*90c8c64dSAndroid Build Coastguard Worker 
102*90c8c64dSAndroid Build Coastguard Worker     /// Serialize to Android.bp format.
write(&self, w: &mut impl std::fmt::Write) -> Result<()>103*90c8c64dSAndroid Build Coastguard Worker     pub fn write(&self, w: &mut impl std::fmt::Write) -> Result<()> {
104*90c8c64dSAndroid Build Coastguard Worker         w.write_str("{\n")?;
105*90c8c64dSAndroid Build Coastguard Worker         // Sort stuff to match what cargo2android.py's output order.
106*90c8c64dSAndroid Build Coastguard Worker         let canonical_order = &[
107*90c8c64dSAndroid Build Coastguard Worker             "name",
108*90c8c64dSAndroid Build Coastguard Worker             "defaults",
109*90c8c64dSAndroid Build Coastguard Worker             "stem",
110*90c8c64dSAndroid Build Coastguard Worker             "host_supported",
111*90c8c64dSAndroid Build Coastguard Worker             "host_cross_supported",
112*90c8c64dSAndroid Build Coastguard Worker             "crate_name",
113*90c8c64dSAndroid Build Coastguard Worker             "cargo_env_compat",
114*90c8c64dSAndroid Build Coastguard Worker             "cargo_pkg_version",
115*90c8c64dSAndroid Build Coastguard Worker             "crate_root",
116*90c8c64dSAndroid Build Coastguard Worker             "srcs",
117*90c8c64dSAndroid Build Coastguard Worker             "test_suites",
118*90c8c64dSAndroid Build Coastguard Worker             "auto_gen_config",
119*90c8c64dSAndroid Build Coastguard Worker             "test_options",
120*90c8c64dSAndroid Build Coastguard Worker             "edition",
121*90c8c64dSAndroid Build Coastguard Worker             "features",
122*90c8c64dSAndroid Build Coastguard Worker             "cfgs",
123*90c8c64dSAndroid Build Coastguard Worker             "flags",
124*90c8c64dSAndroid Build Coastguard Worker             "rustlibs",
125*90c8c64dSAndroid Build Coastguard Worker             "proc_macros",
126*90c8c64dSAndroid Build Coastguard Worker             "static_libs",
127*90c8c64dSAndroid Build Coastguard Worker             "whole_static_libs",
128*90c8c64dSAndroid Build Coastguard Worker             "shared_libs",
129*90c8c64dSAndroid Build Coastguard Worker             "aliases",
130*90c8c64dSAndroid Build Coastguard Worker             "arch",
131*90c8c64dSAndroid Build Coastguard Worker             "target",
132*90c8c64dSAndroid Build Coastguard Worker             "ld_flags",
133*90c8c64dSAndroid Build Coastguard Worker             "compile_multilib",
134*90c8c64dSAndroid Build Coastguard Worker             "include_dirs",
135*90c8c64dSAndroid Build Coastguard Worker             "apex_available",
136*90c8c64dSAndroid Build Coastguard Worker             "prefer_rlib",
137*90c8c64dSAndroid Build Coastguard Worker             "no_stdlibs",
138*90c8c64dSAndroid Build Coastguard Worker             "stdlibs",
139*90c8c64dSAndroid Build Coastguard Worker             "native_bridge_supported",
140*90c8c64dSAndroid Build Coastguard Worker             "product_available",
141*90c8c64dSAndroid Build Coastguard Worker             "recovery_available",
142*90c8c64dSAndroid Build Coastguard Worker             "vendor_available",
143*90c8c64dSAndroid Build Coastguard Worker             "vendor_ramdisk_available",
144*90c8c64dSAndroid Build Coastguard Worker             "ramdisk_available",
145*90c8c64dSAndroid Build Coastguard Worker             "min_sdk_version",
146*90c8c64dSAndroid Build Coastguard Worker             "visibility",
147*90c8c64dSAndroid Build Coastguard Worker         ];
148*90c8c64dSAndroid Build Coastguard Worker         let mut props: Vec<(&String, &BpValue)> = self.map.iter().collect();
149*90c8c64dSAndroid Build Coastguard Worker         props.sort_by_key(|(k, _)| {
150*90c8c64dSAndroid Build Coastguard Worker             let i = canonical_order.iter().position(|x| k == x).unwrap_or(canonical_order.len());
151*90c8c64dSAndroid Build Coastguard Worker             (i, (*k).clone())
152*90c8c64dSAndroid Build Coastguard Worker         });
153*90c8c64dSAndroid Build Coastguard Worker         for (k, v) in props {
154*90c8c64dSAndroid Build Coastguard Worker             w.write_str(k)?;
155*90c8c64dSAndroid Build Coastguard Worker             w.write_str(": ")?;
156*90c8c64dSAndroid Build Coastguard Worker             v.write(w)?;
157*90c8c64dSAndroid Build Coastguard Worker             w.write_str(",\n")?;
158*90c8c64dSAndroid Build Coastguard Worker         }
159*90c8c64dSAndroid Build Coastguard Worker         if let Some(raw_block) = &self.raw_block {
160*90c8c64dSAndroid Build Coastguard Worker             w.write_str(raw_block)?;
161*90c8c64dSAndroid Build Coastguard Worker             w.write_str(",\n")?;
162*90c8c64dSAndroid Build Coastguard Worker         }
163*90c8c64dSAndroid Build Coastguard Worker         w.write_str("}")?;
164*90c8c64dSAndroid Build Coastguard Worker         Ok(())
165*90c8c64dSAndroid Build Coastguard Worker     }
166*90c8c64dSAndroid Build Coastguard Worker }
167*90c8c64dSAndroid Build Coastguard Worker 
168*90c8c64dSAndroid Build Coastguard Worker impl BpValue {
169*90c8c64dSAndroid Build Coastguard Worker     /// Serialize to Android.bp format.
write(&self, w: &mut impl std::fmt::Write) -> Result<()>170*90c8c64dSAndroid Build Coastguard Worker     pub fn write(&self, w: &mut impl std::fmt::Write) -> Result<()> {
171*90c8c64dSAndroid Build Coastguard Worker         match self {
172*90c8c64dSAndroid Build Coastguard Worker             BpValue::Object(p) => p.write(w)?,
173*90c8c64dSAndroid Build Coastguard Worker             BpValue::Bool(b) => write!(w, "{b}")?,
174*90c8c64dSAndroid Build Coastguard Worker             BpValue::String(s) => write!(w, "\"{s}\"")?,
175*90c8c64dSAndroid Build Coastguard Worker             BpValue::List(vs) => {
176*90c8c64dSAndroid Build Coastguard Worker                 w.write_str("[")?;
177*90c8c64dSAndroid Build Coastguard Worker                 for (i, v) in vs.iter().enumerate() {
178*90c8c64dSAndroid Build Coastguard Worker                     v.write(w)?;
179*90c8c64dSAndroid Build Coastguard Worker                     if i != vs.len() - 1 {
180*90c8c64dSAndroid Build Coastguard Worker                         w.write_str(", ")?;
181*90c8c64dSAndroid Build Coastguard Worker                     }
182*90c8c64dSAndroid Build Coastguard Worker                 }
183*90c8c64dSAndroid Build Coastguard Worker                 w.write_str("]")?;
184*90c8c64dSAndroid Build Coastguard Worker             }
185*90c8c64dSAndroid Build Coastguard Worker         }
186*90c8c64dSAndroid Build Coastguard Worker         Ok(())
187*90c8c64dSAndroid Build Coastguard Worker     }
188*90c8c64dSAndroid Build Coastguard Worker }
189*90c8c64dSAndroid Build Coastguard Worker 
190*90c8c64dSAndroid Build Coastguard Worker impl From<bool> for BpValue {
from(x: bool) -> Self191*90c8c64dSAndroid Build Coastguard Worker     fn from(x: bool) -> Self {
192*90c8c64dSAndroid Build Coastguard Worker         BpValue::Bool(x)
193*90c8c64dSAndroid Build Coastguard Worker     }
194*90c8c64dSAndroid Build Coastguard Worker }
195*90c8c64dSAndroid Build Coastguard Worker 
196*90c8c64dSAndroid Build Coastguard Worker impl From<&str> for BpValue {
from(x: &str) -> Self197*90c8c64dSAndroid Build Coastguard Worker     fn from(x: &str) -> Self {
198*90c8c64dSAndroid Build Coastguard Worker         BpValue::String(x.to_string())
199*90c8c64dSAndroid Build Coastguard Worker     }
200*90c8c64dSAndroid Build Coastguard Worker }
201*90c8c64dSAndroid Build Coastguard Worker 
202*90c8c64dSAndroid Build Coastguard Worker impl From<String> for BpValue {
from(x: String) -> Self203*90c8c64dSAndroid Build Coastguard Worker     fn from(x: String) -> Self {
204*90c8c64dSAndroid Build Coastguard Worker         BpValue::String(x)
205*90c8c64dSAndroid Build Coastguard Worker     }
206*90c8c64dSAndroid Build Coastguard Worker }
207*90c8c64dSAndroid Build Coastguard Worker 
208*90c8c64dSAndroid Build Coastguard Worker impl From<PathBuf> for BpValue {
from(x: PathBuf) -> Self209*90c8c64dSAndroid Build Coastguard Worker     fn from(x: PathBuf) -> Self {
210*90c8c64dSAndroid Build Coastguard Worker         BpValue::String(x.to_string_lossy().into_owned())
211*90c8c64dSAndroid Build Coastguard Worker     }
212*90c8c64dSAndroid Build Coastguard Worker }
213*90c8c64dSAndroid Build Coastguard Worker 
214*90c8c64dSAndroid Build Coastguard Worker impl<T: Into<BpValue>> From<Vec<T>> for BpValue {
from(x: Vec<T>) -> Self215*90c8c64dSAndroid Build Coastguard Worker     fn from(x: Vec<T>) -> Self {
216*90c8c64dSAndroid Build Coastguard Worker         BpValue::List(x.into_iter().map(|x| x.into()).collect())
217*90c8c64dSAndroid Build Coastguard Worker     }
218*90c8c64dSAndroid Build Coastguard Worker }
219