This commit is contained in:
Laurent Sansonetti
2013-04-25 02:26:56 +02:00
committed by Watson
parent 7a16c3cdf1
commit 06c18cc293
28 changed files with 1189 additions and 824 deletions

View File

@@ -26,11 +26,15 @@ require 'motion/project/app'
require 'motion/project/config'
require 'motion/project/builder'
require 'motion/project/vendor'
require 'motion/project/template'
require 'motion/project/plist'
App = Motion::Project::App
if Motion::Project::App.template == nil
warn "require 'lib/motion/project' is deprecated, please require 'lib/motion/project/template/ios' instead"
require 'motion/project/template/ios'
end
# Check for software updates.
# Check for updates.
system('/usr/bin/motion update --check')
if $?.exitstatus == 2
puts '=' * 80
@@ -39,115 +43,6 @@ if $?.exitstatus == 2
puts ''
end
desc "Build the project, then run the simulator"
task :default => :simulator
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 device version"
task :device do
App.build('iPhoneOS')
App.codesign('iPhoneOS')
end
end
desc "Run the simulator"
task :simulator => ['build:simulator'] do
app = App.config.app_bundle('iPhoneSimulator')
target = ENV['target'] || App.config.sdk_version
# Cleanup the simulator application sandbox, to avoid having old resource files there.
if ENV['clean']
sim_apps = File.expand_path("~/Library/Application Support/iPhone Simulator/#{target}/Applications")
Dir.glob("#{sim_apps}/**/*.app").each do |app_bundle|
if File.basename(app_bundle) == File.basename(app)
rm_rf File.dirname(app_bundle)
break
end
end
end
# Prepare the device family.
family_int =
if family = ENV['device_family']
App.config.device_family_int(family.downcase.intern)
else
App.config.device_family_ints[0]
end
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, target, retina)
default_simulator = `/usr/bin/defaults read com.apple.iphonesimulator "SimulateDevice"`.strip
if default_simulator != simulate_device && default_simulator != "'#{simulate_device}'"
system("/usr/bin/killall \"iPhone Simulator\" >& /dev/null")
system("/usr/bin/defaults write com.apple.iphonesimulator \"SimulateDevice\" \"'#{simulate_device}'\"")
end
# Launch the simulator.
xcode = App.config.xcode_dir
env = "DYLD_FRAMEWORK_PATH=\"#{xcode}/../Frameworks\":\"#{xcode}/../OtherFrameworks\""
env << ' SIM_SPEC_MODE=1' if App.config.spec_mode
sim = File.join(App.config.bindir, 'sim')
debug = (ENV['debug'] ? 1 : (App.config.spec_mode ? '0' : '2'))
App.info 'Simulate', app
at_exit { system("stty echo") } if $stdout.tty? # 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 an .ipa archive"
task :archive => ['build:device'] do
App.archive
end
namespace :archive do
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
desc "Same as 'spec:simulator'"
task :spec => ['spec:simulator']
namespace :spec do
desc "Run the test/spec suite on the simulator"
task :simulator do
App.config.spec_mode = true
Rake::Task["simulator"].invoke
end
desc "Run the test/spec suite on the device"
task :device do
App.config.spec_mode = true
ENV['debug'] ||= '1'
Rake::Task["device"].invoke
end
end
desc "Deploy on the device"
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 "#{env} #{deploy} #{flags} \"#{device_id}\" \"#{App.config.archive}\""
end
desc "Clear build objects"
task :clean do
App.info 'Delete', App.config.build_dir
@@ -166,44 +61,3 @@ task :config do
puts key.ljust(22) + " : #{map[key].inspect}"
end
end
desc "Generate ctags"
task :ctags do
tags_file = 'tags'
config = App.config
if !File.exist?(tags_file) or File.mtime(config.project_file) > File.mtime(tags_file)
bs_files = config.bridgesupport_files + config.vendor_projects.map { |p| Dir.glob(File.join(p.path, '*.bridgesupport')) }.flatten
ctags = File.join(config.bindir, 'ctags')
config = File.join(config.motiondir, 'data', 'bridgesupport-ctags.cfg')
sh "#{ctags} --options=\"#{config}\" #{bs_files.map { |x| '"' + x + '"' }.join(' ')}"
end
end
desc "Create a .a static library"
task :static do
libs = %w{iPhoneSimulator iPhoneOS}.map do |platform|
'"' + App.build(platform, :static => true) + '"'
end
fat_lib = File.join(App.config.build_dir, App.config.name + '-universal.a')
App.info 'Create', fat_lib
sh "/usr/bin/lipo -create #{libs.join(' ')} -output \"#{fat_lib}\""
end
=begin
# Automatically load project extensions. A project extension is a gem whose
# name starts with `motion-' and which exposes a `lib/motion/project' libdir.
require 'rubygems'
Gem.path.each do |gemdir|
Dir.glob(File.join(gemdir, 'gems', '*')).each do |gempath|
base = File.basename(gempath)
if md = base.match(/^(motion-.*)-((\d+\.)*\d+)/) and File.exist?(File.join(gempath, 'lib', 'motion', 'project'))
ext_name = md[1]
begin
require ext_name
rescue LoadError => e
$stderr.puts "Can't autoload extension `#{ext_name}': #{e.message}"
end
end
end
end
=end

View File

@@ -21,7 +21,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'erb'
require 'motion/project/template'
module Motion; module Project
class App
@@ -38,6 +38,8 @@ module Motion; module Project
end
class << self
attr_accessor :template
def config_mode
@config_mode ||= begin
if mode = ENV['mode']
@@ -55,7 +57,7 @@ module Motion; module Project
def config_without_setup
@configs ||= {}
@configs[config_mode] ||= Motion::Project::Config.new('.', config_mode)
@configs[config_mode] ||= Motion::Project::Config.make(@template, '.', config_mode)
end
def config
@@ -82,8 +84,8 @@ module Motion; module Project
builder.codesign(config, platform)
end
def create(app_name, template_name="ios")
Template.new(app_name, template_name).generate
def create(app_name, template_name=:ios)
Motion::Project::Template.new(app_name, template_name).generate
end
def log(what, msg)
@@ -109,75 +111,5 @@ module Motion; module Project
log what, msg unless VERBOSE
end
end
class Template
# for ERB
attr_reader :name
def initialize(app_name, template_name)
@name = @app_name = app_name
@template_name = template_name
@template_directory = File.expand_path(File.join(__FILE__, "../template/#{@template_name}"))
unless app_name.match(/^[\w\s-]+$/)
fail "Invalid app name"
end
if File.exist?(app_name)
fail "Directory `#{app_name}' already exists"
end
unless File.exist?(@template_directory)
fail "Invalid template name"
end
end
def generate
App.log 'Create', @app_name
FileUtils.mkdir(@app_name)
Dir.chdir(@app_name) do
create_directories()
create_files()
end
end
private
def template_directory
@template_directory
end
def create_directories
Dir.glob(File.join(template_directory, "**/")).each do |dir|
dir.sub!("#{template_directory}/", '')
FileUtils.mkdir_p(dir) if dir.length > 0
end
end
def create_files
Dir.glob(File.join(template_directory, "**/*"), File::FNM_DOTMATCH).each do |src|
dest = src.sub("#{template_directory}/", '')
next if File.directory?(src)
next if dest.include?(".DS_Store")
dest = replace_file_name(dest)
if dest =~ /(.+)\.erb$/
App.log 'Create', "#{@app_name}/#{$1}"
File.open($1, "w") { |io|
io.print ERB.new(File.read(src)).result(binding)
}
else
App.log 'Create', "#{@app_name}/#{dest}"
FileUtils.cp(src, dest)
end
end
end
def replace_file_name(file_name)
file_name = file_name.sub("{name}", "#{@name}")
file_name
end
end
end
end; end

