mirror of
https://github.com/zhigang1992/RubyMotion.git
synced 2026-03-30 17:43:26 +08:00
Extract Dependency and ParalelBuilder to separate files
This commit is contained in:
committed by
Eloy Durán
parent
9212ac506e
commit
d0c759f2c2
@@ -24,6 +24,8 @@
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
require 'thread'
|
||||
require 'motion/project/paralel_builder'
|
||||
require 'motion/project/dependency'
|
||||
|
||||
module Motion; module Project;
|
||||
class Builder
|
||||
@@ -562,214 +564,4 @@ EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ParallelBuilder
|
||||
attr_accessor :files
|
||||
|
||||
def initialize(objs_build_dir, builder)
|
||||
@builders_count = begin
|
||||
if jobs = ENV['jobs']
|
||||
jobs.to_i
|
||||
else
|
||||
`/usr/sbin/sysctl -n machdep.cpu.thread_count`.strip.to_i
|
||||
end
|
||||
end
|
||||
@builders_count = 1 if @builders_count < 1
|
||||
|
||||
@builders = []
|
||||
@builders_count.times do
|
||||
queue = []
|
||||
th = Thread.new do
|
||||
sleep
|
||||
objs = []
|
||||
while path = queue.shift
|
||||
objs << builder.call(objs_build_dir, path)
|
||||
end
|
||||
queue.concat(objs)
|
||||
end
|
||||
@builders << [queue, th]
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
builder_i = 0
|
||||
@files.each do |path|
|
||||
@builders[builder_i][0] << path
|
||||
builder_i += 1
|
||||
builder_i = 0 if builder_i == @builders_count
|
||||
end
|
||||
|
||||
# Start build.
|
||||
@builders.each do |queue, th|
|
||||
sleep 0.01 while th.status != 'sleep'
|
||||
th.wakeup
|
||||
end
|
||||
@builders.each { |queue, th| th.join }
|
||||
@builders
|
||||
end
|
||||
|
||||
def objects
|
||||
objs = []
|
||||
builder_i = 0
|
||||
@files.each do |path|
|
||||
objs << @builders[builder_i][0].shift
|
||||
builder_i += 1
|
||||
builder_i = 0 if builder_i == @builders_count
|
||||
end
|
||||
objs
|
||||
end
|
||||
end
|
||||
|
||||
class Dependency
|
||||
begin
|
||||
require 'ripper'
|
||||
rescue LoadError
|
||||
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '../../ripper18')))
|
||||
require 'ripper'
|
||||
end
|
||||
|
||||
@file_paths = []
|
||||
|
||||
def initialize(paths, dependencies)
|
||||
@file_paths = paths.flatten.sort
|
||||
@dependencies = dependencies
|
||||
end
|
||||
|
||||
def cyclic?(dependencies, def_path, ref_path)
|
||||
deps = dependencies[def_path]
|
||||
if deps
|
||||
if deps.include?(ref_path)
|
||||
return true
|
||||
end
|
||||
deps.each do |file|
|
||||
return true if cyclic?(dependencies, file, ref_path)
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
def run
|
||||
consts_defined = {}
|
||||
consts_referred = {}
|
||||
@file_paths.each do |path|
|
||||
parser = Constant.new(File.read(path))
|
||||
parser.parse
|
||||
parser.defined.each do |const|
|
||||
consts_defined[const] = path
|
||||
end
|
||||
parser.referred.each do |const|
|
||||
consts_referred[const] ||= []
|
||||
consts_referred[const] << path
|
||||
end
|
||||
end
|
||||
|
||||
dependency = @dependencies.dup
|
||||
consts_defined.each do |const, def_path|
|
||||
if consts_referred[const]
|
||||
consts_referred[const].each do |ref_path|
|
||||
if def_path != ref_path
|
||||
if cyclic?(dependency, def_path, ref_path)
|
||||
# remove cyclic dependencies
|
||||
next
|
||||
end
|
||||
|
||||
dependency[ref_path] ||= []
|
||||
dependency[ref_path] << def_path
|
||||
dependency[ref_path].uniq!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return dependency
|
||||
end
|
||||
|
||||
class Constant < Ripper::SexpBuilder
|
||||
attr_accessor :defined
|
||||
attr_accessor :referred
|
||||
|
||||
def initialize(source)
|
||||
@defined = []
|
||||
@referred = []
|
||||
super
|
||||
end
|
||||
|
||||
def on_const_ref(args)
|
||||
args
|
||||
end
|
||||
|
||||
def on_var_field(args)
|
||||
args
|
||||
end
|
||||
|
||||
def on_var_ref(args)
|
||||
type, name, position = args
|
||||
if type == :@const
|
||||
@referred << name
|
||||
return [:referred, name]
|
||||
end
|
||||
end
|
||||
|
||||
def on_const_path_ref(parent, args)
|
||||
type, name, position = args
|
||||
if type == :@const
|
||||
@referred << name
|
||||
if parent && parent[0] == :referred
|
||||
register_referred_constants(parent[1], name)
|
||||
end
|
||||
end
|
||||
args
|
||||
end
|
||||
|
||||
def on_assign(const, *args)
|
||||
type, name, position = const
|
||||
if type == :@const
|
||||
@defined << name
|
||||
return [:defined, name]
|
||||
end
|
||||
end
|
||||
|
||||
def on_module(const, *args)
|
||||
handle_module_class_event(const, args)
|
||||
end
|
||||
|
||||
def on_class(const, *args)
|
||||
handle_module_class_event(const, args)
|
||||
end
|
||||
|
||||
def handle_module_class_event(const, *args)
|
||||
type, name, position = const
|
||||
if type == :@const
|
||||
@defined << name
|
||||
@referred.delete(name)
|
||||
children = args.flatten
|
||||
children.each_with_index do |key, i|
|
||||
if key == :defined
|
||||
register_defined_constants(name, children[i+1])
|
||||
end
|
||||
end
|
||||
return [:defined, name]
|
||||
end
|
||||
end
|
||||
|
||||
def register_defined_constants(parent, child)
|
||||
construct_nest_constants!(@defined, parent, child)
|
||||
end
|
||||
|
||||
def register_referred_constants(parent, child)
|
||||
construct_nest_constants!(@referred, parent, child)
|
||||
end
|
||||
|
||||
def construct_nest_constants!(consts, parent, child)
|
||||
nested = []
|
||||
consts.each do |const|
|
||||
if md = const.match(/^([^:]+)/)
|
||||
nested << "#{parent}::#{const}" if md[0] == child
|
||||
end
|
||||
end
|
||||
consts.concat(nested)
|
||||
end
|
||||
end
|
||||
end
|
||||
end; end
|
||||
|
||||
179
lib/motion/project/dependency.rb
Normal file
179
lib/motion/project/dependency.rb
Normal file
@@ -0,0 +1,179 @@
|
||||
# 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.
|
||||
|
||||
module Motion; module Project;
|
||||
class Dependency
|
||||
begin
|
||||
require 'ripper'
|
||||
rescue LoadError
|
||||
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '../../ripper18')))
|
||||
require 'ripper'
|
||||
end
|
||||
|
||||
@file_paths = []
|
||||
|
||||
def initialize(paths, dependencies)
|
||||
@file_paths = paths.flatten.sort
|
||||
@dependencies = dependencies
|
||||
end
|
||||
|
||||
def cyclic?(dependencies, def_path, ref_path)
|
||||
deps = dependencies[def_path]
|
||||
if deps
|
||||
if deps.include?(ref_path)
|
||||
return true
|
||||
end
|
||||
deps.each do |file|
|
||||
return true if cyclic?(dependencies, file, ref_path)
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
def run
|
||||
consts_defined = {}
|
||||
consts_referred = {}
|
||||
@file_paths.each do |path|
|
||||
parser = Constant.new(File.read(path))
|
||||
parser.parse
|
||||
parser.defined.each do |const|
|
||||
consts_defined[const] = path
|
||||
end
|
||||
parser.referred.each do |const|
|
||||
consts_referred[const] ||= []
|
||||
consts_referred[const] << path
|
||||
end
|
||||
end
|
||||
|
||||
dependency = @dependencies.dup
|
||||
consts_defined.each do |const, def_path|
|
||||
if consts_referred[const]
|
||||
consts_referred[const].each do |ref_path|
|
||||
if def_path != ref_path
|
||||
if cyclic?(dependency, def_path, ref_path)
|
||||
# remove cyclic dependencies
|
||||
next
|
||||
end
|
||||
|
||||
dependency[ref_path] ||= []
|
||||
dependency[ref_path] << def_path
|
||||
dependency[ref_path].uniq!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return dependency
|
||||
end
|
||||
|
||||
class Constant < Ripper::SexpBuilder
|
||||
attr_accessor :defined
|
||||
attr_accessor :referred
|
||||
|
||||
def initialize(source)
|
||||
@defined = []
|
||||
@referred = []
|
||||
super
|
||||
end
|
||||
|
||||
def on_const_ref(args)
|
||||
args
|
||||
end
|
||||
|
||||
def on_var_field(args)
|
||||
args
|
||||
end
|
||||
|
||||
def on_var_ref(args)
|
||||
type, name, position = args
|
||||
if type == :@const
|
||||
@referred << name
|
||||
return [:referred, name]
|
||||
end
|
||||
end
|
||||
|
||||
def on_const_path_ref(parent, args)
|
||||
type, name, position = args
|
||||
if type == :@const
|
||||
@referred << name
|
||||
if parent && parent[0] == :referred
|
||||
register_referred_constants(parent[1], name)
|
||||
end
|
||||
end
|
||||
args
|
||||
end
|
||||
|
||||
def on_assign(const, *args)
|
||||
type, name, position = const
|
||||
if type == :@const
|
||||
@defined << name
|
||||
return [:defined, name]
|
||||
end
|
||||
end
|
||||
|
||||
def on_module(const, *args)
|
||||
handle_module_class_event(const, args)
|
||||
end
|
||||
|
||||
def on_class(const, *args)
|
||||
handle_module_class_event(const, args)
|
||||
end
|
||||
|
||||
def handle_module_class_event(const, *args)
|
||||
type, name, position = const
|
||||
if type == :@const
|
||||
@defined << name
|
||||
@referred.delete(name)
|
||||
children = args.flatten
|
||||
children.each_with_index do |key, i|
|
||||
if key == :defined
|
||||
register_defined_constants(name, children[i+1])
|
||||
end
|
||||
end
|
||||
return [:defined, name]
|
||||
end
|
||||
end
|
||||
|
||||
def register_defined_constants(parent, child)
|
||||
construct_nest_constants!(@defined, parent, child)
|
||||
end
|
||||
|
||||
def register_referred_constants(parent, child)
|
||||
construct_nest_constants!(@referred, parent, child)
|
||||
end
|
||||
|
||||
def construct_nest_constants!(consts, parent, child)
|
||||
nested = []
|
||||
consts.each do |const|
|
||||
if md = const.match(/^([^:]+)/)
|
||||
nested << "#{parent}::#{const}" if md[0] == child
|
||||
end
|
||||
end
|
||||
consts.concat(nested)
|
||||
end
|
||||
end
|
||||
end
|
||||
end;end
|
||||
83
lib/motion/project/paralel_builder.rb
Normal file
83
lib/motion/project/paralel_builder.rb
Normal file
@@ -0,0 +1,83 @@
|
||||
# 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.
|
||||
|
||||
module Motion; module Project;
|
||||
class ParallelBuilder
|
||||
attr_accessor :files
|
||||
|
||||
def initialize(objs_build_dir, builder)
|
||||
@builders_count = begin
|
||||
if jobs = ENV['jobs']
|
||||
jobs.to_i
|
||||
else
|
||||
`/usr/sbin/sysctl -n machdep.cpu.thread_count`.strip.to_i
|
||||
end
|
||||
end
|
||||
@builders_count = 1 if @builders_count < 1
|
||||
|
||||
@builders = []
|
||||
@builders_count.times do
|
||||
queue = []
|
||||
th = Thread.new do
|
||||
sleep
|
||||
objs = []
|
||||
while path = queue.shift
|
||||
objs << builder.call(objs_build_dir, path)
|
||||
end
|
||||
queue.concat(objs)
|
||||
end
|
||||
@builders << [queue, th]
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
builder_i = 0
|
||||
@files.each do |path|
|
||||
@builders[builder_i][0] << path
|
||||
builder_i += 1
|
||||
builder_i = 0 if builder_i == @builders_count
|
||||
end
|
||||
|
||||
# Start build.
|
||||
@builders.each do |queue, th|
|
||||
sleep 0.01 while th.status != 'sleep'
|
||||
th.wakeup
|
||||
end
|
||||
@builders.each { |queue, th| th.join }
|
||||
@builders
|
||||
end
|
||||
|
||||
def objects
|
||||
objs = []
|
||||
builder_i = 0
|
||||
@files.each do |path|
|
||||
objs << @builders[builder_i][0].shift
|
||||
builder_i += 1
|
||||
builder_i = 0 if builder_i == @builders_count
|
||||
end
|
||||
objs
|
||||
end
|
||||
end
|
||||
end;end
|
||||
Reference in New Issue
Block a user