summaryrefslogtreecommitdiffhomepage
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mruby-core-ext.rb35
-rw-r--r--lib/mruby/build.rb50
-rw-r--r--lib/mruby/build/command.rb78
-rw-r--r--lib/mruby/build/load_gems.rb30
-rw-r--r--lib/mruby/gem.rb21
-rw-r--r--lib/mruby/lockfile.rb73
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