View File

@@ -88,7 +88,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}\" VM_OPT_LEVEL=\"#{config.opt_level}\" #{ruby} #{bs_flags} --emit-llvm \"#{bc}\" #{init_func} \"#{path}\""
sh "/usr/bin/env VM_KERNEL_PATH=\"#{kernel}\" VM_OPT_LEVEL=\"#{config.opt_level}\" /usr/bin/arch -arch #{arch} #{ruby} #{bs_flags} --emit-llvm \"#{bc}\" #{init_func} \"#{path}\""
# Assembly.
asm = File.join(objs_build_dir, "#{path}.#{arch}.s")
@@ -180,8 +180,6 @@ module Motion; module Project;
# Generate init file.
init_txt = <<EOS
#import <UIKit/UIKit.h>
extern "C" {
void ruby_sysinit(int *, char ***);
void ruby_init(void);
@@ -213,17 +211,21 @@ RubyMotionInit(int argc, char **argv)
const char *progname = argv[0];
ruby_script(progname);
}
#if !__LP64__
try {
#endif
void *self = rb_vm_top_self();
EOS
app_objs.each do |_, init_func|
init_txt << "#{init_func}(self, 0);\n"
end
init_txt << <<EOS
#if !__LP64__
}
catch (...) {
rb_rb2oc_exc_handler();
}
#endif
initialized = true;
}
}
@@ -248,112 +250,7 @@ EOS
end
# Generate main file.
main_txt = <<EOS
#import <UIKit/UIKit.h>
extern "C" {
void rb_define_global_const(const char *, void *);
void rb_rb2oc_exc_handler(void);
void rb_exit(int);
void RubyMotionInit(int argc, char **argv);
EOS
if config.spec_mode
spec_objs.each do |_, init_func|
main_txt << "void #{init_func}(void *, void *);\n"
end
end
main_txt << <<EOS
}
EOS
if config.spec_mode
main_txt << <<EOS
@interface SpecLauncher : NSObject
@end
#include <dlfcn.h>
@implementation SpecLauncher
+ (id)launcher
{
[UIApplication sharedApplication];
// Enable simulator accessibility.
// Thanks http://www.stewgleadow.com/blog/2011/10/14/enabling-accessibility-for-ios-applications/
NSString *simulatorRoot = [[[NSProcessInfo processInfo] environment] objectForKey:@"IPHONE_SIMULATOR_ROOT"];
if (simulatorRoot != nil) {
void *appSupportLibrary = dlopen([[simulatorRoot stringByAppendingPathComponent:@"/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport"] fileSystemRepresentation], RTLD_LAZY);
CFStringRef (*copySharedResourcesPreferencesDomainForDomain)(CFStringRef domain) = (CFStringRef (*)(CFStringRef)) dlsym(appSupportLibrary, "CPCopySharedResourcesPreferencesDomainForDomain");
if (copySharedResourcesPreferencesDomainForDomain != NULL) {
CFStringRef accessibilityDomain = copySharedResourcesPreferencesDomainForDomain(CFSTR("com.apple.Accessibility"));
if (accessibilityDomain != NULL) {
CFPreferencesSetValue(CFSTR("ApplicationAccessibilityEnabled"), kCFBooleanTrue, accessibilityDomain, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
CFRelease(accessibilityDomain);
}
}
}
// Load the UIAutomation framework.
dlopen("/Developer/Library/PrivateFrameworks/UIAutomation.framework/UIAutomation", RTLD_LOCAL);
SpecLauncher *launcher = [[self alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:launcher selector:@selector(appLaunched:) name:UIApplicationDidBecomeActiveNotification object:nil];
return launcher;
}
- (void)appLaunched:(id)notification
{
// Give a bit of time for the simulator to attach...
[self performSelector:@selector(runSpecs) withObject:nil afterDelay:0.3];
}
- (void)runSpecs
{
EOS
spec_objs.each do |_, init_func|
main_txt << "#{init_func}(self, 0);\n"
end
main_txt << "[NSClassFromString(@\"Bacon\") performSelector:@selector(run)];\n"
main_txt << <<EOS
}
@end
EOS
end
main_txt << <<EOS
int
main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retval = 0;
try {
EOS
main_txt << "[SpecLauncher launcher];\n" if config.spec_mode
main_txt << <<EOS
RubyMotionInit(argc, argv);
EOS
rubymotion_env =
if config.spec_mode
'test'
else
config.development? ? 'development' : 'release'
end
main_txt << "rb_define_global_const(\"RUBYMOTION_ENV\", @\"#{rubymotion_env}\");\n"
main_txt << "rb_define_global_const(\"RUBYMOTION_VERSION\", @\"#{Motion::Version}\");\n"
main_txt << <<EOS
retval = UIApplicationMain(argc, argv, nil, @"#{config.delegate_class}");
rb_exit(retval);
}
catch (...) {
rb_rb2oc_exc_handler();
}
[pool release];
return retval;
}
EOS
main_txt = config.main_cpp_file_txt(spec_objs)
# Compile main file.
main = File.join(objs_build_dir, 'main.mm')
@@ -372,6 +269,10 @@ EOS
# Link executable.
main_exec = config.app_bundle_executable(platform)
unless File.exist?(File.dirname(main_exec))
App.info 'Create', File.dirname(main_exec)
FileUtils.mkdir_p(File.dirname(main_exec))
end
main_exec_created = false
if !File.exist?(main_exec) \
or File.mtime(config.project_file) > File.mtime(main_exec) \
@@ -439,6 +340,7 @@ EOS
end
# Copy resources, handle subdirectories.
app_resources_dir = config.app_resources_dir(platform)
reserved_app_bundle_files = [
'_CodeSignature/CodeResources', 'CodeResources', 'embedded.mobileprovision',
'Info.plist', 'PkgInfo', 'ResourceRules.plist',
@@ -458,7 +360,7 @@ EOS
if reserved_app_bundle_files.include?(res)
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)
dest_path = File.join(app_resources_dir, res)
if !File.exist?(dest_path) or File.mtime(res_path) > File.mtime(dest_path)
FileUtils.mkdir_p(File.dirname(dest_path))
App.info 'Copy', res_path
@@ -468,7 +370,7 @@ EOS
# Delete old resource files.
resources_files = resources_paths.map { |x| path_on_resources_dirs(config.resources_dirs, x) }
Dir.chdir(bundle_path) do
Dir.chdir(app_resources_dir) do
Dir.glob('*').each do |bundle_res|
bundle_res = convert_filesystem_encoding(bundle_res)
next if File.directory?(bundle_res)

View File

@@ -47,44 +47,39 @@ module Motion; module Project
end
end
variable :files, :xcode_dir, :sdk_version, :deployment_target, :frameworks,
:weak_frameworks, :framework_search_paths, :libs, :delegate_class, :name, :build_dir,
:resources_dirs, :specs_dir, :identifier, :codesign_certificate,
:provisioning_profile, :device_family, :interface_orientations, :version,
:short_version, :icons, :prerendered_icon, :background_modes, :seed_id,
:entitlements, :fonts, :status_bar_style, :motiondir, :detect_dependencies
variable :name, :files, :build_dir, :specs_dir, :version, :motiondir
# Internal only.
attr_accessor :build_mode, :spec_mode, :distribution_mode, :dependencies
attr_accessor :build_mode, :spec_mode, :distribution_mode, :dependencies,
:template, :detect_dependencies
ConfigTemplates = {}
def self.register(template)
ConfigTemplates[template] = self
end
def self.make(template, project_dir, build_mode)
klass = ConfigTemplates[template]
unless klass
$stderr.puts "Config template `#{template}' not registered"
exit 1
end
config = klass.new(project_dir, build_mode)
config.template = template
config
end
def initialize(project_dir, build_mode)
@project_dir = project_dir
@files = Dir.glob(File.join(project_dir, 'app/**/*.rb'))
@info_plist = {}
@dependencies = {}
@detect_dependencies = true
@frameworks = ['UIKit', 'Foundation', 'CoreGraphics']
@weak_frameworks = []
@framework_search_paths = []
@libs = []
@delegate_class = 'AppDelegate'
@build_mode = build_mode
@name = 'Untitled'
@resources_dirs = [File.join(project_dir, 'resources')]
@build_dir = File.join(project_dir, 'build')
@specs_dir = File.join(project_dir, 'spec')
@device_family = :iphone
@bundle_signature = '????'
@interface_orientations = [:portrait, :landscape_left, :landscape_right]
@version = '1.0'
@short_version = '1'
@status_bar_style = :default
@background_modes = []
@icons = []
@prerendered_icon = false
@vendor_projects = []
@entitlements = {}
@spec_mode = false
@build_mode = build_mode
@detect_dependencies = true
end
OSX_VERSION = `/usr/bin/sw_vers -productVersion`.strip.sub(/\.\d+$/, '').to_f
@@ -115,40 +110,6 @@ module Motion; module Project
self
end
def xcode_dir
@xcode_dir ||= begin
xcode_dot_app_path = '/Applications/Xcode.app/Contents/Developer'
# First, honor /usr/bin/xcode-select
xcodeselect = '/usr/bin/xcode-select'
if File.exist?(xcodeselect)
path = `#{xcodeselect} -print-path`.strip
if path.match(/^\/Developer\//) and File.exist?(xcode_dot_app_path)
@xcode_error_printed ||= false
$stderr.puts(<<EOS) unless @xcode_error_printed
===============================================================================
It appears that you have a version of Xcode installed in /Applications that has
not been set as the default version. It is possible that RubyMotion may be
using old versions of certain tools which could eventually cause issues.
To fix this problem, you can type the following command in the terminal:
$ sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
===============================================================================
EOS
@xcode_error_printed = true
end
return path if File.exist?(path)
end
# Since xcode-select is borked, we assume the user installed Xcode
# as an app (new in Xcode 4.3).
return xcode_dot_app_path if File.exist?(xcode_dot_app_path)
App.fail "Can't locate any version of Xcode on the system."
end
unescape_path(@xcode_dir)
end
def unescape_path(path)
path.gsub('\\', '')
end
@@ -165,44 +126,12 @@ EOS
App.fail "Can't locate binary `#{name}' on the system."
end
def xcode_version
@xcode_version ||= begin
txt = `#{locate_binary('xcodebuild')} -version`
vers = txt.scan(/Xcode\s(.+)/)[0][0]
build = txt.scan(/Build version\s(.+)/)[0][0]
[vers, build]
end
end
def validate
# Xcode version
App.fail "Xcode 4.x or greater is required" if xcode_version[0] < '4.0'
# sdk_version
['iPhoneSimulator', 'iPhoneOS'].each do |platform|
sdk_path = File.join(platforms_dir, platform + '.platform',
"Developer/SDKs/#{platform}#{sdk_version}.sdk")
unless File.exist?(sdk_path)
App.fail "Can't locate #{platform} SDK #{sdk_version} at `#{sdk_path}'"
end
end
# deployment_target
if deployment_target > sdk_version
App.fail "Deployment target `#{deployment_target}' must be equal or lesser than SDK version `#{sdk_version}'"
end
unless File.exist?(datadir)
App.fail "iOS deployment target #{deployment_target} is not supported by this version of RubyMotion"
end
# icons
if !(icons.is_a?(Array) and icons.all? { |x| x.is_a?(String) })
App.fail "app.icons should be an array of strings."
end
# Do nothing, for now.
end
def supported_versions
@supported_versions ||= Dir.glob(File.join(motiondir, 'data/*')).select{|path| File.directory?(path)}.map do |path|
@supported_versions ||= Dir.glob(File.join(motiondir, 'data', template.to_s, '*')).select{|path| File.directory?(path)}.map do |path|
File.basename path
end
end
@@ -316,58 +245,6 @@ EOS
end
end
def frameworks_dependencies
@frameworks_dependencies ||= begin
# Compute the list of frameworks, including dependencies, that the project uses.
deps = frameworks.dup.uniq
slf = File.join(sdk('iPhoneSimulator'), 'System', 'Library', 'Frameworks')
deps.each do |framework|
framework_path = File.join(slf, framework + '.framework', framework)
if File.exist?(framework_path)
`#{locate_binary('otool')} -L \"#{framework_path}\"`.scan(/\t([^\s]+)\s\(/).each do |dep|
# Only care about public, non-umbrella frameworks (for now).
if md = dep[0].match(/^\/System\/Library\/Frameworks\/(.+)\.framework\/(.+)$/) and md[1] == md[2]
deps << md[1]
deps.uniq!
end
end
end
end
if @framework_search_paths.empty?
deps = deps.select { |dep| File.exist?(File.join(datadir, 'BridgeSupport', dep + '.bridgesupport')) }
end
deps
end
end
def frameworks_stubs_objects(platform)
stubs = []
(frameworks_dependencies + weak_frameworks).uniq.each do |framework|
stubs_obj = File.join(datadir, platform, "#{framework}_stubs.o")
stubs << stubs_obj if File.exist?(stubs_obj)
end
stubs
end
def bridgesupport_files
@bridgesupport_files ||= begin
bs_files = []
deps = ['RubyMotion'] + (frameworks_dependencies + weak_frameworks).uniq
deps << 'UIAutomation' if spec_mode
deps.each do |framework|
supported_versions.each do |ver|
next if ver < deployment_target || sdk_version < ver
bs_path = File.join(datadir(ver), 'BridgeSupport', framework + '.bridgesupport')
if File.exist?(bs_path)
bs_files << bs_path
end
end
end
bs_files
end
end
def spec_core_files
@spec_core_files ||= begin
# Core library + core helpers.
@@ -400,345 +277,7 @@ EOS
end
def datadir(target=deployment_target)
File.join(motiondir, 'data', target)
end
def platforms_dir
File.join(xcode_dir, 'Platforms')
end
def platform_dir(platform)
File.join(platforms_dir, platform + '.platform')
end
def sdk_version
@sdk_version ||= begin
versions = Dir.glob(File.join(platforms_dir, 'iPhoneOS.platform/Developer/SDKs/iPhoneOS*.sdk')).map do |path|
File.basename(path).scan(/iPhoneOS(.*)\.sdk/)[0][0]
end
if versions.size == 0
App.fail "Can't find an iOS SDK in `#{platforms_dir}'"
end
supported_vers = versions.reverse.find { |vers| File.exist?(datadir(vers)) }
unless supported_vers
App.fail "RubyMotion doesn't support any of these SDK versions: #{versions.join(', ')}"
end
supported_vers
end
end
def deployment_target
@deployment_target ||= sdk_version
end
def sdk(platform)
path = File.join(platform_dir(platform), 'Developer/SDKs',
platform + sdk_version + '.sdk')
escape_path(path)
end
def locate_compiler(platform, *execs)
paths = [File.join(platform_dir(platform), 'Developer/usr/bin')]
paths.unshift File.join(xcode_dir, 'Toolchains/XcodeDefault.xctoolchain/usr/bin')
execs.each do |exec|
paths.each do |path|
cc = File.join(path, exec)
return escape_path(cc) if File.exist?(cc)
end
end
App.fail "Can't locate compilers for platform `#{platform}'"
end
def archs
@archs ||= begin
h = {}
%w{iPhoneSimulator iPhoneOS}.each do |platform|
h[platform] = Dir.glob(File.join(datadir, platform, '*.bc')).map do |path|
path.scan(/kernel-(.+).bc$/)[0][0]
end
end
h
end
end
def arch_flags(platform)
archs[platform].map { |x| "-arch #{x}" }.join(' ')
end
def common_flags(platform)
"#{arch_flags(platform)} -isysroot \"#{unescape_path(sdk(platform))}\" -miphoneos-version-min=#{deployment_target} -F#{sdk(platform)}/System/Library/Frameworks"
end
def cflags(platform, cplusplus)
"#{common_flags(platform)} -fexceptions -fblocks -fobjc-legacy-dispatch -fobjc-abi-version=2" + (cplusplus ? '' : ' -std=c99')
end
def ldflags(platform)
ldflags = common_flags(platform)
ldflags << " -fobjc-arc" if deployment_target < '5.0'
ldflags
end
def bundle_name
@name + (spec_mode ? '_spec' : '')
end
def app_bundle(platform)
File.join(versionized_build_dir(platform), bundle_name + '.app')
end
def app_bundle_dsym(platform)
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('iPhoneOS'), bundle_name + '.ipa')
end
def identifier
@identifier ||= "com.yourcompany.#{@name.gsub(/\s/, '')}"
spec_mode ? @identifier + '_spec' : @identifier
end
def device_family_int(family)
case family
when :iphone then 1
when :ipad then 2
else
App.fail "Unknown device_family value: `#{family}'"
end
end
def device_family_string(family, target, retina)
device = case family
when :iphone, 1
"iPhone"
when :ipad, 2
"iPad"
end
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
ary = @device_family.is_a?(Array) ? @device_family : [@device_family]
ary.map { |family| device_family_int(family) }
end
def interface_orientations_consts
@interface_orientations.map do |ori|
case ori
when :portrait then 'UIInterfaceOrientationPortrait'
when :landscape_left then 'UIInterfaceOrientationLandscapeLeft'
when :landscape_right then 'UIInterfaceOrientationLandscapeRight'
when :portrait_upside_down then 'UIInterfaceOrientationPortraitUpsideDown'
else
App.fail "Unknown interface_orientation value: `#{ori}'"
end
end
end
def background_modes_consts
@background_modes.map do |mode|
case mode
when :audio then 'audio'
when :location then 'location'
when :voip then 'voip'
when :newsstand_content then 'newsstand-content'
when :external_accessory then 'external-accessory'
when :bluetooth_central then 'bluetooth-central'
else
App.fail "Unknown background_modes value: `#{mode}'"
end
end
end
def status_bar_style_const
case @status_bar_style
when :default then 'UIStatusBarStyleDefault'
when :black_translucent then 'UIStatusBarStyleBlackTranslucent'
when :black_opaque then 'UIStatusBarStyleBlackOpaque'
else
App.fail "Unknown status_bar_style value: `#{@status_bar_style}'"
end
end
def info_plist
@info_plist
end
def dt_info_plist
{
}
end
def info_plist_data
ios_version_to_build = lambda do |vers|
# XXX we should retrieve these values programmatically.
case vers
when '4.3'; '8F191m'
when '5.0'; '9A334'
when '5.1'; '9B176'
else; '10A403' # 6.0 or later
end
end
Motion::PropertyList.to_s({
'BuildMachineOSBuild' => `sw_vers -buildVersion`.strip,
'MinimumOSVersion' => deployment_target,
'CFBundleDevelopmentRegion' => 'en',
'CFBundleName' => @name,
'CFBundleDisplayName' => @name,
'CFBundleExecutable' => @name,
'CFBundleIdentifier' => identifier,
'CFBundleInfoDictionaryVersion' => '6.0',
'CFBundlePackageType' => 'APPL',
'CFBundleResourceSpecification' => 'ResourceRules.plist',
'CFBundleShortVersionString' => @short_version,
'CFBundleSignature' => @bundle_signature,
'CFBundleSupportedPlatforms' => ['iPhoneOS'],
'CFBundleVersion' => @version,
'CFBundleIconFiles' => icons,
'CFBundleIcons' => {
'CFBundlePrimaryIcon' => {
'CFBundleIconFiles' => icons,
'UIPrerenderedIcon' => prerendered_icon,
}
},
'UIAppFonts' => fonts,
'UIDeviceFamily' => device_family_ints.map { |x| x.to_s },
'UISupportedInterfaceOrientations' => interface_orientations_consts,
'UIStatusBarStyle' => status_bar_style_const,
'UIBackgroundModes' => background_modes_consts,
'DTXcode' => begin
vers = xcode_version[0].gsub(/\./, '')
if vers.length == 2
'0' + vers + '0'
else
'0' + vers
end
end,
'DTXcodeBuild' => xcode_version[1],
'DTSDKName' => "iphoneos#{sdk_version}",
'DTSDKBuild' => ios_version_to_build.call(sdk_version),
'DTPlatformName' => 'iphoneos',
'DTCompiler' => 'com.apple.compilers.llvm.clang.1_0',
'DTPlatformVersion' => sdk_version,
'DTPlatformBuild' => ios_version_to_build.call(sdk_version)
}.merge(dt_info_plist).merge(info_plist))
end
def pkginfo_data
"AAPL#{@bundle_signature}"
end
def codesign_certificate
@codesign_certificate ||= begin
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"
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
certs[0][1..-2] # trim trailing `"` characters
end
end
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 = /iOS Team Provisioning Profile/)
@provisioning_profile ||= begin
paths = Dir.glob(File.expand_path("~/Library/MobileDevice/Provisioning\ Profiles/*.mobileprovision")).select do |path|
text = File.read(path)
text.force_encoding('binary') if RUBY_VERSION >= '1.9.0'
text.scan(/<key>\s*Name\s*<\/key>\s*<string>\s*([^<]+)\s*<\/string>/)[0][0].match(name)
end
if paths.size == 0
App.fail "Can't find a provisioning profile named `#{name}'"
elsif paths.size > 1
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 read_provisioned_profile_array(key)
text = File.read(provisioning_profile)
text.force_encoding('binary') if RUBY_VERSION >= '1.9.0'
text.scan(/<key>\s*#{key}\s*<\/key>\s*<array>(.*?)\s*<\/array>/m)[0][0].scan(/<string>(.*?)<\/string>/).map { |str| str[0].strip }
end
private :read_provisioned_profile_array
def provisioned_devices
@provisioned_devices ||= read_provisioned_profile_array('ProvisionedDevices')
end
def seed_id
@seed_id ||= begin
seed_ids = read_provisioned_profile_array('ApplicationIdentifierPrefix')
if seed_ids.size == 0
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
seed_ids.last
end
end
def entitlements_data
dict = entitlements
if distribution_mode
dict['application-identifier'] ||= seed_id + '.' + identifier
else
# Required for gdb.
dict['get-task-allow'] = true if dict['get-task-allow'].nil?
end
Motion::PropertyList.to_s(dict)
end
def fonts
@fonts ||= begin
resources_dirs.flatten.inject([]) do |fonts, dir|
if File.exist?(dir)
Dir.chdir(dir) do
fonts.concat(Dir.glob('*.{otf,ttf}'))
end
else
fonts
end
end
end
end
def gen_bridge_metadata(headers, bs_file)
sdk_path = self.sdk('iPhoneSimulator')
includes = headers.map { |header| "-I'#{File.dirname(header)}'" }.uniq
a = sdk_version.scan(/(\d+)\.(\d+)/)[0]
sdk_version_headers = ((a[0].to_i * 10000) + (a[1].to_i * 100)).to_s
extra_flags = OSX_VERSION >= 10.7 ? '--no-64-bit' : ''
sh "RUBYOPT='' /usr/bin/gen_bridge_metadata --format complete #{extra_flags} --cflags \"-isysroot #{sdk_path} -miphoneos-version-min=#{sdk_version} -D__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__=#{sdk_version_headers} -I. #{includes.join(' ')}\" #{headers.map { |x| "\"#{x}\"" }.join(' ')} -o \"#{bs_file}\""
File.join(motiondir, 'data', template.to_s, target)
end
end
end; end

