// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Configures gnrt behavior. Types match `gnrt_config.toml` fields. Currently
//! only used for std bindings.
use crate::group::Group;
use std::collections::{BTreeMap, HashMap, HashSet};
use serde::Deserialize;
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct BuildConfig {
pub resolve: ResolveConfig,
#[serde(rename = "gn")]
pub gn_config: GnConfig,
#[serde(rename = "vet")]
pub vet_config: VetConfig,
/// Configuration that applies to all crates
#[serde(rename = "all-crates")]
pub all_config: CrateConfig,
/// Additional configuration options for specific crates. Keyed by crate
/// name. Config is additive with `all_config`.
#[serde(rename = "crate")]
pub per_crate_config: BTreeMap<String, CrateConfig>,
}
impl BuildConfig {
/// Combines the global and per-crate `CrateConfig` for a single
/// `Vec<String>` entry.
pub fn get_combined_set(
&self,
package_name: &str,
entry_getter: impl Fn(&CrateConfig) -> &Vec<String>,
) -> HashSet<&str> {
let all: Option<&Vec<String>> = Some(entry_getter(&self.all_config));
let per: Option<&Vec<String>> = self.per_crate_config.get(package_name).map(entry_getter);
all.into_iter().chain(per).flatten().map(String::as_str).collect()
}
}
/// Configures GN output for this session.
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct GnConfig {
/// Path to a handlebars template for an output GN build file. The path is
/// relative to the config file.
pub build_file_template: std::path::PathBuf,
/// Path to a handlebars template for writing README.chromium files. The
/// path is relative to the config file. Only used for
/// //third_party/rust crates.
#[serde(default)]
pub readme_file_template: std::path::PathBuf,
/// Path to a handlebars template for writing placeholder crates that we
/// don't want to vendor. This is the Cargo.toml file.
#[serde(default)]
pub removed_cargo_template: std::path::PathBuf,
/// Path to a handlebars template for writing placeholder crates that we
/// don't want to vendor. This is the src/lib.rs file.
#[serde(default)]
pub removed_librs_template: std::path::PathBuf,
}
/// Configures Cargo Vet output for this session.
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct VetConfig {
/// Path to a handlebars template for writing Cargo Vet's config.toml file.
/// The path is relative to the config file. Only used for
/// //third_party/rust crates.
#[serde(default)]
pub config_template: std::path::PathBuf,
}
/// Influences dependency resolution for a session.
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ResolveConfig {
/// The Cargo package to use as the root of the dependency graph.
pub root: String,
/// Remove crates from the set of resolved dependencies. Should be used
/// sparingly; it does not affect Cargo's dependency resolution, so the
/// output can easily be incorrect. This is primarily intended to work
/// around bugs in `cargo metadata` output.
pub remove_crates: Vec<String>,
}
/// Customizes GN output for a crate.
#[derive(Clone, Debug, Default, Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct CrateConfig {
/// Dependencies to remove from this crate. Note that this happens after
/// dependency and feature resolution, so if an optional dep's feature is
/// enabled but the dep is removed, the crate will still attempt to
/// reference that dependency.
pub remove_deps: Vec<String>,
/// Deps on generated targets to exclude from this target's `deps` list.
/// These do not affect dependency resolution, so it will not change any
/// other generated targets.
pub exclude_deps_in_gn: Vec<String>,
/// Features that are disallowed (e.g. because the feature-gated code hasn't
/// been audited or because the audit uncovered unsoundness)
pub ban_features: Vec<String>,
/// If true, the build script should not be built or used.
#[serde(default)]
pub remove_build_rs: bool,
/// Include rs and input files under these paths relative to the crate's
/// root source file as part of the crate. The roots may each be a single
/// file or a directory.
#[serde(default)]
pub extra_src_roots: Vec<std::path::PathBuf>,
/// Include input files under these paths relative to the crate's root
/// source file as part of the crate. The roots may each be a single file or
/// a directory.
#[serde(default)]
pub extra_input_roots: Vec<std::path::PathBuf>,
/// Include rs and input files under these relative paths as part of the
/// crate's build script. The roots may each be a single file or a
/// directory.
#[serde(default)]
pub extra_build_script_src_roots: Vec<std::path::PathBuf>,
/// Include input files under these relative paths as part of the crate's
/// build script. The roots may each be a single file or a directory.
#[serde(default)]
pub extra_build_script_input_roots: Vec<std::path::PathBuf>,
#[serde(default)]
pub extra_kv: HashMap<String, serde_json::Value>,
/// Names of binary targets to include. This list is empty by default,
/// which means that the default generated `BUILD.gn` will only cover
/// the library target (if any) of the package.
#[serde(default)]
pub bin_targets: Vec<String>,
// Third-party crate settings.
#[serde(default)]
pub allow_first_party_usage: bool,
#[serde(default)]
pub build_script_outputs: Vec<std::path::PathBuf>,
#[serde(default)]
pub group: Option<Group>,
#[serde(default)]
pub security_critical: Option<bool>,
#[serde(default)]
pub shipped: Option<bool>,
#[serde(default)]
pub license: Option<String>,
#[serde(default)]
pub license_files: Vec<String>,
/// Include `.lib` files under these paths relative to the crate's root
/// source file as part of the crate. They will be available for #[link]
/// directives in the crate. The roots may each be a single file or a
/// directory.
///
/// These paths are the only ones searched for lib files, unlike
/// `extra_src_roots`. Nothing is searched if this is empty.
#[serde(default)]
pub native_libs_roots: Vec<std::path::PathBuf>,
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_get_combined_set_with_global_and_per_crate_entry() {
let all_config =
CrateConfig { bin_targets: vec!["foo".to_string()], ..CrateConfig::default() };
let crate_config =
CrateConfig { bin_targets: vec!["bar".to_string()], ..CrateConfig::default() };
let build_config = BuildConfig {
all_config,
per_crate_config: [("some_crate".to_string(), crate_config)].into_iter().collect(),
..BuildConfig::default()
};
let combined_set = build_config.get_combined_set("some_crate", |cfg| &cfg.bin_targets);
assert_eq!(combined_set.len(), 2);
assert!(combined_set.contains("foo"));
assert!(combined_set.contains("bar"));
}
#[test]
fn test_get_combined_set_with_only_global_entry() {
let all_config =
CrateConfig { bin_targets: vec!["foo".to_string()], ..CrateConfig::default() };
let build_config = BuildConfig { all_config, ..BuildConfig::default() };
let combined_set = build_config.get_combined_set("some_crate", |cfg| &cfg.bin_targets);
assert_eq!(combined_set.len(), 1);
assert!(combined_set.contains("foo"));
}
}