xref: /aosp_15_r20/development/tools/cargo_embargo/src/config.rs (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1*90c8c64dSAndroid Build Coastguard Worker // Copyright (C) 2023 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 //! Code for reading configuration json files, usually called `cargo_embargo.json`.
16*90c8c64dSAndroid Build Coastguard Worker //!
17*90c8c64dSAndroid Build Coastguard Worker //! A single configuration file may cover several Rust packages under its directory tree, and may
18*90c8c64dSAndroid Build Coastguard Worker //! have multiple "variants". A variant is a particular configuration for building a set of
19*90c8c64dSAndroid Build Coastguard Worker //! packages, such as what feature flags to enable. Multiple variants are most often used to build
20*90c8c64dSAndroid Build Coastguard Worker //! both a std variant of a library and a no_std variant. Each variant generates one or more modules
21*90c8c64dSAndroid Build Coastguard Worker //! for each package, usually distinguished by a suffix.
22*90c8c64dSAndroid Build Coastguard Worker //!
23*90c8c64dSAndroid Build Coastguard Worker //! The [`Config`] struct has a map of `PackageConfig`s keyed by package name (for options that
24*90c8c64dSAndroid Build Coastguard Worker //! apply across all variants of a package), and a vector of `VariantConfig`s. There must be at
25*90c8c64dSAndroid Build Coastguard Worker //! least one variant for the configuration to generate any output. Each `VariantConfig` has the
26*90c8c64dSAndroid Build Coastguard Worker //! options that apply to that variant across all packages, and then a map of
27*90c8c64dSAndroid Build Coastguard Worker //! `PackageVariantConfig`s for options specific to a particular package of the variant.
28*90c8c64dSAndroid Build Coastguard Worker 
29*90c8c64dSAndroid Build Coastguard Worker use anyhow::{bail, Context, Result};
30*90c8c64dSAndroid Build Coastguard Worker use serde::{Deserialize, Serialize};
31*90c8c64dSAndroid Build Coastguard Worker use serde_json::{Map, Value};
32*90c8c64dSAndroid Build Coastguard Worker use std::collections::BTreeMap;
33*90c8c64dSAndroid Build Coastguard Worker use std::path::{Path, PathBuf};
34*90c8c64dSAndroid Build Coastguard Worker 
default_apex_available() -> Vec<String>35*90c8c64dSAndroid Build Coastguard Worker fn default_apex_available() -> Vec<String> {
36*90c8c64dSAndroid Build Coastguard Worker     vec!["//apex_available:platform".to_string(), "//apex_available:anyapex".to_string()]
37*90c8c64dSAndroid Build Coastguard Worker }
38*90c8c64dSAndroid Build Coastguard Worker 
is_default_apex_available(apex_available: &[String]) -> bool39*90c8c64dSAndroid Build Coastguard Worker fn is_default_apex_available(apex_available: &[String]) -> bool {
40*90c8c64dSAndroid Build Coastguard Worker     apex_available == default_apex_available()
41*90c8c64dSAndroid Build Coastguard Worker }
42*90c8c64dSAndroid Build Coastguard Worker 
default_true() -> bool43*90c8c64dSAndroid Build Coastguard Worker fn default_true() -> bool {
44*90c8c64dSAndroid Build Coastguard Worker     true
45*90c8c64dSAndroid Build Coastguard Worker }
46*90c8c64dSAndroid Build Coastguard Worker 
is_true(value: &bool) -> bool47*90c8c64dSAndroid Build Coastguard Worker fn is_true(value: &bool) -> bool {
48*90c8c64dSAndroid Build Coastguard Worker     *value
49*90c8c64dSAndroid Build Coastguard Worker }
50*90c8c64dSAndroid Build Coastguard Worker 
is_false(value: &bool) -> bool51*90c8c64dSAndroid Build Coastguard Worker fn is_false(value: &bool) -> bool {
52*90c8c64dSAndroid Build Coastguard Worker     !*value
53*90c8c64dSAndroid Build Coastguard Worker }
54*90c8c64dSAndroid Build Coastguard Worker 
55*90c8c64dSAndroid Build Coastguard Worker /// Options that apply to everything.
56*90c8c64dSAndroid Build Coastguard Worker #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
57*90c8c64dSAndroid Build Coastguard Worker #[serde(deny_unknown_fields)]
58*90c8c64dSAndroid Build Coastguard Worker pub struct Config {
59*90c8c64dSAndroid Build Coastguard Worker     pub variants: Vec<VariantConfig>,
60*90c8c64dSAndroid Build Coastguard Worker     /// Package specific config options across all variants.
61*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
62*90c8c64dSAndroid Build Coastguard Worker     pub package: BTreeMap<String, PackageConfig>,
63*90c8c64dSAndroid Build Coastguard Worker }
64*90c8c64dSAndroid Build Coastguard Worker 
65*90c8c64dSAndroid Build Coastguard Worker /// Inserts entries from `defaults` into `variant` if neither it nor `ignored_fields` contain
66*90c8c64dSAndroid Build Coastguard Worker /// matching keys.
add_defaults_to_variant( variant: &mut Map<String, Value>, defaults: &Map<String, Value>, ignored_fields: &[&str], )67*90c8c64dSAndroid Build Coastguard Worker fn add_defaults_to_variant(
68*90c8c64dSAndroid Build Coastguard Worker     variant: &mut Map<String, Value>,
69*90c8c64dSAndroid Build Coastguard Worker     defaults: &Map<String, Value>,
70*90c8c64dSAndroid Build Coastguard Worker     ignored_fields: &[&str],
71*90c8c64dSAndroid Build Coastguard Worker ) {
72*90c8c64dSAndroid Build Coastguard Worker     for (key, value) in defaults {
73*90c8c64dSAndroid Build Coastguard Worker         if !ignored_fields.contains(&key.as_str()) && !variant.contains_key(key) {
74*90c8c64dSAndroid Build Coastguard Worker             variant.insert(key.to_owned(), value.to_owned());
75*90c8c64dSAndroid Build Coastguard Worker         }
76*90c8c64dSAndroid Build Coastguard Worker     }
77*90c8c64dSAndroid Build Coastguard Worker }
78*90c8c64dSAndroid Build Coastguard Worker 
79*90c8c64dSAndroid Build Coastguard Worker impl Config {
80*90c8c64dSAndroid Build Coastguard Worker     /// Names of all fields in [`Config`] other than `variants` (which is treated specially).
81*90c8c64dSAndroid Build Coastguard Worker     const FIELD_NAMES: [&'static str; 1] = ["package"];
82*90c8c64dSAndroid Build Coastguard Worker 
83*90c8c64dSAndroid Build Coastguard Worker     /// Parses an instance of this config from the given JSON file.
from_file(filename: &Path) -> Result<Self>84*90c8c64dSAndroid Build Coastguard Worker     pub fn from_file(filename: &Path) -> Result<Self> {
85*90c8c64dSAndroid Build Coastguard Worker         let json_string = std::fs::read_to_string(filename)
86*90c8c64dSAndroid Build Coastguard Worker             .with_context(|| format!("failed to read file: {:?}", filename))?;
87*90c8c64dSAndroid Build Coastguard Worker         Self::from_json_str(&json_string)
88*90c8c64dSAndroid Build Coastguard Worker     }
89*90c8c64dSAndroid Build Coastguard Worker 
90*90c8c64dSAndroid Build Coastguard Worker     /// Parses an instance of this config from a string of JSON.
from_json_str(json_str: &str) -> Result<Self>91*90c8c64dSAndroid Build Coastguard Worker     pub fn from_json_str(json_str: &str) -> Result<Self> {
92*90c8c64dSAndroid Build Coastguard Worker         // Ignore comments.
93*90c8c64dSAndroid Build Coastguard Worker         let json_str: String =
94*90c8c64dSAndroid Build Coastguard Worker             json_str.lines().filter(|l| !l.trim_start().starts_with("//")).collect();
95*90c8c64dSAndroid Build Coastguard Worker         // First parse into untyped map.
96*90c8c64dSAndroid Build Coastguard Worker         let mut config: Map<String, Value> =
97*90c8c64dSAndroid Build Coastguard Worker             serde_json::from_str(&json_str).context("failed to parse config")?;
98*90c8c64dSAndroid Build Coastguard Worker 
99*90c8c64dSAndroid Build Coastguard Worker         // Flatten variants. First, get the variants from the config file.
100*90c8c64dSAndroid Build Coastguard Worker         let mut variants = match config.remove("variants") {
101*90c8c64dSAndroid Build Coastguard Worker             Some(Value::Array(v)) => v,
102*90c8c64dSAndroid Build Coastguard Worker             Some(_) => bail!("Failed to parse config: variants is not an array"),
103*90c8c64dSAndroid Build Coastguard Worker             None => {
104*90c8c64dSAndroid Build Coastguard Worker                 // There are no variants, so just put everything into a single variant.
105*90c8c64dSAndroid Build Coastguard Worker                 vec![Value::Object(Map::new())]
106*90c8c64dSAndroid Build Coastguard Worker             }
107*90c8c64dSAndroid Build Coastguard Worker         };
108*90c8c64dSAndroid Build Coastguard Worker         // Set default values in variants from top-level config.
109*90c8c64dSAndroid Build Coastguard Worker         for variant in &mut variants {
110*90c8c64dSAndroid Build Coastguard Worker             let variant = variant
111*90c8c64dSAndroid Build Coastguard Worker                 .as_object_mut()
112*90c8c64dSAndroid Build Coastguard Worker                 .context("Failed to parse config: variant is not an object")?;
113*90c8c64dSAndroid Build Coastguard Worker             add_defaults_to_variant(variant, &config, &Config::FIELD_NAMES);
114*90c8c64dSAndroid Build Coastguard Worker 
115*90c8c64dSAndroid Build Coastguard Worker             if let Some(packages) = config.get("package") {
116*90c8c64dSAndroid Build Coastguard Worker                 // Copy package entries across.
117*90c8c64dSAndroid Build Coastguard Worker                 let variant_packages = variant
118*90c8c64dSAndroid Build Coastguard Worker                     .entry("package")
119*90c8c64dSAndroid Build Coastguard Worker                     .or_insert_with(|| Map::new().into())
120*90c8c64dSAndroid Build Coastguard Worker                     .as_object_mut()
121*90c8c64dSAndroid Build Coastguard Worker                     .context("Failed to parse config: variant package is not an object")?;
122*90c8c64dSAndroid Build Coastguard Worker                 for (package_name, package_config) in packages
123*90c8c64dSAndroid Build Coastguard Worker                     .as_object()
124*90c8c64dSAndroid Build Coastguard Worker                     .context("Failed to parse config: package is not an object")?
125*90c8c64dSAndroid Build Coastguard Worker                 {
126*90c8c64dSAndroid Build Coastguard Worker                     let variant_package = variant_packages
127*90c8c64dSAndroid Build Coastguard Worker                         .entry(package_name)
128*90c8c64dSAndroid Build Coastguard Worker                         .or_insert_with(|| Map::new().into())
129*90c8c64dSAndroid Build Coastguard Worker                         .as_object_mut()
130*90c8c64dSAndroid Build Coastguard Worker                         .context(
131*90c8c64dSAndroid Build Coastguard Worker                             "Failed to parse config: variant package config is not an object",
132*90c8c64dSAndroid Build Coastguard Worker                         )?;
133*90c8c64dSAndroid Build Coastguard Worker                     add_defaults_to_variant(
134*90c8c64dSAndroid Build Coastguard Worker                         variant_package,
135*90c8c64dSAndroid Build Coastguard Worker                         package_config
136*90c8c64dSAndroid Build Coastguard Worker                             .as_object()
137*90c8c64dSAndroid Build Coastguard Worker                             .context("Failed to parse config: package is not an object")?,
138*90c8c64dSAndroid Build Coastguard Worker                         &PackageConfig::FIELD_NAMES,
139*90c8c64dSAndroid Build Coastguard Worker                     );
140*90c8c64dSAndroid Build Coastguard Worker                 }
141*90c8c64dSAndroid Build Coastguard Worker             }
142*90c8c64dSAndroid Build Coastguard Worker         }
143*90c8c64dSAndroid Build Coastguard Worker         // Remove other entries from the top-level config, and put variants back.
144*90c8c64dSAndroid Build Coastguard Worker         config.retain(|key, _| Self::FIELD_NAMES.contains(&key.as_str()));
145*90c8c64dSAndroid Build Coastguard Worker         if let Some(package) = config.get_mut("package") {
146*90c8c64dSAndroid Build Coastguard Worker             for value in package
147*90c8c64dSAndroid Build Coastguard Worker                 .as_object_mut()
148*90c8c64dSAndroid Build Coastguard Worker                 .context("Failed to parse config: package is not an object")?
149*90c8c64dSAndroid Build Coastguard Worker                 .values_mut()
150*90c8c64dSAndroid Build Coastguard Worker             {
151*90c8c64dSAndroid Build Coastguard Worker                 let package_config = value
152*90c8c64dSAndroid Build Coastguard Worker                     .as_object_mut()
153*90c8c64dSAndroid Build Coastguard Worker                     .context("Failed to parse config: package is not an object")?;
154*90c8c64dSAndroid Build Coastguard Worker                 package_config.retain(|key, _| PackageConfig::FIELD_NAMES.contains(&key.as_str()))
155*90c8c64dSAndroid Build Coastguard Worker             }
156*90c8c64dSAndroid Build Coastguard Worker         }
157*90c8c64dSAndroid Build Coastguard Worker         config.insert("variants".to_string(), Value::Array(variants));
158*90c8c64dSAndroid Build Coastguard Worker 
159*90c8c64dSAndroid Build Coastguard Worker         // Parse into `Config` struct.
160*90c8c64dSAndroid Build Coastguard Worker         serde_json::from_value(Value::Object(config)).context("failed to parse config")
161*90c8c64dSAndroid Build Coastguard Worker     }
162*90c8c64dSAndroid Build Coastguard Worker 
163*90c8c64dSAndroid Build Coastguard Worker     /// Serializes an instance of this config to a string of pretty-printed JSON.
to_json_string(&self) -> Result<String>164*90c8c64dSAndroid Build Coastguard Worker     pub fn to_json_string(&self) -> Result<String> {
165*90c8c64dSAndroid Build Coastguard Worker         // First convert to an untyped map.
166*90c8c64dSAndroid Build Coastguard Worker         let Value::Object(mut config) = serde_json::to_value(self)? else {
167*90c8c64dSAndroid Build Coastguard Worker             panic!("Config wasn't a map.");
168*90c8c64dSAndroid Build Coastguard Worker         };
169*90c8c64dSAndroid Build Coastguard Worker 
170*90c8c64dSAndroid Build Coastguard Worker         // Factor out common options which are set for all variants.
171*90c8c64dSAndroid Build Coastguard Worker         let Value::Array(mut variants) = config.remove("variants").unwrap() else {
172*90c8c64dSAndroid Build Coastguard Worker             panic!("variants wasn't an array.")
173*90c8c64dSAndroid Build Coastguard Worker         };
174*90c8c64dSAndroid Build Coastguard Worker         let mut packages = if let Some(Value::Object(packages)) = config.remove("package") {
175*90c8c64dSAndroid Build Coastguard Worker             packages
176*90c8c64dSAndroid Build Coastguard Worker         } else {
177*90c8c64dSAndroid Build Coastguard Worker             Map::new()
178*90c8c64dSAndroid Build Coastguard Worker         };
179*90c8c64dSAndroid Build Coastguard Worker         for (key, value) in variants[0].as_object().unwrap() {
180*90c8c64dSAndroid Build Coastguard Worker             if key == "package" {
181*90c8c64dSAndroid Build Coastguard Worker                 for (package_name, package_config) in value.as_object().unwrap() {
182*90c8c64dSAndroid Build Coastguard Worker                     for (package_key, package_value) in package_config.as_object().unwrap() {
183*90c8c64dSAndroid Build Coastguard Worker                         // Check whether all other variants have the same entry for the same package.
184*90c8c64dSAndroid Build Coastguard Worker                         if variants[1..variants.len()].iter().all(|variant| {
185*90c8c64dSAndroid Build Coastguard Worker                             if let Some(Value::Object(variant_packages)) =
186*90c8c64dSAndroid Build Coastguard Worker                                 variant.as_object().unwrap().get("package")
187*90c8c64dSAndroid Build Coastguard Worker                             {
188*90c8c64dSAndroid Build Coastguard Worker                                 if let Some(Value::Object(variant_package_config)) =
189*90c8c64dSAndroid Build Coastguard Worker                                     variant_packages.get(package_name)
190*90c8c64dSAndroid Build Coastguard Worker                                 {
191*90c8c64dSAndroid Build Coastguard Worker                                     return variant_package_config.get(package_key)
192*90c8c64dSAndroid Build Coastguard Worker                                         == Some(package_value);
193*90c8c64dSAndroid Build Coastguard Worker                                 }
194*90c8c64dSAndroid Build Coastguard Worker                             }
195*90c8c64dSAndroid Build Coastguard Worker                             false
196*90c8c64dSAndroid Build Coastguard Worker                         }) {
197*90c8c64dSAndroid Build Coastguard Worker                             packages
198*90c8c64dSAndroid Build Coastguard Worker                                 .entry(package_name)
199*90c8c64dSAndroid Build Coastguard Worker                                 .or_insert_with(|| Map::new().into())
200*90c8c64dSAndroid Build Coastguard Worker                                 .as_object_mut()
201*90c8c64dSAndroid Build Coastguard Worker                                 .unwrap()
202*90c8c64dSAndroid Build Coastguard Worker                                 .insert(package_key.to_owned(), package_value.to_owned());
203*90c8c64dSAndroid Build Coastguard Worker                         }
204*90c8c64dSAndroid Build Coastguard Worker                     }
205*90c8c64dSAndroid Build Coastguard Worker                 }
206*90c8c64dSAndroid Build Coastguard Worker             } else {
207*90c8c64dSAndroid Build Coastguard Worker                 // Check whether all the other variants have the same entry.
208*90c8c64dSAndroid Build Coastguard Worker                 if variants[1..variants.len()]
209*90c8c64dSAndroid Build Coastguard Worker                     .iter()
210*90c8c64dSAndroid Build Coastguard Worker                     .all(|variant| variant.as_object().unwrap().get(key) == Some(value))
211*90c8c64dSAndroid Build Coastguard Worker                 {
212*90c8c64dSAndroid Build Coastguard Worker                     // Add it to the top-level config.
213*90c8c64dSAndroid Build Coastguard Worker                     config.insert(key.to_owned(), value.to_owned());
214*90c8c64dSAndroid Build Coastguard Worker                 }
215*90c8c64dSAndroid Build Coastguard Worker             }
216*90c8c64dSAndroid Build Coastguard Worker         }
217*90c8c64dSAndroid Build Coastguard Worker         // Remove factored out common options from all variants.
218*90c8c64dSAndroid Build Coastguard Worker         for key in config.keys() {
219*90c8c64dSAndroid Build Coastguard Worker             for variant in &mut variants {
220*90c8c64dSAndroid Build Coastguard Worker                 variant.as_object_mut().unwrap().remove(key);
221*90c8c64dSAndroid Build Coastguard Worker             }
222*90c8c64dSAndroid Build Coastguard Worker         }
223*90c8c64dSAndroid Build Coastguard Worker         // Likewise, remove package options factored out from variants.
224*90c8c64dSAndroid Build Coastguard Worker         for (package_name, package_config) in &packages {
225*90c8c64dSAndroid Build Coastguard Worker             for package_key in package_config.as_object().unwrap().keys() {
226*90c8c64dSAndroid Build Coastguard Worker                 for variant in &mut variants {
227*90c8c64dSAndroid Build Coastguard Worker                     if let Some(Value::Object(variant_packages)) = variant.get_mut("package") {
228*90c8c64dSAndroid Build Coastguard Worker                         if let Some(Value::Object(variant_package_config)) =
229*90c8c64dSAndroid Build Coastguard Worker                             variant_packages.get_mut(package_name)
230*90c8c64dSAndroid Build Coastguard Worker                         {
231*90c8c64dSAndroid Build Coastguard Worker                             variant_package_config.remove(package_key);
232*90c8c64dSAndroid Build Coastguard Worker                         }
233*90c8c64dSAndroid Build Coastguard Worker                     }
234*90c8c64dSAndroid Build Coastguard Worker                 }
235*90c8c64dSAndroid Build Coastguard Worker             }
236*90c8c64dSAndroid Build Coastguard Worker         }
237*90c8c64dSAndroid Build Coastguard Worker         // Remove any variant packages which are now empty.
238*90c8c64dSAndroid Build Coastguard Worker         for variant in &mut variants {
239*90c8c64dSAndroid Build Coastguard Worker             if let Some(Value::Object(variant_packages)) = variant.get_mut("package") {
240*90c8c64dSAndroid Build Coastguard Worker                 variant_packages
241*90c8c64dSAndroid Build Coastguard Worker                     .retain(|_, package_config| !package_config.as_object().unwrap().is_empty());
242*90c8c64dSAndroid Build Coastguard Worker                 if variant_packages.is_empty() {
243*90c8c64dSAndroid Build Coastguard Worker                     variant.as_object_mut().unwrap().remove("package");
244*90c8c64dSAndroid Build Coastguard Worker                 }
245*90c8c64dSAndroid Build Coastguard Worker             }
246*90c8c64dSAndroid Build Coastguard Worker         }
247*90c8c64dSAndroid Build Coastguard Worker         // Put packages and variants back into the top-level config.
248*90c8c64dSAndroid Build Coastguard Worker         if variants.len() > 1 || !variants[0].as_object().unwrap().is_empty() {
249*90c8c64dSAndroid Build Coastguard Worker             config.insert("variants".to_string(), Value::Array(variants));
250*90c8c64dSAndroid Build Coastguard Worker         }
251*90c8c64dSAndroid Build Coastguard Worker         if !packages.is_empty() {
252*90c8c64dSAndroid Build Coastguard Worker             config.insert("package".to_string(), Value::Object(packages));
253*90c8c64dSAndroid Build Coastguard Worker         }
254*90c8c64dSAndroid Build Coastguard Worker 
255*90c8c64dSAndroid Build Coastguard Worker         // Serialise the map into a JSON string.
256*90c8c64dSAndroid Build Coastguard Worker         serde_json::to_string_pretty(&config).context("failed to serialize config")
257*90c8c64dSAndroid Build Coastguard Worker     }
258*90c8c64dSAndroid Build Coastguard Worker }
259*90c8c64dSAndroid Build Coastguard Worker 
260*90c8c64dSAndroid Build Coastguard Worker #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
261*90c8c64dSAndroid Build Coastguard Worker #[serde(deny_unknown_fields)]
262*90c8c64dSAndroid Build Coastguard Worker pub struct VariantConfig {
263*90c8c64dSAndroid Build Coastguard Worker     /// Whether to output `rust_test` modules.
264*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
265*90c8c64dSAndroid Build Coastguard Worker     pub tests: bool,
266*90c8c64dSAndroid Build Coastguard Worker     /// Set of features to enable. If not set, uses the default crate features.
267*90c8c64dSAndroid Build Coastguard Worker     #[serde(skip_serializing_if = "Option::is_none")]
268*90c8c64dSAndroid Build Coastguard Worker     pub features: Option<Vec<String>>,
269*90c8c64dSAndroid Build Coastguard Worker     /// Whether to build with `--workspace`.
270*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
271*90c8c64dSAndroid Build Coastguard Worker     pub workspace: bool,
272*90c8c64dSAndroid Build Coastguard Worker     /// When workspace is enabled, list of `--exclude` crates.
273*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "Vec::is_empty")]
274*90c8c64dSAndroid Build Coastguard Worker     pub workspace_excludes: Vec<String>,
275*90c8c64dSAndroid Build Coastguard Worker     /// Value to use for every generated module's `defaults` field.
276*90c8c64dSAndroid Build Coastguard Worker     #[serde(skip_serializing_if = "Option::is_none")]
277*90c8c64dSAndroid Build Coastguard Worker     pub global_defaults: Option<String>,
278*90c8c64dSAndroid Build Coastguard Worker     /// Value to use for every generated library module's `apex_available` field.
279*90c8c64dSAndroid Build Coastguard Worker     #[serde(default = "default_apex_available", skip_serializing_if = "is_default_apex_available")]
280*90c8c64dSAndroid Build Coastguard Worker     pub apex_available: Vec<String>,
281*90c8c64dSAndroid Build Coastguard Worker     /// Value to use for every generated library module's `native_bridge_supported` field.
282*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
283*90c8c64dSAndroid Build Coastguard Worker     pub native_bridge_supported: bool,
284*90c8c64dSAndroid Build Coastguard Worker     /// Value to use for every generated library module's `product_available` field.
285*90c8c64dSAndroid Build Coastguard Worker     #[serde(default = "default_true", skip_serializing_if = "is_true")]
286*90c8c64dSAndroid Build Coastguard Worker     pub product_available: bool,
287*90c8c64dSAndroid Build Coastguard Worker     /// Value to use for every generated library module's `ramdisk_available` field.
288*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
289*90c8c64dSAndroid Build Coastguard Worker     pub ramdisk_available: bool,
290*90c8c64dSAndroid Build Coastguard Worker     /// Value to use for every generated library module's `recovery_available` field.
291*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
292*90c8c64dSAndroid Build Coastguard Worker     pub recovery_available: bool,
293*90c8c64dSAndroid Build Coastguard Worker     /// Value to use for every generated library module's `vendor_available` field.
294*90c8c64dSAndroid Build Coastguard Worker     #[serde(default = "default_true", skip_serializing_if = "is_true")]
295*90c8c64dSAndroid Build Coastguard Worker     pub vendor_available: bool,
296*90c8c64dSAndroid Build Coastguard Worker     /// Value to use for every generated library module's `vendor_ramdisk_available` field.
297*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
298*90c8c64dSAndroid Build Coastguard Worker     pub vendor_ramdisk_available: bool,
299*90c8c64dSAndroid Build Coastguard Worker     /// Minimum SDK version.
300*90c8c64dSAndroid Build Coastguard Worker     #[serde(skip_serializing_if = "Option::is_none")]
301*90c8c64dSAndroid Build Coastguard Worker     pub min_sdk_version: Option<String>,
302*90c8c64dSAndroid Build Coastguard Worker     /// Map of renames for modules. For example, if a "libfoo" would be generated and there is an
303*90c8c64dSAndroid Build Coastguard Worker     /// entry ("libfoo", "libbar"), the generated module will be called "libbar" instead.
304*90c8c64dSAndroid Build Coastguard Worker     ///
305*90c8c64dSAndroid Build Coastguard Worker     /// Also, affects references to dependencies (e.g. in a "static_libs" list), even those outside
306*90c8c64dSAndroid Build Coastguard Worker     /// the project being processed.
307*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
308*90c8c64dSAndroid Build Coastguard Worker     pub module_name_overrides: BTreeMap<String, String>,
309*90c8c64dSAndroid Build Coastguard Worker     /// Package specific config options.
310*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
311*90c8c64dSAndroid Build Coastguard Worker     pub package: BTreeMap<String, PackageVariantConfig>,
312*90c8c64dSAndroid Build Coastguard Worker     /// `cfg` flags in this list will not be included.
313*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "Vec::is_empty")]
314*90c8c64dSAndroid Build Coastguard Worker     pub cfg_blocklist: Vec<String>,
315*90c8c64dSAndroid Build Coastguard Worker     /// Extra `cfg` flags to enable in output modules.
316*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "Vec::is_empty")]
317*90c8c64dSAndroid Build Coastguard Worker     pub extra_cfg: Vec<String>,
318*90c8c64dSAndroid Build Coastguard Worker     /// Modules in this list will not be generated.
319*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "Vec::is_empty")]
320*90c8c64dSAndroid Build Coastguard Worker     pub module_blocklist: Vec<String>,
321*90c8c64dSAndroid Build Coastguard Worker     /// Modules name => Soong "visibility" property.
322*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
323*90c8c64dSAndroid Build Coastguard Worker     pub module_visibility: BTreeMap<String, Vec<String>>,
324*90c8c64dSAndroid Build Coastguard Worker     /// Whether to run the cargo build and parse its output, rather than just figuring things out
325*90c8c64dSAndroid Build Coastguard Worker     /// from the cargo metadata.
326*90c8c64dSAndroid Build Coastguard Worker     #[serde(default = "default_true", skip_serializing_if = "is_true")]
327*90c8c64dSAndroid Build Coastguard Worker     pub run_cargo: bool,
328*90c8c64dSAndroid Build Coastguard Worker     /// Generate Android build rules at Android.bp for this variant if true.
329*90c8c64dSAndroid Build Coastguard Worker     #[serde(default = "default_true", skip_serializing_if = "is_true")]
330*90c8c64dSAndroid Build Coastguard Worker     pub generate_androidbp: bool,
331*90c8c64dSAndroid Build Coastguard Worker     /// Generate Trusty build rules at rules.mk and Android.bp if true.
332*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
333*90c8c64dSAndroid Build Coastguard Worker     pub generate_rulesmk: bool,
334*90c8c64dSAndroid Build Coastguard Worker }
335*90c8c64dSAndroid Build Coastguard Worker 
336*90c8c64dSAndroid Build Coastguard Worker impl Default for VariantConfig {
default() -> Self337*90c8c64dSAndroid Build Coastguard Worker     fn default() -> Self {
338*90c8c64dSAndroid Build Coastguard Worker         Self {
339*90c8c64dSAndroid Build Coastguard Worker             tests: false,
340*90c8c64dSAndroid Build Coastguard Worker             features: Default::default(),
341*90c8c64dSAndroid Build Coastguard Worker             workspace: false,
342*90c8c64dSAndroid Build Coastguard Worker             workspace_excludes: Default::default(),
343*90c8c64dSAndroid Build Coastguard Worker             global_defaults: None,
344*90c8c64dSAndroid Build Coastguard Worker             apex_available: default_apex_available(),
345*90c8c64dSAndroid Build Coastguard Worker             native_bridge_supported: false,
346*90c8c64dSAndroid Build Coastguard Worker             product_available: true,
347*90c8c64dSAndroid Build Coastguard Worker             ramdisk_available: false,
348*90c8c64dSAndroid Build Coastguard Worker             recovery_available: false,
349*90c8c64dSAndroid Build Coastguard Worker             vendor_available: true,
350*90c8c64dSAndroid Build Coastguard Worker             vendor_ramdisk_available: false,
351*90c8c64dSAndroid Build Coastguard Worker             min_sdk_version: None,
352*90c8c64dSAndroid Build Coastguard Worker             module_name_overrides: Default::default(),
353*90c8c64dSAndroid Build Coastguard Worker             package: Default::default(),
354*90c8c64dSAndroid Build Coastguard Worker             cfg_blocklist: Default::default(),
355*90c8c64dSAndroid Build Coastguard Worker             extra_cfg: Default::default(),
356*90c8c64dSAndroid Build Coastguard Worker             module_blocklist: Default::default(),
357*90c8c64dSAndroid Build Coastguard Worker             module_visibility: Default::default(),
358*90c8c64dSAndroid Build Coastguard Worker             run_cargo: true,
359*90c8c64dSAndroid Build Coastguard Worker             generate_androidbp: true,
360*90c8c64dSAndroid Build Coastguard Worker             generate_rulesmk: false,
361*90c8c64dSAndroid Build Coastguard Worker         }
362*90c8c64dSAndroid Build Coastguard Worker     }
363*90c8c64dSAndroid Build Coastguard Worker }
364*90c8c64dSAndroid Build Coastguard Worker 
365*90c8c64dSAndroid Build Coastguard Worker /// Options that apply to everything in a package (i.e. everything associated with a particular
366*90c8c64dSAndroid Build Coastguard Worker /// Cargo.toml file), for all variants.
367*90c8c64dSAndroid Build Coastguard Worker #[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
368*90c8c64dSAndroid Build Coastguard Worker #[serde(deny_unknown_fields)]
369*90c8c64dSAndroid Build Coastguard Worker pub struct PackageConfig {
370*90c8c64dSAndroid Build Coastguard Worker     /// File with content to append to the end of the generated Android.bp.
371*90c8c64dSAndroid Build Coastguard Worker     #[serde(skip_serializing_if = "Option::is_none")]
372*90c8c64dSAndroid Build Coastguard Worker     pub add_toplevel_block: Option<PathBuf>,
373*90c8c64dSAndroid Build Coastguard Worker     /// Patch file to apply after Android.bp is generated.
374*90c8c64dSAndroid Build Coastguard Worker     #[serde(skip_serializing_if = "Option::is_none")]
375*90c8c64dSAndroid Build Coastguard Worker     pub patch: Option<PathBuf>,
376*90c8c64dSAndroid Build Coastguard Worker     /// Patch file to apply after rules.mk is generated.
377*90c8c64dSAndroid Build Coastguard Worker     #[serde(skip_serializing_if = "Option::is_none")]
378*90c8c64dSAndroid Build Coastguard Worker     pub rulesmk_patch: Option<PathBuf>,
379*90c8c64dSAndroid Build Coastguard Worker     /// `license_text` to use for `license` module, overriding the `license_file` given by the
380*90c8c64dSAndroid Build Coastguard Worker     /// package or the default "LICENSE".
381*90c8c64dSAndroid Build Coastguard Worker     #[serde(skip_serializing_if = "Option::is_none")]
382*90c8c64dSAndroid Build Coastguard Worker     pub license_text: Option<Vec<String>>,
383*90c8c64dSAndroid Build Coastguard Worker }
384*90c8c64dSAndroid Build Coastguard Worker 
385*90c8c64dSAndroid Build Coastguard Worker impl PackageConfig {
386*90c8c64dSAndroid Build Coastguard Worker     /// Names of all the fields on `PackageConfig`.
387*90c8c64dSAndroid Build Coastguard Worker     const FIELD_NAMES: [&'static str; 4] =
388*90c8c64dSAndroid Build Coastguard Worker         ["add_toplevel_block", "license_text", "patch", "rulesmk_patch"];
389*90c8c64dSAndroid Build Coastguard Worker }
390*90c8c64dSAndroid Build Coastguard Worker 
391*90c8c64dSAndroid Build Coastguard Worker /// Options that apply to everything in a package (i.e. everything associated with a particular
392*90c8c64dSAndroid Build Coastguard Worker /// Cargo.toml file), for a particular variant.
393*90c8c64dSAndroid Build Coastguard Worker #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
394*90c8c64dSAndroid Build Coastguard Worker #[serde(deny_unknown_fields)]
395*90c8c64dSAndroid Build Coastguard Worker pub struct PackageVariantConfig {
396*90c8c64dSAndroid Build Coastguard Worker     /// Link against `alloc`. Only valid if `no_std` is also true.
397*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
398*90c8c64dSAndroid Build Coastguard Worker     pub alloc: bool,
399*90c8c64dSAndroid Build Coastguard Worker     /// Whether to compile for device. Defaults to true.
400*90c8c64dSAndroid Build Coastguard Worker     #[serde(default = "default_true", skip_serializing_if = "is_true")]
401*90c8c64dSAndroid Build Coastguard Worker     pub device_supported: bool,
402*90c8c64dSAndroid Build Coastguard Worker     /// Whether to compile for host. Defaults to true.
403*90c8c64dSAndroid Build Coastguard Worker     #[serde(default = "default_true", skip_serializing_if = "is_true")]
404*90c8c64dSAndroid Build Coastguard Worker     pub host_supported: bool,
405*90c8c64dSAndroid Build Coastguard Worker     /// Whether to compile for non-build host targets. Defaults to true.
406*90c8c64dSAndroid Build Coastguard Worker     #[serde(default = "default_true", skip_serializing_if = "is_true")]
407*90c8c64dSAndroid Build Coastguard Worker     pub host_cross_supported: bool,
408*90c8c64dSAndroid Build Coastguard Worker     /// Add a `compile_multilib: "first"` property to host modules.
409*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
410*90c8c64dSAndroid Build Coastguard Worker     pub host_first_multilib: bool,
411*90c8c64dSAndroid Build Coastguard Worker     /// Generate "rust_library_rlib" instead of "rust_library".
412*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
413*90c8c64dSAndroid Build Coastguard Worker     pub force_rlib: bool,
414*90c8c64dSAndroid Build Coastguard Worker     /// Whether to disable "unit_test" for "rust_test" modules.
415*90c8c64dSAndroid Build Coastguard Worker     // TODO: Should probably be a list of modules or crates. A package might have a mix of unit and
416*90c8c64dSAndroid Build Coastguard Worker     // integration tests.
417*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
418*90c8c64dSAndroid Build Coastguard Worker     pub no_presubmit: bool,
419*90c8c64dSAndroid Build Coastguard Worker     /// File with content to append to the end of each generated module.
420*90c8c64dSAndroid Build Coastguard Worker     #[serde(skip_serializing_if = "Option::is_none")]
421*90c8c64dSAndroid Build Coastguard Worker     pub add_module_block: Option<PathBuf>,
422*90c8c64dSAndroid Build Coastguard Worker     /// Modules in this list will not be added as dependencies of generated modules.
423*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "Vec::is_empty")]
424*90c8c64dSAndroid Build Coastguard Worker     pub dep_blocklist: Vec<String>,
425*90c8c64dSAndroid Build Coastguard Worker     /// Don't link against `std`, only `core`.
426*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
427*90c8c64dSAndroid Build Coastguard Worker     pub no_std: bool,
428*90c8c64dSAndroid Build Coastguard Worker     /// Copy build.rs output to ./out/* and add a genrule to copy ./out/* to genrule output.
429*90c8c64dSAndroid Build Coastguard Worker     /// For crates with code pattern:
430*90c8c64dSAndroid Build Coastguard Worker     ///     include!(concat!(env!("OUT_DIR"), "/<some_file>.rs"))
431*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "is_false")]
432*90c8c64dSAndroid Build Coastguard Worker     pub copy_out: bool,
433*90c8c64dSAndroid Build Coastguard Worker     /// Add the given files to the given tests' `data` property. The key is the test source filename
434*90c8c64dSAndroid Build Coastguard Worker     /// relative to the crate root.
435*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
436*90c8c64dSAndroid Build Coastguard Worker     pub test_data: BTreeMap<String, Vec<String>>,
437*90c8c64dSAndroid Build Coastguard Worker     /// Static libraries in this list will instead be added as whole_static_libs.
438*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "Vec::is_empty")]
439*90c8c64dSAndroid Build Coastguard Worker     pub whole_static_libs: Vec<String>,
440*90c8c64dSAndroid Build Coastguard Worker     /// Directories with headers to export for C usage.
441*90c8c64dSAndroid Build Coastguard Worker     #[serde(default, skip_serializing_if = "Vec::is_empty")]
442*90c8c64dSAndroid Build Coastguard Worker     pub exported_c_header_dir: Vec<PathBuf>,
443*90c8c64dSAndroid Build Coastguard Worker }
444*90c8c64dSAndroid Build Coastguard Worker 
445*90c8c64dSAndroid Build Coastguard Worker impl Default for PackageVariantConfig {
default() -> Self446*90c8c64dSAndroid Build Coastguard Worker     fn default() -> Self {
447*90c8c64dSAndroid Build Coastguard Worker         Self {
448*90c8c64dSAndroid Build Coastguard Worker             alloc: false,
449*90c8c64dSAndroid Build Coastguard Worker             device_supported: true,
450*90c8c64dSAndroid Build Coastguard Worker             host_supported: true,
451*90c8c64dSAndroid Build Coastguard Worker             host_cross_supported: true,
452*90c8c64dSAndroid Build Coastguard Worker             host_first_multilib: false,
453*90c8c64dSAndroid Build Coastguard Worker             force_rlib: false,
454*90c8c64dSAndroid Build Coastguard Worker             no_presubmit: false,
455*90c8c64dSAndroid Build Coastguard Worker             add_module_block: None,
456*90c8c64dSAndroid Build Coastguard Worker             dep_blocklist: Default::default(),
457*90c8c64dSAndroid Build Coastguard Worker             no_std: false,
458*90c8c64dSAndroid Build Coastguard Worker             copy_out: false,
459*90c8c64dSAndroid Build Coastguard Worker             test_data: Default::default(),
460*90c8c64dSAndroid Build Coastguard Worker             whole_static_libs: Default::default(),
461*90c8c64dSAndroid Build Coastguard Worker             exported_c_header_dir: Default::default(),
462*90c8c64dSAndroid Build Coastguard Worker         }
463*90c8c64dSAndroid Build Coastguard Worker     }
464*90c8c64dSAndroid Build Coastguard Worker }
465*90c8c64dSAndroid Build Coastguard Worker 
466*90c8c64dSAndroid Build Coastguard Worker #[cfg(test)]
467*90c8c64dSAndroid Build Coastguard Worker mod tests {
468*90c8c64dSAndroid Build Coastguard Worker     use super::*;
469*90c8c64dSAndroid Build Coastguard Worker 
470*90c8c64dSAndroid Build Coastguard Worker     #[test]
variant_config()471*90c8c64dSAndroid Build Coastguard Worker     fn variant_config() {
472*90c8c64dSAndroid Build Coastguard Worker         let config = Config::from_json_str(
473*90c8c64dSAndroid Build Coastguard Worker             r#"{
474*90c8c64dSAndroid Build Coastguard Worker             "tests": true,
475*90c8c64dSAndroid Build Coastguard Worker             "package": {
476*90c8c64dSAndroid Build Coastguard Worker                 "argh": {
477*90c8c64dSAndroid Build Coastguard Worker                     "patch": "patches/Android.bp.patch"
478*90c8c64dSAndroid Build Coastguard Worker                 },
479*90c8c64dSAndroid Build Coastguard Worker                 "another": {
480*90c8c64dSAndroid Build Coastguard Worker                     "add_toplevel_block": "block.bp",
481*90c8c64dSAndroid Build Coastguard Worker                     "device_supported": false,
482*90c8c64dSAndroid Build Coastguard Worker                     "force_rlib": true
483*90c8c64dSAndroid Build Coastguard Worker                 },
484*90c8c64dSAndroid Build Coastguard Worker                 "rulesmk": {
485*90c8c64dSAndroid Build Coastguard Worker                     "rulesmk_patch": "patches/rules.mk.patch"
486*90c8c64dSAndroid Build Coastguard Worker                 }
487*90c8c64dSAndroid Build Coastguard Worker             },
488*90c8c64dSAndroid Build Coastguard Worker             "variants": [
489*90c8c64dSAndroid Build Coastguard Worker                 {},
490*90c8c64dSAndroid Build Coastguard Worker                 {
491*90c8c64dSAndroid Build Coastguard Worker                     "generate_androidbp": false,
492*90c8c64dSAndroid Build Coastguard Worker                     "generate_rulesmk": true,
493*90c8c64dSAndroid Build Coastguard Worker                     "tests": false,
494*90c8c64dSAndroid Build Coastguard Worker                     "features": ["feature"],
495*90c8c64dSAndroid Build Coastguard Worker                     "vendor_available": false,
496*90c8c64dSAndroid Build Coastguard Worker                     "package": {
497*90c8c64dSAndroid Build Coastguard Worker                         "another": {
498*90c8c64dSAndroid Build Coastguard Worker                             "alloc": false,
499*90c8c64dSAndroid Build Coastguard Worker                             "force_rlib": false
500*90c8c64dSAndroid Build Coastguard Worker                         },
501*90c8c64dSAndroid Build Coastguard Worker                         "variant_package": {
502*90c8c64dSAndroid Build Coastguard Worker                             "add_module_block": "variant_module_block.bp"
503*90c8c64dSAndroid Build Coastguard Worker                         }
504*90c8c64dSAndroid Build Coastguard Worker                     }
505*90c8c64dSAndroid Build Coastguard Worker                 }
506*90c8c64dSAndroid Build Coastguard Worker             ]
507*90c8c64dSAndroid Build Coastguard Worker         }"#,
508*90c8c64dSAndroid Build Coastguard Worker         )
509*90c8c64dSAndroid Build Coastguard Worker         .unwrap();
510*90c8c64dSAndroid Build Coastguard Worker 
511*90c8c64dSAndroid Build Coastguard Worker         assert_eq!(
512*90c8c64dSAndroid Build Coastguard Worker             config,
513*90c8c64dSAndroid Build Coastguard Worker             Config {
514*90c8c64dSAndroid Build Coastguard Worker                 variants: vec![
515*90c8c64dSAndroid Build Coastguard Worker                     VariantConfig {
516*90c8c64dSAndroid Build Coastguard Worker                         generate_androidbp: true,
517*90c8c64dSAndroid Build Coastguard Worker                         generate_rulesmk: false,
518*90c8c64dSAndroid Build Coastguard Worker                         tests: true,
519*90c8c64dSAndroid Build Coastguard Worker                         features: None,
520*90c8c64dSAndroid Build Coastguard Worker                         vendor_available: true,
521*90c8c64dSAndroid Build Coastguard Worker                         package: [
522*90c8c64dSAndroid Build Coastguard Worker                             ("argh".to_string(), PackageVariantConfig { ..Default::default() }),
523*90c8c64dSAndroid Build Coastguard Worker                             (
524*90c8c64dSAndroid Build Coastguard Worker                                 "another".to_string(),
525*90c8c64dSAndroid Build Coastguard Worker                                 PackageVariantConfig {
526*90c8c64dSAndroid Build Coastguard Worker                                     device_supported: false,
527*90c8c64dSAndroid Build Coastguard Worker                                     force_rlib: true,
528*90c8c64dSAndroid Build Coastguard Worker                                     ..Default::default()
529*90c8c64dSAndroid Build Coastguard Worker                                 },
530*90c8c64dSAndroid Build Coastguard Worker                             ),
531*90c8c64dSAndroid Build Coastguard Worker                             ("rulesmk".to_string(), PackageVariantConfig { ..Default::default() }),
532*90c8c64dSAndroid Build Coastguard Worker                         ]
533*90c8c64dSAndroid Build Coastguard Worker                         .into_iter()
534*90c8c64dSAndroid Build Coastguard Worker                         .collect(),
535*90c8c64dSAndroid Build Coastguard Worker                         ..Default::default()
536*90c8c64dSAndroid Build Coastguard Worker                     },
537*90c8c64dSAndroid Build Coastguard Worker                     VariantConfig {
538*90c8c64dSAndroid Build Coastguard Worker                         generate_androidbp: false,
539*90c8c64dSAndroid Build Coastguard Worker                         generate_rulesmk: true,
540*90c8c64dSAndroid Build Coastguard Worker                         tests: false,
541*90c8c64dSAndroid Build Coastguard Worker                         features: Some(vec!["feature".to_string()]),
542*90c8c64dSAndroid Build Coastguard Worker                         vendor_available: false,
543*90c8c64dSAndroid Build Coastguard Worker                         package: [
544*90c8c64dSAndroid Build Coastguard Worker                             ("argh".to_string(), PackageVariantConfig { ..Default::default() }),
545*90c8c64dSAndroid Build Coastguard Worker                             (
546*90c8c64dSAndroid Build Coastguard Worker                                 "another".to_string(),
547*90c8c64dSAndroid Build Coastguard Worker                                 PackageVariantConfig {
548*90c8c64dSAndroid Build Coastguard Worker                                     alloc: false,
549*90c8c64dSAndroid Build Coastguard Worker                                     device_supported: false,
550*90c8c64dSAndroid Build Coastguard Worker                                     force_rlib: false,
551*90c8c64dSAndroid Build Coastguard Worker                                     ..Default::default()
552*90c8c64dSAndroid Build Coastguard Worker                                 },
553*90c8c64dSAndroid Build Coastguard Worker                             ),
554*90c8c64dSAndroid Build Coastguard Worker                             ("rulesmk".to_string(), PackageVariantConfig { ..Default::default() }),
555*90c8c64dSAndroid Build Coastguard Worker                             (
556*90c8c64dSAndroid Build Coastguard Worker                                 "variant_package".to_string(),
557*90c8c64dSAndroid Build Coastguard Worker                                 PackageVariantConfig {
558*90c8c64dSAndroid Build Coastguard Worker                                     add_module_block: Some("variant_module_block.bp".into()),
559*90c8c64dSAndroid Build Coastguard Worker                                     ..Default::default()
560*90c8c64dSAndroid Build Coastguard Worker                                 },
561*90c8c64dSAndroid Build Coastguard Worker                             ),
562*90c8c64dSAndroid Build Coastguard Worker                         ]
563*90c8c64dSAndroid Build Coastguard Worker                         .into_iter()
564*90c8c64dSAndroid Build Coastguard Worker                         .collect(),
565*90c8c64dSAndroid Build Coastguard Worker                         ..Default::default()
566*90c8c64dSAndroid Build Coastguard Worker                     },
567*90c8c64dSAndroid Build Coastguard Worker                 ],
568*90c8c64dSAndroid Build Coastguard Worker                 package: [
569*90c8c64dSAndroid Build Coastguard Worker                     (
570*90c8c64dSAndroid Build Coastguard Worker                         "argh".to_string(),
571*90c8c64dSAndroid Build Coastguard Worker                         PackageConfig {
572*90c8c64dSAndroid Build Coastguard Worker                             patch: Some("patches/Android.bp.patch".into()),
573*90c8c64dSAndroid Build Coastguard Worker                             ..Default::default()
574*90c8c64dSAndroid Build Coastguard Worker                         },
575*90c8c64dSAndroid Build Coastguard Worker                     ),
576*90c8c64dSAndroid Build Coastguard Worker                     (
577*90c8c64dSAndroid Build Coastguard Worker                         "another".to_string(),
578*90c8c64dSAndroid Build Coastguard Worker                         PackageConfig {
579*90c8c64dSAndroid Build Coastguard Worker                             add_toplevel_block: Some("block.bp".into()),
580*90c8c64dSAndroid Build Coastguard Worker                             ..Default::default()
581*90c8c64dSAndroid Build Coastguard Worker                         },
582*90c8c64dSAndroid Build Coastguard Worker                     ),
583*90c8c64dSAndroid Build Coastguard Worker                     (
584*90c8c64dSAndroid Build Coastguard Worker                         "rulesmk".to_string(),
585*90c8c64dSAndroid Build Coastguard Worker                         PackageConfig {
586*90c8c64dSAndroid Build Coastguard Worker                             rulesmk_patch: Some("patches/rules.mk.patch".into()),
587*90c8c64dSAndroid Build Coastguard Worker                             ..Default::default()
588*90c8c64dSAndroid Build Coastguard Worker                         },
589*90c8c64dSAndroid Build Coastguard Worker                     ),
590*90c8c64dSAndroid Build Coastguard Worker                 ]
591*90c8c64dSAndroid Build Coastguard Worker                 .into_iter()
592*90c8c64dSAndroid Build Coastguard Worker                 .collect(),
593*90c8c64dSAndroid Build Coastguard Worker             }
594*90c8c64dSAndroid Build Coastguard Worker         );
595*90c8c64dSAndroid Build Coastguard Worker     }
596*90c8c64dSAndroid Build Coastguard Worker 
597*90c8c64dSAndroid Build Coastguard Worker     /// Tests that variant configuration options are factored out to the top level where possible.
598*90c8c64dSAndroid Build Coastguard Worker     #[test]
factor_variants()599*90c8c64dSAndroid Build Coastguard Worker     fn factor_variants() {
600*90c8c64dSAndroid Build Coastguard Worker         let config = Config {
601*90c8c64dSAndroid Build Coastguard Worker             variants: vec![
602*90c8c64dSAndroid Build Coastguard Worker                 VariantConfig {
603*90c8c64dSAndroid Build Coastguard Worker                     features: Some(vec![]),
604*90c8c64dSAndroid Build Coastguard Worker                     tests: true,
605*90c8c64dSAndroid Build Coastguard Worker                     vendor_available: false,
606*90c8c64dSAndroid Build Coastguard Worker                     package: [(
607*90c8c64dSAndroid Build Coastguard Worker                         "argh".to_string(),
608*90c8c64dSAndroid Build Coastguard Worker                         PackageVariantConfig {
609*90c8c64dSAndroid Build Coastguard Worker                             dep_blocklist: vec!["bad_dep".to_string()],
610*90c8c64dSAndroid Build Coastguard Worker                             ..Default::default()
611*90c8c64dSAndroid Build Coastguard Worker                         },
612*90c8c64dSAndroid Build Coastguard Worker                     )]
613*90c8c64dSAndroid Build Coastguard Worker                     .into_iter()
614*90c8c64dSAndroid Build Coastguard Worker                     .collect(),
615*90c8c64dSAndroid Build Coastguard Worker                     ..Default::default()
616*90c8c64dSAndroid Build Coastguard Worker                 },
617*90c8c64dSAndroid Build Coastguard Worker                 VariantConfig {
618*90c8c64dSAndroid Build Coastguard Worker                     features: Some(vec![]),
619*90c8c64dSAndroid Build Coastguard Worker                     tests: true,
620*90c8c64dSAndroid Build Coastguard Worker                     product_available: false,
621*90c8c64dSAndroid Build Coastguard Worker                     module_name_overrides: [("argh".to_string(), "argh_nostd".to_string())]
622*90c8c64dSAndroid Build Coastguard Worker                         .into_iter()
623*90c8c64dSAndroid Build Coastguard Worker                         .collect(),
624*90c8c64dSAndroid Build Coastguard Worker                     vendor_available: false,
625*90c8c64dSAndroid Build Coastguard Worker                     package: [(
626*90c8c64dSAndroid Build Coastguard Worker                         "argh".to_string(),
627*90c8c64dSAndroid Build Coastguard Worker                         PackageVariantConfig {
628*90c8c64dSAndroid Build Coastguard Worker                             dep_blocklist: vec!["bad_dep".to_string()],
629*90c8c64dSAndroid Build Coastguard Worker                             no_std: true,
630*90c8c64dSAndroid Build Coastguard Worker                             ..Default::default()
631*90c8c64dSAndroid Build Coastguard Worker                         },
632*90c8c64dSAndroid Build Coastguard Worker                     )]
633*90c8c64dSAndroid Build Coastguard Worker                     .into_iter()
634*90c8c64dSAndroid Build Coastguard Worker                     .collect(),
635*90c8c64dSAndroid Build Coastguard Worker                     ..Default::default()
636*90c8c64dSAndroid Build Coastguard Worker                 },
637*90c8c64dSAndroid Build Coastguard Worker             ],
638*90c8c64dSAndroid Build Coastguard Worker             package: [(
639*90c8c64dSAndroid Build Coastguard Worker                 "argh".to_string(),
640*90c8c64dSAndroid Build Coastguard Worker                 PackageConfig { add_toplevel_block: Some("block.bp".into()), ..Default::default() },
641*90c8c64dSAndroid Build Coastguard Worker             )]
642*90c8c64dSAndroid Build Coastguard Worker             .into_iter()
643*90c8c64dSAndroid Build Coastguard Worker             .collect(),
644*90c8c64dSAndroid Build Coastguard Worker         };
645*90c8c64dSAndroid Build Coastguard Worker 
646*90c8c64dSAndroid Build Coastguard Worker         assert_eq!(
647*90c8c64dSAndroid Build Coastguard Worker             config.to_json_string().unwrap(),
648*90c8c64dSAndroid Build Coastguard Worker             r#"{
649*90c8c64dSAndroid Build Coastguard Worker   "features": [],
650*90c8c64dSAndroid Build Coastguard Worker   "package": {
651*90c8c64dSAndroid Build Coastguard Worker     "argh": {
652*90c8c64dSAndroid Build Coastguard Worker       "add_toplevel_block": "block.bp",
653*90c8c64dSAndroid Build Coastguard Worker       "dep_blocklist": [
654*90c8c64dSAndroid Build Coastguard Worker         "bad_dep"
655*90c8c64dSAndroid Build Coastguard Worker       ]
656*90c8c64dSAndroid Build Coastguard Worker     }
657*90c8c64dSAndroid Build Coastguard Worker   },
658*90c8c64dSAndroid Build Coastguard Worker   "tests": true,
659*90c8c64dSAndroid Build Coastguard Worker   "variants": [
660*90c8c64dSAndroid Build Coastguard Worker     {},
661*90c8c64dSAndroid Build Coastguard Worker     {
662*90c8c64dSAndroid Build Coastguard Worker       "module_name_overrides": {
663*90c8c64dSAndroid Build Coastguard Worker         "argh": "argh_nostd"
664*90c8c64dSAndroid Build Coastguard Worker       },
665*90c8c64dSAndroid Build Coastguard Worker       "package": {
666*90c8c64dSAndroid Build Coastguard Worker         "argh": {
667*90c8c64dSAndroid Build Coastguard Worker           "no_std": true
668*90c8c64dSAndroid Build Coastguard Worker         }
669*90c8c64dSAndroid Build Coastguard Worker       },
670*90c8c64dSAndroid Build Coastguard Worker       "product_available": false
671*90c8c64dSAndroid Build Coastguard Worker     }
672*90c8c64dSAndroid Build Coastguard Worker   ],
673*90c8c64dSAndroid Build Coastguard Worker   "vendor_available": false
674*90c8c64dSAndroid Build Coastguard Worker }"#
675*90c8c64dSAndroid Build Coastguard Worker         );
676*90c8c64dSAndroid Build Coastguard Worker     }
677*90c8c64dSAndroid Build Coastguard Worker 
678*90c8c64dSAndroid Build Coastguard Worker     #[test]
factor_trivial_variant()679*90c8c64dSAndroid Build Coastguard Worker     fn factor_trivial_variant() {
680*90c8c64dSAndroid Build Coastguard Worker         let config = Config {
681*90c8c64dSAndroid Build Coastguard Worker             variants: vec![VariantConfig {
682*90c8c64dSAndroid Build Coastguard Worker                 tests: true,
683*90c8c64dSAndroid Build Coastguard Worker                 package: [("argh".to_string(), Default::default())].into_iter().collect(),
684*90c8c64dSAndroid Build Coastguard Worker                 ..Default::default()
685*90c8c64dSAndroid Build Coastguard Worker             }],
686*90c8c64dSAndroid Build Coastguard Worker             package: Default::default(),
687*90c8c64dSAndroid Build Coastguard Worker         };
688*90c8c64dSAndroid Build Coastguard Worker 
689*90c8c64dSAndroid Build Coastguard Worker         assert_eq!(
690*90c8c64dSAndroid Build Coastguard Worker             config.to_json_string().unwrap(),
691*90c8c64dSAndroid Build Coastguard Worker             r#"{
692*90c8c64dSAndroid Build Coastguard Worker   "tests": true
693*90c8c64dSAndroid Build Coastguard Worker }"#
694*90c8c64dSAndroid Build Coastguard Worker         );
695*90c8c64dSAndroid Build Coastguard Worker     }
696*90c8c64dSAndroid Build Coastguard Worker }
697