polyhorn_cli/ios/tasks/
generate_xcodeproj.rs1use std::fs::{create_dir_all, File};
2use std::io::Write;
3use std::process::{Command, Stdio};
4
5use super::{IOSContext, IOSError};
6use crate::core::{Manager, Task};
7use crate::ios::{infoplist, xcodegen};
8
9pub struct GenerateXcodeproj;
11
12impl Task for GenerateXcodeproj {
13 type Context = IOSContext;
14 type Error = IOSError;
15
16 fn verb(&self) -> &str {
17 "Generating"
18 }
19
20 fn message(&self) -> &str {
21 "Xcodeproj"
22 }
23
24 fn detail(&self) -> &str {
25 ""
26 }
27
28 fn run(
29 &self,
30 context: Self::Context,
31 _manager: &mut Manager,
32 ) -> Result<Self::Context, Self::Error> {
33 let target_dir = context.config.target_dir.join("polyhorn-ios");
34
35 let _ = create_dir_all(&target_dir);
36 let _ = create_dir_all(&target_dir.join("Sources"));
37
38 let mut file = File::create(target_dir.join("Sources/main.m")).unwrap();
39 file.write_all(&mut include_bytes!("../../../ios/template/main.m.tmpl").to_owned())
40 .unwrap();
41
42 let infoplist = infoplist::InfoPlist {
44 bundle_development_region: "$(DEVELOPMENT_LANGUAGE)",
45 bundle_executable: "$(EXECUTABLE_NAME)",
46 bundle_identifier: "$(PRODUCT_BUNDLE_IDENTIFIER)",
47 bundle_info_dictionary_version: "6.0",
48 bundle_name: "$(PRODUCT_NAME)",
49 bundle_package_type: "$(PRODUCT_BUNDLE_PACKAGE_TYPE)",
50 bundle_short_version_string: "1.0",
51 bundle_version: "1",
52 requires_iphone_os: true,
53 launch_storyboard_name: "LaunchScreen",
54 required_device_capabilities: &[infoplist::DeviceCapability::Armv7],
55 supported_interface_orientations: &[infoplist::InterfaceOrientation::Portrait],
56 supported_interface_orientations_ipad: &[infoplist::InterfaceOrientation::Portrait],
57 };
58 plist::to_writer_xml(
59 &mut File::create(target_dir.join("Sources/Info.plist")).unwrap(),
60 &infoplist,
61 )
62 .unwrap();
63
64 let path = context.universal_binary_path.as_ref().unwrap();
65 let filename = path.file_name().unwrap().to_str().unwrap().to_owned();
66 let mut path = path.to_owned();
67 path.pop();
68 let path = path.to_str().unwrap().to_owned();
69
70 let project = xcodegen::Project {
71 name: context.config.spec.app.name.to_owned(),
72 targets: vec![(
73 context.config.spec.app.name.to_owned(),
74 xcodegen::Target {
75 product_type: xcodegen::ProductType::Application,
76 platform: vec![xcodegen::Platform::IOS].into_iter().collect(),
77 deployment_targets: vec![(xcodegen::Platform::IOS, "8.0".to_owned())]
78 .into_iter()
79 .collect(),
80 sources: vec![xcodegen::TargetSource {
81 path: "Sources".to_owned(),
82 }],
83 settings: vec![
84 (
85 "PRODUCT_BUNDLE_IDENTIFIER".to_owned(),
86 context.config.spec.app.ios.bundle_identifier.clone(),
87 ),
88 ("LIBRARY_SEARCH_PATHS".to_owned(), path),
89 ("OTHER_LDFLAGS".to_owned(), "-ObjC -lc++".to_owned()),
90 ]
91 .into_iter()
92 .collect(),
93 dependencies: vec![xcodegen::Dependency::Framework {
94 framework: filename,
95 embed: false,
96 }],
97 },
98 )]
99 .into_iter()
100 .collect(),
101 };
102
103 let file = File::create(target_dir.join("project.yml")).unwrap();
104
105 serde_yaml::to_writer(file, &project).unwrap();
106
107 Command::new("xcodegen")
108 .arg("generate")
109 .arg("--spec")
110 .arg(target_dir.join("project.yml"))
111 .arg("--project")
112 .arg(&target_dir)
113 .stdout(Stdio::null())
114 .spawn()?
115 .wait()?;
116
117 Ok(context)
118 }
119}