zoi_cli/cmd/package/
build.rs1use std::path::PathBuf;
7
8use anyhow::Result;
9use clap::Parser;
10use colored::Colorize;
11
12#[derive(Parser, Debug)]
14pub struct BuildCommand {
15 #[arg(required = true)]
17 pub package_file: PathBuf,
18
19 #[arg(long)]
21 pub r#type: Option<String>,
22
23 #[arg(long, short, num_args = 1.., default_values_t = vec!["current".to_string()])]
26 pub platform: Vec<String>,
27
28 #[arg(long, num_args = 1..)]
30 pub sub: Option<Vec<String>>,
31
32 #[arg(long)]
34 pub sign: Option<String>,
35
36 #[arg(long)]
38 pub test: bool,
39
40 #[arg(long, short = 'o')]
42 pub output_dir: Option<PathBuf>,
43
44 #[arg(long)]
46 pub install_deps: bool,
47
48 #[arg(long)]
50 pub version_override: Option<String>,
51
52 #[arg(long, default_value = "native")]
54 pub method: String,
55
56 #[arg(long)]
58 pub image: Option<String>,
59
60 #[arg(long)]
62 pub fakeroot: bool,
63
64 #[arg(long)]
68 pub pure: bool,
69
70 #[arg(long, default_value = "@core/base:dev")]
73 pub root_package: String,
74
75 #[arg(long)]
78 pub no_zsa: bool
79}
80
81pub fn run(mut args: BuildCommand) -> Result<()> {
88 let mut _temp_root = None;
89
90 if args.pure {
91 if args.method == "docker" {
92 return Err(anyhow::anyhow!(
93 "--pure is not compatible with --method docker"
94 ));
95 }
96 args.method = "bwrap".to_string();
97
98 let temp = tempfile::Builder::new().prefix("zoi-pure-").tempdir()?;
99 println!(
100 "{} Initializing pure build environment in {}...",
101 "::".bold().blue(),
102 temp.path().display()
103 );
104
105 let etc_dir = temp.path().join("etc");
109 std::fs::create_dir_all(&etc_dir)?;
110 std::fs::write(
111 etc_dir.join("os-release"),
112 "ID=zoios\nID_LIKE=zoios\n"
113 )?;
114
115 crate::pkg::sysroot::set_sysroot(temp.path().to_path_buf());
116 _temp_root = Some(temp);
117
118 let root_dep = crate::pkg::dependencies::parse_dependency_string(
120 &args.root_package
121 )?;
122 crate::pkg::install::dep_install::install_dependency(
123 &root_dep,
124 "pure-root",
125 crate::pkg::types::Scope::System,
126 true,
127 true,
128 &std::sync::Mutex::new(std::collections::HashSet::new()),
129 &mut Vec::new(),
130 None
131 )?;
132 }
133
134 if args.install_deps {
135 install_dependencies_for_build(&args, args.test)?;
136 }
137
138 if args.test {
139 println!("Running tests before building...");
140 crate::pkg::package::test::run(&args)?;
141 println!("Tests passed, proceeding with build...");
142 }
143
144 let mut _temp_zsa_bundle = None;
149 if !args.no_zsa && args.package_file.to_string_lossy().ends_with(".pkg.lua")
150 {
151 let temp = tempfile::Builder::new()
152 .prefix("zoi-build-zsa-")
153 .tempdir()?;
154 println!("{} Bundling source archive...", "::".bold().blue());
155 let zsa_path = crate::pkg::package::bundle::run(
156 &args.package_file,
157 Some(temp.path()),
158 None,
159 args.version_override.as_deref(),
160 args.r#type.as_deref()
161 )?;
162
163 if args.output_dir.is_none() {
167 args.output_dir = args.package_file.parent().map(PathBuf::from);
168 }
169
170 println!("{} Building from source bundle...", "::".bold().blue());
171 args.package_file = zsa_path;
172 _temp_zsa_bundle = Some(temp);
173 }
174
175 crate::pkg::package::build::run(
176 &args.package_file,
177 args.r#type.as_deref(),
178 &args.platform,
179 args.sign,
180 args.output_dir.as_deref(),
181 args.version_override.as_deref(),
182 args.sub,
183 false,
184 &args.method,
185 args.image.as_deref(),
186 args.fakeroot,
187 args.install_deps,
188 args.test
189 )
190}
191
192pub fn install_dependencies_for_build(
199 args: &BuildCommand,
200 include_test: bool
201) -> Result<()> {
202 for platform in &args.platform {
203 let current_platform = if platform == "current" {
204 crate::pkg::utils::get_platform()?
205 } else {
206 platform.clone()
207 };
208
209 if let Some(mut dep_strings) =
210 crate::pkg::package::build::get_build_dependencies(
211 &args.package_file,
212 args.r#type.as_deref(),
213 ¤t_platform,
214 args.version_override.as_deref(),
215 false
216 )?
217 {
218 if include_test
219 && let Some(test_deps) =
220 crate::pkg::package::build::get_test_dependencies(
221 &args.package_file,
222 ¤t_platform,
223 args.version_override.as_deref(),
224 false
225 )?
226 {
227 dep_strings.extend(test_deps);
228 }
229
230 if !dep_strings.is_empty() {
231 println!(
232 "{} Installing build/test dependencies...",
233 "::".bold().blue()
234 );
235 let processed =
236 std::sync::Mutex::new(std::collections::HashSet::new());
237 let mut installed = Vec::new();
238 for dep_str in dep_strings {
239 let dep =
240 crate::pkg::dependencies::parse_dependency_string(
241 &dep_str
242 )?;
243 crate::pkg::install::dep_install::install_dependency(
244 &dep,
245 "build",
246 if crate::pkg::sysroot::get_sysroot().is_some() {
247 crate::pkg::types::Scope::System
248 } else {
249 crate::pkg::types::Scope::User
250 },
251 true,
252 true,
253 &processed,
254 &mut installed,
255 None
256 )?;
257 }
258 }
259 }
260 }
261 Ok(())
262}