diff options
| -rw-r--r-- | .travis.yml | 4 | ||||
| -rw-r--r-- | build_config.rb | 3 | ||||
| -rw-r--r-- | include/mruby.h | 4 | ||||
| -rwxr-xr-x | minirake | 129 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mirb/tools/mirb/mirb.c | 6 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mruby-config/mrbgem.rake | 5 | ||||
| -rw-r--r-- | mrbgems/mruby-compiler/mrbgem.rake | 4 | ||||
| -rw-r--r-- | mrbgems/mruby-io/mrbgem.rake | 3 | ||||
| -rw-r--r-- | mrbgems/mruby-test/mrbgem.rake | 18 | ||||
| -rw-r--r-- | tasks/libmruby.rake | 1 | ||||
| -rw-r--r-- | tasks/mrbgems.rake | 1 |
11 files changed, 147 insertions, 31 deletions
diff --git a/.travis.yml b/.travis.yml index 56c54914a..d8c22c046 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ sudo: false matrix: include: - os: linux - sudo: 9000 + sudo: false - os: osx osx_image: xcode7.1 @@ -17,4 +17,4 @@ addons: env: MRUBY_CONFIG=travis_config.rb env: MRUBY_CONFIG=travis_config.rb -script: "./minirake all test" +script: "./minirake -j4 all test" diff --git a/build_config.rb b/build_config.rb index 1429837be..7f52b5ee9 100644 --- a/build_config.rb +++ b/build_config.rb @@ -8,7 +8,8 @@ MRuby::Build.new do |conf| toolchain :gcc end - enable_debug + # Turn on `enable_debug` for better debugging + # enable_debug # Use mrbgems # conf.gem 'examples/mrbgems/ruby_extension_example' diff --git a/include/mruby.h b/include/mruby.h index 8c4f9280b..b0bfe78b5 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -994,8 +994,8 @@ MRB_API mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, size_t len); #define mrb_str_new_lit(mrb, lit) mrb_str_new_static(mrb, (lit), mrb_strlen_lit(lit)) #ifdef _WIN32 -char* mrb_utf8_from_locale(const char *p, int len); -char* mrb_locale_from_utf8(const char *p, int len); +MRB_API char* mrb_utf8_from_locale(const char *p, int len); +MRB_API char* mrb_locale_from_utf8(const char *p, int len); #define mrb_locale_free(p) free(p) #define mrb_utf8_free(p) free(p) #else @@ -6,6 +6,12 @@ require 'getoptlong' require 'fileutils' +require 'fiber' + +$rake_fiber_table = {} +$rake_jobs = 1 +$rake_failed = [] +$rake_root_fiber = Fiber.current class String def ext(newext='') @@ -86,14 +92,31 @@ module MiniRake @name.to_s end + def done?; @done end + def running?; @running end + # Invoke the task if it is needed. Prerequites are invoked first. def invoke puts "Invoke #{name} (already=[#{@already_invoked}], needed=[#{needed?}])" if $trace return if @already_invoked - @already_invoked = true prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten - prerequisites.each { |n| Task[n].invoke } - execute if needed? + prerequisites.each do |n| + t = Task[n] + unless t.done? + return prerequisites.select{|v| v = Task[v]; v && (!v.done? || !v.running?) } + end + end + + @already_invoked = true + + if needed? + @running = true + return Fiber.new do + self.execute + end + end + + @done = true end # Execute the actions associated with this task. @@ -103,6 +126,8 @@ module MiniRake unless $dryrun @actions.each { |act| act.call(self) } end + @done = true + @running = false end # Is this task needed? @@ -281,7 +306,19 @@ module MiniRake # Run the system command +cmd+. def sh(cmd) puts cmd if $verbose - system(cmd) or fail "Command Failed: [#{cmd}]" + + if $rake_jobs == 1 || Fiber.current == $rake_root_fiber + system(cmd) or fail "Command Failed: [#{cmd}]" + return + end + + pid = Process.spawn(cmd) + $rake_fiber_table[pid] = { + fiber: Fiber.current, + command: cmd, + process_waiter: Process.detach(pid) + } + Fiber.yield end def desc(text) @@ -329,7 +366,9 @@ class RakeApp ['--verbose', '-v', GetoptLong::NO_ARGUMENT, "Log message to standard output."], ['--directory', '-C', GetoptLong::REQUIRED_ARGUMENT, - "Change executing directory of rakefiles."] + "Change executing directory of rakefiles."], + ['--jobs', '-j', GetoptLong::REQUIRED_ARGUMENT, + 'Execute rake with parallel jobs.'] ] # Create a RakeApp object. @@ -422,6 +461,8 @@ class RakeApp exit when '--directory' Dir.chdir value + when '--jobs' + $rake_jobs = [value.to_i, 1].max else fail "Unknown option: #{opt}" end @@ -447,12 +488,12 @@ class RakeApp end here = Dir.pwd end - tasks = [] + root_tasks = [] ARGV.each do |task_name| if /^(\w+)=(.*)/.match(task_name) ENV[$1] = $2 else - tasks << task_name + root_tasks << task_name end end puts "(in #{Dir.pwd})" @@ -461,20 +502,82 @@ class RakeApp if $show_tasks display_tasks else - tasks.push("default") if tasks.size == 0 - tasks.each do |task_name| - MiniRake::Task[task_name].invoke + root_tasks.push("default") if root_tasks.empty? + # revese tasks for popping + root_tasks.reverse! + + tasks = [] + until root_tasks.empty? + root_name = root_tasks.pop + tasks << root_name + until tasks.empty? + task_name = tasks.pop + t = MiniRake::Task[task_name] + f = t.invoke + + # append additional tasks to task queue + if f.kind_of?(Array) + tasks.push(*f) + tasks.uniq! + end + + unless f.kind_of? Fiber + tasks.insert 0, task_name unless t.done? + if root_name == task_name + wait_process + end + next + end + + f.resume + end end + + wait_process until $rake_fiber_table.empty? + end + rescue Exception => e + begin + $rake_failed << e + wait_process until $rake_fiber_table.empty? + rescue Exception => next_e + e = next_e + retry end - rescue Exception => ex - puts "rake aborted!" + end + + return if $rake_failed.empty? + + puts "rake aborted!" + $rake_failed.each do |ex| puts ex.message if $trace puts ex.backtrace.join("\n") else puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || "" end - exit 1 + end + exit 1 + end + + def wait_process + sleep 0.1 + + exited = [] + $rake_fiber_table.each do |pid, v| + exited << pid unless v[:process_waiter].alive? + end + + exited.each do |pid| + ent = $rake_fiber_table.delete pid + st = ent[:process_waiter].value + + # ignore process that isn't created by `sh` method + return if ent.nil? + + if st.exitstatus != 0 + raise "Command Failed: [#{ent[:command]}]" + end + ent[:fiber].resume end end end diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index 5b77f5bac..5c2b58da5 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -661,6 +661,12 @@ done: if (args.rfp) fclose(args.rfp); mrb_free(mrb, args.argv); + if (args.libv) { + for (i = 0; i < args.libc; ++i) { + mrb_free(mrb, args.libv[i]); + } + mrb_free(mrb, args.libv); + } mrbc_context_free(mrb, cxt); mrb_close(mrb); diff --git a/mrbgems/mruby-bin-mruby-config/mrbgem.rake b/mrbgems/mruby-bin-mruby-config/mrbgem.rake index 66d6ef80b..32ae2164b 100644 --- a/mrbgems/mruby-bin-mruby-config/mrbgem.rake +++ b/mrbgems/mruby-bin-mruby-config/mrbgem.rake @@ -19,9 +19,10 @@ MRuby.each_target do mruby_config_path = "#{build_dir}/bin/#{mruby_config}" @bins << mruby_config - file mruby_config_path => libfile("#{build_dir}/lib/libmruby") do |t| + make_cfg = "#{build_dir}/lib/libmruby.flags.mak" + file mruby_config_path => [libfile("#{build_dir}/lib/libmruby"), make_cfg] do |t| FileUtils.copy "#{File.dirname(__FILE__)}/#{mruby_config}", t.name - config = Hash[open("#{build_dir}/lib/libmruby.flags.mak").read.split("\n").map {|x| a = x.split(/\s*=\s*/, 2); [a[0], a[1].gsub('\\"', '"') ]}] + config = Hash[open(make_cfg).read.split("\n").map {|x| a = x.split(/\s*=\s*/, 2); [a[0], a[1].gsub('\\"', '"') ]}] IO.write(t.name, File.open(t.name) {|f| f.read.gsub (/echo (MRUBY_CFLAGS|MRUBY_LIBS|MRUBY_LDFLAGS_BEFORE_LIBS|MRUBY_LDFLAGS|MRUBY_LIBMRUBY_PATH)/) {|x| config[$1].empty? ? '' : "echo #{config[$1]}"} }) diff --git a/mrbgems/mruby-compiler/mrbgem.rake b/mrbgems/mruby-compiler/mrbgem.rake index 3bf6d6ae3..e9e0cc2c7 100644 --- a/mrbgems/mruby-compiler/mrbgem.rake +++ b/mrbgems/mruby-compiler/mrbgem.rake @@ -23,10 +23,10 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec| cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"] end end - file objfile("#{current_build_dir}/core/y.tab") => lex_def # Parser - file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y"] do |t| + file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y", lex_def] do |t| + FileUtils.mkdir_p File.dirname t.name yacc.run t.name, t.prerequisites.first end diff --git a/mrbgems/mruby-io/mrbgem.rake b/mrbgems/mruby-io/mrbgem.rake index 50fa49678..d79964590 100644 --- a/mrbgems/mruby-io/mrbgem.rake +++ b/mrbgems/mruby-io/mrbgem.rake @@ -4,7 +4,7 @@ MRuby::Gem::Specification.new('mruby-io') do |spec| spec.summary = 'IO and File class' spec.cc.include_paths << "#{build.root}/src" - + case RUBY_PLATFORM when /mingw|mswin/ spec.linker.libraries += ['Ws2_32'] @@ -14,4 +14,5 @@ MRuby::Gem::Specification.new('mruby-io') do |spec| if build.kind_of?(MRuby::CrossBuild) && %w(x86_64-w64-mingw32 i686-w64-mingw32).include?(build.host_target) spec.linker.libraries += ['ws2_32'] end + spec.add_test_dependency 'mruby-time', core: 'mruby-time' end diff --git a/mrbgems/mruby-test/mrbgem.rake b/mrbgems/mruby-test/mrbgem.rake index 27c635a5d..11d780f75 100644 --- a/mrbgems/mruby-test/mrbgem.rake +++ b/mrbgems/mruby-test/mrbgem.rake @@ -23,7 +23,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| mrbtest_objs = [] driver_obj = objfile("#{build_dir}/driver") - driver = "#{spec.dir}/driver.c" + # driver = "#{spec.dir}/driver.c" assert_c = "#{build_dir}/assert.c" assert_rb = "#{MRUBY_ROOT}/test/assert.rb" @@ -31,7 +31,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| mrbtest_objs << assert_lib file assert_lib => assert_c - file assert_c => assert_rb do |t| + file assert_c => [assert_rb, build.mrbcfile] do |t| open(t.name, 'w') do |f| mrbc.run f, assert_rb, 'mrbtest_assert_irep' end @@ -45,7 +45,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| dep_list = build.gems.tsort_dependencies(g.test_dependencies, gem_table).select(&:generate_functions) file test_rbobj => g.test_rbireps - file g.test_rbireps => [g.test_rbfiles].flatten do |t| + file g.test_rbireps => [g.test_rbfiles, build.mrbcfile].flatten do |t| FileUtils.mkdir_p File.dirname(t.name) open(t.name, 'w') do |f| g.print_gem_test_header(f) @@ -146,7 +146,8 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| gem_flags_after_libraries = build.gems.map { |g| g.linker.flags_after_libraries } gem_libraries = build.gems.map { |g| g.linker.libraries } gem_library_paths = build.gems.map { |g| g.linker.library_paths } - build.linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries + build.linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, + gem_flags_before_libraries, gem_flags_after_libraries end end @@ -163,13 +164,14 @@ MRuby::Gem::Specification.new('mruby-test') do |spec| nil end current_gem_list = build.gems.map(&:name).join("\n") - if active_gem_list != current_gem_list - File.write active_gems_path, current_gem_list + task active_gems_path do |t| + FileUtils.mkdir_p File.dirname t.name + File.write t.name, current_gem_list end - file clib => active_gems_path + file clib => active_gems_path if active_gem_list != current_gem_list file mlib => clib - file clib => init do |t| + file clib => [init, build.mrbcfile] do |_t| _pp "GEN", "*.rb", "#{clib.relative_path}" FileUtils.mkdir_p File.dirname(clib) open(clib, 'w') do |f| diff --git a/tasks/libmruby.rake b/tasks/libmruby.rake index 540aa3eb5..b6ef29986 100644 --- a/tasks/libmruby.rake +++ b/tasks/libmruby.rake @@ -4,6 +4,7 @@ MRuby.each_target do end file "#{build_dir}/lib/libmruby.flags.mak" => [__FILE__, libfile("#{build_dir}/lib/libmruby")] do |t| + FileUtils.mkdir_p File.dirname t.name open(t.name, 'w') do |f| f.puts "MRUBY_CFLAGS = #{cc.all_flags}" diff --git a/tasks/mrbgems.rake b/tasks/mrbgems.rake index 1b964524c..64e5b0353 100644 --- a/tasks/mrbgems.rake +++ b/tasks/mrbgems.rake @@ -53,6 +53,7 @@ MRuby.each_target do # legal documents file "#{build_dir}/LEGAL" => [MRUBY_CONFIG, __FILE__] do |t| + FileUtils.mkdir_p File.dirname t.name open(t.name, 'w+') do |f| f.puts <<LEGAL Copyright (c) #{Time.now.year} mruby developers |
