polyhorn_cli/ios/tasks/
generate_xcodeproj.rs

1use 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
9/// This task generates an xcodeproj.
10pub 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        // Write the info plist.
43        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}