xcode_build_rs/
lib.rs

1// //! # Warning: This library is unstable, only the executable's behaviour is subject to semver
2
3// use std::env;
4
5// use camino::{Utf8Path, Utf8PathBuf};
6// use clap::{Args, Parser, Subcommand};
7// use color_eyre::{
8// 	eyre::{eyre, Context as _, Report},
9// 	Section as _,
10// };
11// use serde::Deserialize;
12// use tracing::info;
13
14// #[derive(Parser, Debug)]
15// #[command(version, about)]
16// #[command(name = "cargo", bin_name = "cargo")]
17// pub enum TopLevel {
18// 	#[clap(name = "xcode-build-rs")]
19// 	XCodeBuild(XcodeBuild),
20// }
21
22// impl TopLevel {
23// 	fn inner(&self) -> &XcodeBuild {
24// 		match self {
25// 			TopLevel::XCodeBuild(inner) => inner,
26// 		}
27// 	}
28// }
29
30// #[derive(clap::Args, Debug)]
31// #[command(version, about)]
32// pub struct XcodeBuild {
33// 	#[clap(subcommand)]
34// 	mode: Mode,
35
36// 	#[clap(flatten)]
37// 	options: Options,
38// }
39
40// impl TopLevel {
41// 	pub fn options(&self) -> &Options {
42// 		&self.inner().options
43// 	}
44
45// 	pub fn mode(&self) -> &Mode {
46// 		&self.inner().mode
47// 	}
48// }
49
50// #[derive(Subcommand, Clone, Debug)]
51// pub enum Mode {
52// 	/// Run in XCode
53// 	Xcode,
54// 	/// Run a test build for an iOS simulator
55// 	Test,
56// }
57
58// #[derive(Args, Debug)]
59// pub struct Options {
60// 	/// By default, doesn't display colour because this can be annoying in the XCode terminal
61// 	#[arg(long, alias = "colour")]
62// 	pub colour: bool,
63
64// 	/// The --manifest-path option to pass to `cargo rustc builds`.
65// 	/// Often you can pass `.`
66// 	#[arg(long, alias = "manifest-dir")]
67// 	manifest_dir: Utf8PathBuf,
68// }
69
70// impl Options {
71// 	/// Specifically to the *file* `Cargo.toml`, *not directory*
72// 	pub fn manifest_path(&self) -> Utf8PathBuf {
73// 		self.manifest_dir.to_owned().join("Cargo.toml")
74// 	}
75// }
76
77// #[derive(Deserialize, Debug, Default)]
78// pub struct Config {
79// 	/// What features to enable for iOS builds
80// 	#[serde(default)]
81// 	ios: Flags,
82// }
83
84// #[derive(Debug, Deserialize, Clone)]
85// pub struct Flags {
86// 	#[serde(default)]
87// 	features: Vec<String>,
88// 	/// Whether or not to pass the flag `--no-default-features` to `cargo rustc`
89// 	/// See https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options
90// 	#[serde(default = "Flags::default_default_features")]
91// 	default_features: bool,
92// }
93
94// impl Flags {
95// 	/// Default for [Self::default_features]
96// 	fn default_default_features() -> bool {
97// 		true
98// 	}
99// }
100
101// impl Default for Flags {
102// 	fn default() -> Self {
103// 		Flags {
104// 			default_features: Flags::default_default_features(),
105// 			features: vec![],
106// 		}
107// 	}
108// }
109
110// impl Config {
111// 	pub fn retrieve_from_toml_config(manifest_path: &Utf8Path) -> Result<Config, Report> {
112// 		match std::fs::read_to_string(manifest_path) {
113// 			Err(err) => {
114// 				info!(
115// 					message = "Cannot find `Cargo.toml` file in manifest_dir, using default config",
116// 					?err,
117// 					?manifest_path
118// 				);
119// 				Ok(Config::default())
120// 			}
121// 			Ok(config) => {
122// 				let raw_config: toml::Value = toml::from_str(&config)
123// 					.wrap_err_with(|| format!("Cannot parse Cargo.toml file: {:?}", manifest_path))?;
124// 				let config = raw_config
125// 					.get("package")
126// 					.and_then(|package| package.get("metadata"))
127// 					.and_then(|metadata| metadata.get("xcode-build-rs"));
128// 				match config {
129// 					None => {
130// 						info!("Using default config since `package.metadata.xcode_build_rs` section is missing from Cargo.toml");
131// 						Ok(Config::default())
132// 					}
133// 					Some(config) => {
134// 						let config: Config = config
135// 							.clone()
136// 							.try_into()
137// 							.wrap_err("Cannot deserialize `xcode-build-rs` section of Cargo.toml")?;
138// 						info!(message = "Deserialized Config from Cargo.toml", ?config);
139// 						Ok(config)
140// 					}
141// 				}
142// 			}
143// 		}
144// 	}
145
146// 	pub fn ios_feature_flags(&self) -> Flags {
147// 		self.ios.clone()
148// 	}
149// }
150
151// impl Flags {
152// 	pub fn into_args(&self) -> Vec<String> {
153// 		let mut args = vec![];
154// 		if !self.default_features {
155// 			args.push("--no-default-features".into());
156// 		}
157// 		for feature in self.features.iter() {
158// 			args.push("--features".into());
159// 			args.push(feature.clone());
160// 		}
161// 		args
162// 	}
163// }
164
165// pub fn release_profile() -> Result<bool, Report> {
166// 	let mut is_release_build = true;
167// 	const CONFIGURATION: &str = "CONFIGURATION";
168// 	let configuration_env_var = env::var(CONFIGURATION);
169// 	if configuration_env_var == Ok("Release".into()) {
170// 		is_release_build = true;
171// 		info!(
172// 			message =
173// 				"Assuming a --release profile since the CONFIGURATION env flag was set to 'Release'",
174// 			?configuration_env_var
175// 		);
176// 	} else if configuration_env_var == Ok("Debug".into()) {
177// 		is_release_build = false;
178// 		info!(
179// 			message =
180// 				"Assuming not a release profile since the CONFIGURATION env flag was set to 'Debug'",
181// 			?configuration_env_var
182// 		);
183// 	} else {
184// 		info!(
185// 			message = "No known release profile was provided in the CONFIGURATION env var",
186// 			?configuration_env_var,
187// 			?is_release_build
188// 		);
189// 	}
190// 	Ok(is_release_build)
191// }
192
193// pub fn is_simulator() -> Result<bool, Report> {
194// 	let mut is_simulator = false;
195// 	if let Some(llvm_target_triple_suffix) = env::var_os("LLVM_TARGET_TRIPLE_SUFFIX") {
196// 		if llvm_target_triple_suffix == *"-simulator" {
197// 			info!(
198// 				message = "Assuming building for a simulator",
199// 				?llvm_target_triple_suffix
200// 			);
201// 			is_simulator = true;
202// 		}
203// 	}
204// 	Ok(is_simulator)
205// }
206
207// pub enum Archs {
208// 	X86_64,
209// 	Arm64,
210// }
211
212// pub fn parse_archs() -> color_eyre::Result<Archs> {
213// 	impl Archs {
214// 		fn try_from_str(str: &str) -> Result<Self, Report> {
215// 			Ok(match str {
216// 				"x86_64" => Archs::X86_64,
217// 				"arm64" => Archs::Arm64,
218// 				_ => {
219// 					return Err(eyre!("Cannot parse ARCHS env variable").note(format!("ARCHS: {:?}", str)))
220// 				}
221// 			})
222// 		}
223// 	}
224
225// 	match env::var("ARCHS") {
226// 		Err(e) => Err(e).wrap_err("No ARCHS env var present")?,
227// 		Ok(archs) => Archs::try_from_str(&archs),
228// 	}
229// }
230
231// pub fn rustc(
232// 	target: &'static str,
233// 	release: bool,
234// 	flags: Flags,
235// 	manifest_dir: &Utf8Path,
236// ) -> Result<(), Report> {
237// 	let rustc_path = which::which("cargo").wrap_err("Cannot find cargo executable path")?;
238// 	// don't change this to pure. just don't.
239// 	let mut rustc = bossy::Command::impure(&rustc_path).with_args([
240// 		"rustc",
241// 		"--crate-type",
242// 		"staticlib",
243// 		"--lib",
244// 		"--target",
245// 		target,
246// 		"--manifest-path",
247// 		manifest_dir.as_str(),
248// 	]);
249// 	for flag in flags.into_args() {
250// 		rustc.add_arg(flag);
251// 	}
252// 	if release {
253// 		rustc.add_arg("--release");
254// 	}
255// 	info!(message = "About to run rustc", cwd = ?cwd(), ?rustc_path, ?flags, ?manifest_dir);
256// 	rustc
257// 		.run_and_wait()
258// 		.wrap_err("rustc invocation failed, likely a Rust-side build error")?;
259// 	Ok(())
260// }
261
262// pub fn cwd() -> Result<Utf8PathBuf, Report> {
263// 	Utf8PathBuf::try_from(env::current_dir().wrap_err("Cannot find cwd")?).wrap_err("CWD is not UTF8")
264// }
265
266// pub fn debug_confirm_on_path(
267// 	paths: &[std::path::PathBuf],
268// 	bin: &'static str,
269// ) -> Result<bool, Report> {
270// 	let bin_path = which::which(bin).wrap_err("Couldn't find binary")?;
271// 	let bin_dir = {
272// 		let mut bin_path = bin_path.clone();
273// 		bin_path.pop();
274// 		bin_path
275// 	};
276// 	let bin_contained = paths.contains(&bin_dir);
277// 	info!(
278// 		?bin_contained,
279// 		?bin_dir,
280// 		?bin_path,
281// 		"Debug searching for `{}` bin path, was successful: {}",
282// 		bin,
283// 		bin_contained
284// 	);
285// 	Ok(bin_contained)
286// }