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