xargo_lib/
config.rs

1use std::path::PathBuf;
2
3use anyhow::{anyhow, Result};
4use serde::Deserialize;
5
6#[derive(Debug, Hash)]
7pub struct Config {
8    pub memcpy: bool,
9    pub sysroot_path: PathBuf,
10    pub panic_immediate_abort: bool,
11}
12
13#[derive(Debug, Deserialize, Default)]
14struct ParseConfig {
15    pub memcpy: Option<bool>,
16    pub sysroot_path: Option<String>,
17    pub panic_immediate_abort: Option<bool>,
18}
19
20impl Config {
21    pub fn from_metadata(metadata: &cargo_metadata::Metadata, quiet: bool) -> Result<Config> {
22        let root_manifest = metadata.workspace_root.join("Cargo.toml");
23        let root_package = metadata
24            .packages
25            .iter()
26            .find(|package| package.manifest_path == root_manifest);
27
28        let config = match root_package {
29            Some(root_package) => {
30                let crate_metadata = root_package.metadata.get("cargo-xbuild");
31                match crate_metadata {
32                    Some(json) => serde_json::from_value(json.clone()).map_err(|e| {
33                        anyhow!(
34                            "parsing package.metadata.cargo-xbuild section failed: {}",
35                            e
36                        )
37                    })?,
38                    None => ParseConfig::default(),
39                }
40            }
41            None => {
42                // The project has no root package. This could be because it only defines a
43                // dummy `Cargo.toml` at the root without a `[package]` section.
44                //
45                // The problem in this case is that we don't have a reasonable place to read
46                // the config from. There are multiple `Cargo.toml`s in this workspace and it
47                // is not clear which one is the "canonical" Cargo.toml with the xbuild config.
48                //
49                // So we can't read the config for such projects. To make this transparent to
50                // the user, we print a warning.
51                if !quiet {
52                    eprintln!(
53                        "WARNING: There is no root package to read the cargo-xbuild config from."
54                    );
55                }
56                // There is no config to read, so we use default options
57                ParseConfig::default()
58            }
59        };
60
61        Ok(Config {
62            memcpy: config.memcpy.unwrap_or(true),
63            sysroot_path: PathBuf::from(config.sysroot_path.unwrap_or("target/sysroot".into())),
64            panic_immediate_abort: config.panic_immediate_abort.unwrap_or(false),
65        })
66    }
67}