diff --git a/lib/motion/project.rb b/lib/motion/project.rb index e4f29247..8710ae02 100644 --- a/lib/motion/project.rb +++ b/lib/motion/project.rb @@ -81,13 +81,13 @@ task :simulator => ['build:simulator'] do else App.config.device_family_ints[0] end - retina = ENV['retina'] == 'true' + retina = ENV['retina'] # Configure the SimulateDevice variable (the only way to specify if we want to run in retina mode or not). - simulate_device = App.config.device_family_string(family_int, retina) + simulate_device = App.config.device_family_string(family_int, target, retina) if `/usr/bin/defaults read com.apple.iphonesimulator "SimulateDevice"`.strip != simulate_device system("/usr/bin/killall \"iPhone Simulator\" >& /dev/null") - system("/usr/bin/defaults write com.apple.iphonesimulator \"SimulateDevice\" \"'#{App.config.device_family_string(family_int, retina)}'\"") + system("/usr/bin/defaults write com.apple.iphonesimulator \"SimulateDevice\" \"'#{simulate_device}'\"") end # Launch the simulator. @@ -95,45 +95,23 @@ task :simulator => ['build:simulator'] do env = xcode.match(/^\/Applications/) ? "DYLD_FRAMEWORK_PATH=\"#{xcode}/../Frameworks\":\"#{xcode}/../OtherFrameworks\"" : '' env << ' NO_FOREGROUND_SIM=1' if App.config.spec_mode sim = File.join(App.config.bindir, 'sim') - debug = (ENV['debug'] || (App.config.spec_mode ? '0' : '2')).to_i - debug = 2 if debug < 0 or debug > 2 + debug = (ENV['debug'] ? 1 : (App.config.spec_mode ? '0' : '2')) App.info 'Simulate', app at_exit { system("stty echo") } # Just in case the simulator launcher crashes and leaves the terminal without echo. sh "#{env} #{sim} #{debug} #{family_int} #{target} \"#{xcode}\" \"#{app}\"" end -desc "Create archives for everything" -task :archive => ['archive:development', 'archive:release'] - -def create_ipa - app_bundle = App.config.app_bundle('iPhoneOS') - archive = App.config.archive - if !File.exist?(archive) or File.mtime(app_bundle) > File.mtime(archive) - App.info 'Create', archive - tmp = "/tmp/ipa_root" - sh "/bin/rm -rf #{tmp}" - sh "/bin/mkdir -p #{tmp}/Payload" - sh "/bin/cp -r \"#{app_bundle}\" #{tmp}/Payload" - Dir.chdir(tmp) do - sh "/bin/chmod -R 755 Payload" - sh "/usr/bin/zip -q -r archive.zip Payload" - end - sh "/bin/cp #{tmp}/archive.zip \"#{archive}\"" - end +desc "Create an .ipa archive" +task :archive => ['build:device'] do + App.archive end namespace :archive do - desc "Create an .ipa archive for development" - task :development do - App.config_mode = :development - Rake::Task["build:device"].execute - App.archive - end - - desc "Create an .ipa for release (AppStore)" - task :release do - App.config_mode = :release - Rake::Task["build:device"].execute + desc "Create an .ipa archive for distribution (AppStore)" + task :distribution do + App.config_without_setup.build_mode = :release + App.config.distribution_mode = true + Rake::Task["build:device"].invoke App.archive end end @@ -145,15 +123,16 @@ task :spec do end desc "Deploy on the device" -task :device => 'archive:development' do +task :device => :archive do App.info 'Deploy', App.config.archive device_id = (ENV['id'] or App.config.device_id) unless App.config.provisioned_devices.include?(device_id) App.fail "Device ID `#{device_id}' not provisioned in profile `#{App.config.provisioning_profile}'" end + env = "XCODE_DIR=\"#{App.config.xcode_dir}\"" deploy = File.join(App.config.bindir, 'deploy') flags = Rake.application.options.trace ? '-d' : '' - sh "#{deploy} #{flags} \"#{device_id}\" \"#{App.config.archive}\"" + sh "#{env} #{deploy} #{flags} \"#{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 104466b2..be66b2cd 100644 --- a/lib/motion/project/app.rb +++ b/lib/motion/project/app.rb @@ -37,31 +37,35 @@ module Motion; module Project class << self def config_mode - @config_mode or :development + @config_mode ||= begin + if mode = ENV['mode'] + case mode = mode.intern + when :development, :release + mode + else + fail "Invalid value for build mode `#{mode}' (must be :development or :release)" + end + else + :development + end + end end - def config_mode=(mode) - @config_mode = mode - end - - def configs - @configs ||= { - :development => Motion::Project::Config.new('.', :development), - :release => Motion::Project::Config.new('.', :release) - } + def config_without_setup + @configs ||= {} + @configs[config_mode] ||= Motion::Project::Config.new('.', config_mode) end def config - configs[config_mode] + config_without_setup.setup end def builder @builder ||= Motion::Project::Builder.new end - def setup - configs.each_value { |x| yield x } - config.validate + def setup(&block) + config.setup_blocks << block end def build(platform, opts={}) diff --git a/lib/motion/project/builder.rb b/lib/motion/project/builder.rb index 66ec40eb..496eb939 100644 --- a/lib/motion/project/builder.rb +++ b/lib/motion/project/builder.rb @@ -64,7 +64,9 @@ module Motion; module Project; FileUtils.mkdir_p(objs_build_dir) any_obj_file_built = false build_file = Proc.new do |path| - obj ||= File.join(objs_build_dir, "#{path}.o") + rpath = path + path = File.expand_path(path) + obj = File.join(objs_build_dir, "#{path}.o") should_rebuild = (!File.exist?(obj) \ or File.mtime(path) > File.mtime(obj) \ or File.mtime(ruby) > File.mtime(obj)) @@ -73,7 +75,7 @@ module Motion; module Project; init_func = should_rebuild ? "MREP_#{`/usr/bin/uuidgen`.strip.gsub('-', '')}" : `#{config.locate_binary('nm')} #{obj}`.scan(/T\s+_(MREP_.*)/)[0][0] if should_rebuild - App.info 'Compile', path + App.info 'Compile', rpath FileUtils.mkdir_p(File.dirname(obj)) arch_objs = [] archs.each do |arch| @@ -84,7 +86,7 @@ module Motion; module Project; # LLVM bitcode. bc = File.join(objs_build_dir, "#{path}.#{arch}.bc") bs_flags = bs_files.map { |x| "--uses-bs \"" + x + "\" " }.join(' ') - sh "/usr/bin/env VM_KERNEL_PATH=\"#{kernel}\" #{ruby} #{bs_flags} --emit-llvm \"#{bc}\" #{init_func} \"#{path}\"" + sh "/usr/bin/env VM_KERNEL_PATH=\"#{kernel}\" VM_OPT_LEVEL=\"#{config.opt_level}\" #{ruby} #{bs_flags} --emit-llvm \"#{bc}\" #{init_func} \"#{path}\"" # Assembly. asm = File.join(objs_build_dir, "#{path}.#{arch}.s") @@ -458,8 +460,8 @@ EOS sh "/usr/bin/dsymutil \"#{main_exec}\" -o \"#{dsym_path}\"" end - # Strip all symbols. Only in release mode. - if main_exec_created and config.release? + # Strip all symbols. Only in distribution mode. + if main_exec_created and config.distribution_mode App.info "Strip", main_exec sh "#{config.locate_binary('strip')} \"#{main_exec}\"" end diff --git a/lib/motion/project/config.rb b/lib/motion/project/config.rb index b0b65523..b1a1541b 100644 --- a/lib/motion/project/config.rb +++ b/lib/motion/project/config.rb @@ -54,7 +54,8 @@ module Motion; module Project :short_version, :icons, :prerendered_icon, :background_modes, :seed_id, :entitlements, :fonts, :status_bar_style, :motiondir - attr_accessor :spec_mode + # Internal only. + attr_accessor :build_mode, :spec_mode, :distribution_mode def initialize(project_dir, build_mode) @project_dir = project_dir @@ -98,6 +99,19 @@ module Motion; module Project map end + def setup_blocks + @setup_blocks ||= [] + end + + def setup + if @setup_blocks + @setup_blocks.each { |b| b.call(self) } + @setup_blocks = nil + validate + end + self + end + def xcode_dir @xcode_dir ||= begin xcode_dot_app_path = '/Applications/Xcode.app/Contents/Developer' @@ -214,6 +228,14 @@ EOS yield if release? end + def opt_level + @opt_level ||= case @build_mode + when :development; 0 + when :release; 3 + else; 0 + end + end + def versionized_build_dir(platform) File.join(build_dir, platform + '-' + deployment_target + '-' + build_mode_name) end @@ -464,14 +486,23 @@ EOS end end - def device_family_string(family, retina) + def device_family_string(family, target, retina) device = case family when :iphone, 1 "iPhone" when :ipad, 2 "iPad" end - retina ? device + " (Retina)" : device + case retina + when 'true' + device + (family == 1 and target >= '6.0' ? ' (Retina 4-inch)' : ' (Retina)') + when '3.5' + device + ' (Retina 3.5-inch)' + when '4' + device + ' (Retina 4-inch)' + else + device + end end def device_family_ints @@ -566,7 +597,7 @@ EOS def codesign_certificate @codesign_certificate ||= begin - cert_type = (development? ? 'Developer' : 'Distribution') + cert_type = (distribution_mode ? 'Distribution' : 'Developer') certs = `/usr/bin/security -q find-certificate -a`.scan(/"iPhone #{cert_type}: [^"]+"/).uniq if certs.size == 0 App.fail "Can't find an iPhone Developer certificate in the keychain" @@ -629,8 +660,11 @@ EOS def entitlements_data dict = entitlements - if release? + if distribution_mode dict['application-identifier'] ||= seed_id + '.' + identifier + else + # Required for gdb. + dict['get-task-allow'] ||= true end Motion::PropertyList.to_s(dict) end