View File

@@ -0,0 +1,98 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'erb'
module Motion; module Project
class Template
# for ERB
attr_reader :name
def initialize(app_name, template_name)
@name = @app_name = app_name
@template_name = template_name.to_s
@template_directory = File.expand_path(File.join(__FILE__, "../template/#{@template_name}"))
unless app_name.match(/^[\w\s-]+$/)
fail "Invalid app name"
end
if File.exist?(app_name)
fail "Directory `#{app_name}' already exists"
end
unless File.exist?(@template_directory)
fail "Invalid template name"
end
end
def generate
App.log 'Create', @app_name
FileUtils.mkdir(@app_name)
Dir.chdir(@app_name) do
create_directories()
create_files()
end
end
private
def template_directory
@template_directory
end
def create_directories
template_files = File.join(template_directory, 'files')
Dir.glob(File.join(template_files, "**/")).each do |dir|
dir.sub!("#{template_files}/", '')
FileUtils.mkdir_p(dir) if dir.length > 0
end
end
def create_files
template_files = File.join(template_directory, 'files')
Dir.glob(File.join(template_files, "**/*"), File::FNM_DOTMATCH).each do |src|
dest = src.sub("#{template_files}/", '')
next if File.directory?(src)
next if dest.include?(".DS_Store")
dest = replace_file_name(dest)
if dest =~ /(.+)\.erb$/
App.log 'Create', "#{@app_name}/#{$1}"
File.open($1, "w") { |io|
io.print ERB.new(File.read(src)).result(binding)
}
else
App.log 'Create', "#{@app_name}/#{dest}"
FileUtils.cp(src, dest)
end
end
end
def replace_file_name(file_name)
file_name = file_name.sub("{name}", "#{@name}")
file_name
end
end
end; end

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,161 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'motion/project/app'
App = Motion::Project::App
App.template = :ios
require 'motion/project'
require 'motion/project/template/ios/config'
desc "Build the project, then run the simulator"
task :default => :simulator
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 device version"
task :device do
App.build('iPhoneOS')
App.codesign('iPhoneOS')
end
end
desc "Run the simulator"
task :simulator => ['build:simulator'] do
app = App.config.app_bundle('iPhoneSimulator')
target = ENV['target'] || App.config.sdk_version
# Cleanup the simulator application sandbox, to avoid having old resource files there.
if ENV['clean']
sim_apps = File.expand_path("~/Library/Application Support/iPhone Simulator/#{target}/Applications")
Dir.glob("#{sim_apps}/**/*.app").each do |app_bundle|
if File.basename(app_bundle) == File.basename(app)
rm_rf File.dirname(app_bundle)
break
end
end
end
# Prepare the device family.
family_int =
if family = ENV['device_family']
App.config.device_family_int(family.downcase.intern)
else
App.config.device_family_ints[0]
end
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, target, retina)
default_simulator = `/usr/bin/defaults read com.apple.iphonesimulator "SimulateDevice"`.strip
if default_simulator != simulate_device && default_simulator != "'#{simulate_device}'"
system("/usr/bin/killall \"iPhone Simulator\" >& /dev/null")
system("/usr/bin/defaults write com.apple.iphonesimulator \"SimulateDevice\" \"'#{simulate_device}'\"")
end
# Launch the simulator.
xcode = App.config.xcode_dir
env = "DYLD_FRAMEWORK_PATH=\"#{xcode}/../Frameworks\":\"#{xcode}/../OtherFrameworks\""
env << ' SIM_SPEC_MODE=1' if App.config.spec_mode
sim = File.join(App.config.bindir, 'sim')
debug = (ENV['debug'] ? 1 : (App.config.spec_mode ? '0' : '2'))
App.info 'Simulate', app
at_exit { system("stty echo") } if $stdout.tty? # 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 an .ipa archive"
task :archive => ['build:device'] do
App.archive
end
namespace :archive do
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
desc "Same as 'spec:simulator'"
task :spec => ['spec:simulator']
namespace :spec do
desc "Run the test/spec suite on the simulator"
task :simulator do
App.config.spec_mode = true
Rake::Task["simulator"].invoke
end
desc "Run the test/spec suite on the device"
task :device do
App.config.spec_mode = true
ENV['debug'] ||= '1'
Rake::Task["device"].invoke
end
end
desc "Deploy on the device"
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 "#{env} #{deploy} #{flags} \"#{device_id}\" \"#{App.config.archive}\""
end
desc "Generate ctags"
task :ctags do
tags_file = 'tags'
config = App.config
if !File.exist?(tags_file) or File.mtime(config.project_file) > File.mtime(tags_file)
bs_files = config.bridgesupport_files + config.vendor_projects.map { |p| Dir.glob(File.join(p.path, '*.bridgesupport')) }.flatten
ctags = File.join(config.bindir, 'ctags')
config = File.join(config.motiondir, 'data', 'bridgesupport-ctags.cfg')
sh "#{ctags} --options=\"#{config}\" #{bs_files.map { |x| '"' + x + '"' }.join(' ')}"
end
end
desc "Create a .a static library"
task :static do
libs = %w{iPhoneSimulator iPhoneOS}.map do |platform|
'"' + App.build(platform, :static => true) + '"'
end
fat_lib = File.join(App.config.build_dir, App.config.name + '-universal.a')
App.info 'Create', fat_lib
sh "/usr/bin/lipo -create #{libs.join(' ')} -output \"#{fat_lib}\""
end

