nitc/ios: add Assets.xcassets
[nit.git] / src / platform / ios.nit
1 # This file is part of NIT ( http://www.nitlanguage.org )
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Compile programs for the iOS platform
16 module ios
17
18 import platform
19 import compiler::abstract_compiler
20 import xcode_templates
21 import app_annotations
22
23 redef class ToolContext
24 redef fun platform_from_name(name)
25 do
26 if name == "ios" then return new IOSPlatform
27 return super
28 end
29 end
30
31 private class IOSPlatform
32 super Platform
33
34 redef fun supports_libunwind do return false
35 redef fun supports_libgc do return false
36 redef fun toolchain(toolcontext, compiler) do return new IOSToolchain(toolcontext, compiler)
37 end
38
39 private class IosProject
40 super AppProject
41
42 redef fun namespace do return super.to_camel_case
43 end
44
45 private class IOSToolchain
46 super MakefileToolchain
47
48 # Root of the iOS project, usually `nit_compile/ios/`
49 var ios_project_root: String is noinit
50
51 # `app.nit` project for the current compilation target
52 var app_project = new IosProject(compiler.modelbuilder, compiler.mainmodule) is lazy
53
54 redef fun default_outname do return "{super}.app"
55
56 # Compile C files in `ios_project_root/app_project.name`
57 redef fun compile_dir
58 do
59 ios_project_root = root_compile_dir/"ios"
60 return ios_project_root/app_project.short_name
61 end
62
63 redef fun write_files(compile_dir, cfiles)
64 do
65 # Clear the project directory before writing anything
66 if ios_project_root.file_exists then ios_project_root.rmdir
67 compile_dir.mkdir
68
69 super
70 end
71
72 redef fun write_makefile(compile_dir, cfiles)
73 do
74 var project_name = app_project.short_name
75
76 # ---
77 # project_folder (source code)
78
79 # Create the plist in the same directory as the generated C code
80 if not compile_dir.file_exists then compile_dir.mkdir
81 var plist = new PlistTemplate(app_project.name, app_project.namespace,
82 app_project.version, app_project.version_code.to_s)
83 plist.write_to_file compile_dir/"Info.plist"
84
85 # Copy the folder `ios/AppIcon.appiconset` from the root of the project
86 var project_root = "."
87 var mpackage = compiler.mainmodule.first_real_mmodule.mpackage
88 if mpackage != null then
89 var root = mpackage.root
90 if root != null then
91 var filepath = root.filepath
92 if filepath != null then
93 project_root = filepath
94 end
95 end
96 end
97
98 var icon_dir = project_root / "ios" / "AppIcon.appiconset"
99 var icons_found = icon_dir.file_exists
100 if icons_found then
101
102 # Prepare the `Assets.xcassets` folder
103 var target_assets_dir = compile_dir / "Assets.xcassets"
104 if not target_assets_dir.file_exists then target_assets_dir.mkdir
105
106 """
107 {
108 "info" : {
109 "version" : 1,
110 "author" : "nitc"
111 }
112 }""".write_to_file target_assets_dir / "Contents.json"
113
114 # copy the res folder to the compile dir
115 icon_dir = icon_dir.realpath
116 toolcontext.exec_and_check(["cp", "-R", icon_dir, target_assets_dir], "iOS project error")
117 end
118
119 # TODO Register asset files
120
121 # ---
122 # project_folder.xcodeproj (projet meta data)
123
124 # Create an XCode project directory
125 var dir = ios_project_root/project_name+".xcodeproj"
126 if not dir.file_exists then dir.mkdir
127
128 # Create a PBX project file
129 var pbx = new PbxprojectTemplate(project_name)
130
131 ## Register all source files
132 for file in cfiles do pbx.add_file new PbxFile(file)
133 for file in compiler.extern_bodies do
134 pbx.add_file new PbxFile(file.filename.basename)
135 end
136
137 # Basic storyboard, mainly to have the right screen size
138 var launch_screen_storyboard = new LaunchScreenStoryboardTemplate
139 launch_screen_storyboard.title = app_project.name
140 launch_screen_storyboard.subtitle = "app.nit"
141 launch_screen_storyboard.write_to_file ios_project_root / "LaunchScreen.storyboard"
142
143 # Register the Assets.xcassets folder in the project description
144 if icons_found then
145 var xcassets = new PbxFile("Assets.xcassets")
146 pbx.add_file xcassets
147 end
148
149 pbx.write_to_file dir / "project.pbxproj"
150 end
151
152 redef fun compile_c_code(compile_dir)
153 do
154 var project_name = app_project.short_name
155 var release = toolcontext.opt_release.value
156 var outfile = outfile(compiler.mainmodule)
157
158 # Compile with `xcodebuild`
159 #
160 # TODO support more than the iPhone and the simulator.
161 var args = ["sh", "-c", "cd {ios_project_root}; " +
162 "xcodebuild -target '{project_name}' " +
163 "-destination 'platform=iOS Simulator,name=iPhone' " +
164 "-configuration {if release then "Release" else "Debug"} " +
165 "ONLY_ACTIVE_ARCH=NO "+
166 "-sdk iphonesimulator build"]
167 toolcontext.exec_and_check(args, "iOS project error")
168
169 # Move compiled app to destination
170 if outfile.file_exists then outfile.rmdir
171 args = ["mv", "{ios_project_root}/build/Debug-iphonesimulator/{project_name}.app", outfile]
172 toolcontext.exec_and_check(args, "iOS project error")
173 end
174 end