cli/commands/build/
build_context.rs1use crate::{
2 cargo_manifest::{CargoManifest, CargoPackage, Metadata},
3 error::{Error, Result},
4};
5use creator_tools::{
6 commands::{
7 android, apple, find_package_cargo_manifest_path, find_workspace_cargo_manifest_path,
8 },
9 tools::AndroidSdk,
10 types::{
11 android_manifest::AndroidManifest, apple_bundle::prelude::InfoPlist, AndroidTarget,
12 AppleTarget,
13 },
14 utils::Config,
15};
16use std::path::PathBuf;
17
18pub struct BuildContext {
19 pub workspace_manifest_path: PathBuf,
20 pub package_manifest_path: PathBuf,
21 pub project_path: PathBuf,
22 pub cargo_manifest: CargoManifest,
23 pub cargo_package: CargoPackage<Metadata>,
24 pub target_dir: PathBuf,
25}
26
27impl BuildContext {
28 pub fn new(config: &Config, target_dir: Option<PathBuf>) -> Result<Self> {
29 let workspace_manifest_path = find_workspace_cargo_manifest_path(config.current_dir())?;
30 let package_manifest_path = find_package_cargo_manifest_path(config.current_dir())?;
31 let project_path = package_manifest_path.parent().unwrap().to_owned();
32 let target_dir =
33 target_dir.unwrap_or_else(|| workspace_manifest_path.parent().unwrap().join("target"));
34 info!("Parsing Cargo.toml");
35 let cargo_manifest = CargoManifest::from_path_with_metadata(&package_manifest_path)?;
36 let cargo_package = cargo_manifest
37 .package
38 .clone()
39 .ok_or(Error::InvalidManifest)?;
40 Ok(Self {
41 workspace_manifest_path,
42 package_manifest_path,
43 project_path,
44 cargo_manifest,
45 cargo_package,
46 target_dir,
47 })
48 }
49
50 pub fn package_name(&self) -> String {
51 self.cargo_package.name.clone()
52 }
53
54 pub fn package_version(&self) -> String {
55 self.cargo_package.version.clone()
56 }
57
58 pub fn target_sdk_version(&self, sdk: &AndroidSdk) -> u32 {
59 if let Some(metadata) = &self.cargo_package.metadata {
60 if let Some(target_sdk_version) = metadata.target_sdk_version {
61 return target_sdk_version;
62 };
63 };
64 sdk.default_platform()
65 }
66
67 pub fn android_build_targets(&self, build_targets: &Vec<AndroidTarget>) -> Vec<AndroidTarget> {
68 if !build_targets.is_empty() {
69 return build_targets.clone();
70 };
71 if self.cargo_package.metadata.is_none() {
72 return vec![AndroidTarget::Aarch64LinuxAndroid];
73 };
74 let targets = self
75 .cargo_package
76 .metadata
77 .clone()
78 .unwrap()
79 .android_build_targets;
80 if targets.is_some() && !targets.as_ref().unwrap().is_empty() {
81 return targets.unwrap();
82 };
83 vec![AndroidTarget::Aarch64LinuxAndroid]
84 }
85
86 pub fn android_res(&self) -> Option<PathBuf> {
87 self.cargo_package
88 .metadata
89 .as_ref()
90 .map(|m| m.android_res.clone())
91 .unwrap_or_default()
92 }
93
94 pub fn android_assets(&self) -> Option<PathBuf> {
95 self.cargo_package
96 .metadata
97 .as_ref()
98 .map(|m| m.android_assets.clone())
99 .unwrap_or_default()
100 }
101
102 pub fn gen_android_manifest(
103 &self,
104 sdk: &AndroidSdk,
105 package_name: &String,
106 debuggable: bool,
107 ) -> Result<AndroidManifest> {
108 if let Some(metadata) = &self.cargo_package.metadata {
109 if metadata.use_android_manifest {
110 let path = metadata
111 .android_manifest_path
112 .clone()
113 .unwrap_or_else(|| self.project_path.join("AndroidManifest.xml"));
114 Ok(android::read_android_manifest(&path)?)
115 } else {
116 let mut manifest = android::gen_minimal_android_manifest(
117 metadata.android_app_id.clone(),
118 package_name,
119 metadata.app_name.clone(),
120 metadata
121 .version_name
122 .clone()
123 .unwrap_or(self.package_version()),
124 metadata.version_code.clone(),
125 metadata.min_sdk_version,
126 metadata
127 .target_sdk_version
128 .unwrap_or_else(|| sdk.default_platform()),
129 metadata.max_sdk_version,
130 metadata.icon.clone(),
131 debuggable,
132 );
133 if !metadata.android_permissions.is_empty() {
134 manifest.uses_permission = metadata.android_permissions.clone();
135 }
136 Ok(manifest)
137 }
138 } else {
139 let target_sdk_version = sdk.default_platform();
140 Ok(android::gen_minimal_android_manifest(
141 None,
142 package_name,
143 None,
144 self.package_version(),
145 None,
146 None,
147 target_sdk_version,
148 None,
149 None,
150 debuggable,
151 ))
152 }
153 }
154
155 pub fn gen_info_plist(&self, package_name: &String) -> Result<InfoPlist> {
156 if let Some(metadata) = &self.cargo_package.metadata {
157 if metadata.use_info_plist {
158 let path = metadata
159 .info_plist_path
160 .clone()
161 .unwrap_or_else(|| self.project_path.join("Info.plist"));
162 Ok(apple::read_info_plist(&path)?)
163 } else {
164 Ok(apple::gen_minimal_info_plist(
165 package_name,
166 metadata.app_name.clone(),
167 metadata
168 .version_name
169 .clone()
170 .unwrap_or(self.package_version()),
171 ))
172 }
173 } else {
174 Ok(apple::gen_minimal_info_plist(
175 package_name,
176 None,
177 self.package_version(),
178 ))
179 }
180 }
181
182 pub fn apple_build_targets(&self, build_targets: &Vec<AppleTarget>) -> Vec<AppleTarget> {
183 if !build_targets.is_empty() {
184 return build_targets.clone();
185 };
186 if self.cargo_package.metadata.is_none() {
187 return vec![AppleTarget::X86_64AppleIos];
188 };
189 let targets = self
190 .cargo_package
191 .metadata
192 .clone()
193 .unwrap()
194 .apple_build_targets;
195 if targets.is_some() && !targets.as_ref().unwrap().is_empty() {
196 return targets.unwrap();
197 };
198 vec![AppleTarget::X86_64AppleIos]
199 }
200
201 pub fn apple_res(&self) -> Option<PathBuf> {
202 self.cargo_package
203 .metadata
204 .as_ref()
205 .map(|m| m.apple_res.clone())
206 .unwrap_or_default()
207 }
208
209 pub fn apple_assets(&self) -> Option<PathBuf> {
210 self.cargo_package
211 .metadata
212 .as_ref()
213 .map(|m| m.apple_assets.clone())
214 .unwrap_or_default()
215 }
216}