mirror of
https://github.com/zhigang1992/RubyMotion.git
synced 2026-05-30 00:51:50 +08:00
283 lines
8.3 KiB
Ruby
283 lines
8.3 KiB
Ruby
# encoding: utf-8
|
|
|
|
# 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'
|
|
require 'motion/util/version'
|
|
|
|
module Motion; module Project;
|
|
class OSXConfig < XcodeConfig
|
|
register :osx
|
|
|
|
variable :icon, :copyright, :category,
|
|
:embedded_frameworks, :external_frameworks,
|
|
:codesign_for_development, :codesign_for_release,
|
|
:eval_support
|
|
|
|
def initialize(project_dir, build_mode)
|
|
super
|
|
@icon = ''
|
|
@copyright = "Copyright © #{Time.now.year} #{`whoami`.strip}. All rights reserved."
|
|
@category = 'utilities'
|
|
@frameworks = ['AppKit', 'Foundation', 'CoreGraphics', 'CoreServices']
|
|
@embedded_frameworks = []
|
|
@external_frameworks = []
|
|
@codesign_for_development = false
|
|
@codesign_for_release = true
|
|
@eval_support = false
|
|
end
|
|
|
|
def platforms; ['MacOSX']; end
|
|
def local_platform; 'MacOSX'; end
|
|
def deploy_platform; 'MacOSX'; end
|
|
def device_family; 'mac'; end
|
|
|
|
def validate
|
|
%w{ embedded_frameworks external_frameworks }.each do |attr|
|
|
value = send(attr)
|
|
if !(value.is_a?(Array) and value.all? { |x| File.exist?(x) and File.extname(x) == '.framework' })
|
|
App.fail "app.#{attr} should be an array of framework paths"
|
|
end
|
|
end
|
|
|
|
super
|
|
end
|
|
|
|
def archs
|
|
archs = super
|
|
if development?
|
|
# We only build for the native architecture in development mode, to speed up builds.
|
|
native_arch = `/usr/bin/uname -m`.strip
|
|
if archs['MacOSX'].include?(native_arch)
|
|
archs['MacOSX'] = [native_arch]
|
|
end
|
|
end
|
|
archs
|
|
end
|
|
|
|
def app_icons_info_plist_path(platform)
|
|
'/dev/null'
|
|
end
|
|
|
|
# On OS X only one file is ever created. E.g. NAME.icns
|
|
def configure_app_icons_from_asset_bundle(platform)
|
|
self.icon = app_icon_name_from_asset_bundle
|
|
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 archive_extension
|
|
'.pkg'
|
|
end
|
|
|
|
def codesign_certificate
|
|
super('Mac')
|
|
end
|
|
|
|
def needs_repl_sandbox_entitlements?
|
|
development? && codesign_for_development && entitlements['com.apple.security.app-sandbox']
|
|
end
|
|
|
|
def entitlements_data
|
|
dict = entitlements.dup
|
|
if needs_repl_sandbox_entitlements?
|
|
files = (dict['com.apple.security.temporary-exception.files.absolute-path.read-only'] ||= [])
|
|
files << datadir('librubymotion-repl.dylib')
|
|
end
|
|
Motion::PropertyList.to_s(dict)
|
|
end
|
|
|
|
def common_flags(platform)
|
|
super + " -mmacosx-version-min=#{deployment_target}"
|
|
end
|
|
|
|
def bridgesupport_flags
|
|
"--format complete --64-bit"
|
|
end
|
|
|
|
def bridgesupport_cflags
|
|
a = sdk_version.scan(/(\d+)\.(\d+)/)[0]
|
|
major = a[0].to_i
|
|
minor = a[1].to_i
|
|
if major <= 10 && minor <= 9
|
|
sdk_version_headers = "#{major}#{minor}0"
|
|
else
|
|
sdk_version_headers = "#{major}#{minor}00"
|
|
end
|
|
"-mmacosx-version-min=#{sdk_version} -D__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__=#{sdk_version_headers}"
|
|
end
|
|
|
|
def app_bundle_raw(platform)
|
|
File.join(versionized_build_dir(platform), bundle_name + '.app')
|
|
end
|
|
|
|
def app_bundle(platform)
|
|
File.join(app_bundle_raw(platform), '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 app_sandbox_repl_socket_path
|
|
File.expand_path(File.join('~/Library/Containers', identifier, "Data/rubymotion-repl-#{Time.now.to_i}"))
|
|
end
|
|
|
|
def generic_info_plist
|
|
super.merge({
|
|
'NSHumanReadableCopyright' => copyright,
|
|
'NSPrincipalClass' => 'NSApplication',
|
|
'CFBundleIconFile' => (icon or ''),
|
|
'LSMinimumSystemVersion' => deployment_target,
|
|
'LSApplicationCategoryType' => (@category.start_with?('public.app-category') ? @category : 'public.app-category.' + @category)
|
|
})
|
|
end
|
|
|
|
def merged_info_plist
|
|
generic_info_plist.merge(dt_info_plist).merge(info_plist)
|
|
end
|
|
|
|
def info_plist_data(platform)
|
|
Motion::PropertyList.to_s(merged_info_plist)
|
|
end
|
|
|
|
def strip_args
|
|
''
|
|
end
|
|
|
|
def deployment_target
|
|
@deployment_target ||= osx_version
|
|
end
|
|
|
|
def supported_sdk_versions(versions)
|
|
versions.reverse.find { |vers|
|
|
Util::Version.new(osx_version) <= Util::Version.new(vers) && File.exist?(datadir(vers))
|
|
}
|
|
end
|
|
|
|
def osx_version
|
|
`sw_vers -productVersion`.strip.match(/((\d+).(\d+))/)[0]
|
|
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);
|
|
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
|
|
|
|
@implementation SpecLauncher
|
|
|
|
- (void)runSpecs
|
|
{
|
|
EOS
|
|
spec_objs.each do |_, init_func|
|
|
main_txt << "#{init_func}(self, 0);\n"
|
|
end
|
|
main_txt << <<EOS
|
|
[NSClassFromString(@\"Bacon\") performSelector:@selector(run)];
|
|
}
|
|
|
|
- (void)appLaunched:(NSNotification *)notification
|
|
{
|
|
[self runSpecs];
|
|
}
|
|
|
|
@end
|
|
EOS
|
|
end
|
|
|
|
main_txt << <<EOS
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
EOS
|
|
if ENV['ARR_CYCLES_DISABLE']
|
|
main_txt << <<EOS
|
|
setenv("ARR_CYCLES_DISABLE", "1", true);
|
|
EOS
|
|
end
|
|
main_txt << <<EOS
|
|
RubyMotionInit(argc, argv);
|
|
NSApplication *app = [NSClassFromString(@"#{merged_info_plist['NSPrincipalClass']}") sharedApplication];
|
|
[app setDelegate:[NSClassFromString(@"#{delegate_class}") new]];
|
|
EOS
|
|
if spec_mode
|
|
main_txt << " SpecLauncher *specLauncher = [[SpecLauncher alloc] init];\n"
|
|
main_txt << " [[NSNotificationCenter defaultCenter] addObserver:specLauncher selector:@selector(appLaunched:) name:NSApplicationDidFinishLaunchingNotification object:nil];\n"
|
|
end
|
|
if use_application_main_function?
|
|
main_txt << " NSApplicationMain(argc, (const char **)argv);\n"
|
|
else
|
|
main_txt << " [app run];\n"
|
|
end
|
|
main_txt << <<EOS
|
|
[pool release];
|
|
rb_exit(0);
|
|
return 0;
|
|
}
|
|
EOS
|
|
end
|
|
|
|
# If the user specifies a custom principal class the NSApplicationMain()
|
|
# function will only work if they have also specified a nib or storyboard.
|
|
def use_application_main_function?
|
|
info = merged_info_plist
|
|
if info['NSPrincipalClass'] == 'NSApplication'
|
|
true
|
|
else
|
|
files = info.values_at('NSMainNibFile', 'NSMainStoryboardFile').compact
|
|
files.any? { |file| !file.strip.empty? }
|
|
end
|
|
end
|
|
end
|
|
end; end
|