@@ -27,10 +27,12 @@ module Motion; module Project;
2727 class Builder
2828 include Rake ::DSL if Rake . const_defined? ( :DSL )
2929
30- def build ( config , platform )
30+ def build ( config , platform , opts )
3131 datadir = config . datadir
3232 archs = config . archs [ platform ]
3333
34+ static_library = opts . delete ( :static )
35+
3436 ruby = File . join ( config . bindir , 'ruby' )
3537 llc = File . join ( config . bindir , 'llc' )
3638
@@ -160,15 +162,15 @@ def build(config, platform)
160162 FileUtils . touch ( objs_build_dir ) if project_file_changed
161163
162164 app_objs = objs
165+ spec_objs = [ ]
163166 if config . spec_mode
164167 # Build spec files too, but sequentially.
165- objs << build_file . call ( File . expand_path ( File . join ( File . dirname ( __FILE__ ) , '../spec.rb' ) ) )
166168 spec_objs = config . spec_files . map { |path | build_file . call ( path ) }
167169 objs += spec_objs
168170 end
169171
170- # Generate main file.
171- main_txt = <<EOS
172+ # Generate init file.
173+ init_txt = <<EOS
172174#import <UIKit/UIKit.h>
173175
174176extern "C" {
@@ -184,8 +186,72 @@ def build(config, platform)
184186 void rb_rb2oc_exc_handler(void);
185187 void rb_exit(int);
186188EOS
187- objs . each do |_ , init_func |
188- main_txt << "void #{ init_func } (void *, void *);\n "
189+ app_objs . each do |_ , init_func |
190+ init_txt << "void #{ init_func } (void *, void *);\n "
191+ end
192+ init_txt << <<EOS
193+ }
194+
195+ extern "C"
196+ void
197+ RubyMotionInit(int argc, char **argv)
198+ {
199+ static bool initialized = false;
200+ if (!initialized) {
201+ ruby_init();
202+ ruby_init_loadpath();
203+ if (argc > 0) {
204+ const char *progname = argv[0];
205+ ruby_script(progname);
206+ }
207+ try {
208+ void *self = rb_vm_top_self();
209+ EOS
210+ app_objs . each do |_ , init_func |
211+ init_txt << "#{ init_func } (self, 0);\n "
212+ end
213+ init_txt << <<EOS
214+ }
215+ catch (...) {
216+ rb_rb2oc_exc_handler();
217+ }
218+ initialized = true;
219+ }
220+ }
221+ EOS
222+
223+ # Compile init file.
224+ init = File . join ( objs_build_dir , 'init.mm' )
225+ init_o = File . join ( objs_build_dir , 'init.o' )
226+ if !( File . exist? ( init ) and File . exist? ( init_o ) and File . read ( init ) == init_txt )
227+ File . open ( init , 'w' ) { |io | io . write ( init_txt ) }
228+ sh "#{ cxx } \" #{ init } \" #{ config . cflags ( platform , true ) } -c -o \" #{ init_o } \" "
229+ end
230+
231+ if static_library
232+ # Create a static archive with all object files + the runtime.
233+ lib = File . join ( config . versionized_build_dir ( platform ) , config . name + '.a' )
234+ App . info 'Create' , lib
235+ cp File . join ( datadir , platform , 'libmacruby-static.a' ) , lib
236+ objs_list = objs . map { |path , _ | path } . unshift ( init_o , *config . frameworks_stubs_objects ( platform ) ) . map { |x | "\" #{ x } \" " } . join ( ' ' )
237+ sh "/usr/bin/ar -cr \" #{ lib } \" #{ objs_list } "
238+ return lib
239+ end
240+
241+ # Generate main file.
242+ main_txt = <<EOS
243+ #import <UIKit/UIKit.h>
244+
245+ extern "C" {
246+ void rb_define_const(void *, const char *, void *);
247+ void rb_rb2oc_exc_handler(void);
248+ void rb_exit(int);
249+ void RubyMotionInit(int argc, char **argv);
250+ EOS
251+ if config . spec_mode
252+ spec_objs . each do |_ , init_func |
253+ main_txt << "void #{ init_func } (void *, void *);\n "
254+ end
189255 end
190256 main_txt << <<EOS
191257}
@@ -196,11 +262,31 @@ def build(config, platform)
196262@interface SpecLauncher : NSObject
197263@end
198264
265+ #include <dlfcn.h>
266+
199267@implementation SpecLauncher
200268
201269+ (id)launcher
202270{
203271 [UIApplication sharedApplication];
272+
273+ // Enable simulator accessibility.
274+ // Thanks http://www.stewgleadow.com/blog/2011/10/14/enabling-accessibility-for-ios-applications/
275+ NSString *simulatorRoot = [[[NSProcessInfo processInfo] environment] objectForKey:@"IPHONE_SIMULATOR_ROOT"];
276+ if (simulatorRoot != nil) {
277+ void *appSupportLibrary = dlopen([[simulatorRoot stringByAppendingPathComponent:@"/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport"] fileSystemRepresentation], RTLD_LAZY);
278+ CFStringRef (*copySharedResourcesPreferencesDomainForDomain)(CFStringRef domain) = (CFStringRef (*)(CFStringRef)) dlsym(appSupportLibrary, "CPCopySharedResourcesPreferencesDomainForDomain");
279+
280+ if (copySharedResourcesPreferencesDomainForDomain != NULL) {
281+ CFStringRef accessibilityDomain = copySharedResourcesPreferencesDomainForDomain(CFSTR("com.apple.Accessibility"));
282+
283+ if (accessibilityDomain != NULL) {
284+ CFPreferencesSetValue(CFSTR("ApplicationAccessibilityEnabled"), kCFBooleanTrue, accessibilityDomain, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
285+ CFRelease(accessibilityDomain);
286+ }
287+ }
288+ }
289+
204290 SpecLauncher *launcher = [[self alloc] init];
205291 [[NSNotificationCenter defaultCenter] addObserver:launcher selector:@selector(appLaunched:) name:UIApplicationDidBecomeActiveNotification object:nil];
206292 return launcher;
@@ -230,18 +316,20 @@ def build(config, platform)
230316main(int argc, char **argv)
231317{
232318 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
233- const char *progname = argv[0];
234- ruby_init();
235- ruby_init_loadpath();
236- ruby_script(progname);
237319 int retval = 0;
238320 try {
239- void *self = rb_vm_top_self();
240321EOS
241322 main_txt << "[SpecLauncher launcher];\n " if config . spec_mode
242- app_objs . each do |_ , init_func |
243- main_txt << "#{ init_func } (self, 0);\n "
244- end
323+ main_txt << <<EOS
324+ RubyMotionInit(argc, argv);
325+ EOS
326+ rubymotion_env =
327+ if config . spec_mode
328+ 'test'
329+ else
330+ config . development? ? 'development' : 'release'
331+ end
332+ main_txt << "rb_define_const([NSObject class], \" RUBYMOTION_ENV\" , @\" #{ rubymotion_env } \" );\n "
245333 main_txt << <<EOS
246334 retval = UIApplicationMain(argc, argv, nil, @"#{ config . delegate_class } ");
247335 rb_exit(retval);
@@ -279,14 +367,9 @@ def build(config, platform)
279367 or vendor_libs . any? { |lib | File . mtime ( lib ) > File . mtime ( main_exec ) } \
280368 or File . mtime ( File . join ( datadir , platform , 'libmacruby-static.a' ) ) > File . mtime ( main_exec )
281369 App . info 'Link' , main_exec
282- objs_list = objs . map { |path , _ | path } . unshift ( main_o ) . map { |x | "\" #{ x } \" " } . join ( ' ' )
370+ objs_list = objs . map { |path , _ | path } . unshift ( init_o , main_o , * config . frameworks_stubs_objects ( platform ) ) . map { |x | "\" #{ x } \" " } . join ( ' ' )
283371 frameworks = config . frameworks_dependencies . map { |x | "-framework #{ x } " } . join ( ' ' )
284- framework_stubs_objs = [ ]
285- config . frameworks_dependencies . each do |framework |
286- stubs_obj = File . join ( datadir , platform , "#{ framework } _stubs.o" )
287- framework_stubs_objs << "\" #{ stubs_obj } \" " if File . exist? ( stubs_obj )
288- end
289- sh "#{ cxx } -o \" #{ main_exec } \" #{ objs_list } #{ framework_stubs_objs . join ( ' ' ) } #{ config . ldflags ( platform ) } -L#{ File . join ( datadir , platform ) } -lmacruby-static -lobjc -licucore #{ frameworks } #{ config . libs . join ( ' ' ) } #{ vendor_libs . map { |x | '-force_load "' + x + '"' } . join ( ' ' ) } "
372+ sh "#{ cxx } -o \" #{ main_exec } \" #{ objs_list } #{ config . ldflags ( platform ) } -L#{ File . join ( datadir , platform ) } -lmacruby-static -lobjc -licucore #{ frameworks } #{ config . libs . join ( ' ' ) } #{ vendor_libs . map { |x | '-force_load "' + x + '"' } . join ( ' ' ) } "
290373 main_exec_created = true
291374 end
292375
0 commit comments