mirror of
https://github.com/zhigang1992/RubyMotion.git
synced 2026-04-06 22:39:46 +08:00
130 lines
5.1 KiB
Ruby
130 lines
5.1 KiB
Ruby
require 'fileutils'
|
|
require 'rubygems'
|
|
require 'nokogiri'
|
|
|
|
def die(*msg)
|
|
$stderr.puts msg
|
|
exit 1
|
|
end
|
|
|
|
xcode = '/Applications/Xcode45-DP4.app'
|
|
sdk_version = '6.0'
|
|
die "Xcode 4.5 must be installed as '#{xcode}'" unless File.exist?(xcode)
|
|
|
|
sdk = File.join(xcode, "Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator#{sdk_version}.sdk")
|
|
die "Can't locate SDK as '#{sdk}'" unless File.exist?(sdk)
|
|
sdk_frameworks = File.join(sdk, 'System/Library/Frameworks')
|
|
|
|
bridgesupport_dir = File.join(File.dirname(__FILE__), 'BridgeSupport')
|
|
iphoneos_dir = File.join(File.dirname(__FILE__), 'iPhoneOS')
|
|
iphonesimulator_dir = File.join(File.dirname(__FILE__), 'iPhoneSimulator')
|
|
|
|
task :apply_exceptions do
|
|
Dir.glob(File.join(sdk_frameworks, "**/*.h")).each do |h|
|
|
h_orig = h + '.orig'
|
|
next if File.exist?(h_orig)
|
|
txt = File.read(h)
|
|
txt.force_encoding(Encoding::ASCII_8BIT) if txt.respond_to?(:force_encoding)
|
|
# workaround for new objc enum parsing bug
|
|
changed = true if txt.gsub!(/NS_(ENUM|OPTIONS)\(([^\s,]+)\s*,\s*([^)]+)\)/, '\2 \3; enum')
|
|
case File.basename(h)
|
|
when 'CTRunDelegate.h'
|
|
# workaround for missing symbol bug in CoreText headers
|
|
changed = true if txt.sub!(/^(CFTypeID CTRunDelegateGetTypeID)/m, '//\1')
|
|
when 'NSCompoundPredicate.h'
|
|
# workaround for weird ivar name masked by preprocessor macro
|
|
changed = true if txt.sub!(/NSUInteger\s+_type;/, 'NSUInteger _name;')
|
|
end
|
|
if changed
|
|
FileUtils.cp h, h_orig
|
|
File.open(h, 'w') { |io| io.write txt }
|
|
end
|
|
end
|
|
end
|
|
|
|
task :remove_exceptions do
|
|
Dir.glob(File.join(sdk_frameworks, "**/*.h")).each do |h|
|
|
h_orig = h + '.orig'
|
|
FileUtils.mv h_orig, h if File.exist?(h_orig)
|
|
end
|
|
end
|
|
|
|
task :bridgesupport do
|
|
FileUtils.mkdir_p bridgesupport_dir
|
|
Dir.glob(File.join(sdk_frameworks, '*.framework')).each do |framework_path|
|
|
framework = File.basename(framework_path, '.framework')
|
|
next if ['Kernel', 'System', 'IOKit'].include?(framework)
|
|
next unless File.exist?(File.join(framework_path, framework))
|
|
next unless File.exist?(File.join(framework_path, 'Headers'))
|
|
dest = File.join(bridgesupport_dir, "#{framework}.bridgesupport")
|
|
next if File.exist?(dest)
|
|
a = sdk_version.scan(/(\d+)\.(\d+)/)[0]
|
|
sdk_version_headers = ((a[0].to_i * 10000) + (a[1].to_i * 100)).to_s
|
|
sh "/usr/bin/gen_bridge_metadata --format complete --no-64-bit --cflags \"-isysroot #{sdk} -miphoneos-version-min=#{sdk_version} -D__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__=#{sdk_version_headers} -framework #{framework}\" --framework #{sdk_frameworks}/#{framework}.framework > #{dest}"
|
|
end
|
|
end
|
|
|
|
task :stubs do
|
|
Dir.glob(File.join(bridgesupport_dir, '*.bridgesupport')) do |bs_path|
|
|
framework = File.basename(bs_path).sub(/\.bridgesupport/, '')
|
|
includes = case framework
|
|
when 'OpenGLES'
|
|
['OpenGLES/EAGLDrawable.h']
|
|
else
|
|
['UIKit/UIKit.h', "#{framework}/#{framework}.h"]
|
|
end
|
|
|
|
# Generate code.
|
|
code = File.join(bridgesupport_dir, "#{framework}_stubs.m")
|
|
unless File.exist?(code)
|
|
text = ''
|
|
includes.each { |inc| text << "#import <#{inc}>\n" }
|
|
doc = Nokogiri::XML(File.read(bs_path))
|
|
did_something = false
|
|
doc.xpath("/signatures/function[@inline=\"true\"]").each do |node|
|
|
name = node['name'].to_s
|
|
retval = node.xpath('./retval')[0]['declared_type'].to_s
|
|
args = node.xpath('./arg').map { |node| node['declared_type'].to_s }
|
|
proto = "#{retval} __concrete__#{name}("
|
|
proto << (0...args.size).to_a.map { |i| "#{args[i]} arg#{i}" }.join(', ')
|
|
proto << ")"
|
|
func = ''
|
|
func << proto
|
|
func << "\n{\n "
|
|
func << " return " if retval != 'void'
|
|
func << name << '('
|
|
func << (0...args.size).to_a.map { |i| "arg#{i}" }.join(', ')
|
|
func << ");\n}\n\n"
|
|
text << func
|
|
did_something = true
|
|
end
|
|
next unless did_something
|
|
File.open(code, 'w') { |io| io.write(text) }
|
|
|
|
# Compile code.
|
|
[%w{iPhoneOS armv6 armv7}, %w{iPhoneSimulator i386}].each do |platform, *archs|
|
|
obj = File.join(platform, "#{framework}_stubs.o")
|
|
next if File.exist?(obj)
|
|
platform_dev = File.join(xcode, "Contents/Developer/Platforms/#{platform}.platform/Developer")
|
|
cflags = "-isysroot #{platform_dev}/SDKs/#{platform}#{sdk_version}.sdk "
|
|
cflags << archs.map { |a| "-arch #{a}" }.join(' ')
|
|
cflags << " -miphoneos-version-min=#{sdk_version} -Wall -Werror -O3 -fobjc-abi-version=2 -fobjc-legacy-dispatch"
|
|
sh "#{platform_dev}/usr/bin/gcc #{cflags} #{code} -c -o #{obj}"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
desc "Update RubyMotion to latest SDK beta"
|
|
task :update => [:apply_exceptions, :bridgesupport, :remove_exceptions, :stubs]
|
|
|
|
desc "Clean up generated files"
|
|
task :clean do
|
|
Dir.glob(File.join(bridgesupport_dir, '*.{m,bridgesupport}')).each do |bs|
|
|
FileUtils.rm_f bs unless File.basename(bs) == 'RubyMotion.bridgesupport'
|
|
end
|
|
%w{iPhoneOS iPhoneSimulator}.each do |platform|
|
|
Dir.glob(File.join(platform, "*.o")).each { |o| FileUtils.rm_f o }
|
|
end
|
|
end
|