xcframework/conf/
configuration.rs1use crate::cmd::modulemap;
2use anyhow::{Context, Result, anyhow, bail};
3use camino_fs::Utf8PathBuf;
4use cargo_metadata::{Metadata, MetadataCommand, Package, TargetKind};
5
6use super::{CliArgs, LibType, XCFrameworkConfiguration};
7
8#[derive(Debug)]
9pub struct Configuration {
10 pub cargo_section: XCFrameworkConfiguration,
11 pub cli: CliArgs,
12 pub lib_type: LibType,
13 pub lib_name: String,
15 pub target_dir: Utf8PathBuf,
17 pub build_dir: Utf8PathBuf,
19}
20
21impl Configuration {
22 pub fn new(
23 metadata: &Metadata,
24 package: &Package,
25 mut cli: CliArgs,
26 xc_conf: XCFrameworkConfiguration,
27 ) -> Result<Self> {
28 let target_dir = cli
30 .target_dir
31 .as_ref()
32 .unwrap_or(&metadata.target_directory)
33 .clone();
34
35 let build_dir = target_dir.join("xcframework");
36 let wanted_lib_type = cli.lib_type.clone().or_else(|| xc_conf.lib_type.clone());
37
38 let (lib_type, target) = get_libtype(package, wanted_lib_type)?;
39
40 if xc_conf.build_std && lib_type == LibType::StaticLib {
41 let already_set = cli
42 .unstable_flags
43 .as_ref()
44 .map(|f| f.contains("build-std=std"))
45 .unwrap_or(false);
46 if !already_set {
47 if let Some(flag) = cli.unstable_flags.to_owned() {
48 cli.unstable_flags = Some(format!("{flag},build-std=std"));
49 } else {
50 cli.unstable_flags = Some("build-std=std".to_string());
51 }
52 }
53 }
54 Ok(Self {
55 cargo_section: xc_conf,
56 cli,
57 lib_type,
58 lib_name: target.name.clone(),
59 target_dir,
60 build_dir,
61 })
62 }
63
64 pub fn load(cli: CliArgs) -> Result<Self> {
65 let manifest_path = cli
66 .manifest_path
67 .clone()
68 .unwrap_or_else(|| Utf8PathBuf::from("Cargo.toml"));
69 let mut dir = manifest_path.clone();
70 dir.pop();
71
72 let metadata = MetadataCommand::new().manifest_path(manifest_path).exec()?;
73
74 let workspace_packages = metadata.workspace_packages();
75 let package = if let Some(package) = &cli.package {
76 workspace_packages
77 .iter()
78 .find(|p| p.name.as_str() == package)
79 .ok_or(anyhow!("Could not find package '{package}'"))?
80 } else {
81 metadata
82 .root_package()
83 .ok_or(anyhow!("Could not find root package in metadata"))?
84 };
85
86 let Some(section) = package.metadata.get("xcframework") else {
87 bail!("Missing [package.metadata.xcframework] section in Cargo.toml");
88 };
89
90 let xc_conf = XCFrameworkConfiguration::parse(section, &dir, true)
91 .context("Error in Cargo.toml section [package.metadata.xcframework]")?;
92
93 Self::new(&metadata, package, cli, xc_conf)
94 }
95
96 pub fn module_name(&self) -> Result<String> {
97 modulemap::get_module_name(self)
98 }
99
100 pub fn profile(&self) -> &str {
101 if self.cli.release {
102 "release"
103 } else {
104 self.cli.profile.as_deref().unwrap_or("debug")
105 }
106 }
107}
108
109fn get_libtype(
110 package: &Package,
111 libtype: Option<LibType>,
112) -> Result<(LibType, &cargo_metadata::Target)> {
113 let staticlib = package.targets.iter().find(|t| {
114 t.kind.contains(&TargetKind::StaticLib) || t.kind.contains(&TargetKind::StaticLib)
115 });
116 let dylib = package
117 .targets
118 .iter()
119 .find(|t| t.kind.contains(&TargetKind::CDyLib) || t.kind.contains(&TargetKind::CDyLib));
120 use LibType::*;
121 Ok(match (staticlib, dylib, libtype) {
122 (Some(staticlib), None, None) => (StaticLib, staticlib),
123 (Some(staticlib), _, Some(StaticLib)) => (StaticLib, staticlib),
124 (Some(_staticlib), None, Some(CDyLib)) => {
125 bail!("Please add 'cdylib' to '[lib] crate-type' in Cargo.toml")
126 }
127 (None, Some(dylib), None) => (CDyLib, dylib),
128 (_, Some(dylib), Some(CDyLib)) => (CDyLib, dylib),
129 (_, Some(_dylib), Some(StaticLib)) => {
130 bail!("Please add 'staticlib' to '[lib] crate-type' in Cargo.toml")
131 }
132 (Some(_), Some(_), None) => {
133 bail!("Please set '[package.metadata.xcframework] lib-type' in Cargo.toml")
134 }
135 (None, None, _) => bail!("Missing '[lib] crate-type' in Cargo.toml"),
136 })
137}