mirror of
https://github.com/zhigang1992/RubyMotion.git
synced 2026-04-07 22:42:10 +08:00
add support for archive release (appstore)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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}'"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user