add support for archive release (appstore)

This commit is contained in:
Laurent Sansonetti
2012-02-10 20:49:24 +01:00
parent 2d64b3b860
commit 0112488f88
6 changed files with 159 additions and 25 deletions

View File

@@ -1,4 +1,7 @@
# Simple property list helper.
require 'time' # For Time#iso8601
module Motion
class PropertyList
class << self
@@ -39,6 +42,10 @@ EOS
str << indent_line("<true/>", indent)
when FalseClass
str << indent_line("<false/>", indent)
when Time
str << indent_line("<date>#{plist.utc.iso8601}</date>", indent)
when Integer
str << indent_line("<real>#{plist}</real>", indent)
else
raise "Invalid plist object of type `#{plist.class}' (must be either a Hash, Array, String, or boolean true/false value)"
end

View File

@@ -8,20 +8,20 @@ task :default => :simulator
App = Motion::Project::App
desc "Build everything"
task :build => ['build:simulator', 'build:device']
namespace :build do
desc "Build the simulator version"
task :simulator do
App.build('iPhoneSimulator')
end
desc "Build the iOS version"
task :ios do
desc "Build the device version"
task :device do
App.build('iPhoneOS')
App.codesign('iPhoneOS')
end
desc "Build everything"
task :all => [:simulator, :ios]
end
desc "Run the simulator"
@@ -55,8 +55,10 @@ task :simulator => ['build:simulator'] do
sh "#{sim} #{debug} #{family_int} #{target} \"#{app}\""
end
desc "Create an .ipa archive"
task :archive => ['build:ios'] do
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)
@@ -73,6 +75,22 @@ task :archive => ['build:ios'] do
end
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 and .xcarchive for release (AppStore)"
task :release do
App.config_mode = :release
Rake::Task["build:device"].execute
App.archive
end
end
desc "Run specs"
task :spec do
App.config.spec_mode = true
@@ -80,7 +98,7 @@ task :spec do
end
desc "Deploy on the device"
task :deploy => :archive do
task :device => :archive do
App.info 'Deploy', App.config.archive
unless App.config.provisioned_devices.include?(App.config.device_id)
App.fail "Connected device ID `#{App.config.device_id}' not provisioned in profile `#{App.config.provisioning_profile}'"

View File

@@ -13,8 +13,23 @@ module Motion; module Project
end
class << self
def config_mode
@config_mode or :development
end
def config_mode=(mode)
@config_mode = mode
end
def configs
@configs ||= {
:development => Motion::Project::Config.new('.', :development),
:release => Motion::Project::Config.new('.', :release)
}
end
def config
@config ||= Motion::Project::Config.new('.')
configs[config_mode]
end
def builder
@@ -22,7 +37,7 @@ module Motion; module Project
end
def setup
yield config
configs.each_value { |x| yield x }
config.validate
end
@@ -30,6 +45,10 @@ module Motion; module Project
builder.build(config, platform)
end
def archive
builder.archive(config)
end
def codesign(platform)
builder.codesign(config, platform)
end

View File