View File

@@ -0,0 +1,303 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'motion/project/xcode_config'
module Motion; module Project;
class IOSConfig < XcodeConfig
register :ios
variable :device_family, :interface_orientations, :background_modes,
:status_bar_style
def initialize(project_dir, build_mode)
super
@frameworks = ['UIKit', 'Foundation', 'CoreGraphics']
@device_family = :iphone
@interface_orientations = [:portrait, :landscape_left, :landscape_right]
@background_modes = []
@status_bar_style = :default
end
def platforms; ['iPhoneSimulator', 'iPhoneOS']; end
def local_platform; 'iPhoneSimulator'; end
def deploy_platform; 'iPhoneOS'; end
def locate_compiler(platform, *execs)
paths = [File.join(platform_dir(platform), 'Developer/usr/bin')]
paths.unshift File.join(xcode_dir, 'Toolchains/XcodeDefault.xctoolchain/usr/bin')
execs.each do |exec|
paths.each do |path|
cc = File.join(path, exec)
return escape_path(cc) if File.exist?(cc)
end
end
App.fail "Can't locate compilers for platform `#{platform}'"
end
def common_flags(platform)
super + " -miphoneos-version-min=#{deployment_target}"
end
def device_family_int(family)
case family
when :iphone then 1
when :ipad then 2
else
App.fail "Unknown device_family value: `#{family}'"
end
end
def device_family_string(family, target, retina)
device = case family
when :iphone, 1
"iPhone"
when :ipad, 2
"iPad"
end
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
ary = @device_family.is_a?(Array) ? @device_family : [@device_family]
ary.map { |family| device_family_int(family) }
end
def interface_orientations_consts
@interface_orientations.map do |ori|
case ori
when :portrait then 'UIInterfaceOrientationPortrait'
when :landscape_left then 'UIInterfaceOrientationLandscapeLeft'
when :landscape_right then 'UIInterfaceOrientationLandscapeRight'
when :portrait_upside_down then 'UIInterfaceOrientationPortraitUpsideDown'
else
App.fail "Unknown interface_orientation value: `#{ori}'"
end
end
end
def background_modes_consts
@background_modes.map do |mode|
case mode
when :audio then 'audio'
when :location then 'location'
when :voip then 'voip'
when :newsstand_content then 'newsstand-content'
when :external_accessory then 'external-accessory'
when :bluetooth_central then 'bluetooth-central'
else
App.fail "Unknown background_modes value: `#{mode}'"
end
end
end
def status_bar_style_const
case @status_bar_style
when :default then 'UIStatusBarStyleDefault'
when :black_translucent then 'UIStatusBarStyleBlackTranslucent'
when :black_opaque then 'UIStatusBarStyleBlackOpaque'
else
App.fail "Unknown status_bar_style value: `#{@status_bar_style}'"
end
end
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 app_bundle(platform)
File.join(versionized_build_dir(platform), bundle_name + '.app')
end
def app_bundle_executable(platform)
File.join(app_bundle(platform), name)
end
def app_resources_dir(platform)
app_bundle(platform)
end
def info_plist_data
ios_version_to_build = lambda do |vers|
# XXX we should retrieve these values programmatically.
case vers
when '4.3'; '8F191m'
when '5.0'; '9A334'
when '5.1'; '9B176'
else; '10A403' # 6.0 or later
end
end
Motion::PropertyList.to_s({
'MinimumOSVersion' => deployment_target,
'CFBundleResourceSpecification' => 'ResourceRules.plist',
'CFBundleSupportedPlatforms' => [deploy_platform],
'CFBundleIconFiles' => icons,
'CFBundleIcons' => {
'CFBundlePrimaryIcon' => {
'CFBundleIconFiles' => icons,
'UIPrerenderedIcon' => prerendered_icon,
}
},
'UIAppFonts' => fonts,
'UIDeviceFamily' => device_family_ints.map { |x| x.to_s },
'UISupportedInterfaceOrientations' => interface_orientations_consts,
'UIStatusBarStyle' => status_bar_style_const,
'UIBackgroundModes' => background_modes_consts,
'DTXcode' => begin
vers = xcode_version[0].gsub(/\./, '')
if vers.length == 2
'0' + vers + '0'
else
'0' + vers
end
end,
'DTXcodeBuild' => xcode_version[1],
'DTSDKName' => "iphoneos#{sdk_version}",
'DTSDKBuild' => ios_version_to_build.call(sdk_version),
'DTPlatformName' => 'iphoneos',
'DTCompiler' => 'com.apple.compilers.llvm.clang.1_0',
'DTPlatformVersion' => sdk_version,
'DTPlatformBuild' => ios_version_to_build.call(sdk_version)
}.merge(generic_info_plist).merge(dt_info_plist).merge(info_plist))
end
def main_cpp_file_txt(spec_objs)
main_txt = <<EOS
#import <UIKit/UIKit.h>
extern "C" {
void rb_define_global_const(const char *, void *);
void rb_rb2oc_exc_handler(void);
void rb_exit(int);
void RubyMotionInit(int argc, char **argv);
EOS
if spec_mode
spec_objs.each do |_, init_func|
main_txt << "void #{init_func}(void *, void *);\n"
end
end
main_txt << <<EOS
}
EOS
if spec_mode
main_txt << <<EOS
@interface SpecLauncher : NSObject
@end
#include <dlfcn.h>
@implementation SpecLauncher
+ (id)launcher
{
[UIApplication sharedApplication];
// Enable simulator accessibility.
// Thanks http://www.stewgleadow.com/blog/2011/10/14/enabling-accessibility-for-ios-applications/
NSString *simulatorRoot = [[[NSProcessInfo processInfo] environment] objectForKey:@"IPHONE_SIMULATOR_ROOT"];
if (simulatorRoot != nil) {
void *appSupportLibrary = dlopen([[simulatorRoot stringByAppendingPathComponent:@"/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport"] fileSystemRepresentation], RTLD_LAZY);
CFStringRef (*copySharedResourcesPreferencesDomainForDomain)(CFStringRef domain) = (CFStringRef (*)(CFStringRef)) dlsym(appSupportLibrary, "CPCopySharedResourcesPreferencesDomainForDomain");
if (copySharedResourcesPreferencesDomainForDomain != NULL) {
CFStringRef accessibilityDomain = copySharedResourcesPreferencesDomainForDomain(CFSTR("com.apple.Accessibility"));
if (accessibilityDomain != NULL) {
CFPreferencesSetValue(CFSTR("ApplicationAccessibilityEnabled"), kCFBooleanTrue, accessibilityDomain, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
CFRelease(accessibilityDomain);
}
}
}
// Load the UIAutomation framework.
dlopen("/Developer/Library/PrivateFrameworks/UIAutomation.framework/UIAutomation", RTLD_LOCAL);
SpecLauncher *launcher = [[self alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:launcher selector:@selector(appLaunched:) name:UIApplicationDidBecomeActiveNotification object:nil];
return launcher;
}
- (void)appLaunched:(id)notification
{
// Give a bit of time for the simulator to attach...
[self performSelector:@selector(runSpecs) withObject:nil afterDelay:0.3];
}
- (void)runSpecs
{
EOS
spec_objs.each do |_, init_func|
main_txt << "#{init_func}(self, 0);\n"
end
main_txt << "[NSClassFromString(@\"Bacon\") performSelector:@selector(run)];\n"
main_txt << <<EOS
}
@end
EOS
end
main_txt << <<EOS
int
main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retval = 0;
try {
EOS
main_txt << "[SpecLauncher launcher];\n" if spec_mode
main_txt << <<EOS
RubyMotionInit(argc, argv);
EOS
main_txt << define_global_env_txt
main_txt << <<EOS
retval = UIApplicationMain(argc, argv, nil, @"#{delegate_class}");
rb_exit(retval);
}
catch (...) {
rb_rb2oc_exc_handler();
}
[pool release];
return retval;
}
EOS
end
end
end; end

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
$:.unshift("/Library/RubyMotion/lib")
require 'motion/project'
require 'motion/project/template/ios'
Motion::Project::App.setup do |app|
# Use `rake config' to see complete project settings.

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,45 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'motion/project/app'
App = Motion::Project::App
App.template = :osx
require 'motion/project'
require 'motion/project/template/osx/config'
desc "Build the project, then run it"
task :default => :run
desc "Build the project"
task :build do
App.build('MacOSX')
end
desc "Run the project"
task :run => 'build' do
exec = App.config.app_bundle_executable('MacOSX')
App.info 'Run', exec
sh exec
end

View File

@@ -0,0 +1,111 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'motion/project/xcode_config'
module Motion; module Project;
class OSXConfig < XcodeConfig
register :osx
variable :copyright
def initialize(project_dir, build_mode)
super
@copyright = "Copyright © #{Time.now.year} #{`whoami`.strip}. All rights reserved."
@frameworks = ['AppKit', 'Foundation', 'CoreGraphics']
end
def platforms; ['MacOSX']; end
def local_platform; 'MacOSX'; end
def deploy_platform; 'MacOSX'; end
def locate_compiler(platform, *execs)
execs.each do |exec|
cc = File.join('/usr/bin', exec)
return escape_path(cc) if File.exist?(cc)
end
App.fail "Can't locate compilers for platform `#{platform}'"
end
def archs; { 'MacOSX' => ['x86_64'] }; end
def common_flags(platform)
super + " -mmacosx-version-min=#{deployment_target}"
end
def app_bundle(platform)
File.join(versionized_build_dir(platform), bundle_name + '.app', 'Contents')
end
def app_bundle_executable(platform)
File.join(app_bundle(platform), 'MacOS', name)
end
def app_resources_dir(platform)
File.join(app_bundle(platform), 'Resources')
end
def info_plist_data
Motion::PropertyList.to_s({
'NSHumanReadableCopyright' => copyright,
'NSPrincipalClass' => 'NSApplication'
}.merge(generic_info_plist).merge(dt_info_plist).merge(info_plist))
end
def main_cpp_file_txt(spec_objs)
main_txt = <<EOS
#import <AppKit/AppKit.h>
extern "C" {
void rb_define_global_const(const char *, void *);
void rb_rb2oc_exc_handler(void);
void rb_exit(int);
void RubyMotionInit(int argc, char **argv);
}
int
main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#if !__LP64__
try {
#endif
RubyMotionInit(argc, argv);
#{define_global_env_txt}
NSApplication *app = [NSApplication sharedApplication];
[app setDelegate:[NSClassFromString(@"#{delegate_class}") new]];
[app run];
rb_exit(0);
#if !__LP64__
}
catch (...) {
rb_rb2oc_exc_handler();
}
#endif
[pool release];
return 0;
}
EOS
end
end
end; end

