Files
RubyMotion/lib/motion/project/config.rb

307 lines
8.5 KiB
Ruby

# 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 Config
include Rake::DSL if Rake.const_defined?(:DSL)
VARS = []
def self.variable(*syms)
syms.each do |sym|
attr_accessor sym
VARS << sym.to_s
end
end
class Deps < Hash
def []=(key, val)
key = relpath(key)
val = [val] unless val.is_a?(Array)
val = val.map { |x| relpath(x) }
super
end
def relpath(path)
/^\./.match(path) ? path : File.join('.', path)
end
end
variable :name, :files, :build_dir, :specs_dir, :resources_dirs, :version,
:motiondir
# Internal only.
attr_accessor :build_mode, :spec_mode, :distribution_mode, :dependencies,
:template, :detect_dependencies, :exclude_from_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'))
@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')
@version = '1.0'
@detect_dependencies = true
@exclude_from_detect_dependencies = []
@vendor_projects = []
end
OSX_VERSION = `/usr/bin/sw_vers -productVersion`.strip.sub(/\.\d+$/, '').to_f
def variables
map = {}
VARS.each do |sym|
map[sym] =
begin
send(sym)
rescue Exception
'Error'
end
end
map
end
def setup_blocks
@setup_blocks ||= []
end
def setup
if @setup_blocks
@setup_blocks.each { |b| b.call(self) }
@setup_blocks = nil
validate
end
self
end
def unescape_path(path)
path.gsub('\\', '')
end
def escape_path(path)
path.gsub(' ', '\\ ')
end
def locate_binary(name)
[File.join(xcode_dir, 'usr/bin'), '/usr/bin'].each do |dir|
path = File.join(dir, name)
return escape_path(path) if File.exist?(path)
end
App.fail "Can't locate binary `#{name}' on the system."
end
def validate
# Do nothing, for now.
end
def supported_versions
@supported_versions ||= Dir.glob(File.join(motiondir, 'data', template.to_s, '*')).select{|path| File.directory?(path)}.map do |path|
File.basename path
end
end
def resources_dir
warn("`app.resources_dir' is deprecated; use `app.resources_dirs'");
@resources_dirs.first
end
def resources_dir=(dir)
warn("`app.resources_dir' is deprecated; use `app.resources_dirs'");
@resources_dirs = [dir]
end
def build_dir
unless File.directory?(@build_dir)
tried = false
begin
FileUtils.mkdir_p(@build_dir)
rescue Errno::EACCES
raise if tried
require 'digest/sha1'
hash = Digest::SHA1.hexdigest(File.expand_path(project_dir))
tmp = File.join(ENV['TMPDIR'], hash)
App.warn "Cannot create build_dir `#{@build_dir}'. Check the permissions. Using a temporary build directory instead: `#{tmp}'"
@build_dir = tmp
tried = true
retry
end
end
@build_dir
end
def build_mode_name
@build_mode.to_s.capitalize
end
def development?
@build_mode == :development
end
def release?
@build_mode == :release
end
def development
yield if development?
end
def release
yield if release?
end
def opt_level
@opt_level ||= case @build_mode
when :development; 0
when :release; 3
else; 0
end
end
def versionized_build_dir(platform)
File.join(build_dir, platform + '-' + deployment_target + '-' + build_mode_name)
end
attr_reader :project_dir
def project_file
File.join(@project_dir, 'Rakefile')
end
def files_dependencies(deps_hash)
res_path = lambda do |x|
path = /^\.{0,2}\//.match(x) ? x : File.join('.', x)
unless @files.flatten.include?(path)
App.fail "Can't resolve dependency `#{path}'"
end
path
end
deps_hash.each do |path, deps|
deps = [deps] unless deps.is_a?(Array)
@dependencies[res_path.call(path)] = deps.map(&res_path)
end
end
attr_reader :vendor_projects
def vendor_project(path, type, opts={})
opts[:force_load] = true unless opts[:force_load] == false
@vendor_projects << Motion::Project::Vendor.new(path, type, self, opts)
end
def unvendor_project(path)
@vendor_projects.delete_if { |x| x.path == path }
end
def file_dependencies(file)
deps = @dependencies[file]
if deps
deps = deps.map { |x| file_dependencies(x) }
else
deps = []
end
deps << file
deps
end
def ordered_build_files
@ordered_build_files ||= begin
@files.flatten.map { |file| file_dependencies(file) }.flatten.uniq
end
end
def spec_core_files
@spec_core_files ||= begin
# Core library + core helpers.
Dir.chdir(File.join(File.dirname(__FILE__), '..')) do
(['spec.rb'] +
Dir.glob(File.join('spec', 'helpers', '*.rb')) +
Dir.glob(File.join('project', 'template', App.template.to_s, 'spec-helpers', '*.rb'))).
map { |x| File.expand_path(x) }
end
end
end
def spec_files
@spec_files ||= begin
# Project helpers.
helpers = Dir.glob(File.join(specs_dir, 'helpers', '*.rb'))
# Project specs.
specs = Dir.glob(File.join(specs_dir, '**', '*.rb')) - helpers
if files_filter = ENV['files']
# Filter specs we want to run. A filter can be either the basename of a spec file or its path.
files_filter = files_filter.split(',')
files_filter.map! { |x| File.exist?(x) ? File.expand_path(x) : x }
specs.delete_if { |x| [File.expand_path(x), File.basename(x, '.rb'), File.basename(x, '_spec.rb')].none? { |p| files_filter.include?(p) } }
end
spec_core_files + helpers + specs
end
end
def motiondir
@motiondir ||= File.expand_path(File.join(File.dirname(__FILE__), '../../..'))
end
def bindir
File.join(motiondir, 'bin')
end
def datadir(target=deployment_target)
File.join(motiondir, 'data', template.to_s, target)
end
def strip_args
''
end
def print_crash_message
$stderr.puts ''
$stderr.puts '=' * 80
$stderr.puts <<EOS
The application terminated. A crash report file may have been generated by the
system, use `rake crashlog' to open it. Use `rake debug=1' to restart the app
in the debugger.
EOS
$stderr.puts '=' * 80
end
end
end; end