@@ -23,8 +23,9 @@ module Motion; module Project;
cc = File.join(config.platform_dir(platform), 'Developer/usr/bin/gcc')
cxx = File.join(config.platform_dir(platform), 'Developer/usr/bin/g++')
build_dir = File.join(config.versionized_build_dir, platform)
build_dir = File.join(config.versionized_build_dir(platform))
App.info 'Build', build_dir
# Prepare the list of BridgeSupport files needed.
bs_files = config.bridgesupport_files
@@ -77,7 +78,8 @@ module Motion; module Project;
# Object.
arch_obj = File.join(objs_build_dir, "#{path}.#{arch}.o")
sh "#{cc} -fexceptions -c -arch #{arch} \"#{asm}\" -o \"#{arch_obj}\""
[bc, asm].each { |x| File.unlink(x) }
arch_objs << arch_obj
end
@@ -247,7 +249,8 @@ EOS
end
# Link executable.
main_exec = File.join(bundle_path, config.name)
main_exec = config.app_bundle_executable(platform)
main_exec_created = false
if !File.exist?(main_exec) \
or File.mtime(config.project_file) > File.mtime(main_exec) \
or objs.any? { |path, _| File.mtime(path) > File.mtime(main_exec) } \
@@ -262,6 +265,7 @@ EOS
framework_stubs_objs << "\"#{stubs_obj}\"" if File.exist?(stubs_obj)
end
sh "#{cxx} -o \"#{main_exec}\" #{objs_list} #{arch_flags} #{framework_stubs_objs.join(' ')} -isysroot \"#{sdk}\" -miphoneos-version-min=#{config.deployment_target} -L#{File.join(datadir, platform)} -lmacruby-static -lobjc -licucore #{frameworks} #{config.libs.join(' ')} #{vendor_libs.map { |x| '-force_load ' + x }.join(' ')}"
main_exec_created = true
end
# Create bundle/Info.plist.
@@ -321,6 +325,12 @@ EOS
App.info "Create", dsym_path
sh "/usr/bin/dsymutil \"#{main_exec}\" -o \"#{dsym_path}\""
end
# Strip all symbols. Only in release mode.
if main_exec_created and config.release?
App.info "Strip", main_exec
sh "/usr/bin/strip \"#{main_exec}\""
end
end
def codesign(config, platform)
@@ -374,10 +384,57 @@ PLIST
if File.mtime(config.project_file) > File.mtime(bundle_path) \
or !system("#{codesign_cmd} --verify \"#{bundle_path}\" >& /dev/null")
App.info 'Codesign', bundle_path
entitlements = File.join(config.versionized_build_dir, platform, "Entitlements.plist")
entitlements = File.join(config.versionized_build_dir(platform), "Entitlements.plist")
File.open(entitlements, 'w') { |io| io.write(config.entitlements_data) }
sh "#{codesign_cmd} -f -s \"#{config.codesign_certificate}\" --resource-rules=\"#{resource_rules_plist}\" --entitlements #{entitlements} \"#{bundle_path}\""
end
end
def archive(config)
# Create .ipa archive.
app_bundle = config.app_bundle('iPhoneOS')
archive = 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
# Create .xcarchive. Only in release mode.
if config.release?
xcarchive = File.join(File.dirname(app_bundle), config.name + '.xcarchive')
if !File.exist?(xcarchive) or File.mtime(app_bundle) > File.mtime(xcarchive)
App.info 'Create', xcarchive
apps = File.join(xcarchive, 'Products', 'Applications')
FileUtils.mkdir_p apps
sh "/bin/cp -r \"#{app_bundle}\" \"#{apps}\""
dsyms = File.join(xcarchive, 'dSYMs')
FileUtils.mkdir_p dsyms
sh "/bin/cp -r \"#{config.app_bundle_dsym('iPhoneOS')}\" \"#{dsyms}\""
app_path = "Applications/#{config.name}.app"
info_plist = {
'ApplicationProperties' => {
'ApplicationPath' => app_path,
'CFBundleIdentifier' => config.identifier,
'IconPaths' => config.icons.map { |x| File.join(app_path, x) },
},
'ArchiveVersion' => 1,
'CreationDate' => Time.now,
'Name' => config.name,
'SchemeName' => config.name
}
File.open(File.join(xcarchive, 'Info.plist'), 'w') do |io|
io.write Motion::PropertyList.to_s(info_plist)
end
end
end
end
end
end; end

View File

@@ -30,7 +30,9 @@ module Motion; module Project
:device_family, :interface_orientations, :version, :icons,
:prerendered_icon, :seed_id, :entitlements, :fonts
def initialize(project_dir)
attr_accessor :spec_mode
def initialize(project_dir, build_mode)
@project_dir = project_dir
@files = Dir.glob(File.join(project_dir, 'app/**/*.rb'))
@dependencies = {}
@@ -50,6 +52,8 @@ module Motion; module Project
@prerendered_icon = false
@vendor_projects = []
@entitlements = {}
@spec_mode = false
@build_mode = build_mode
end
def variables
@@ -65,6 +69,13 @@ module Motion; module Project
map
end
def load_setup(b)
@setups ||= []
@setups << b
b.call self
validate
end
def validate
# sdk_version
['iPhoneSimulator', 'iPhoneOS'].each do |platform|
@@ -103,8 +114,28 @@ module Motion; module Project
@build_dir
end
def versionized_build_dir
File.join(build_dir, deployment_target)
def build_mode_name
@build_mode.to_s.capitalize
end
def development?
@build_mode == :development
end
def release?
@build_mode == :release
end
def development
yield if development?
end
def release
yield if release?
end
def versionized_build_dir(platform)
File.join(build_dir, platform + '-' + deployment_target + '-' + build_mode_name)
end
attr_reader :project_dir
@@ -191,8 +222,6 @@ module Motion; module Project
end
end
attr_accessor :spec_mode
def spec_files
Dir.glob(File.join(specs_dir, '**', '*.rb'))
end
@@ -243,15 +272,19 @@ module Motion; module Project
end
def app_bundle(platform)
File.join(versionized_build_dir, platform, bundle_name + '.app')
File.join(versionized_build_dir(platform), bundle_name + '.app')
end
def app_bundle_dsym(platform)
File.join(versionized_build_dir, platform, bundle_name + '.dSYM')
File.join(versionized_build_dir(platform), bundle_name + '.dSYM')
end
def app_bundle_executable(platform)
File.join(app_bundle(platform), name)
end
def archive
File.join(versionized_build_dir, bundle_name + '.ipa')
File.join(versionized_build_dir('iPhoneOS'), bundle_name + '.ipa')
end
def identifier

View File

@@ -72,8 +72,8 @@ module Motion; module Project; class Config
end
end; end; end
desc "Submit build to TestFlight"
task :testflight => :archive do
desc "Submit a development archive to TestFlight"
task :testflight => 'archive:development' do
# Retrieve configuration settings.
prefs = App.config.testflight
unless prefs.api_token