diff --git a/Rakefile b/Rakefile index 74bea31d..3c29a2a3 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,6 @@ PLATFORMS_DIR = '/Developer/Platforms' SDK_VERSION = '4.3' -PROJECT_VERSION = '0.0.7' +PROJECT_VERSION = '0.0.8' verbose(true) @@ -50,7 +50,7 @@ gem_spec = Gem::Specification.new do |spec| files = [] files.concat(Dir.glob('./lib/**/*')) files.concat(Dir.glob('./data/BridgeSupport/*.bridgesupport')) - files.concat(%w{./data/deploy ./data/llc ./data/ruby}) + files.concat(%w{./data/deploy ./data/sim ./data/llc ./data/ruby}) files.concat(Dir.glob('./data/iPhoneOS/*')) files.concat(Dir.glob('./data/iPhoneSimulator/*')) files.concat(Dir.glob('./doc/html/**/*')) diff --git a/data/Rakefile b/data/Rakefile index 8fbb8a12..9c4363f4 100644 --- a/data/Rakefile +++ b/data/Rakefile @@ -4,7 +4,7 @@ SDK_VERSION = ENV['sdk_version'] verbose(true) task :default => :all -task :all => [:vm_files, :bridgesupport_files, :bridgesupport_static_stubs, :deploy] +task :all => [:vm_files, :bridgesupport_files, :bridgesupport_static_stubs, :deploy, :sim] task :vm_files do install '../vm/miniruby', 'ruby' @@ -86,6 +86,11 @@ task :deploy do sh "/usr/bin/strip -x deploy" end -task :clean do - %w{ruby llc iPhoneOS iPhoneSimulator BridgeSupport deploy}.each { |path| rm_rf(path) } +task :sim do + sh "/usr/bin/gcc -I./src -std=c99 -Wall -O3 src/sim.m -o sim -framework Foundation" + sh "/usr/bin/strip -x sim" +end + +task :clean do + %w{ruby llc iPhoneOS iPhoneSimulator BridgeSupport deploy sim}.each { |path| rm_rf(path) } end diff --git a/data/src/sim.m b/data/src/sim.m new file mode 100644 index 00000000..1b1282c8 --- /dev/null +++ b/data/src/sim.m @@ -0,0 +1,128 @@ +#import +#import +#import + +@interface Delegate : NSObject +@end + +@implementation Delegate + +- (void)session:(id)session didEndWithError:(NSError *)error +{ + if (error == nil) { + //fprintf(stderr, "*** simulator session ended without error\n"); + exit(0); + } + else { + fprintf(stderr, "*** simulator session ended with error: %s\n", + [[error description] UTF8String]); + exit(1); + } +} + +- (void)session:(id)session didStart:(BOOL)flag withError:(NSError *)error +{ + if (!flag || error != nil) { + fprintf(stderr, "*** simulator session started with error: %s\n", + [[error description] UTF8String]); + exit(1); + } + //fprintf(stderr, "*** simulator session started\n"); + system("open -a \"iPhone Simulator\""); +} + +@end + +static void +usage(void) +{ + system("open http://www.youtube.com/watch?v=QH2-TGUlwu4"); + exit(1); +} + +int +main(int argc, char **argv) +{ + [[NSAutoreleasePool alloc] init]; + + if (argc != 4) { + usage(); + } + + NSNumber *device_family = [NSNumber numberWithInt:atoi(argv[1])]; + NSString *sdk_version = [NSString stringWithUTF8String:argv[2]]; + NSString *app_path = [NSString stringWithUTF8String:realpath(argv[3], NULL)]; + + [[NSBundle bundleWithPath:@"/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/iPhoneSimulatorRemoteClient.framework"] load]; + + Class AppSpecifier = + NSClassFromString(@"DTiPhoneSimulatorApplicationSpecifier"); + assert(AppSpecifier != nil); + + Class SystemRoot = NSClassFromString(@"DTiPhoneSimulatorSystemRoot"); + assert(SystemRoot != nil); + + Class SessionConfig = NSClassFromString(@"DTiPhoneSimulatorSessionConfig"); + assert(SessionConfig != nil); + + Class Session = NSClassFromString(@"DTiPhoneSimulatorSession"); + assert(Session != nil); + + // Create application specifier. + id app_spec = ((id (*)(id, SEL, id))objc_msgSend)(AppSpecifier, + @selector(specifierWithApplicationPath:), app_path); + assert(app_spec != nil); + + // Create system root. + id system_root = ((id (*)(id, SEL, id))objc_msgSend)(SystemRoot, + @selector(rootWithSDKVersion:), sdk_version); + assert(system_root != nil); + + // Create session config. + id config = [[SessionConfig alloc] init]; + ((void (*)(id, SEL, id))objc_msgSend)(config, + @selector(setApplicationToSimulateOnStart:), app_spec); + ((void (*)(id, SEL, id))objc_msgSend)(config, + @selector(setSimulatedApplicationLaunchArgs:), [NSArray array]); + ((void (*)(id, SEL, id))objc_msgSend)(config, + @selector(setSimulatedApplicationLaunchEnvironment:), + [NSDictionary dictionary]); + ((void (*)(id, SEL, BOOL))objc_msgSend)(config, + @selector(setSimulatedApplicationShouldWaitForDebugger:), NO); + ((void (*)(id, SEL, id))objc_msgSend)(config, + @selector(setSimulatedDeviceFamily:), device_family); + ((void (*)(id, SEL, id))objc_msgSend)(config, + @selector(setSimulatedSystemRoot:), system_root); + ((void (*)(id, SEL, id))objc_msgSend)(config, + @selector(setLocalizedClientName:), @"NYANCAT"); + + char path[MAXPATHLEN]; + fcntl(STDOUT_FILENO, F_GETPATH, &path); + ((void (*)(id, SEL, id))objc_msgSend)(config, + @selector(setSimulatedApplicationStdOutPath:), + [NSString stringWithUTF8String:path]); + + fcntl(STDERR_FILENO, F_GETPATH, &path); + ((void (*)(id, SEL, id))objc_msgSend)(config, + @selector(setSimulatedApplicationStdErrPath:), + [NSString stringWithUTF8String:path]); + + // Create session. + id session = [[Session alloc] init]; + id delegate = [[Delegate alloc] init]; + ((void (*)(id, SEL, id))objc_msgSend)(session, @selector(setDelegate:), + delegate); + + // Start session. + NSError *error = nil; + if (!((BOOL (*)(id, SEL, id, double, id *))objc_msgSend)(session, + @selector(requestStartWithConfig:timeout:error:), config, 0.0, + &error)) { + fprintf(stderr, "*** can't start simulator: %s\n", + [[error description] UTF8String]); + exit(1); + } + + [[NSRunLoop mainRunLoop] run]; + return 0; +} diff --git a/lib/rubixir/rake.rb b/lib/rubixir/rake.rb index b1098081..ce008a67 100644 --- a/lib/rubixir/rake.rb +++ b/lib/rubixir/rake.rb @@ -27,9 +27,10 @@ end desc "Run the simulator" task :simulator => ['build:simulator'] do - app = Rubixir::CONFIG.app_bundle('iPhoneSimulator', true) - sim = File.join(Rubixir::CONFIG.platform_dir('iPhoneSimulator'), '/Developer/Applications/iPhone Simulator.app/Contents/MacOS/iPhone Simulator') - sh "\"#{sim}\" -SimulateApplication \"#{app}\"" + sim = File.join(Rubixir::CONFIG.datadir, 'sim') + app = Rubixir::CONFIG.app_bundle('iPhoneSimulator') + family = Rubixir::CONFIG.device_family_ints[0] + sh "#{sim} #{family} #{Rubixir::CONFIG.sdk_version} \"#{app}\"" end desc "Create an .ipa package" diff --git a/lib/rubixir/rake/config.rb b/lib/rubixir/rake/config.rb index a2196581..24c3a74b 100644 --- a/lib/rubixir/rake/config.rb +++ b/lib/rubixir/rake/config.rb @@ -11,7 +11,7 @@ module Rubixir variable :files, :platforms_dir, :sdk_version, :frameworks, :app_delegate_class, :app_name, :build_dir, :resources_dir, - :codesign_certificate, :provisioning_profile + :codesign_certificate, :provisioning_profile, :device_family def initialize(project_dir) @files = Dir.glob(File.join(project_dir, 'app/**/*.rb')) @@ -21,6 +21,7 @@ module Rubixir @app_name = 'My App' @build_dir = File.join(project_dir, 'build') @resources_dir = File.join(project_dir, 'resources') + @device_family = :iphone @bundle_signature = '????' end @@ -61,16 +62,27 @@ module Rubixir platform + sdk_version + '.sdk') end - def app_bundle(platform, exec=false) - path = File.join(@build_dir, platform, @app_name + '.app') - path = File.join(path, @app_name) if exec - path + def app_bundle(platform) + File.join(@build_dir, platform, @app_name + '.app') end def archive File.join(@build_dir, @app_name + '.ipa') end + def device_family_ints + ary = @device_family.is_a?(Array) ? @device_family : [@device_family] + ary.map do |family| + case family + when :iphone then 1 + when :ipad then 2 + else + $stderr.puts "unknown device family #{family}" + exit 1 + end + end + end + def plist_data < @@ -127,7 +139,7 @@ module Rubixir #{sdk_version} UIDeviceFamily - 1 + #{device_family_ints.map { |family| '' + family.to_s + '' }.join('')} UISupportedInterfaceOrientations diff --git a/sample/hello/Rakefile b/sample/hello/Rakefile index e1b5c0d5..93d2a6ce 100644 --- a/sample/hello/Rakefile +++ b/sample/hello/Rakefile @@ -2,3 +2,4 @@ $:.unshift('../../lib') require 'rubixir/rake' Rubixir::CONFIG.app_name = 'Hello' +Rubixir::CONFIG.device_family = :iphone