polyhorn_cli/ios/tasks/
mod.rs

1//! Tasks and context specific for building and running on iOS.
2
3use std::collections::HashMap;
4use std::path::PathBuf;
5
6mod boot_ios_simulator;
7mod build_runtime_library;
8mod build_runtime_library_v2;
9mod build_xcodeproj;
10mod create_universal_binary;
11mod generate_xcassets;
12mod generate_xcodeproj;
13mod install_on_ios_simulator;
14mod open_ios_simulator;
15mod run_on_ios_simulator;
16
17pub use boot_ios_simulator::BootIOSSimulator;
18pub use build_runtime_library::BuildRuntimeLibrary;
19pub use build_runtime_library_v2::BuildRuntimeLibraryV2;
20pub use build_xcodeproj::BuildXcodeproj;
21pub use create_universal_binary::CreateUniversalBinary;
22pub use generate_xcassets::GenerateXcassets;
23pub use generate_xcodeproj::GenerateXcodeproj;
24pub use install_on_ios_simulator::InstallOnIOSSimulator;
25pub use open_ios_simulator::OpenIOSSimulator;
26pub use run_on_ios_simulator::RunOnIOSSimulator;
27
28pub use crate::core::tasks::InstallTarget;
29pub use crate::core::tasks::{Dependency, DependencyCheck, InstallDependencies};
30
31use crate::core::{Manager, Task};
32use crate::Config;
33
34/// Context that gets passed through each task.
35#[derive(Debug)]
36pub struct IOSContext {
37    /// The platform-independent configuration that gets passed to each command.
38    pub config: Config,
39
40    /// A map between iOS architectures and the path to the product for each.
41    pub products: HashMap<String, PathBuf>,
42
43    /// This will contain a path to the universal binary which is basically a
44    /// bundle of architecture-specific static libraries.
45    pub universal_binary_path: Option<PathBuf>,
46}
47
48/// Represents one of the iOS-specific tasks.
49pub enum IOSTask {
50    /// This task boots an iOS Simulator (if necessary).
51    BootIOSSimulator(BootIOSSimulator),
52
53    /// This task builds the runtime library for the given target and with the
54    /// given profile.
55    BuildRuntimeLibrary(BuildRuntimeLibrary),
56
57    /// This task builds the runtime library for the given target and with the
58    /// given profile.
59    BuildRuntimeLibraryV2(BuildRuntimeLibraryV2),
60
61    /// This task builds an .xcodeproj with a given scheme, configuration and
62    /// destination.
63    BuildXcodeproj(BuildXcodeproj),
64
65    /// This task creates a universal binary from one or multiple
66    /// architecture-specific static libraries for iOS.
67    CreateUniversalBinary(CreateUniversalBinary),
68
69    /// This task generates an Xcode-compatible assets catalog for the assets of
70    /// the Polyhorn project that is being compiled and its dependencies.
71    GenerateXcassets(GenerateXcassets),
72
73    /// This task generates an xcodeproj.
74    GenerateXcodeproj(GenerateXcodeproj),
75
76    /// This task checks if a given set of dependencies exist and if necessary,
77    /// installs the dependencies that weren't found.
78    InstallDependencies(InstallDependencies),
79
80    /// This task installs an application on the iOS Simulator with a given
81    /// identifier.
82    InstallOnIOSSimulator(InstallOnIOSSimulator),
83
84    /// This task installs a target with a given name using rustup, if
85    /// necessary.
86    InstallTarget(InstallTarget),
87
88    /// This task opens the iOS Simulator GUI, which is not open by default when
89    /// booting a (new) simulator.
90    OpenIOSSimulator(OpenIOSSimulator),
91
92    /// This task launches the application on an iOS Simulator with a given
93    /// identifier.
94    RunOnIOSSimulator(RunOnIOSSimulator),
95}
96
97/// Represents an error that is returned by one of the iOS-specific tasks.
98#[derive(Debug)]
99pub enum IOSError {
100    /// Returned by tasks that have not yet been implemented for a specific host
101    /// operating system.
102    UnsupportedHostOS(&'static str),
103
104    /// Returned by the `BuildRuntimeLibrary` task when Cargo fails to build the
105    /// runtime library (most likely because of an error in user code, e.g.
106    /// syntax error).
107    CompilationFailure,
108
109    /// Returned by tasks when an io error occurs.
110    IO(std::io::Error),
111
112    /// Returned by tasks that interact with `simctl`, an Apple-provided utility
113    /// to programmatically control the iOS Simulator, in the event that it
114    /// returns an error.
115    Simctl(simctl::Error),
116}
117
118impl From<std::io::Error> for IOSError {
119    fn from(error: std::io::Error) -> Self {
120        IOSError::IO(error)
121    }
122}
123
124impl From<simctl::Error> for IOSError {
125    fn from(error: simctl::Error) -> Self {
126        IOSError::Simctl(error)
127    }
128}
129
130impl Task for IOSTask {
131    type Context = IOSContext;
132    type Error = IOSError;
133
134    fn verb(&self) -> &str {
135        match self {
136            IOSTask::BootIOSSimulator(task) => task.verb(),
137            IOSTask::BuildRuntimeLibrary(task) => task.verb(),
138            IOSTask::BuildRuntimeLibraryV2(task) => task.verb(),
139            IOSTask::BuildXcodeproj(task) => task.verb(),
140            IOSTask::CreateUniversalBinary(task) => task.verb(),
141            IOSTask::GenerateXcassets(task) => task.verb(),
142            IOSTask::GenerateXcodeproj(task) => task.verb(),
143            IOSTask::InstallDependencies(task) => task.verb(),
144            IOSTask::InstallOnIOSSimulator(task) => task.verb(),
145            IOSTask::InstallTarget(task) => task.verb(),
146            IOSTask::OpenIOSSimulator(task) => task.verb(),
147            IOSTask::RunOnIOSSimulator(task) => task.verb(),
148        }
149    }
150
151    fn message(&self) -> &str {
152        match self {
153            IOSTask::BootIOSSimulator(task) => task.message(),
154            IOSTask::BuildRuntimeLibrary(task) => task.message(),
155            IOSTask::BuildRuntimeLibraryV2(task) => task.message(),
156            IOSTask::BuildXcodeproj(task) => task.message(),
157            IOSTask::CreateUniversalBinary(task) => task.message(),
158            IOSTask::GenerateXcassets(task) => task.message(),
159            IOSTask::GenerateXcodeproj(task) => task.message(),
160            IOSTask::InstallDependencies(task) => task.message(),
161            IOSTask::InstallOnIOSSimulator(task) => task.message(),
162            IOSTask::InstallTarget(task) => task.message(),
163            IOSTask::OpenIOSSimulator(task) => task.message(),
164            IOSTask::RunOnIOSSimulator(task) => task.message(),
165        }
166    }
167
168    fn detail(&self) -> &str {
169        match self {
170            IOSTask::BootIOSSimulator(task) => task.detail(),
171            IOSTask::BuildRuntimeLibrary(task) => task.detail(),
172            IOSTask::BuildRuntimeLibraryV2(task) => task.detail(),
173            IOSTask::BuildXcodeproj(task) => task.detail(),
174            IOSTask::CreateUniversalBinary(task) => task.detail(),
175            IOSTask::GenerateXcassets(task) => task.detail(),
176            IOSTask::GenerateXcodeproj(task) => task.detail(),
177            IOSTask::InstallDependencies(task) => task.detail(),
178            IOSTask::InstallOnIOSSimulator(task) => task.detail(),
179            IOSTask::InstallTarget(task) => task.detail(),
180            IOSTask::OpenIOSSimulator(task) => task.detail(),
181            IOSTask::RunOnIOSSimulator(task) => task.detail(),
182        }
183    }
184
185    fn run(
186        &self,
187        context: Self::Context,
188        manager: &mut Manager,
189    ) -> Result<Self::Context, Self::Error> {
190        match self {
191            IOSTask::BootIOSSimulator(task) => task.run(context, manager),
192            IOSTask::BuildRuntimeLibrary(task) => task.run(context, manager),
193            IOSTask::BuildRuntimeLibraryV2(task) => task.run(context, manager),
194            IOSTask::BuildXcodeproj(task) => task.run(context, manager),
195            IOSTask::CreateUniversalBinary(task) => task.run(context, manager),
196            IOSTask::GenerateXcassets(task) => task.run(context, manager),
197            IOSTask::GenerateXcodeproj(task) => task.run(context, manager),
198            IOSTask::InstallDependencies(task) => task
199                .run((), manager)
200                .map_err(|error| IOSError::IO(error))
201                .map(|_| context),
202            IOSTask::InstallOnIOSSimulator(task) => task.run(context, manager),
203            IOSTask::InstallTarget(task) => task
204                .run((), manager)
205                .map_err(|error| IOSError::IO(error))
206                .map(|_| context),
207            IOSTask::OpenIOSSimulator(task) => task.run(context, manager),
208            IOSTask::RunOnIOSSimulator(task) => task.run(context, manager),
209        }
210    }
211}