PLATFORMS_DIR = ENV['platforms_dir'] SDK_VERSIONS = ENV['sdk_versions'].split(',') verbose(true) task :default => :all task :all => [:vm_files, :bridgesupport_files, :bridgesupport_static_stubs] task :vm_files do SDK_VERSIONS.each do |sdk_version| ios = File.join(sdk_version, 'iPhoneOS') mkdir_p ios objs = "../vm/iPhoneOS#{sdk_version}.objs" Dir.glob(File.join(objs, 'kernel-*.bc')).each do |path| install path, ios end install File.join(objs, 'libmacruby-static.a'), ios sim = File.join(sdk_version, 'iPhoneSimulator') mkdir_p sim objs = "../vm/iPhoneSimulator#{sdk_version}.objs" Dir.glob(File.join(objs, 'kernel-*.bc')).each do |path| install path, sim end install File.join(objs, 'libmacruby-static.a'), sim end end EXCLUDED_FRAMEWORKS = ['Kernel', 'System', 'CoreAudio', 'IOKit'] task :bridgesupport_files do platform_dev_path = "#{PLATFORMS_DIR}/iPhoneSimulator.platform/Developer" SDK_VERSIONS.each do |sdk_version| sdk_path = "#{platform_dev_path}/SDKs/iPhoneSimulator#{sdk_version}.sdk" sdk_frameworks = "#{sdk_path}/System/Library/Frameworks" mkdir_p "#{sdk_version}/BridgeSupport" rm_bs = "#{sdk_version}/BridgeSupport/RubyMotion.bridgesupport" cp 'RubyMotion.bridgesupport', rm_bs Dir.glob(File.join(sdk_frameworks, '*.framework')).each do |framework_path| framework = File.basename(framework_path, '.framework') next if EXCLUDED_FRAMEWORKS.include?(framework) next unless File.exist?(File.join(framework_path, framework)) dest = "#{sdk_version}/BridgeSupport/#{framework}.bridgesupport" unless 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_path} -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 end end def generate_bs_static_stub(file, includes) require 'rubygems' require 'nokogiri' text = '' includes.each { |inc| text << "#import <#{inc}>\n" } doc = Nokogiri::XML(File.read(file)) 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 did_something ? text : nil end task :bridgesupport_static_stubs do SDK_VERSIONS.each do |sdk_version| Dir.glob("#{sdk_version}/BridgeSupport/*.bridgesupport") do |bs_path| framework = File.basename(bs_path).sub(/\.bridgesupport/, '') code = "#{sdk_version}/BridgeSupport/#{framework}_stubs.m" includes = case framework when 'OpenGLES' ['OpenGLES/EAGLDrawable.h'] else ['UIKit/UIKit.h', "#{framework}/#{framework}.h"] end unless File.exist?(code) text = generate_bs_static_stub(bs_path, includes) next unless text File.open(code, 'w') { |io| io.write(text) } end [%w{iPhoneOS armv6 armv7}, %w{iPhoneSimulator i386}].each do |platform, *archs| obj = "#{sdk_version}/#{platform}/#{framework}_stubs.o" next if File.exist?(obj) platform_dev = "#{PLATFORMS_DIR}/#{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 task :clean do SDK_VERSIONS.each { |path| rm_rf(path) } end