diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/mruby-core-ext.rb | 35 | ||||
| -rw-r--r-- | lib/mruby/build.rb | 50 | ||||
| -rw-r--r-- | lib/mruby/build/command.rb | 78 | ||||
| -rw-r--r-- | lib/mruby/build/load_gems.rb | 30 | ||||
| -rw-r--r-- | lib/mruby/gem.rb | 21 | ||||
| -rw-r--r-- | lib/mruby/lockfile.rb | 73 |
6 files changed, 198 insertions, 89 deletions
diff --git a/lib/mruby-core-ext.rb b/lib/mruby-core-ext.rb index 4c6d3ca76..7b78bfa91 100644 --- a/lib/mruby-core-ext.rb +++ b/lib/mruby-core-ext.rb @@ -1,3 +1,5 @@ +autoload :Pathname, 'pathname' + class Object class << self def attr_block(*syms) @@ -16,39 +18,6 @@ class String def relative_path relative_path_from(Dir.pwd) end - - # Compatible with 1.9 on 1.8 - def %(params) - if params.is_a?(Hash) - str = self.clone - params.each do |k, v| - str.gsub!("%{#{k}}") { v } - end - str - else - if params.is_a?(Array) - sprintf(self, *params) - else - sprintf(self, params) - end - end - end -end - -class Symbol - # Compatible with 1.9 on 1.8 - def to_proc - proc { |obj, *args| obj.send(self, *args) } - end -end - -module Enumerable - # Compatible with 1.9 on 1.8 - def each_with_object(memo) - return to_enum :each_with_object, memo unless block_given? - each { |obj| yield obj, memo } - memo - end end $pp_show = true diff --git a/lib/mruby/build.rb b/lib/mruby/build.rb index 63125d4fa..375b2933a 100644 --- a/lib/mruby/build.rb +++ b/lib/mruby/build.rb @@ -1,7 +1,11 @@ +require "mruby-core-ext" require "mruby/build/load_gems" require "mruby/build/command" module MRuby + autoload :Gem, "mruby/gem" + autoload :Lockfile, "mruby/lockfile" + class << self def targets @targets ||= {} @@ -22,7 +26,6 @@ module MRuby def initialize(name, &block) @name, @initializer = name.to_s, block - MRuby::Toolchain.toolchains ||= {} MRuby::Toolchain.toolchains[@name] = self end @@ -30,13 +33,8 @@ module MRuby conf.instance_exec(conf, params, &@initializer) end - def self.load - Dir.glob("#{MRUBY_ROOT}/tasks/toolchains/*.rake").each do |file| - Kernel.load file - end - end + self.toolchains = {} end - Toolchain.load class Build class << self @@ -70,7 +68,7 @@ module MRuby @file_separator = '/' @build_dir = "#{build_dir}/#{@name}" - @gem_clone_dir = "#{build_dir}/mrbgems" + @gem_clone_dir = "#{build_dir}/repos/#{@name}" @cc = Command::Compiler.new(self, %w(.c)) @cxx = Command::Compiler.new(self, %w(.cc .cxx .cpp)) @objc = Command::Compiler.new(self, %w(.m)) @@ -90,6 +88,7 @@ module MRuby @cxx_abi_enabled = false @enable_bintest = false @enable_test = false + @enable_lock = true @toolchains = [] MRuby.targets[@name] = self @@ -118,6 +117,14 @@ module MRuby @enable_debug = true end + def disable_lock + @enable_lock = false + end + + def lock_enabled? + Lockfile.enabled? && @enable_lock + end + def disable_cxx_exception if @cxx_exception_enabled or @cxx_abi_enabled raise "cxx_exception already enabled" @@ -155,8 +162,8 @@ module MRuby compilers.each { |c| c.defines += %w(MRB_ENABLE_CXX_EXCEPTION MRB_ENABLE_CXX_ABI) c.flags << c.cxx_compile_flag + c.flags = c.flags.flatten - c.cxx_invalid_flags.flatten } - compilers.each { |c| c.flags << c.cxx_compile_flag } linker.command = cxx.command if toolchains.find { |v| v == 'gcc' } @cxx_abi_enabled = true end @@ -196,10 +203,15 @@ EOS end def toolchain(name, params={}) - tc = Toolchain.toolchains[name.to_s] - fail "Unknown #{name} toolchain" unless tc + name = name.to_s + tc = Toolchain.toolchains[name] || begin + path = "#{MRUBY_ROOT}/tasks/toolchains/#{name}.rake" + fail "Unknown #{name} toolchain" unless File.exist?(path) + load path + Toolchain.toolchains[name] + end tc.setup(self, params) - @toolchains.unshift name.to_s + @toolchains.unshift name end def primary_toolchain @@ -226,6 +238,10 @@ EOS gem :core => 'mruby-bin-mrbc' end + def locks + Lockfile.build(@name) + end + def mrbcfile return @mrbcfile if @mrbcfile @@ -255,7 +271,7 @@ EOS if name.is_a?(Array) name.flatten.map { |n| filename(n) } else - '"%s"' % name.gsub('/', file_separator) + name.gsub('/', file_separator) end end @@ -263,15 +279,18 @@ EOS if name.is_a?(Array) name.flatten.map { |n| cygwin_filename(n) } else - '"%s"' % `cygpath -w "#{filename(name)}"`.strip + `cygpath -w "#{filename(name)}"`.strip end end def exefile(name) if name.is_a?(Array) name.flatten.map { |n| exefile(n) } - else + elsif File.extname(name).empty? "#{name}#{exts.executable}" + else + # `name` sometimes have (non-standard) extension (e.g. `.bat`). + name end end @@ -311,6 +330,7 @@ EOS end def run_bintest + puts ">>> Bintest #{name} <<<" targets = @gems.select { |v| File.directory? "#{v.dir}/bintest" }.map { |v| filename v.dir } targets << filename(".") if File.directory? "./bintest" sh "ruby test/bintest.rb#{verbose_flag} #{targets.join ' '}" diff --git a/lib/mruby/build/command.rb b/lib/mruby/build/command.rb index 694b4a24c..bff250c93 100644 --- a/lib/mruby/build/command.rb +++ b/lib/mruby/build/command.rb @@ -41,7 +41,7 @@ module MRuby class Command::Compiler < Command attr_accessor :flags, :include_paths, :defines, :source_exts attr_accessor :compile_options, :option_define, :option_include_path, :out_ext - attr_accessor :cxx_compile_flag, :cxx_exception_flag + attr_accessor :cxx_compile_flag, :cxx_exception_flag, :cxx_invalid_flags def initialize(build, source_exts=[]) super(build) @@ -53,6 +53,7 @@ module MRuby @option_include_path = '-I%s' @option_define = '-D%s' @compile_options = '%{flags} -o %{outfile} -c %{infile}' + @cxx_invalid_flags = [] end alias header_search_paths include_paths @@ -67,8 +68,8 @@ module MRuby path && build.filename("#{path}/#{name}").sub(/^"(.*)"$/, '\1') end - def all_flags(_defineds=[], _include_paths=[], _flags=[]) - define_flags = [defines, _defineds].flatten.map{ |d| option_define % d } + def all_flags(_defines=[], _include_paths=[], _flags=[]) + define_flags = [defines, _defines].flatten.map{ |d| option_define % d } include_path_flags = [include_paths, _include_paths].flatten.map do |f| if MRUBY_BUILD_HOST_IS_CYGWIN option_include_path % cygwin_filename(f) @@ -79,14 +80,14 @@ module MRuby [flags, define_flags, include_path_flags, _flags].flatten.join(' ') end - def run(outfile, infile, _defineds=[], _include_paths=[], _flags=[]) + def run(outfile, infile, _defines=[], _include_paths=[], _flags=[]) FileUtils.mkdir_p File.dirname(outfile) _pp "CC", infile.relative_path, outfile.relative_path if MRUBY_BUILD_HOST_IS_CYGWIN - _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags), + _run compile_options, { :flags => all_flags(_defines, _include_paths, _flags), :infile => cygwin_filename(infile), :outfile => cygwin_filename(outfile) } else - _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags), + _run compile_options, { :flags => all_flags(_defines, _include_paths, _flags), :infile => filename(infile), :outfile => filename(outfile) } end end @@ -127,13 +128,40 @@ module MRuby end private + + # + # === Example of +.d+ file + # + # ==== Without <tt>-MP</tt> compiler flag + # + # /build/host/src/array.o: \ + # /src/array.c \ + # /include/mruby/common.h \ + # /include/mruby/value.h \ + # /src/value_array.h + # + # ==== With <tt>-MP</tt> compiler flag + # + # /build/host/src/array.o: \ + # /src/array.c \ + # /include/mruby/common.h \ + # /include/mruby/value.h \ + # /src/value_array.h + # + # /include/mruby/common.h: + # + # /include/mruby/value.h: + # + # /src/value_array.h: + # def get_dependencies(file) file = file.ext('d') unless File.extname(file) == '.d' + deps = [] if File.exist?(file) - File.read(file).gsub("\\\n ", "").scan(/^\S+:\s+(.+)$/).flatten.map {|s| s.split(' ') }.flatten - else - [] - end + [ MRUBY_CONFIG ] + File.foreach(file){|line| deps << $1 if /^ +(.*?)(?: *\\)?$/ =~ line} + deps.uniq! + end + deps << MRUBY_CONFIG end end @@ -243,15 +271,16 @@ module MRuby class Command::Git < Command attr_accessor :flags - attr_accessor :clone_options, :pull_options, :checkout_options + attr_accessor :clone_options, :pull_options, :checkout_options, :reset_options def initialize(build) super @command = 'git' @flags = %w[] @clone_options = "clone %{flags} %{url} %{dir}" - @pull_options = "pull" - @checkout_options = "checkout %{checksum_hash}" + @pull_options = "--git-dir '%{repo_dir}/.git' --work-tree '%{repo_dir}' pull" + @checkout_options = "--git-dir '%{repo_dir}/.git' --work-tree '%{repo_dir}' checkout %{checksum_hash}" + @reset_options = "--git-dir '%{repo_dir}/.git' --work-tree '%{repo_dir}' reset %{checksum_hash}" end def run_clone(dir, url, _flags = []) @@ -260,19 +289,26 @@ module MRuby end def run_pull(dir, url) - root = Dir.pwd - Dir.chdir dir _pp "GIT PULL", url, dir.relative_path - _run pull_options - Dir.chdir root + _run pull_options, { :repo_dir => dir } end def run_checkout(dir, checksum_hash) - root = Dir.pwd - Dir.chdir dir _pp "GIT CHECKOUT", checksum_hash - _run checkout_options, { :checksum_hash => checksum_hash } - Dir.chdir root + _run checkout_options, { :checksum_hash => checksum_hash, :repo_dir => dir } + end + + def run_reset_hard(dir, checksum_hash) + _pp "GIT RESET", checksum_hash + _run reset_options, { :checksum_hash => checksum_hash, :repo_dir => dir } + end + + def commit_hash(dir) + `#{@command} --git-dir '#{dir}/.git' --work-tree '#{dir}' rev-parse --verify HEAD`.strip + end + + def current_branch(dir) + `#{@command} --git-dir '#{dir}/.git' --work-tree '#{dir}' rev-parse --abbrev-ref HEAD`.strip end end diff --git a/lib/mruby/build/load_gems.rb b/lib/mruby/build/load_gems.rb index 723be6ffc..7f2c7202b 100644 --- a/lib/mruby/build/load_gems.rb +++ b/lib/mruby/build/load_gems.rb @@ -83,11 +83,18 @@ module MRuby # by default the 'master' branch is used branch = params[:branch] ? params[:branch] : 'master' + lock = locks[url] if lock_enabled? + if File.exist?(gemdir) if $pull_gems git.run_pull gemdir, url - else - gemdir + # Jump to the top of the branch + git.run_checkout(gemdir, branch) + git.run_reset_hard gemdir, "origin/#{branch}" + elsif params[:checksum_hash] + git.run_reset_hard(gemdir, params[:checksum_hash]) + elsif lock + git.run_reset_hard(gemdir, lock['commit']) end else options = [params[:options]] || [] @@ -96,14 +103,21 @@ module MRuby options << "--depth 1" unless params[:checksum_hash] FileUtils.mkdir_p "#{gem_clone_dir}" git.run_clone gemdir, url, options - end - if params[:checksum_hash] # Jump to the specified commit - git.run_checkout gemdir, params[:checksum_hash] - else - # Jump to the top of the branch - git.run_checkout gemdir, branch if $pull_gems + if params[:checksum_hash] + git.run_reset_hard gemdir, params[:checksum_hash] + elsif lock + git.run_reset_hard gemdir, lock['commit'] + end + end + + if lock_enabled? + locks[url] = { + 'url' => url, + 'branch' => git.current_branch(gemdir), + 'commit' => git.commit_hash(gemdir), + } end gemdir << "/#{params[:path]}" if params[:path] diff --git a/lib/mruby/gem.rb b/lib/mruby/gem.rb index b32b1eed2..6cb067b91 100644 --- a/lib/mruby/gem.rb +++ b/lib/mruby/gem.rb @@ -1,7 +1,6 @@ -require 'pathname' require 'forwardable' -require 'tsort' -require 'shellwords' +autoload :TSort, 'tsort' +autoload :Shellwords, 'shellwords' module MRuby module Gem @@ -112,17 +111,13 @@ module MRuby end def add_test_dependency(*args) - add_dependency(*args) if build.test_enabled? + add_dependency(*args) if build.test_enabled? || build.bintest_enabled? end def add_conflict(name, *req) @conflicts << {:gem => name, :requirements => req.empty? ? nil : req} end - def self.bin=(bin) - @bins = [bin].flatten - end - def build_dir "#{build.build_dir}/mrbgems/#{name}" end @@ -271,16 +266,18 @@ module MRuby # ~> compare algorithm # # Example: + # ~> 2 means >= 2.0.0 and < 3.0.0 # ~> 2.2 means >= 2.2.0 and < 3.0.0 - # ~> 2.2.0 means >= 2.2.0 and < 2.3.0 + # ~> 2.2.2 means >= 2.2.2 and < 2.3.0 def twiddle_wakka_ok?(other) gr_or_eql = (self <=> other) >= 0 - still_minor = (self <=> other.skip_minor) < 0 - gr_or_eql and still_minor + still_major_or_minor = (self <=> other.skip_major_or_minor) < 0 + gr_or_eql and still_major_or_minor end - def skip_minor + def skip_major_or_minor a = @ary.dup + a << 0 if a.size == 1 # ~> 2 can also be represented as ~> 2.0 a.slice!(-1) a[-1] = a[-1].succ a diff --git a/lib/mruby/lockfile.rb b/lib/mruby/lockfile.rb new file mode 100644 index 000000000..ce1442a89 --- /dev/null +++ b/lib/mruby/lockfile.rb @@ -0,0 +1,73 @@ +autoload :YAML, 'yaml' + +module MRuby + autoload :Source, 'mruby/source' + + class Lockfile + class << self + def enable + @enabled = true + end + + def disable + @enabled = false + end + + def enabled? + @enabled + end + + def build(target_name) + instance.build(target_name) + end + + def write + instance.write if enabled? + end + + def instance + @instance ||= new("#{MRUBY_CONFIG}.lock") + end + end + + def initialize(filename) + @filename = filename + end + + def build(target_name) + read[target_name] ||= {} + end + + def write + locks = {"mruby_version" => mruby} + locks["builds"] = @builds if @builds + File.write(@filename, YAML.dump(locks)) + end + + private + + def read + @builds ||= if File.exist?(@filename) + YAML.load_file(@filename)["builds"] || {} + else + {} + end + end + + def mruby + mruby = { + 'version' => MRuby::Source::MRUBY_VERSION, + 'release_no' => MRuby::Source::MRUBY_RELEASE_NO, + } + + git_dir = "#{MRUBY_ROOT}/.git" + if File.directory?(git_dir) + mruby['git_commit'] = `git --git-dir '#{git_dir}' --work-tree '#{MRUBY_ROOT}' rev-parse --verify HEAD`.strip + end + + mruby + end + + enable + end +end |
