From bfe3c0cdb34c766902bb4729f6e42efd07643e02 Mon Sep 17 00:00:00 2001 From: Laurent Sansonetti Date: Sun, 25 Dec 2011 17:06:22 +0100 Subject: [PATCH] better deploy (check if connected device is provisioned), more build system output fixes, misc changes --- bin/deploy.m | 62 ++++++++++++++++++++++++----------- lib/motion/project.rb | 6 +++- lib/motion/project/app.rb | 15 ++++++--- lib/motion/project/builder.rb | 12 ++++--- lib/motion/project/config.rb | 61 ++++++++++++++++++++-------------- 5 files changed, 103 insertions(+), 53 deletions(-) diff --git a/bin/deploy.m b/bin/deploy.m index 7ac311bb..865f499d 100644 --- a/bin/deploy.m +++ b/bin/deploy.m @@ -82,6 +82,7 @@ init_private_funcs(void) } static bool debug_mode = false; +static bool discovery_mode = false; #define LOG(fmt, ...) \ do { \ @@ -159,6 +160,7 @@ read_plist(NSFileHandle *handle) return plist; } +static NSString *device_id = nil; static NSString *app_package_path = nil; static NSData *app_package_data = nil; @@ -233,7 +235,7 @@ device_go(am_device_t dev) } } - fprintf(stderr, "package has been successfully installed on device\n"); + LOG("package has been successfully installed on device"); [handle release]; } @@ -243,9 +245,15 @@ device_subscribe_cb(am_device_notif_context_t ctx) am_device_t dev = am_device_from_notif_context(ctx); CFStringRef name = _AMDeviceGetName(dev); if (name != NULL) { - fprintf(stderr, "found usb mobile device %s\n", [(id)name UTF8String]); - device_go(dev); - exit(0); + if (discovery_mode) { + printf("%s\n", [(id)name UTF8String]); + exit(0); + } + else if ([(id)name isEqualToString:device_id]) { + LOG("found usb mobile device %s", [(id)name UTF8String]); + device_go(dev); + exit(0); + } } } @@ -266,24 +274,34 @@ main(int argc, char **argv) if (strcmp(argv[i], "-d") == 0) { debug_mode = true; } + else if (strcmp(argv[i], "-D") == 0) { + discovery_mode = true; + } else { - if (app_package_path != nil) { - usage(); + if (device_id == nil) { + device_id = [[NSString stringWithUTF8String:argv[i]] retain]; + } + else { + if (app_package_path != nil) { + usage(); + } + app_package_path = [[NSString stringWithUTF8String:argv[i]] + retain]; } - app_package_path = [[NSString stringWithUTF8String:argv[i]] retain]; } } - if (app_package_path == nil) { - usage(); - } - - app_package_data = - [[NSData dataWithContentsOfFile:app_package_path] retain]; - if (app_package_data == nil) { - fprintf(stderr, "can't read data from %s\n", - [app_package_path fileSystemRepresentation]); - exit(1); + if (!discovery_mode) { + if (device_id == nil || app_package_path == nil) { + usage(); + } + app_package_data = + [[NSData dataWithContentsOfFile:app_package_path] retain]; + if (app_package_data == nil) { + fprintf(stderr, "can't read data from %s\n", + [app_package_path fileSystemRepresentation]); + exit(1); + } } init_private_funcs(); @@ -294,8 +312,12 @@ main(int argc, char **argv) ¬if)); // Run one second, should be enough to catch an attached device. - [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; + [[NSRunLoop mainRunLoop] runUntilDate: + [NSDate dateWithTimeIntervalSinceNow:1]]; - fprintf(stderr, "error: can't find any device\n"); - return 1; + if (!discovery_mode) { + fprintf(stderr, "error: can't find device ID %s\n", + [device_id UTF8String]); + } + exit(1); } diff --git a/lib/motion/project.rb b/lib/motion/project.rb index ecd237f7..7abf9ffa 100644 --- a/lib/motion/project.rb +++ b/lib/motion/project.rb @@ -85,9 +85,13 @@ end desc "Deploy on the device" task :deploy => :archive do App.info 'Deploy', App.config.archive + unless App.config.provisioned_devices.include?(App.config.device_id) + $stderr.puts "Connected device ID `#{App.config.device_id}' not provisioned in profile `#{App.config.provisioning_profile}'" + exit 1 + end deploy = File.join(App.config.bindir, 'deploy') flags = Rake.application.options.trace ? '-d' : '' - sh "#{deploy} #{flags} \"#{App.config.archive}\"" + sh "#{deploy} #{flags} \"#{App.config.device_id}\" \"#{App.config.archive}\"" end desc "Clear build objects" diff --git a/lib/motion/project/app.rb b/lib/motion/project/app.rb index 28e905e8..4c6c6b0a 100644 --- a/lib/motion/project/app.rb +++ b/lib/motion/project/app.rb @@ -22,14 +22,21 @@ module Motion; module Project builder.codesign(config, platform) end + def log(what, msg) + $stderr.puts what.rjust(10) + ' ' + msg + end + def warn(msg) - $stderr.puts "WARNING!".rjust(10) + ' ' + msg + log 'WARNING!', msg + end + + def fail(msg) + log 'ERROR!', msg + exit 1 end def info(what, msg) - unless Rake.verbose - $stderr.puts what.rjust(10) + ' ' + msg - end + log what, msg unless Rake.verbose end end end diff --git a/lib/motion/project/builder.rb b/lib/motion/project/builder.rb index 8a4b2125..fcc591da 100644 --- a/lib/motion/project/builder.rb +++ b/lib/motion/project/builder.rb @@ -11,8 +11,7 @@ module Motion; module Project; llc = File.join(config.bindir, 'llc') if config.spec_mode and config.spec_files.empty? - $stderr.puts "No spec files in `#{config.specs_dir}'" - exit 1 + App.fail "No spec files in `#{config.specs_dir}'" end # Locate SDK. @@ -140,6 +139,12 @@ EOS } - (void)appLaunched:(id)notification +{ + // Give a bit of time to the simulator to attach... + [self performSelector:@selector(runSpecs) withObject:nil afterDelay:0.1]; +} + +- (void)runSpecs { EOS spec_objs.each do |_, init_func| @@ -244,8 +249,7 @@ EOS resources_files.each do |res| res_path = File.join(config.resources_dir, res) if reserved_app_bundle_files.include?(res) - $stderr.puts "Cannot use `#{res_path}' as a resource file because it's a reserved application bundle file" - exit 1 + App.fail "Cannot use `#{res_path}' as a resource file because it's a reserved application bundle file" end dest_path = File.join(bundle_path, res) if !File.exist?(dest_path) or File.mtime(res_path) > File.mtime(dest_path) diff --git a/lib/motion/project/config.rb b/lib/motion/project/config.rb index dae86200..3f5cd8b8 100644 --- a/lib/motion/project/config.rb +++ b/lib/motion/project/config.rb @@ -26,9 +26,9 @@ module Motion; module Project variable :files, :platforms_dir, :sdk_version, :frameworks, :libs, :delegate_class, :name, :build_dir, :resources_dir, :specs_dir, - :identifier, :codesign_certificate, :provisioning_profile, - :device_family, :interface_orientations, :version, :icons, - :prerendered_icon, :seed_id, :entitlements + :identifier, :codesign_certificate, :provisioning_profile, :device_family, + :interface_orientations, :version, :icons, :prerendered_icon, :seed_id, + :entitlements def initialize(project_dir) @project_dir = project_dir @@ -55,8 +55,12 @@ module Motion; module Project def variables map = {} VARS.each do |sym| - val = send(sym) rescue "ERROR" - map[sym] = val + map[sym] = + begin + send(sym) + rescue Exception + 'Error' + end end map end @@ -67,13 +71,11 @@ module Motion; module Project sdk_path = File.join(platforms_dir, platform + '.platform', "Developer/SDKs/#{platform}#{sdk_version}.sdk") unless File.exist?(sdk_path) - $stderr.puts "Can't locate #{platform} SDK #{sdk_version} at `#{sdk_path}'" - exit 1 + App.fail "Can't locate #{platform} SDK #{sdk_version} at `#{sdk_path}'" end end unless File.exist?(datadir) - $stderr.puts "iOS SDK #{sdk_version} is not supported by this version of RubyMotion" - exit 1 + App.fail "iOS SDK #{sdk_version} is not supported by this version of RubyMotion" end end @@ -156,8 +158,7 @@ module Motion; module Project File.basename(path).scan(/iPhoneOS(.*)\.sdk/)[0][0] end if versions.size == 0 - $stderr.puts "Can't find an iOS SDK in `#{platforms_dir}'" - exit 1 + App.fail "Can't find an iOS SDK in `#{platforms_dir}'" #elsif versions.size > 1 # $stderr.puts "found #{versions.size} SDKs, will use the latest one" end @@ -187,8 +188,7 @@ module Motion; module Project when :iphone then 1 when :ipad then 2 else - $stderr.puts "Unknown device_family value: `#{family}'" - exit 1 + App.fail "Unknown device_family value: `#{family}'" end end @@ -205,8 +205,7 @@ module Motion; module Project when :landscape_right then 'UIInterfaceOrientationLandscapeRight' when :portrait_upside_down then 'UIInterfaceOrientationPortraitUpsideDown' else - $stderr.puts "Unknown interface_orientation value: `#{ori}'" - exit 1 + App.fail "Unknown interface_orientation value: `#{ori}'" end end end @@ -251,8 +250,7 @@ module Motion; module Project @codesign_certificate ||= begin certs = `/usr/bin/security -q find-certificate -a`.scan(/"iPhone Developer: [^"]+"/).uniq if certs.size == 0 - $stderr.puts "Can't find an iPhone Developer certificate in the keychain" - exit 1 + App.fail "Can't find an iPhone Developer certificate in the keychain" elsif certs.size > 1 App.warn "Found #{certs.size} iPhone Developer certificates in the keychain. Set the `codesign_certificate' project setting. Will use the first certificate: `#{certs[0]}'" end @@ -260,26 +258,41 @@ module Motion; module Project end end - def provisioning_profile + def device_id + @device_id ||= begin + deploy = File.join(App.config.bindir, 'deploy') + device_id = `#{deploy} -D`.strip + if device_id.empty? + App.fail "Can't find an iOS device connected on USB" + end + device_id + end + end + + def provisioning_profile(name = 'Dev Profile') @provisioning_profile ||= begin - paths = Dir.glob(File.expand_path("~/Library/MobileDevice/Provisioning\ Profiles/*.mobileprovision")) + paths = Dir.glob(File.expand_path("~/Library/MobileDevice/Provisioning\ Profiles/*.mobileprovision")).select do |path| + File.read(path).scan(/\s*Name\s*<\/key>\s*\s*([^<]+)\s*<\/string>/)[0][0] == name + end if paths.size == 0 - $stderr.puts "Can't find a provisioning profile" - exit 1 + App.fail "Can't find a provisioning profile named `#{name}'" elsif paths.size > 1 - App.warn "Found #{paths.size} provisioning profiles. Set the `provisioning_profile' project setting. Will use the first one: `#{paths[0]}'" + App.warn "Found #{paths.size} provisioning profiles named `#{name}'. Set the `provisioning_profile' project setting. Will use the first one: `#{paths[0]}'" end paths[0] end end + def provisioned_devices + @provisioned_devices ||= File.read(provisioning_profile).scan(/\s*ProvisionedDevices\s*<\/key>\s*(\s*\s*([^<\s]+)\s*<\/string>)+\s*<\/array>/).map { |ary| ary[1] } + end + def seed_id @seed_id ||= begin txt = File.read(provisioning_profile) seed_ids = txt.scan(/\s*ApplicationIdentifierPrefix\s*<\/key>\s*(\s*\s*([^<\s]+)\s*<\/string>)+\s*<\/array>/).map { |ary| ary[1] } if seed_ids.size == 0 - $stderr.puts "Can't find an application seed ID in the provisioning profile" - exit 1 + App.fail "Can't find an application seed ID in the provisioning profile `#{provisioning_profile}'" elsif seed_ids.size > 1 App.warn "Found #{seed_ids.size} seed IDs in the provisioning profile. Set the `seed_id' project setting. Will use the last one: `#{seed_ids.last}'" end