From 480dcd2e6c4c30b4dcc46ad7507df3f862767938 Mon Sep 17 00:00:00 2001 From: Mark Villacampa Date: Mon, 25 Aug 2014 22:14:31 +0200 Subject: [PATCH] Added support for targets. iOS frameworks supported through the FrameworkTarget class. --- lib/motion/project/builder.rb | 30 ++++ lib/motion/project/target.rb | 26 ++++ lib/motion/project/target/framework_target.rb | 140 ++++++++++++++++++ lib/motion/project/template/ios/builder.rb | 7 + lib/motion/project/xcode_config.rb | 14 ++ 5 files changed, 217 insertions(+) create mode 100644 lib/motion/project/target.rb create mode 100644 lib/motion/project/target/framework_target.rb diff --git a/lib/motion/project/builder.rb b/lib/motion/project/builder.rb index c05ef13a..25589f29 100644 --- a/lib/motion/project/builder.rb +++ b/lib/motion/project/builder.rb @@ -88,6 +88,19 @@ module Motion; module Project; embedded_frameworks = external_frameworks = [] end + # Build targets + unless config.targets.empty? + config.targets.each do |target| + target.build(platform) + end + + # Prepare target frameworks + target_frameworks = [] + config.targets.select { |t| t.type == :framework }.each do |target| + target_frameworks << target.framework_name + end + end + # Build object files. objs_build_dir = File.join(build_dir, 'objs') FileUtils.mkdir_p(objs_build_dir) @@ -181,6 +194,8 @@ module Motion; module Project; # Generate init file. init_txt = < + extern "C" { void ruby_sysinit(int *, char ***); void ruby_init(void); @@ -219,6 +234,14 @@ RubyMotionInit(int argc, char **argv) void *self = rb_vm_top_self(); EOS init_txt << config.define_global_env_txt + + unless target_frameworks.empty? + init_txt << "NSString *frameworks_path = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: @\"Frameworks\"];\n" + target_frameworks.each do |framework| + init_txt << "[[NSBundle bundleWithPath: [frameworks_path stringByAppendingPathComponent: @\"#{framework}\"]] load];\n" + end + end + app_objs.each do |_, init_func| init_txt << "#{init_func}(self, 0);\n" end @@ -418,6 +441,13 @@ EOS end end + # Copy target products + unless config.targets.empty? + config.targets.each do |target| + target.copy_products(platform) + end + end + # Create bundle/Info.plist. bundle_info_plist = File.join(bundle_path, 'Info.plist') if !File.exist?(bundle_info_plist) or File.mtime(config.project_file) > File.mtime(bundle_info_plist) diff --git a/lib/motion/project/target.rb b/lib/motion/project/target.rb new file mode 100644 index 00000000..8c5b2ee7 --- /dev/null +++ b/lib/motion/project/target.rb @@ -0,0 +1,26 @@ +# 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/target/framework_target' \ No newline at end of file diff --git a/lib/motion/project/target/framework_target.rb b/lib/motion/project/target/framework_target.rb new file mode 100644 index 00000000..73cbd24e --- /dev/null +++ b/lib/motion/project/target/framework_target.rb @@ -0,0 +1,140 @@ +# 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/builder' + +module Motion; module Project + class FrameworkTarget + include Rake::DSL if Object.const_defined?(:Rake) && Rake.const_defined?(:DSL) + + attr_accessor :type + + def initialize(path, type, config, opts) + @path = path + @full_path = File.expand_path(path) + @type = type + @config = config + @opts = opts + end + + def build(platform) + @platform = platform + + command = if platform == 'iPhoneSimulator' + "build:simulator" + else + if @config.distribution_mode + "archive:distribution" + else + "build:device" + end + end + + success = system("cd #{@full_path} && bundle exec rake #{command}") + unless success + App.fail "Target '#{@path}' failed to build" + end + end + + def copy_products(platform) + src_path = framework_path + dest_path = File.join(@config.app_bundle(platform), 'Frameworks', framework_name) + FileUtils.mkdir_p(File.join(@config.app_bundle(platform), 'Frameworks')) + + if !File.exist?(dest_path) or File.mtime(src_path) > File.mtime(dest_path) + App.info 'Copy', src_path + FileUtils.cp_r(src_path, dest_path) + end + end + + def codesign(platform) + # Create bundle/ResourceRules.plist. + resource_rules_plist = File.join(@config.app_bundle(platform), 'Frameworks', framework_name, 'ResourceRules.plist') + unless File.exist?(resource_rules_plist) + App.info 'Create', resource_rules_plist + File.open(resource_rules_plist, 'w') do |io| + io.write(<<-PLIST) + + + + + rules + + .* + + Info.plist + + omit + + weight + 10 + + ResourceRules.plist + + omit + + weight + 100 + + + + +PLIST + end + end + + codesign_cmd = "CODESIGN_ALLOCATE=\"#{File.join(@config.platform_dir(platform), 'Developer/usr/bin/codesign_allocate')}\" /usr/bin/codesign" + + framework_path = File.join(@config.app_bundle(platform), 'Frameworks', framework_name) + if File.mtime(@config.project_file) > File.mtime(framework_path) \ + or !system("#{codesign_cmd} --verify \"#{framework_path}\" >& /dev/null") + App.info 'Codesign', framework_path + # TODO remove one of these + sh "#{codesign_cmd} -f -s \"#{@config.codesign_certificate}\" --resource-rules=\"#{resource_rules_plist}\" \"#{framework_path}\"" + sh "#{codesign_cmd} -f -s \"#{@config.codesign_certificate}\" --preserve-metadata=\"identifier,entitlements,resource-rules\" \"#{framework_path}\"" + end + end + + def clean + system("cd #{@full_path} && bundle exec rake clean") + end + + def build_dir(config, platform) + platform + '-' + config.deployment_target + '-' + config.build_mode_name + end + + def framework_path + @framework_path ||= begin + path = File.join(@path, 'build', build_dir(@config, @platform), '*.framework') + Dir[path].sort_by{ |f| File.mtime(f) }.first + end + end + + def framework_name + File.basename(framework_path) + end + + end +end;end \ No newline at end of file diff --git a/lib/motion/project/template/ios/builder.rb b/lib/motion/project/template/ios/builder.rb index 749c56e5..045b6473 100644 --- a/lib/motion/project/template/ios/builder.rb +++ b/lib/motion/project/template/ios/builder.rb @@ -57,6 +57,13 @@ module Motion; module Project bundle_path = config.app_bundle(platform) raise unless File.exist?(bundle_path) + # Codesign targets + unless config.targets.empty? + config.targets.each do |target| + target.codesign(platform) + end + end + # Create bundle/ResourceRules.plist. resource_rules_plist = File.join(bundle_path, 'ResourceRules.plist') unless File.exist?(resource_rules_plist) diff --git a/lib/motion/project/xcode_config.rb b/lib/motion/project/xcode_config.rb index 29a55e31..3b197561 100644 --- a/lib/motion/project/xcode_config.rb +++ b/lib/motion/project/xcode_config.rb @@ -25,6 +25,7 @@ require 'motion/project/config' require 'motion/util/code_sign' +require 'motion/project/target' module Motion; module Project; class XcodeConfig < Config @@ -43,6 +44,7 @@ module Motion; module Project; @external_frameworks = [] @framework_search_paths = [] @libs = [] + @targets = [] @bundle_signature = '????' @short_version = nil @entitlements = {} @@ -453,6 +455,18 @@ EOS def clean_project super @vendor_projects.each { |vendor| vendor.clean } + @targets.each { |target| target.clean } + end + + attr_accessor :targets + + def target(path, type, opts={}) + case type + when :framework + @targets << Motion::Project::FrameworkTarget.new(path, type, self, opts) + else + App.fail("Unsupported target type '#{type}'") + end end end end; end