View File

@@ -0,0 +1,16 @@
.repl_history
build
tags
app/pixate_code.rb
resources/*.nib
resources/*.momd
resources/*.storyboardc
.DS_Store
nbproject
.redcar
#*#
*~
*.sw[po]
.eprj
.sass-cache
.idea

View File

@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
$:.unshift("/Library/RubyMotion/lib")
require 'motion/project/template/osx'
Motion::Project::App.setup do |app|
# Use `rake config' to see complete project settings.
app.name = '<%= name %>'
end

View File

@@ -0,0 +1,4 @@
class AppDelegate
def applicationDidFinishLaunching(notification)
end
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,9 @@
describe "Application '<%= name %>'" do
before do
@app = UIApplication.sharedApplication
end
it "has one window" do
@app.windows.size.should == 1
end
end

View File

@@ -0,0 +1,383 @@
# Copyright (c) 2012, HipByte SPRL and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
module Motion; module Project;
class XcodeConfig < Config
variable :xcode_dir, :sdk_version, :deployment_target, :frameworks,
:weak_frameworks, :framework_search_paths, :libs, :resources_dirs,
:identifier, :codesign_certificate, :provisioning_profile,
:short_version, :icons, :prerendered_icon, :seed_id, :entitlements,
:fonts, :delegate_class
def initialize(project_dir, build_mode)
super
@info_plist = {}
@dependencies = {}
@frameworks = []
@weak_frameworks = []
@framework_search_paths = []
@libs = []
@bundle_signature = '????'
@short_version = '1'
@icons = []
@prerendered_icon = false
@vendor_projects = []
@entitlements = {}
@delegate_class = 'AppDelegate'
@spec_mode = false
end
def xcode_dir
@xcode_dir ||= begin
xcode_dot_app_path = '/Applications/Xcode.app/Contents/Developer'
# First, honor /usr/bin/xcode-select
xcodeselect = '/usr/bin/xcode-select'
if File.exist?(xcodeselect)
path = `#{xcodeselect} -print-path`.strip
if path.match(/^\/Developer\//) and File.exist?(xcode_dot_app_path)
@xcode_error_printed ||= false
$stderr.puts(<<EOS) unless @xcode_error_printed
===============================================================================
It appears that you have a version of Xcode installed in /Applications that has
not been set as the default version. It is possible that RubyMotion may be
using old versions of certain tools which could eventually cause issues.
To fix this problem, you can type the following command in the terminal:
$ sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
===============================================================================
EOS
@xcode_error_printed = true
end
return path if File.exist?(path)
end
# Since xcode-select is borked, we assume the user installed Xcode
# as an app (new in Xcode 4.3).
return xcode_dot_app_path if File.exist?(xcode_dot_app_path)
App.fail "Can't locate any version of Xcode on the system."
end
unescape_path(@xcode_dir)
end
def xcode_version
@xcode_version ||= begin
txt = `#{locate_binary('xcodebuild')} -version`
vers = txt.scan(/Xcode\s(.+)/)[0][0]
build = txt.scan(/Build version\s(.+)/)[0][0]
[vers, build]
end
end
def platforms; raise; end
def local_platform; raise; end
def deploy_platform; raise; end
def validate
# Xcode version
App.fail "Xcode 4.x or greater is required" if xcode_version[0] < '4.0'
# sdk_version
platforms.each do |platform|
sdk_path = File.join(platforms_dir, platform + '.platform',
"Developer/SDKs/#{platform}#{sdk_version}.sdk")
unless File.exist?(sdk_path)
App.fail "Can't locate #{platform} SDK #{sdk_version} at `#{sdk_path}'"
end
end
# deployment_target
if deployment_target > sdk_version
App.fail "Deployment target `#{deployment_target}' must be equal or lesser than SDK version `#{sdk_version}'"
end
unless File.exist?(datadir)
App.fail "iOS deployment target #{deployment_target} is not supported by this version of RubyMotion"
end
# icons
if !(icons.is_a?(Array) and icons.all? { |x| x.is_a?(String) })
App.fail "app.icons should be an array of strings."
end
super
end
def platforms_dir
File.join(xcode_dir, 'Platforms')
end
def platform_dir(platform)
File.join(platforms_dir, platform + '.platform')
end
def sdk_version
@sdk_version ||= begin
versions = Dir.glob(File.join(platforms_dir, "#{deploy_platform}.platform/Developer/SDKs/#{deploy_platform}*.sdk")).map do |path|
File.basename(path).scan(/#{deploy_platform}(.*)\.sdk/)[0][0]
end
if versions.size == 0
App.fail "Can't find an iOS SDK in `#{platforms_dir}'"
end
supported_vers = versions.reverse.find { |vers| File.exist?(datadir(vers)) }
unless supported_vers
App.fail "RubyMotion doesn't support any of these SDK versions: #{versions.join(', ')}"
end
supported_vers
end
end
def deployment_target
@deployment_target ||= sdk_version
end
def sdk(platform)
path = File.join(platform_dir(platform), 'Developer/SDKs',
platform + sdk_version + '.sdk')
escape_path(path)
end
def frameworks_dependencies
@frameworks_dependencies ||= begin
# Compute the list of frameworks, including dependencies, that the project uses.
deps = frameworks.dup.uniq
slf = File.join(sdk(local_platform), 'System', 'Library', 'Frameworks')
deps.each do |framework|
framework_path = File.join(slf, framework + '.framework', framework)
if File.exist?(framework_path)
`#{locate_binary('otool')} -L \"#{framework_path}\"`.scan(/\t([^\s]+)\s\(/).each do |dep|
# Only care about public, non-umbrella frameworks (for now).
if md = dep[0].match(/^\/System\/Library\/Frameworks\/(.+)\.framework\/(.+)$/) and md[1] == md[2]
deps << md[1]
deps.uniq!
end
end
end
end
if @framework_search_paths.empty?
deps = deps.select { |dep| File.exist?(File.join(datadir, 'BridgeSupport', dep + '.bridgesupport')) }
end
deps
end
end
def frameworks_stubs_objects(platform)
stubs = []
(frameworks_dependencies + weak_frameworks).uniq.each do |framework|
stubs_obj = File.join(datadir, platform, "#{framework}_stubs.o")
stubs << stubs_obj if File.exist?(stubs_obj)
end
stubs
end
def bridgesupport_files
@bridgesupport_files ||= begin
bs_files = []
deps = ['RubyMotion'] + (frameworks_dependencies + weak_frameworks).uniq
deps << 'UIAutomation' if spec_mode
deps.each do |framework|
supported_versions.each do |ver|
next if ver < deployment_target || sdk_version < ver
bs_path = File.join(datadir(ver), 'BridgeSupport', framework + '.bridgesupport')
if File.exist?(bs_path)
bs_files << bs_path
end
end
end
bs_files
end
end
def archs
@archs ||= begin
h = {}
platforms.each do |platform|
h[platform] = Dir.glob(File.join(datadir, platform, '*.bc')).map do |path|
path.scan(/kernel-(.+).bc$/)[0][0]
end
end
h
end
end
def arch_flags(platform)
archs[platform].map { |x| "-arch #{x}" }.join(' ')
end
def common_flags(platform)
"#{arch_flags(platform)} -isysroot \"#{unescape_path(sdk(platform))}\" -F#{sdk(platform)}/System/Library/Frameworks"
end
def cflags(platform, cplusplus)
"#{common_flags(platform)} -fexceptions -fblocks -fobjc-legacy-dispatch -fobjc-abi-version=2" + (cplusplus ? '' : ' -std=c99')
end
def ldflags(platform)
ldflags = common_flags(platform)
ldflags << " -fobjc-arc" if deployment_target < '5.0'
ldflags
end
def bundle_name
@name + (spec_mode ? '_spec' : '')
end
def app_bundle_dsym(platform)
File.join(versionized_build_dir(platform), bundle_name + '.dSYM')
end
def archive
File.join(versionized_build_dir(deploy_platform), bundle_name + '.ipa')
end
def identifier
@identifier ||= "com.yourcompany.#{@name.gsub(/\s/, '')}"
spec_mode ? @identifier + '_spec' : @identifier
end
def info_plist
@info_plist
end
def dt_info_plist
{}
end
def generic_info_plist
{
'BuildMachineOSBuild' => `sw_vers -buildVersion`.strip,
'CFBundleDevelopmentRegion' => 'en',
'CFBundleName' => @name,
'CFBundleDisplayName' => @name,
'CFBundleIdentifier' => identifier,
'CFBundleExecutable' => @name,
'CFBundleInfoDictionaryVersion' => '6.0',
'CFBundlePackageType' => 'APPL',
'CFBundleShortVersionString' => @short_version,
'CFBundleSignature' => @bundle_signature,
'CFBundleVersion' => @version
}
end
def pkginfo_data
"AAPL#{@bundle_signature}"
end
def codesign_certificate
@codesign_certificate ||= begin
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"
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
certs[0][1..-2] # trim trailing `"` characters
end
end
def provisioning_profile(name = /iOS Team Provisioning Profile/)
@provisioning_profile ||= begin
paths = Dir.glob(File.expand_path("~/Library/MobileDevice/Provisioning\ Profiles/*.mobileprovision")).select do |path|
text = File.read(path)
text.force_encoding('binary') if RUBY_VERSION >= '1.9.0'
text.scan(/<key>\s*Name\s*<\/key>\s*<string>\s*([^<]+)\s*<\/string>/)[0][0].match(name)
end
if paths.size == 0
App.fail "Can't find a provisioning profile named `#{name}'"
elsif paths.size > 1
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 read_provisioned_profile_array(key)
text = File.read(provisioning_profile)
text.force_encoding('binary') if RUBY_VERSION >= '1.9.0'
text.scan(/<key>\s*#{key}\s*<\/key>\s*<array>(.*?)\s*<\/array>/m)[0][0].scan(/<string>(.*?)<\/string>/).map { |str| str[0].strip }
end
private :read_provisioned_profile_array
def provisioned_devices
@provisioned_devices ||= read_provisioned_profile_array('ProvisionedDevices')
end
def seed_id
@seed_id ||= begin
seed_ids = read_provisioned_profile_array('ApplicationIdentifierPrefix')
if seed_ids.size == 0
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
seed_ids.last
end
end
def entitlements_data
dict = entitlements
if distribution_mode
dict['application-identifier'] ||= seed_id + '.' + identifier
else
# Required for gdb.
dict['get-task-allow'] = true if dict['get-task-allow'].nil?
end
Motion::PropertyList.to_s(dict)
end
def fonts
@fonts ||= begin
resources_dirs.flatten.inject([]) do |fonts, dir|
if File.exist?(dir)
Dir.chdir(dir) do
fonts.concat(Dir.glob('*.{otf,ttf}'))
end
else
fonts
end
end
end
end
def gen_bridge_metadata(headers, bs_file)
sdk_path = self.sdk(local_platform)
includes = headers.map { |header| "-I'#{File.dirname(header)}'" }.uniq
a = sdk_version.scan(/(\d+)\.(\d+)/)[0]
sdk_version_headers = ((a[0].to_i * 10000) + (a[1].to_i * 100)).to_s
extra_flags = OSX_VERSION >= 10.7 ? '--no-64-bit' : ''
sh "RUBYOPT='' /usr/bin/gen_bridge_metadata --format complete #{extra_flags} --cflags \"-isysroot #{sdk_path} -miphoneos-version-min=#{sdk_version} -D__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__=#{sdk_version_headers} -I. #{includes.join(' ')}\" #{headers.map { |x| "\"#{x}\"" }.join(' ')} -o \"#{bs_file}\""
end
def define_global_env_txt
rubymotion_env =
if spec_mode
'test'
else
development? ? 'development' : 'release'
end
"rb_define_global_const(\"RUBYMOTION_ENV\", @\"#{rubymotion_env}\");\nrb_define_global_const(\"RUBYMOTION_VERSION\", @\"#{Motion::Version}\");\n"
end
end
end; end