--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Basic structure for Nit apps on iOS
+module app
+
+import platform
+import ::app
+
+in "ObjC Header" `{
+ #import <UIKit/UIKit.h>
+
+ // Our interface to the iOS system
+ @interface AppDelegate: UIResponder <UIApplicationDelegate>
+
+ // The main window
+ @property (strong, nonatomic) UIWindow *window;
+ @end
+`}
+
+in "ObjC" `{
+
+ // Global reference to the App from app.nit
+ App app_nit_ios_app;
+
+ // Our own C argc and argv
+ int app_nit_ios_argc;
+ char **app_nit_ios_argv;
+
+ @implementation AppDelegate
+
+ - (BOOL)application:(UIApplication *)application
+ willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+
+ // Set aside `application` to be used from Nit
+ App_ui_application__assign(app_nit_ios_app, application);
+ App_app_delegate__assign(app_nit_ios_app, self);
+
+ // Complete the callback
+ return App_will_finish_launching_with_options(app_nit_ios_app);
+ }
+
+ - (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+
+ return App_did_finish_launching_with_options(app_nit_ios_app);
+ }
+
+ - (void)applicationWillResignActive:(UIApplication *)application {
+ App_will_resign_active(app_nit_ios_app);
+ }
+
+ - (void)applicationDidEnterBackground:(UIApplication *)application {
+ App_did_enter_background(app_nit_ios_app);
+ }
+
+ - (void)applicationWillEnterForeground:(UIApplication *)application {
+ App_will_enter_foreground(app_nit_ios_app);
+ }
+
+ - (void)applicationDidBecomeActive:(UIApplication *)application {
+ App_did_become_active(app_nit_ios_app);
+ }
+
+ - (void)applicationWillTerminate:(UIApplication *)application {
+ App_will_terminate(app_nit_ios_app);
+ }
+
+ @end
+`}
+
+# Application interface to the iOS system
+extern class AppDelegate in "ObjC" `{ AppDelegate * `}
+end
+
+# Graphical application to which events are sent
+extern class UIApplication in "ObjC" `{ UIApplication * `}
+end
+
+redef class App
+
+ # Main graphical application
+ var ui_application: UIApplication
+
+ # Application interface to the iOS system
+ var app_delegate: AppDelegate
+
+ # Copy back to C the command line arguments
+ #
+ # Nit extracts the first arguments from the `args` sequence,
+ # so we need to add it back. That's why Nit's `args` is smaller than in C.
+ private fun register_args(program_name: NativeString, argc: Int,
+ argv: Sequence[String]) import Sequence[String].[], String.to_cstring in "ObjC" `{
+ app_nit_ios_argc = argc+1;
+
+ // TODO copy or pin the strings when needed
+ app_nit_ios_argv = malloc(argc * sizeof(char*));
+ app_nit_ios_argv[0] = program_name;
+ for (int i = 0; i < argc; i ++) {
+ String arg = Sequence_of_String__index(argv, i);
+ app_nit_ios_argv[i+1] = String_to_cstring(arg);
+ }
+ `}
+
+ # Register `self` globally in C so it can be retrieved from iOS callbacks
+ private fun register_globally in "ObjC" `{
+ App_incr_ref(recv);
+ app_nit_ios_app = recv;
+ `}
+
+ # Entry point to the iOS framework
+ private fun ui_application_main: Bool import did_finish_launching_with_options,
+ will_finish_launching_with_options,
+ will_resign_active, did_enter_background, will_enter_foreground,
+ did_become_active, will_terminate, ui_application=, app_delegate= in "ObjC" `{
+
+ @autoreleasepool {
+ return UIApplicationMain(app_nit_ios_argc, app_nit_ios_argv,
+ nil, NSStringFromClass([AppDelegate class]));
+ }
+ `}
+
+ # The application is about to launch
+ #
+ # Redef this method to set the very first custom code to be executed.
+ fun will_finish_launching_with_options: Bool do return true
+
+ # The application just launched but is not yet displayed to the user
+ #
+ # Redef this method to customize the behavior.
+ fun did_finish_launching_with_options: Bool do return true
+
+ # The application is about to move from active to inactive state
+ #
+ # This can occur for certain types of temporary interruptions
+ # (such as an incoming phone call or SMS message) or when the
+ # user quits the application and it begins the transition to
+ # the background state.
+ #
+ # Redef this method to pause ongoing tasks, disable timers, and
+ # throttle down OpenGL ES frame rates. Games should use this
+ # method to pause.
+ fun will_resign_active do end
+
+ # The application just left foreground it can be suspended at any time
+ #
+ # Redef this method to release shared resources, save user data,
+ # invalidate timers, and store application state to restore your
+ # application to its current state in case it is terminated later.
+ #
+ # If your application supports background execution, this method
+ # is called instead of `will_terminate` when the user quits.
+ fun did_enter_background do end
+
+ # The application will enter the foreground
+ #
+ # Called as part of the transition from the background to the
+ # inactive state.
+ #
+ # Redef to und changes made on entering the background.
+ fun will_enter_foreground do end
+
+ # The application just became active
+ #
+ # Redef to restart any tasks that were paused (or not yet started) while
+ # the application was inactive. If the application was previously
+ # in the background, optionally refresh the user interface.
+ fun did_become_active do end
+
+ # The application is about to terminate (not suspended)
+ #
+ # Redef to save data if appropriate.
+ fun will_terminate do end
+end
+
+app.register_args(program_name.to_cstring, args.length, args)
+app.register_globally
+
+var ret = app.ui_application_main
+exit if ret then 0 else 1
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Simple iOS app with a single label
+module hello_ios
+
+import ios
+
+redef class App
+ redef fun did_finish_launching_with_options
+ do
+ return app_delegate.hello_world
+ end
+end
+
+redef class AppDelegate
+
+ # Print and show "Hello World!"
+ private fun hello_world: Bool in "ObjC" `{
+
+ // Print to the console
+ NSLog(@"Hello World!");
+
+ // Display "Hello world!" on the screen
+ recv.window = [[UIWindow alloc] initWithFrame:
+ [[UIScreen mainScreen] bounds]];
+ recv.window.backgroundColor = [UIColor whiteColor];
+
+ UILabel *label = [[UILabel alloc] init];
+ label.text = @"Hello World!";
+ label.center = CGPointMake(100, 100);
+ [label sizeToFit];
+
+ [recv.window addSubview: label];
+ [recv.window makeKeyAndVisible];
+
+ return YES;
+ `}
+end
--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# iOS services for Nit app on iOS
+module ios
+
+import platform
+import app
--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Triggers compilation for the iOS platform
+module platform is platform "ios"
// cmd exited on SIGINT: in my opinion the user wants the main to be discontinued
kill(getpid(), SIGINT);
}
+ return status;
}
#
# assert "abAB12<>&".escape_to_c == "abAB12<>&"
# assert "\n\"'\\".escape_to_c == "\\n\\\"\\'\\\\"
+ #
+ # Most non-printable characters (bellow ASCII 32) are escaped to an octal form `\nnn`.
+ # Three digits are always used to avoid following digits to be interpreted as an element
+ # of the octal sequence.
+ #
+ # assert "{0.ascii}{1.ascii}{8.ascii}{31.ascii}{32.ascii}".escape_to_c == "\\000\\001\\010\\037 "
+ #
+ # The exceptions are the common `\t` and `\n`.
fun escape_to_c: String
do
var b = new FlatBuffer
var c = chars[i]
if c == '\n' then
b.append("\\n")
+ else if c == '\t' then
+ b.append("\\t")
else if c == '\0' then
- b.append("\\0")
+ b.append("\\000")
else if c == '"' then
b.append("\\\"")
else if c == '\'' then
else if c == '\\' then
b.append("\\\\")
else if c.ascii < 32 then
- b.append("\\{c.ascii.to_base(8, false)}")
+ b.add('\\')
+ var oct = c.ascii.to_base(8, false)
+ # Force 3 octal digits since it is the
+ # maximum allowed in the C specification
+ if oct.length == 1 then
+ b.add('0')
+ b.add('0')
+ else if oct.length == 2 then
+ b.add('0')
+ end
+ b.append(oct)
else
b.add(c)
end
protected fun write_and_make(compiler: AbstractCompiler)
do
var platform = compiler.target_platform
- var toolchain = platform.toolchain(toolcontext)
+ var toolchain = platform.toolchain(toolcontext, compiler)
compile_dir = toolchain.compile_dir
- toolchain.write_and_make compiler
+ toolchain.write_and_make
end
end
redef class Platform
# The specific tool-chain associated to the platform
- fun toolchain(toolcontext: ToolContext): Toolchain do return new MakefileToolchain(toolcontext)
+ fun toolchain(toolcontext: ToolContext, compiler: AbstractCompiler): Toolchain
+ do
+ return new MakefileToolchain(toolcontext, compiler)
+ end
end
+# Build toolchain for a specific target program, varies per `Platform`
class Toolchain
+
+ # Toolcontext
var toolcontext: ToolContext
+ # Compiler of the target program
+ var compiler: AbstractCompiler
+
+ # Directory where to generate all C files
fun compile_dir: String
do
var compile_dir = toolcontext.opt_compile_dir.value
return compile_dir
end
- fun write_and_make(compiler: AbstractCompiler) is abstract
+ # Write all C files and compile them
+ fun write_and_make is abstract
end
+# Default toolchain using a Makefile
class MakefileToolchain
super Toolchain
- redef fun write_and_make(compiler)
+ redef fun write_and_make
do
var compile_dir = compile_dir
compile_dir.mkdir
var cfiles = new Array[String]
- write_files(compiler, compile_dir, cfiles)
+ write_files(compile_dir, cfiles)
# Generate the Makefile
- write_makefile(compiler, compile_dir, cfiles)
+ write_makefile(compile_dir, cfiles)
var time1 = get_time
self.toolcontext.info("*** END WRITING C: {time1-time0} ***", 2)
time0 = time1
self.toolcontext.info("*** COMPILING C ***", 1)
- compile_c_code(compiler, compile_dir)
+ compile_c_code(compile_dir)
time1 = get_time
self.toolcontext.info("*** END COMPILING C: {time1-time0} ***", 2)
end
- fun write_files(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
+ # Write all source files to the `compile_dir`
+ fun write_files(compile_dir: String, cfiles: Array[String])
do
var platform = compiler.target_platform
if self.toolcontext.opt_stacktrace.value == "nitstack" and platform.supports_libunwind then compiler.build_c_to_nit_bindings
self.toolcontext.info("Total C source files to compile: {cfiles.length}", 2)
end
- fun makefile_name(mainmodule: MModule): String do return "{mainmodule.c_name}.mk"
+ # Get the name of the Makefile to use
+ fun makefile_name: String do return "{compiler.mainmodule.c_name}.mk"
- fun default_outname(mainmodule: MModule): String
+ # Get the default name of the executable to produce
+ fun default_outname: String
do
+ var mainmodule = compiler.mainmodule
+
# Search a non fictive module
var res = mainmodule.name
while mainmodule.is_fictive do
do
var res = self.toolcontext.opt_output.value
if res != null then return res
- res = default_outname(mainmodule)
+ res = default_outname
var dir = self.toolcontext.opt_dir.value
if dir != null then return dir.join_path(res)
return res
end
- fun write_makefile(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
+ # Write the Makefile
+ fun write_makefile(compile_dir: String, cfiles: Array[String])
do
var mainmodule = compiler.mainmodule
var platform = compiler.target_platform
# 2. copy the binary at the right place in the `all` goal.
outpath = mainmodule.c_name
end
- var makename = makefile_name(mainmodule)
+ var makename = makefile_name
var makepath = "{compile_dir}/{makename}"
var makefile = new FileWriter.open(makepath)
makepath.file_copy_to "{compile_dir}/Makefile"
end
- fun compile_c_code(compiler: AbstractCompiler, compile_dir: String)
+ # The C code is generated, compile it to an executable
+ fun compile_c_code(compile_dir: String)
do
- var makename = makefile_name(compiler.mainmodule)
+ var makename = makefile_name
var makeflags = self.toolcontext.opt_make_flags.value
if makeflags == null then makeflags = ""
self.header.add_decl("#include <stdlib.h>")
self.header.add_decl("#include <stdio.h>")
self.header.add_decl("#include <string.h>")
+ self.header.add_decl("#include <sys/types.h>\n")
+ self.header.add_decl("#include <unistd.h>\n")
self.header.add_decl("#include \"gc_chooser.h\"")
self.header.add_decl("#ifdef ANDROID")
self.header.add_decl(" #include <android/log.h>")
import platform::android
import platform::pnacl
import platform::emscripten
+import platform::ios
var v2 = compiler.new_visitor
v2.add "{c_ret} {n2}{c_sig} \{"
v2.require_declaration(m.const_color)
- var call = "(({c_funptrtype})({selfvar}->class->vft[{m.const_color}]))({arguments.join(", ")});"
+ var call = "(({c_funptrtype})({v2.class_info(selfvar)}->vft[{m.const_color}]))({arguments.join(", ")});"
if ret != null then
v2.add "return {call}"
else
var v2 = compiler.new_visitor
v2.add "{c_ret} {n2}{c_sig} \{"
v2.require_declaration(m.const_color)
- var call = "(({c_funptrtype})({selfvar}->class->vft[{m.const_color}]))({arguments.join(", ")});"
+ var call = "(({c_funptrtype})({v2.class_info(selfvar)}->vft[{m.const_color}]))({arguments.join(", ")});"
if ret != null then
v2.add "return {call}"
else
redef fun supports_linker_script do return false
- redef fun toolchain(toolcontext) do return new AndroidToolchain(toolcontext)
+ redef fun toolchain(toolcontext, compiler) do return new AndroidToolchain(toolcontext, compiler)
end
class AndroidToolchain
return "{android_project_root}/jni/nit_compile/"
end
- redef fun default_outname(mainmodule) do return "{mainmodule.name}.apk"
+ redef fun default_outname do return "{super}.apk"
- redef fun write_files(compiler, compile_dir, cfiles)
+ redef fun write_files(compile_dir, cfiles)
do
var android_project_root = android_project_root.as(not null)
var project = toolcontext.modelbuilder.android_project_for(compiler.mainmodule)
if not dir.file_exists then dir.mkdir
# compile normal C files
- super(compiler, compile_dir, cfiles)
+ super
# Gather extra C files generated elsewhere than in super
for f in compiler.extern_bodies do
end
end
- redef fun write_makefile(compiler, compile_dir, cfiles)
+ redef fun write_makefile(compile_dir, cfiles)
do
# Do nothing, already done in `write_files`
end
- redef fun compile_c_code(compiler, compile_dir)
+ redef fun compile_c_code(compile_dir)
do
var android_project_root = android_project_root.as(not null)
var short_project_name = compiler.mainmodule.name.replace("-", "_")
redef fun supports_libunwind do return false
redef fun supports_libgc do return false
redef fun supports_linker_script do return false
- redef fun toolchain(toolcontext) do return new EnscriptenToolchain(toolcontext)
+ redef fun toolchain(toolcontext, compiler) do return new EnscriptenToolchain(toolcontext, compiler)
end
class EnscriptenToolchain
super MakefileToolchain
- redef fun makefile_name(mainmodule) do return "{mainmodule.name}.js.mk"
+ redef fun makefile_name do return "{super}.js.mk"
- redef fun default_outname(mainmodule) do return "{super}.js"
+ redef fun default_outname do return "{super}.js"
- redef fun write_makefile(compiler, compile_dir, cfiles)
+ redef fun write_makefile(compile_dir, cfiles)
do
super
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org )
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Compile programs for the iOS platform
+module ios
+
+import platform
+import compiler::abstract_compiler
+import xcode_templates
+private import annotation
+
+redef class ToolContext
+ redef fun platform_from_name(name)
+ do
+ if name == "ios" then return new IOSPlatform
+ return super
+ end
+end
+
+private class IOSPlatform
+ super Platform
+
+ redef fun supports_libunwind do return false
+ redef fun supports_libgc do return false
+ redef fun toolchain(toolcontext, compiler) do return new IOSToolchain(toolcontext, compiler)
+end
+
+private class IOSToolchain
+ super MakefileToolchain
+
+ # Root of the iOS project, usually `.nit_compile/ios/`
+ var ios_project_root: String is noinit
+
+ redef fun default_outname do return "{super}.app"
+
+ # Name of the current project of `compiler`
+ fun project_name: String
+ do
+ var project_name = null
+ # TODO unite the app_name annotation from Android with iOS
+ var annot = compiler.modelbuilder.lookup_annotation_on_modules("app_name", compiler.mainmodule)
+ if annot != null then project_name = annot.arg_as_string(compiler.modelbuilder)
+ if project_name == null then project_name = compiler.mainmodule.name
+ return project_name
+ end
+
+ # Compile C files in `ios_project_root/project_name`
+ redef fun compile_dir
+ do
+ ios_project_root = super/"ios"
+ return ios_project_root/project_name
+ end
+
+ redef fun write_files(compile_dir, cfiles)
+ do
+ # Clear the project directory before writing anything
+ if ios_project_root.file_exists then ios_project_root.rmdir
+ compile_dir.mkdir
+
+ super
+ end
+
+ redef fun write_makefile(compile_dir, cfiles)
+ do
+ var project_name = project_name
+
+ # Create an XCode project directory
+ var dir = ios_project_root/project_name+".xcodeproj"
+ if not dir.file_exists then dir.mkdir
+
+ # Create a PBX project file
+ var pbx = new PbxprojectTemplate(project_name)
+
+ ## Register all source files
+ for file in cfiles do pbx.add_file new PbxFile(file)
+ for file in compiler.extern_bodies do
+ pbx.add_file new PbxFile(file.filename.basename(""))
+ end
+
+ ## TODO Register asset files
+
+ pbx.write_to_file dir/"project.pbxproj"
+
+ # Create the plist in the same directory as the generated C code
+ if not compile_dir.file_exists then compile_dir.mkdir
+ var plist = new PlistTemplate("org.nitlanguage") # TODO customize using an annotation
+ plist.write_to_file compile_dir/"Info.plist"
+ end
+
+ redef fun compile_c_code(compile_dir)
+ do
+ var project_name = project_name
+ var release = toolcontext.opt_release.value
+ var outfile = outfile(compiler.mainmodule)
+
+ # Compile with `xcodebuild`
+ #
+ # TODO support more than the iPhone and the simulator.
+ var args = ["sh", "-c", "cd {ios_project_root}; " +
+ "xcodebuild -target '{project_name}' " +
+ "-destination 'platform=iOS Simulator,name=iPhone' " +
+ "-configuration {if release then "Release" else "Debug"} " +
+ "-sdk iphonesimulator build"]
+ toolcontext.exec_and_check(args, "iOS project error")
+
+ # Move compiled app to destination
+ if outfile.file_exists then outfile.rmdir
+ args = ["mv", "{ios_project_root}/build/Debug-iphonesimulator/{project_name}.app", outfile]
+ toolcontext.exec_and_check(args, "iOS project error")
+ end
+end
redef fun no_main do return true
- redef fun toolchain(toolcontext) do return new PnaclToolchain(toolcontext)
+ redef fun toolchain(toolcontext, compiler) do return new PnaclToolchain(toolcontext, compiler)
end
class PnaclToolchain
super MakefileToolchain
- redef fun write_files(compiler, compile_dir, cfiles)
+ redef fun write_files(compile_dir, cfiles)
do
var app_name = compiler.mainmodule.name
if not dir.file_exists then dir.mkdir
# compile normal C files
- super(compiler, compile_dir, cfiles)
+ super
# Gather extra C files generated elsewhere than in super
for f in compiler.extern_bodies do
""".write_to_file(file)
end
- redef fun write_makefile(compiler, compile_dir, cfiles)
+ redef fun write_makefile(compile_dir, cfiles)
do
# Do nothing, already done in `write_files`
end
- redef fun compile_c_code(compiler, compile_dir)
+ redef fun compile_c_code(compile_dir)
do
# Generate the pexe
toolcontext.exec_and_check(["make", "-C", compile_dir, "-j", "4"], "PNaCl project error")
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Templates and other services to create XCode projects
+module xcode_templates
+
+import template
+
+import platform
+import compiler::abstract_compiler
+
+redef class Sys
+ # Map to identify the PBX file type for a given file extension
+ private var pbx_file_types: Map[String, String] is lazy do
+ var map = new HashMap[String, String]
+
+ # Source code
+ map["m"] = "sourcecode.c.objc"
+ map["c"] = "sourcecode.c.c"
+ map["h"] = "sourcecode.c.h"
+ map["cpp"] = "sourcecode.cpp.cpp"
+ map["hpp"] = "sourcecode.cpp.h"
+ map["vsh"] = "sourcecode.glsl"
+ map["fsh"] = "sourcecode.glsl"
+
+ # Images
+ map["png"] = "image.png"
+ map["gif"] = "image.gif"
+ map["jpg"] = "image.jpeg"
+ map["jpeg"] = "image.jpeg"
+ map["pdf"] = "image.pdf"
+ map["ico"] = "image.ico"
+
+ # Others
+ map["app"] = "wrapper.application"
+ map["plist"] = "text.plist.xml"
+ map["storyboard"] = "file.storyboard"
+ map["xib"] = "file.xib"
+ map["xcassets"] = "folder.assetcatalog"
+ map["xctest"] = "wrapper.cfbundle"
+
+ return map
+ end
+
+ # Generator of PBX UUIDs quique to an execution of the compiler
+ private var pbx_uuid_generator = new PbxUUIDGenerator is lazy
+end
+
+# Generator of PBX UUIDs
+#
+# PBX UUID are composed of 24 hex characters.
+# They only need to be unique within the same project.
+#
+# This implementation simply counts upward from 0.
+class PbxUUIDGenerator
+ private var seed = 0
+
+ # Generate a new UUID
+ fun next_uuid: String
+ do
+ seed += 1
+
+ var hex_val = seed.to_hex.to_upper
+ return "0"*(24-hex_val.length) + hex_val
+ end
+end
+
+# Reference to a file for the PBX format of a project file
+#
+# TODO create subclasses for different file types, this is currently for
+# compilable source files only.
+class PbxFile
+
+ # Path to `self`
+ var path: String
+
+ # UUID for build elements
+ private var build_uuid: String = sys.pbx_uuid_generator.next_uuid is lazy
+
+ # File reference UUID
+ private var ref_uuid: String = sys.pbx_uuid_generator.next_uuid is lazy
+
+ # Documentation to add besides this file in the template
+ private fun doc: String do return path
+
+ # PBX file type for `self`
+ fun file_type: String
+ do
+ var map = sys.pbx_file_types
+ var ext = path.file_extension
+ if ext != null and map.keys.has(ext) then return map[ext]
+ return "unknown"
+ end
+
+ # PBX description of this file
+ private fun description: Writable do return """
+ {{{ref_uuid}}} /* {{{doc}}} */ = {
+ isa = PBXFileReference;
+ fileEncoding = 4;
+ lastKnownFileType = {{{file_type}}};
+ path = {{{path}}};
+ sourceTree = "<group>";
+ };
+"""
+
+ private fun add_to_project(project: PbxprojectTemplate)
+ do
+ project.source_files.add self
+ project.files.add self
+ end
+end
+
+# Template for a PBX project file, usually a `project.pbcproj`
+#
+# This file list all information required to build an XCode project.
+# It would usually be written and read by XCode.
+# From the command line, xcodebuild can read this file but not write it.
+#
+# Information in the file (simplified list):
+#
+# * Compilable source files
+# * Asset files
+# * Build configurations (Release and debug modes, cflags, etc.)
+# * List of files composing the project
+class PbxprojectTemplate
+ super Template
+
+ # Name of the project
+ var name: String
+
+ # All body/implementation source files to be compiled
+ private var source_files = new Array[PbxFile]
+
+ # All asset files added to the app package
+ private var asset_files = new Array[PbxFile]
+
+ # All files used by this project
+ private var files = new Array[PbxFile]
+
+ # Add `file` to this project
+ fun add_file(file: PbxFile) do file.add_to_project(self)
+
+ redef fun rendering
+ do
+ add """
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+"""
+
+ # List build files (compilable sources and assets) with their reference UUID
+ for array in [source_files, asset_files] do for file in array do add """
+ {{{file.build_uuid}}} /* {{{file.doc}}} */ = {
+ isa = PBXBuildFile;
+ fileRef = {{{file.ref_uuid}}} /* {{{file.doc}}} */;
+ };
+"""
+
+ add """
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ AF9F83EA1A5F0D21004B62C0 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = AF9F83C41A5F0D21004B62C0 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = AF9F83CB1A5F0D21004B62C0;
+ remoteInfo = {{{name}}};
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ /* Static generated files */
+ AF9F83CC1A5F0D21004B62C0 /* {{{name}}}.app */ = {
+ isa = PBXFileReference;
+ explicitFileType = wrapper.application;
+ includeInIndex = 0;
+ path = {{{name}}}.app;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ AF9F83D01A5F0D21004B62C0 /* Info.plist */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = text.plist.xml;
+ path = Info.plist;
+ sourceTree = "<group>";
+ };
+ AF9F83DE1A5F0D21004B62C0 /* Base */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = file.storyboard;
+ name = Base;
+ path = Base.lproj/Main.storyboard;
+ sourceTree = "<group>";
+ };
+ AF9F83E01A5F0D21004B62C0 /* Images.xcassets */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = folder.assetcatalog;
+ path = Images.xcassets;
+ sourceTree = "<group>";
+ };
+ AF9F83E31A5F0D21004B62C0 /* Base */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = file.xib;
+ name = Base;
+ path = Base.lproj/LaunchScreen.xib;
+ sourceTree = "<group>";
+ };
+ AF9F83E91A5F0D21004B62C0 /* {{{name}}}Tests.xctest */ = {
+ isa = PBXFileReference;
+ explicitFileType = wrapper.cfbundle;
+ includeInIndex = 0;
+ path = {{{name}}}Tests.xctest;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ AF9F83EE1A5F0D21004B62C0 /* Info.plist */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = text.plist.xml;
+ path = Info.plist;
+ sourceTree = "<group>";
+ };
+ AF9F83EF1A5F0D21004B62C0 /* {{{name}}}Tests.m */ = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ path = {{{name}}}Tests.m;
+ sourceTree = "<group>";
+ };
+
+ /* Changing generated files */
+"""
+ # Describe all known files
+ for file in files do add file.description
+
+ add """
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ AF9F83C91A5F0D21004B62C0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ AF9F83E61A5F0D21004B62C0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ AF9F83C31A5F0D21004B62C0 = {
+ isa = PBXGroup;
+ children = (
+ AF9F83CE1A5F0D21004B62C0 /* {{{name}}} */,
+ AF9F83EC1A5F0D21004B62C0 /* {{{name}}}Tests */,
+ AF9F83CD1A5F0D21004B62C0 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ AF9F83CD1A5F0D21004B62C0 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ AF9F83CC1A5F0D21004B62C0 /* {{{name}}}.app */,
+ AF9F83E91A5F0D21004B62C0 /* {{{name}}}Tests.xctest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ AF9F83CE1A5F0D21004B62C0 /* {{{name}}} */ = {
+ isa = PBXGroup;
+ children = (
+"""
+ # Reference all known files
+ for file in files do add """
+ {{{file.ref_uuid}}} /* {{{file.doc}}} */,
+"""
+
+ add """
+ );
+ path = {{{name}}};
+ sourceTree = "<group>";
+ };
+ AF9F83CF1A5F0D21004B62C0 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ AF9F83D01A5F0D21004B62C0 /* Info.plist */,
+ AF9F83D11A5F0D21004B62C0 /* main.m */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ AF9F83EC1A5F0D21004B62C0 /* {{{name}}}Tests */ = {
+ isa = PBXGroup;
+ children = (
+ AF9F83EF1A5F0D21004B62C0 /* {{{name}}}Tests.m */,
+ AF9F83ED1A5F0D21004B62C0 /* Supporting Files */,
+ );
+ path = {{{name}}}Tests;
+ sourceTree = "<group>";
+ };
+ AF9F83ED1A5F0D21004B62C0 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ AF9F83EE1A5F0D21004B62C0 /* Info.plist */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ AF9F83CB1A5F0D21004B62C0 /* {{{name}}} */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = AF9F83F31A5F0D21004B62C0 /* Build configuration list for PBXNativeTarget "{{{name}}}" */;
+ buildPhases = (
+ AF9F83C81A5F0D21004B62C0 /* Sources */,
+ AF9F83C91A5F0D21004B62C0 /* Frameworks */,
+ AF9F83CA1A5F0D21004B62C0 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = {{{name}}};
+ productName = {{{name}}};
+ productReference = AF9F83CC1A5F0D21004B62C0 /* {{{name}}}.app */;
+ productType = "com.apple.product-type.application";
+ };
+ AF9F83E81A5F0D21004B62C0 /* {{{name}}}Tests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = AF9F83F61A5F0D21004B62C0 /* Build configuration list for PBXNativeTarget "{{{name}}}Tests" */;
+ buildPhases = (
+ AF9F83E51A5F0D21004B62C0 /* Sources */,
+ AF9F83E61A5F0D21004B62C0 /* Frameworks */,
+ AF9F83E71A5F0D21004B62C0 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ AF9F83EB1A5F0D21004B62C0 /* PBXTargetDependency */,
+ );
+ name = {{{name}}}Tests;
+ productName = {{{name}}}Tests;
+ productReference = AF9F83E91A5F0D21004B62C0 /* {{{name}}}Tests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ AF9F83C41A5F0D21004B62C0 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0610;
+ TargetAttributes = {
+ AF9F83CB1A5F0D21004B62C0 = {
+ CreatedOnToolsVersion = 6.1.1;
+ };
+ AF9F83E81A5F0D21004B62C0 = {
+ CreatedOnToolsVersion = 6.1.1;
+ TestTargetID = AF9F83CB1A5F0D21004B62C0;
+ };
+ };
+ };
+ buildConfigurationList = AF9F83C71A5F0D21004B62C0 /* Build configuration list for PBXProject "{{{name}}}" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = AF9F83C31A5F0D21004B62C0;
+ productRefGroup = AF9F83CD1A5F0D21004B62C0 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ AF9F83CB1A5F0D21004B62C0 /* {{{name}}} */,
+ AF9F83E81A5F0D21004B62C0 /* {{{name}}}Tests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ AF9F83CA1A5F0D21004B62C0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+"""
+ # Reference all asset files by their build UUID
+ for file in asset_files do add """
+ {{{file.build_uuid}}} /* {{{file.doc}}} */,
+"""
+
+ add """
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ AF9F83E71A5F0D21004B62C0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ AF9F83C81A5F0D21004B62C0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+"""
+ # Reference all compilable source files by their build UUID
+ for file in source_files do add """
+ {{{file.build_uuid}}} /* {{{file.doc}}} */,
+"""
+ add """
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ AF9F83E51A5F0D21004B62C0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ AF9F83F01A5F0D21004B62C0 /* {{{name}}}Tests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ AF9F83EB1A5F0D21004B62C0 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = AF9F83CB1A5F0D21004B62C0 /* {{{name}}} */;
+ targetProxy = AF9F83EA1A5F0D21004B62C0 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ AF9F83DD1A5F0D21004B62C0 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ AF9F83DE1A5F0D21004B62C0 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "<group>";
+ };
+ AF9F83E21A5F0D21004B62C0 /* LaunchScreen.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ AF9F83E31A5F0D21004B62C0 /* Base */,
+ );
+ name = LaunchScreen.xib;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ AF9F83F11A5F0D21004B62C0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.1;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ AF9F83F21A5F0D21004B62C0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.1;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ AF9F83F41A5F0D21004B62C0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ INFOPLIST_FILE = {{{name}}}/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ AF9F83F51A5F0D21004B62C0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ INFOPLIST_FILE = {{{name}}}/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ AF9F83F71A5F0D21004B62C0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(SDKROOT)/Developer/Library/Frameworks",
+ "$(inherited)",
+ );
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ INFOPLIST_FILE = {{{name}}}Tests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{{name}}}.app/{{{name}}}";
+ };
+ name = Debug;
+ };
+ AF9F83F81A5F0D21004B62C0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(SDKROOT)/Developer/Library/Frameworks",
+ "$(inherited)",
+ );
+ INFOPLIST_FILE = {{{name}}}Tests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{{name}}}.app/{{{name}}}";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ AF9F83C71A5F0D21004B62C0 /* Build configuration list for PBXProject "{{{name}}}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ AF9F83F11A5F0D21004B62C0 /* Debug */,
+ AF9F83F21A5F0D21004B62C0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ AF9F83F31A5F0D21004B62C0 /* Build configuration list for PBXNativeTarget "{{{name}}}" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ AF9F83F41A5F0D21004B62C0 /* Debug */,
+ AF9F83F51A5F0D21004B62C0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ };
+ AF9F83F61A5F0D21004B62C0 /* Build configuration list for PBXNativeTarget "{{{name}}}Tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ AF9F83F71A5F0D21004B62C0 /* Debug */,
+ AF9F83F81A5F0D21004B62C0 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = AF9F83C41A5F0D21004B62C0 /* Project object */;
+}
+"""
+ end
+end
+
+# Template for a property list used by XCode for iOS projects
+class PlistTemplate
+ super Template
+
+ # Package of the app
+ var package_name: String
+
+ redef fun rendering
+ do
+ add """
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>{{{package_name}}}.$(PRODUCT_NAME:rfc1034identifier)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>\\?\\?\\?\\?</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
+"""
+ end
+end
cocoa_extern_types
cocoa_message_box
hello_cocoa
+hello_ios
+test_platform_ios
AParExprs ../src/test_parser.nit:71,7--36
TOpar "(" ../src/test_parser.nit:71,7
AStringExpr ../src/test_parser.nit:71,8--35
- TString "\" -n\11do not print anything\"" ../src/test_parser.nit:71,8--35
+ TString "\" -n\tdo not print anything\"" ../src/test_parser.nit:71,8--35
TCpar ")" ../src/test_parser.nit:71,36
ACallExpr ../src/test_parser.nit:72,2--25
AImplicitSelfExpr ../src/test_parser.nit:72,2
AParExprs ../src/test_parser.nit:72,7--25
TOpar "(" ../src/test_parser.nit:72,7
AStringExpr ../src/test_parser.nit:72,8--24
- TString "\" -l\11only lexer\"" ../src/test_parser.nit:72,8--24
+ TString "\" -l\tonly lexer\"" ../src/test_parser.nit:72,8--24
TCpar ")" ../src/test_parser.nit:72,25
ACallExpr ../src/test_parser.nit:73,2--41
AImplicitSelfExpr ../src/test_parser.nit:73,2
AParExprs ../src/test_parser.nit:73,7--41
TOpar "(" ../src/test_parser.nit:73,7
AStringExpr ../src/test_parser.nit:73,8--40
- TString "\" -p\11lexer and parser (default)\"" ../src/test_parser.nit:73,8--40
+ TString "\" -p\tlexer and parser (default)\"" ../src/test_parser.nit:73,8--40
TCpar ")" ../src/test_parser.nit:73,41
ACallExpr ../src/test_parser.nit:74,2--68
AImplicitSelfExpr ../src/test_parser.nit:74,2
AParExprs ../src/test_parser.nit:74,7--68
TOpar "(" ../src/test_parser.nit:74,7
AStringExpr ../src/test_parser.nit:74,8--67
- TString "\" -e\11instead on files, each argument is a content to parse\"" ../src/test_parser.nit:74,8--67
+ TString "\" -e\tinstead on files, each argument is a content to parse\"" ../src/test_parser.nit:74,8--67
TCpar ")" ../src/test_parser.nit:74,68
ACallExpr ../src/test_parser.nit:75,2--51
AImplicitSelfExpr ../src/test_parser.nit:75,2
AParExprs ../src/test_parser.nit:75,7--51
TOpar "(" ../src/test_parser.nit:75,7
AStringExpr ../src/test_parser.nit:75,8--50
- TString "\" -i\11tree to parse are read interactively\"" ../src/test_parser.nit:75,8--50
+ TString "\" -i\ttree to parse are read interactively\"" ../src/test_parser.nit:75,8--50
TCpar ")" ../src/test_parser.nit:75,51
ACallExpr ../src/test_parser.nit:76,2--30
AImplicitSelfExpr ../src/test_parser.nit:76,2
AParExprs ../src/test_parser.nit:76,7--30
TOpar "(" ../src/test_parser.nit:76,7
AStringExpr ../src/test_parser.nit:76,8--29
- TString "\" -h\11print this help\"" ../src/test_parser.nit:76,8--29
+ TString "\" -h\tprint this help\"" ../src/test_parser.nit:76,8--29
TCpar ")" ../src/test_parser.nit:76,30
AIfExpr ../src/test_parser.nit:77,6--146,3
TKwif "if" ../src/test_parser.nit:77,6--7
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import ios