Skip to main content

mopro_ffi/app_config/
constants.rs

1use color_eyre::eyre::ContextCompat;
2
3pub const BUILD_MODE_ENV: &str = "CONFIGURATION";
4pub const IOS_ARCHS_ENV: &str = "IOS_ARCHS";
5pub const ANDROID_ARCHS_ENV: &str = "ANDROID_ARCHS";
6pub const FLUTTER_ARCHS_ENV: &str = "FLUTTER_ARCHS";
7pub const REACT_NATIVE_ARCHS_ENV: &str = "REACT_NATIVE_ARCHS";
8
9pub const IOS_BINDINGS_DIR: &str = "MoproiOSBindings";
10pub const IOS_SWIFT_FILE: &str = "mopro.swift";
11pub const IOS_XCFRAMEWORKS_DIR: &str = "MoproBindings.xcframework";
12
13pub const ANDROID_BINDINGS_DIR: &str = "MoproAndroidBindings";
14pub const ANDROID_JNILIBS_DIR: &str = "jniLibs";
15pub const ANDROID_UNIFFI_DIR: &str = "uniffi";
16pub const ANDROID_PACKAGE_NAME: &str = "mopro";
17pub const ANDROID_KT_FILE: &str = "mopro.kt";
18
19pub const WEB_BINDINGS_DIR: &str = "MoproWasmBindings";
20
21pub const ARCH_X86_64: &str = "x86_64";
22pub const ARCH_ARM_64: &str = "aarch64";
23pub const ARCH_I686: &str = "x86";
24pub const ARCH_ARM_V7_ABI: &str = "armeabi-v7a";
25pub const ARCH_ARM_64_V8: &str = "arm64-v8a";
26
27pub const FLUTTER_BINDINGS_DIR: &str = "mopro_flutter_bindings";
28pub const REACT_NATIVE_BINDINGS_DIR: &str = "MoproReactNativeBindings";
29
30#[derive(Debug, Copy, Clone, PartialEq, Eq)]
31pub enum Mode {
32    Debug,
33    Release,
34}
35
36struct ModeInfo {
37    mode: Mode,
38    str: &'static str,
39}
40
41const MODES: [ModeInfo; 2] = [
42    ModeInfo {
43        mode: Mode::Debug,
44        str: "debug",
45    },
46    ModeInfo {
47        mode: Mode::Release,
48        str: "release",
49    },
50];
51
52impl Mode {
53    pub fn as_str(&self) -> &'static str {
54        MODES
55            .iter()
56            .find(|info| info.mode == *self)
57            .map(|info| info.str)
58            .expect("Unsupported Mode, only support 'release' and 'debug'")
59    }
60
61    pub fn parse_from_str(s: &str) -> Self {
62        MODES
63            .iter()
64            .find(|info| info.str.to_lowercase() == s.to_lowercase())
65            .map(|info| info.mode)
66            .expect("Unsupported Mode String, only support 'release' and 'debug'")
67    }
68
69    pub fn from_idx(idx: usize) -> Self {
70        MODES[idx].mode
71    }
72
73    pub fn idx(s: &str) -> Option<usize> {
74        MODES
75            .iter()
76            .enumerate()
77            .find(|(_, m)| m.str == s)
78            .map(|(i, _)| i)
79    }
80
81    pub fn all_strings() -> Vec<&'static str> {
82        MODES.iter().map(|info| info.str).collect()
83    }
84}
85
86//
87// Architecture Section
88//
89
90pub trait Arch {
91    fn platform() -> Box<dyn Platform>;
92    fn as_str(&self) -> &'static str;
93    fn parse_from_str<S: AsRef<str>>(s: S) -> Self;
94    fn all_strings() -> Vec<&'static str>;
95    fn all_display_strings() -> Vec<(String, String)>;
96    fn env_var_name() -> &'static str;
97}
98
99// https://developer.apple.com/documentation/xcode/build-settings-reference#Architectures
100#[derive(Debug, Copy, Clone, PartialEq, Eq)]
101pub enum IosArch {
102    Aarch64Apple,
103    Aarch64AppleSim,
104    X8664Apple,
105}
106
107struct IosArchInfo {
108    #[allow(dead_code)] // currently not used
109    arch: IosArch,
110    str: &'static str,
111    description: &'static str,
112}
113
114const IOS_ARCHS: [IosArchInfo; 3] = [
115    IosArchInfo {
116        arch: IosArch::Aarch64Apple,
117        str: "aarch64-apple-ios",
118        description: "64-bit iOS devices (iPhone/iPad)",
119    },
120    IosArchInfo {
121        arch: IosArch::Aarch64AppleSim,
122        str: "aarch64-apple-ios-sim",
123        description: "ARM64 iOS simulator on Apple Silicon Macs",
124    },
125    IosArchInfo {
126        arch: IosArch::X8664Apple,
127        str: "x86_64-apple-ios",
128        description: "x86_64 iOS simulator on Intel Macs",
129    },
130];
131
132impl Arch for IosArch {
133    fn platform() -> Box<dyn Platform> {
134        Box::new(IosPlatform)
135    }
136
137    fn as_str(&self) -> &'static str {
138        IOS_ARCHS
139            .iter()
140            .find(|info| info.arch == *self)
141            .map(|info| info.str)
142            .expect("Unsupported iOS Arch")
143    }
144
145    fn parse_from_str<S: AsRef<str>>(s: S) -> Self {
146        IOS_ARCHS
147            .iter()
148            .find(|info| info.str.to_lowercase() == s.as_ref().to_lowercase())
149            .map(|info| info.arch)
150            .context(format!("Unsupported iOS Arch '{}'", s.as_ref()))
151            .unwrap()
152    }
153
154    fn all_strings() -> Vec<&'static str> {
155        IOS_ARCHS.iter().map(|info| info.str).collect()
156    }
157
158    fn all_display_strings() -> Vec<(String, String)> {
159        IOS_ARCHS
160            .iter()
161            .map(|info| (info.str.to_string(), info.description.to_string()))
162            .collect()
163    }
164
165    fn env_var_name() -> &'static str {
166        IOS_ARCHS_ENV
167    }
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq)]
171pub enum AndroidArch {
172    X8664Linux,
173    I686Linux,
174    Armv7LinuxAbi,
175    Aarch64Linux,
176}
177
178struct AndroidArchInfo {
179    arch: AndroidArch,
180    str: &'static str,
181    description: &'static str,
182}
183
184const ANDROID_ARCHS: [AndroidArchInfo; 4] = [
185    AndroidArchInfo {
186        arch: AndroidArch::X8664Linux,
187        str: "x86_64-linux-android",
188        description: "64-bit Android emulators (x86_64 architecture)",
189    },
190    AndroidArchInfo {
191        arch: AndroidArch::I686Linux,
192        str: "i686-linux-android",
193        description: "32-bit Android emulators (x86 architecture, legacy)",
194    },
195    AndroidArchInfo {
196        arch: AndroidArch::Armv7LinuxAbi,
197        str: "armv7-linux-androideabi",
198        description: "32-bit ARM devices (older Android smartphones/tablets)",
199    },
200    AndroidArchInfo {
201        arch: AndroidArch::Aarch64Linux,
202        str: "aarch64-linux-android",
203        description: "64-bit ARM devices (modern Android smartphones/tablets)",
204    },
205];
206
207impl Arch for AndroidArch {
208    fn platform() -> Box<dyn Platform> {
209        Box::new(AndroidPlatform)
210    }
211
212    fn as_str(&self) -> &'static str {
213        ANDROID_ARCHS
214            .iter()
215            .find(|info| info.arch == *self)
216            .map(|info| info.str)
217            .expect("Unsupported Android Arch")
218    }
219
220    fn parse_from_str<S: AsRef<str>>(s: S) -> Self {
221        ANDROID_ARCHS
222            .iter()
223            .find(|info| info.str.to_lowercase() == s.as_ref().to_lowercase())
224            .map(|info| info.arch)
225            .context(format!("Unsupported Android Arch '{}'", s.as_ref()))
226            .unwrap()
227    }
228
229    fn all_strings() -> Vec<&'static str> {
230        ANDROID_ARCHS.iter().map(|info| info.str).collect()
231    }
232
233    fn all_display_strings() -> Vec<(String, String)> {
234        ANDROID_ARCHS
235            .iter()
236            .map(|info| (info.str.to_string(), info.description.to_string()))
237            .collect()
238    }
239
240    fn env_var_name() -> &'static str {
241        ANDROID_ARCHS_ENV
242    }
243}
244
245pub struct WebArch;
246
247impl Arch for WebArch {
248    fn platform() -> Box<dyn Platform> {
249        Box::new(WebPlatform)
250    }
251
252    fn as_str(&self) -> &'static str {
253        "wasm32-unknown-unknown"
254    }
255
256    fn parse_from_str<S: AsRef<str>>(_s: S) -> Self {
257        WebArch
258    }
259
260    fn all_strings() -> Vec<&'static str> {
261        vec!["wasm32-unknown-unknown"]
262    }
263
264    fn all_display_strings() -> Vec<(String, String)> {
265        vec![(
266            "wasm32-unknown-unknown".to_string(),
267            "WebAssembly".to_string(),
268        )]
269    }
270
271    fn env_var_name() -> &'static str {
272        "WEB_ARCHS"
273    }
274}
275
276// TODO: reuse iOS, Android constants
277#[derive(Debug, Clone, Copy, PartialEq, Eq)]
278
279pub enum FlutterArch {
280    Aarch64Apple,
281    Aarch64AppleSim,
282    X8664Apple,
283    X8664Linux,
284    I686Linux,
285    Armv7LinuxAbi,
286    Aarch64Linux,
287}
288struct FlutterArchInfo {
289    arch: FlutterArch,
290    str: &'static str,
291    description: &'static str,
292}
293
294const FLUTTER_ARCHS: [FlutterArchInfo; 7] = [
295    FlutterArchInfo {
296        arch: FlutterArch::Aarch64Apple,
297        str: "aarch64-apple-ios",
298        description: "64-bit iOS devices (iPhone/iPad)",
299    },
300    FlutterArchInfo {
301        arch: FlutterArch::Aarch64AppleSim,
302        str: "aarch64-apple-ios-sim",
303        description: "ARM64 iOS simulator on Apple Silicon Macs",
304    },
305    FlutterArchInfo {
306        arch: FlutterArch::X8664Apple,
307        str: "x86_64-apple-ios",
308        description: "x86_64 iOS simulator on Intel Macs",
309    },
310    FlutterArchInfo {
311        arch: FlutterArch::X8664Linux,
312        str: "x86_64-linux-android",
313        description: "64-bit Android emulators (x86_64 architecture)",
314    },
315    FlutterArchInfo {
316        arch: FlutterArch::I686Linux,
317        str: "i686-linux-android",
318        description: "32-bit Android emulators (x86 architecture, legacy)",
319    },
320    FlutterArchInfo {
321        arch: FlutterArch::Armv7LinuxAbi,
322        str: "armv7-linux-androideabi",
323        description: "32-bit ARM devices (older Android smartphones/tablets)",
324    },
325    FlutterArchInfo {
326        arch: FlutterArch::Aarch64Linux,
327        str: "aarch64-linux-android",
328        description: "64-bit ARM devices (modern Android smartphones/tablets)",
329    },
330];
331
332impl Arch for FlutterArch {
333    fn platform() -> Box<dyn Platform> {
334        Box::new(FlutterPlatform)
335    }
336
337    fn as_str(&self) -> &'static str {
338        FLUTTER_ARCHS
339            .iter()
340            .find(|info| info.arch == *self)
341            .map(|info| info.str)
342            .expect("Unsupported iOS Arch")
343    }
344
345    fn parse_from_str<S: AsRef<str>>(s: S) -> Self {
346        FLUTTER_ARCHS
347            .iter()
348            .find(|info| info.str.to_lowercase() == s.as_ref().to_lowercase())
349            .map(|info| info.arch)
350            .context(format!("Unsupported iOS Arch '{}'", s.as_ref()))
351            .unwrap()
352    }
353
354    fn all_strings() -> Vec<&'static str> {
355        FLUTTER_ARCHS.iter().map(|info| info.str).collect()
356    }
357
358    fn all_display_strings() -> Vec<(String, String)> {
359        FLUTTER_ARCHS
360            .iter()
361            .map(|info| (info.str.to_string(), info.description.to_string()))
362            .collect()
363    }
364
365    fn env_var_name() -> &'static str {
366        FLUTTER_ARCHS_ENV
367    }
368}
369
370// TODO: reuse iOS, Android constants
371#[derive(Debug, Clone, Copy, PartialEq, Eq)]
372
373pub enum ReactNativeArch {
374    Aarch64Apple,
375    Aarch64AppleSim,
376    X8664Apple,
377    X8664Linux,
378    I686Linux,
379    Armv7LinuxAbi,
380    Aarch64Linux,
381}
382struct ReactNativeArchInfo {
383    arch: ReactNativeArch,
384    str: &'static str,
385    description: &'static str,
386}
387
388const REACT_NATIVE_ARCHS: [ReactNativeArchInfo; 7] = [
389    ReactNativeArchInfo {
390        arch: ReactNativeArch::Aarch64Apple,
391        str: "aarch64-apple-ios",
392        description: "64-bit iOS devices (iPhone/iPad)",
393    },
394    ReactNativeArchInfo {
395        arch: ReactNativeArch::Aarch64AppleSim,
396        str: "aarch64-apple-ios-sim",
397        description: "ARM64 iOS simulator on Apple Silicon Macs",
398    },
399    ReactNativeArchInfo {
400        arch: ReactNativeArch::X8664Apple,
401        str: "x86_64-apple-ios",
402        description: "x86_64 iOS simulator on Intel Macs",
403    },
404    ReactNativeArchInfo {
405        arch: ReactNativeArch::X8664Linux,
406        str: "x86_64-linux-android",
407        description: "64-bit Android emulators (x86_64 architecture)",
408    },
409    ReactNativeArchInfo {
410        arch: ReactNativeArch::I686Linux,
411        str: "i686-linux-android",
412        description: "32-bit Android emulators (x86 architecture, legacy)",
413    },
414    ReactNativeArchInfo {
415        arch: ReactNativeArch::Armv7LinuxAbi,
416        str: "armv7-linux-androideabi",
417        description: "32-bit ARM devices (older Android smartphones/tablets)",
418    },
419    ReactNativeArchInfo {
420        arch: ReactNativeArch::Aarch64Linux,
421        str: "aarch64-linux-android",
422        description: "64-bit ARM devices (modern Android smartphones/tablets)",
423    },
424];
425
426impl Arch for ReactNativeArch {
427    fn platform() -> Box<dyn Platform> {
428        Box::new(ReactNativePlatform)
429    }
430
431    fn as_str(&self) -> &'static str {
432        REACT_NATIVE_ARCHS
433            .iter()
434            .find(|info| info.arch == *self)
435            .map(|info| info.str)
436            .expect("Unsupported React Native Arch")
437    }
438
439    fn parse_from_str<S: AsRef<str>>(s: S) -> Self {
440        REACT_NATIVE_ARCHS
441            .iter()
442            .find(|info| info.str.to_lowercase() == s.as_ref().to_lowercase())
443            .map(|info| info.arch)
444            .context(format!("Unsupported React Native Arch '{}'", s.as_ref()))
445            .unwrap()
446    }
447
448    fn all_strings() -> Vec<&'static str> {
449        REACT_NATIVE_ARCHS.iter().map(|info| info.str).collect()
450    }
451
452    fn all_display_strings() -> Vec<(String, String)> {
453        REACT_NATIVE_ARCHS
454            .iter()
455            .map(|info| (info.str.to_string(), info.description.to_string()))
456            .collect()
457    }
458
459    fn env_var_name() -> &'static str {
460        REACT_NATIVE_ARCHS_ENV
461    }
462}
463
464//
465// Platform Section
466//
467
468pub trait Platform {
469    fn identifier() -> &'static str
470    where
471        Self: Sized;
472}
473
474pub trait PlatformBuilder: Platform {
475    type Arch: Arch;
476    type Params: Default;
477
478    fn build(
479        mode: Mode,
480        project_dir: &std::path::Path,
481        target_arch: Vec<Self::Arch>,
482        params: Self::Params,
483    ) -> anyhow::Result<std::path::PathBuf>;
484}
485
486pub struct IosPlatform;
487
488impl Platform for IosPlatform {
489    fn identifier() -> &'static str {
490        "iOS Bindings Builder"
491    }
492}
493
494pub struct AndroidPlatform;
495
496impl Platform for AndroidPlatform {
497    fn identifier() -> &'static str {
498        "Android Bindings Builder"
499    }
500}
501
502pub struct WebPlatform;
503
504impl Platform for WebPlatform {
505    fn identifier() -> &'static str {
506        "Web Bindings Builder"
507    }
508}
509
510pub struct FlutterPlatform;
511
512impl Platform for FlutterPlatform {
513    fn identifier() -> &'static str {
514        "Flutter Bindings Builder"
515    }
516}
517
518pub struct ReactNativePlatform;
519
520impl Platform for ReactNativePlatform {
521    fn identifier() -> &'static str {
522        "React Native Bindings Builder"
523    }
524}