polyhorn_cli/android/tasks/
mod.rs

1//! Tasks and context specific for building and running on Android.
2
3use std::collections::HashMap;
4use std::path::PathBuf;
5
6mod build_runtime_library;
7mod find_android_studio;
8mod generate_source_tree;
9mod install;
10mod link_native_libraries;
11mod run;
12
13pub use build_runtime_library::BuildRuntimeLibrary;
14pub use find_android_studio::FindAndroidStudio;
15pub use generate_source_tree::GenerateSourceTree;
16pub use install::Install;
17pub use link_native_libraries::LinkNativeLibraries;
18pub use run::Run;
19
20pub use crate::core::tasks::InstallTarget;
21
22use crate::core::{Manager, Task};
23use crate::Config;
24
25/// Context that gets passed through each task.
26#[derive(Debug)]
27pub struct AndroidContext {
28    /// The platform-independent configuration that gets passed to each command.
29    pub config: Config,
30
31    /// The Java home that is resolved after the `FindAndroidStudio` task.
32    pub java_home: Option<PathBuf>,
33
34    /// The Android SDK root that is resolved after the `FindAndroidStudio`
35    /// task.
36    pub android_sdk_root: Option<PathBuf>,
37
38    /// A map between Android ABIs and the path to the product for each.
39    pub products: HashMap<String, PathBuf>,
40}
41
42/// Represents one of the Android-specific tasks.
43pub enum AndroidTask {
44    /// This tasks builds the runtime library for the given target and with the
45    /// given profile.
46    BuildRuntimeLibrary(BuildRuntimeLibrary),
47
48    /// This task generates a new source tree based on the template that ships
49    /// with `polyhorn-cli`.
50    GenerateSourceTree(GenerateSourceTree),
51
52    /// This task attempts to locate Android Studio and uses the result to
53    /// locate the Android SDK and Java home. The Android Studio itself isn't
54    /// used, but it's the easiest way of obtaining a working installation of
55    /// the SDK, NDK and Java that are all compatible.
56    FindAndroidStudio(FindAndroidStudio),
57
58    /// This task invokes Gradle to install a debug-build on the user's device
59    /// or emulator.
60    Install(Install),
61
62    /// This task installs a target with a given name using rustup, if
63    /// necessary.
64    InstallTarget(InstallTarget),
65
66    /// This task copies all products from the `BuildRuntimeLibrary` task into
67    /// the `jniLibs` folder of the Android source tree.
68    LinkNativeLibraries(LinkNativeLibraries),
69
70    /// This task launches the newly installed Polyhorn-powered app on a user's
71    /// device or emulator.
72    Run(Run),
73}
74
75/// Represents an error that is returned by one of the Android-specific tasks.
76#[derive(Debug)]
77pub enum AndroidError {
78    /// Returned by tasks that have not yet been implemented for a specific host
79    /// operating system.
80    UnsupportedHostOS(&'static str),
81
82    /// Returned by the `BuildRuntimeLibrary` task when Cargo fails to build the
83    /// runtime library (most likely because of an error in user code, e.g.
84    /// syntax error).
85    CompilationFailure,
86
87    /// Returned when platform-specific logic for locating Android Studio is
88    /// implemented, but couldn't find it at the expected path (which is given
89    /// as an argument).
90    AndroidStudioNotFound(PathBuf),
91
92    /// Returned when platform-specific logic for locating Java is implemented,
93    /// but couldn't find it at the expected path (which is given as an
94    /// argument).
95    JavaNotFound(PathBuf),
96
97    /// Returned when platform-specific logic for locating Android SDK is
98    /// implemented, but couldn't find it at the expected path (which is given
99    /// as an argument).
100    AndroidSDKNotFound(PathBuf),
101
102    /// Returned when platform-specific logic for locating Android NDK is
103    /// implemented, but couldn't find it at the expected path (which is given
104    /// as an argument).
105    AndroidNDKNotFound(PathBuf),
106
107    /// Returned by tasks when an io error occurs.
108    IO(std::io::Error),
109}
110
111impl From<std::io::Error> for AndroidError {
112    fn from(error: std::io::Error) -> Self {
113        AndroidError::IO(error)
114    }
115}
116
117impl Task for AndroidTask {
118    type Context = AndroidContext;
119    type Error = AndroidError;
120
121    fn verb(&self) -> &str {
122        match self {
123            AndroidTask::BuildRuntimeLibrary(task) => task.verb(),
124            AndroidTask::FindAndroidStudio(task) => task.verb(),
125            AndroidTask::GenerateSourceTree(task) => task.verb(),
126            AndroidTask::LinkNativeLibraries(task) => task.verb(),
127            AndroidTask::Install(task) => task.verb(),
128            AndroidTask::InstallTarget(task) => task.verb(),
129            AndroidTask::Run(task) => task.verb(),
130        }
131    }
132
133    fn message(&self) -> &str {
134        match self {
135            AndroidTask::BuildRuntimeLibrary(task) => task.message(),
136            AndroidTask::FindAndroidStudio(task) => task.message(),
137            AndroidTask::GenerateSourceTree(task) => task.message(),
138            AndroidTask::LinkNativeLibraries(task) => task.message(),
139            AndroidTask::Install(task) => task.message(),
140            AndroidTask::InstallTarget(task) => task.message(),
141            AndroidTask::Run(task) => task.message(),
142        }
143    }
144
145    fn detail(&self) -> &str {
146        match self {
147            AndroidTask::BuildRuntimeLibrary(task) => task.detail(),
148            AndroidTask::FindAndroidStudio(task) => task.detail(),
149            AndroidTask::GenerateSourceTree(task) => task.detail(),
150            AndroidTask::LinkNativeLibraries(task) => task.detail(),
151            AndroidTask::Install(task) => task.detail(),
152            AndroidTask::InstallTarget(task) => task.detail(),
153            AndroidTask::Run(task) => task.detail(),
154        }
155    }
156
157    fn run(
158        &self,
159        context: Self::Context,
160        manager: &mut Manager,
161    ) -> Result<Self::Context, Self::Error> {
162        match self {
163            AndroidTask::BuildRuntimeLibrary(task) => task.run(context, manager),
164            AndroidTask::FindAndroidStudio(task) => task.run(context, manager),
165            AndroidTask::GenerateSourceTree(task) => task.run(context, manager),
166            AndroidTask::LinkNativeLibraries(task) => task.run(context, manager),
167            AndroidTask::Install(task) => task.run(context, manager),
168            AndroidTask::InstallTarget(task) => task
169                .run((), manager)
170                .map_err(|error| AndroidError::IO(error))
171                .map(|_| context),
172            AndroidTask::Run(task) => task.run(context, manager),
173        }
174    }
175}