summaryrefslogtreecommitdiffhomepage
path: root/tasks
diff options
context:
space:
mode:
Diffstat (limited to 'tasks')
-rw-r--r--tasks/benchmark.rake91
-rw-r--r--tasks/mrbgem_spec.rake13
-rw-r--r--tasks/mrbgems.rake21
-rw-r--r--tasks/mrbgems_test.rake9
-rw-r--r--tasks/mruby_build.rake51
-rw-r--r--tasks/mruby_build_gem.rake2
-rw-r--r--tasks/ruby_ext.rake11
-rw-r--r--tasks/toolchains/gcc.rake2
-rw-r--r--tasks/toolchains/visualcpp.rake2
9 files changed, 182 insertions, 20 deletions
diff --git a/tasks/benchmark.rake b/tasks/benchmark.rake
new file mode 100644
index 000000000..84e69ebee
--- /dev/null
+++ b/tasks/benchmark.rake
@@ -0,0 +1,91 @@
+module MRuby
+ BENCHMARK_REPEAT = 4
+end
+
+$dat_files = []
+
+def bm_files
+ Dir.glob("#{MRUBY_ROOT}/benchmark/bm_*.rb")
+end
+
+def build_config_name
+ if ENV['MRUBY_CONFIG']
+ File.basename(ENV['MRUBY_CONFIG'], '.rb').gsub('build_config_', '')
+ else
+ "build"
+ end
+end
+
+def plot_file
+ File.join(MRUBY_ROOT, 'benchmark', "#{build_config_name}.png")
+end
+
+def plot
+ opts_file = "#{MRUBY_ROOT}/benchmark/plot.gpl"
+ opts = File.read(opts_file).each_line.to_a.map(&:strip).join(';')
+
+ dat_files = $dat_files.group_by {|f| File.dirname(f).split(File::SEPARATOR)[-1]}
+
+ opts += ";set output '#{plot_file}'"
+
+ opts += ';plot '
+
+ opts += dat_files.keys.map do |data_file|
+ %Q['-' u 2:3:4:xtic(1) w hist title columnheader(1)]
+ end.join(',')
+ opts += ';'
+
+ cmd = %Q{gnuplot -p -e "#{opts}"}
+
+ IO.popen(cmd, 'w') do |p|
+ dat_files.each do |target_name, bm_files|
+ p.puts target_name.gsub('_', '-')
+ bm_files.each do |bm_file|
+ p.write File.read(bm_file)
+ end
+ p.puts "e"
+ end
+ end
+end
+
+
+MRuby.each_target do |target|
+ next if target.name == 'host'
+ mruby_bin = "#{target.build_dir}/bin/mruby"
+
+ bm_files.each do |bm_file|
+ bm_name = File.basename bm_file, ".rb"
+
+ dat_dir = File.join('benchmark', build_config_name, target.name)
+ dat_file = File.join(dat_dir, "#{bm_name}.dat")
+ $dat_files << dat_file
+
+ directory dat_dir
+
+ file dat_file => [bm_file, dat_dir, mruby_bin] do |task|
+ print bm_name
+ puts "..."
+
+ data = (0...MRuby::BENCHMARK_REPEAT).map do |n|
+ str = %x{(time -f "%e %S %U" #{mruby_bin} #{bm_file}) 2>&1 >/dev/null}
+ str.split(' ').map(&:to_f)
+ end
+
+ File.open(task.name, "w") do |f|
+ data = data.map {|_,r,s| (r + s) / 2.0}
+ min = data.min
+ max = data.max
+ avg = data.inject(&:+) / data.size
+ f.puts "#{bm_name.gsub('_', '-')} #{avg} #{min} #{max}"
+ end
+ end
+ end
+end
+
+file plot_file => $dat_files do
+ plot
+end
+
+task :benchmark => plot_file do
+ plot
+end
diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake
index 745b2f29d..e6e17e182 100644
--- a/tasks/mrbgem_spec.rake
+++ b/tasks/mrbgem_spec.rake
@@ -36,6 +36,8 @@ module MRuby
attr_accessor :export_include_paths
+ attr_reader :generate_functions
+
attr_block MRuby::Build::COMMANDS
def initialize(name, &block)
@@ -56,7 +58,9 @@ module MRuby
@objs = Dir.glob("#{dir}/src/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
objfile(f.relative_path_from(@dir).to_s.pathmap("#{build_dir}/%X"))
end
- @objs << objfile("#{build_dir}/gem_init")
+
+ @generate_functions = !(@rbfiles.empty? && @objs.empty?)
+ @objs << objfile("#{build_dir}/gem_init") if @generate_functions
@test_rbfiles = Dir.glob("#{dir}/test/*.rb")
@test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
@@ -89,7 +93,7 @@ module MRuby
compiler.include_paths << "#{dir}/include" if File.directory? "#{dir}/include"
end
- define_gem_init_builder
+ define_gem_init_builder if @generate_functions
end
def add_dependency(name, *requirements)
@@ -179,6 +183,7 @@ module MRuby
def print_gem_test_header(f)
print_gem_comment(f)
+ f.puts %Q[#include <stdio.h>]
f.puts %Q[#include <stdlib.h>]
f.puts %Q[#include "mruby.h"]
f.puts %Q[#include "mruby/irep.h"]
@@ -293,7 +298,7 @@ module MRuby
@ary.empty?
end
- def generate_gem_table
+ def generate_gem_table build
gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res }
default_gems = []
@@ -376,7 +381,7 @@ module MRuby
end
def check(build)
- gem_table = generate_gem_table
+ gem_table = generate_gem_table build
@ary = tsort_dependencies gem_table.keys, gem_table, true
diff --git a/tasks/mrbgems.rake b/tasks/mrbgems.rake
index 2d17be931..1cf05ee4e 100644
--- a/tasks/mrbgems.rake
+++ b/tasks/mrbgems.rake
@@ -10,6 +10,17 @@ MRuby.each_target do
file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG, __FILE__] do |t|
FileUtils.mkdir_p "#{build_dir}/mrbgems"
open(t.name, 'w') do |f|
+ gem_func_gems = gems.select { |g| g.generate_functions }
+ gem_func_decls = gem_func_gems.each_with_object('') do |g, s|
+ s << "void GENERATED_TMP_mrb_#{g.funcname}_gem_init(mrb_state*);\n" \
+ "void GENERATED_TMP_mrb_#{g.funcname}_gem_final(mrb_state*);\n"
+ end
+ gem_init_calls = gem_func_gems.each_with_object('') do |g, s|
+ s << " GENERATED_TMP_mrb_#{g.funcname}_gem_init(mrb);\n"
+ end
+ gem_final_calls = gem_func_gems.each_with_object('') do |g, s|
+ s << " GENERATED_TMP_mrb_#{g.funcname}_gem_final(mrb);\n"
+ end
f.puts %Q[/*]
f.puts %Q[ * This file contains a list of all]
f.puts %Q[ * initializing methods which are]
@@ -22,19 +33,17 @@ MRuby.each_target do
f.puts %Q[]
f.puts %Q[#include "mruby.h"]
f.puts %Q[]
- f.puts %Q[#{gems.map{|g| "void GENERATED_TMP_mrb_%s_gem_init(mrb_state* mrb);" % g.funcname}.join("\n")}]
- f.puts %Q[]
- f.puts %Q[#{gems.map{|g| "void GENERATED_TMP_mrb_%s_gem_final(mrb_state* mrb);" % g.funcname}.join("\n")}]
+ f.write gem_func_decls
f.puts %Q[]
f.puts %Q[static void]
f.puts %Q[mrb_final_mrbgems(mrb_state *mrb) {]
- f.puts %Q[#{gems.map{|g| "GENERATED_TMP_mrb_%s_gem_final(mrb);" % g.funcname}.join("\n")}]
+ f.write gem_final_calls
f.puts %Q[}]
f.puts %Q[]
f.puts %Q[void]
f.puts %Q[mrb_init_mrbgems(mrb_state *mrb) {]
- f.puts %Q[#{gems.map{|g| "GENERATED_TMP_mrb_%s_gem_init(mrb);" % g.funcname}.join("\n")}]
- f.puts %Q[mrb_state_atexit(mrb, mrb_final_mrbgems);]
+ f.write gem_init_calls
+ f.puts %Q[ mrb_state_atexit(mrb, mrb_final_mrbgems);] unless gem_final_calls.empty?
f.puts %Q[}]
end
end
diff --git a/tasks/mrbgems_test.rake b/tasks/mrbgems_test.rake
index b732fa772..0ee508360 100644
--- a/tasks/mrbgems_test.rake
+++ b/tasks/mrbgems_test.rake
@@ -1,13 +1,14 @@
MRuby.each_target do
- gem_table = gems.generate_gem_table
+ gem_table = gems.generate_gem_table self
gems.each do |g|
test_rbobj = g.test_rbireps.ext(exts.object)
g.test_objs << test_rbobj
- dep_list = gems.tsort_dependencies g.test_dependencies, gem_table
+ dep_list = 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 + [File.join(g.dir, 'mrbgem.rake'), g.build.mrbcfile, __FILE__, "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake"] do |t|
+ FileUtils.mkdir_p File.dirname(t.name)
open(t.name, 'w') do |f|
g.print_gem_test_header(f)
test_preload = g.test_preload and [g.dir, MRUBY_ROOT].map {|dir|
@@ -46,6 +47,10 @@ MRuby.each_target do
g.test_rbfiles.count.times do |i|
f.puts %Q[ ai = mrb_gc_arena_save(mrb);]
f.puts %Q[ mrb2 = mrb_open_core(mrb_default_allocf, NULL);]
+ f.puts %Q[ if (mrb2 == NULL) {]
+ f.puts %Q[ fprintf(stderr, "Invalid mrb_state, exiting \%s", __FUNCTION__);]
+ f.puts %Q[ exit(EXIT_FAILURE);]
+ f.puts %Q[ }]
dep_list.each do |d|
f.puts %Q[ GENERATED_TMP_mrb_#{d.funcname}_gem_init(mrb2);]
f.puts %Q[ mrb_state_atexit(mrb2, GENERATED_TMP_mrb_#{d.funcname}_gem_final);]
diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake
index 06bb2a4e6..50bed0fbe 100644
--- a/tasks/mruby_build.rake
+++ b/tasks/mruby_build.rake
@@ -8,6 +8,7 @@ module MRuby
end
def each_target(&block)
+ return to_enum(:each_target) if block.nil?
@targets.each do |key, target|
target.instance_eval(&block)
end
@@ -79,7 +80,7 @@ module MRuby
@git = Command::Git.new(self)
@mrbc = Command::Mrbc.new(self)
- @bins = %w(mrbc)
+ @bins = []
@gems, @libmruby = MRuby::Gem::List.new, []
@build_mrbtest_lib_only = false
@cxx_abi_enabled = false
@@ -91,10 +92,17 @@ module MRuby
MRuby::Build.current = MRuby.targets[@name]
MRuby.targets[@name].instance_eval(&block)
+
+ build_mrbc_exec if name == 'host'
end
def enable_debug
- compilers.each { |c| c.defines += %w(MRB_DEBUG) }
+ compilers.each do |c|
+ c.defines += %w(MRB_DEBUG)
+ if toolchains.any? { |toolchain| toolchain == "gcc" }
+ c.flags += %w(-g3 -O0)
+ end
+ end
@mrbc.compile_options += ' -g'
end
@@ -109,10 +117,37 @@ module MRuby
def enable_cxx_abi
return if @cxx_exception_disabled or @cxx_abi_enabled
compilers.each { |c| c.defines += %w(MRB_ENABLE_CXX_EXCEPTION) }
- linker.command = cxx.command
+ linker.command = cxx.command if toolchains.find { |v| v == 'gcc' }
@cxx_abi_enabled = true
end
+ def compile_as_cxx src, cxx_src, obj = nil, includes = []
+ src = File.absolute_path src
+ cxx_src = File.absolute_path cxx_src
+ obj = objfile(cxx_src) if obj.nil?
+
+ file cxx_src => [src, __FILE__] do |t|
+ File.open(t.name, 'w') do |f|
+ f.write <<EOS
+#define __STDC_CONSTANT_MACROS
+#define __STDC_LIMIT_MACROS
+
+extern "C" {
+#include "#{src}"
+}
+
+#{File.basename(src) == 'error.c'? 'mrb_int mrb_jmpbuf::jmpbuf_id = 0;' : ''}
+EOS
+ end
+ end
+
+ file obj => cxx_src do |t|
+ cxx.run t.name, t.prerequisites.first, [], ["#{MRUBY_ROOT}/src"] + includes
+ end
+
+ obj
+ end
+
def enable_bintest
@enable_bintest = true
end
@@ -136,8 +171,16 @@ module MRuby
MRUBY_ROOT
end
+ def build_mrbc_exec
+ gem :core => 'mruby-bin-mrbc'
+ end
+
def mrbcfile
- MRuby.targets[@name].exefile("#{MRuby.targets[@name].build_dir}/bin/mrbc")
+ return @mrbcfile if @mrbcfile
+
+ mrbc_build = MRuby.targets['host']
+ gems.each { |v| mrbc_build = self if v.name == 'mruby-bin-mrbc' }
+ @mrbcfile = mrbc_build.exefile("#{mrbc_build.build_dir}/bin/mrbc")
end
def compilers
diff --git a/tasks/mruby_build_gem.rake b/tasks/mruby_build_gem.rake
index 5d2dc030c..dbbade487 100644
--- a/tasks/mruby_build_gem.rake
+++ b/tasks/mruby_build_gem.rake
@@ -31,7 +31,7 @@ module MRuby
return nil unless Gem.current
Gem.current.dir = gemdir
- Gem.current.build = MRuby::Build.current
+ Gem.current.build = self.is_a?(MRuby::Build) ? self : MRuby::Build.current
Gem.current.build_config_initializer = block
gems << Gem.current
diff --git a/tasks/ruby_ext.rake b/tasks/ruby_ext.rake
index 38dfff0a3..4c6d3ca76 100644
--- a/tasks/ruby_ext.rake
+++ b/tasks/ruby_ext.rake
@@ -22,7 +22,7 @@ class String
if params.is_a?(Hash)
str = self.clone
params.each do |k, v|
- str.gsub!("%{#{k}}", v)
+ str.gsub!("%{#{k}}") { v }
end
str
else
@@ -42,6 +42,15 @@ class Symbol
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
if $verbose.nil?
diff --git a/tasks/toolchains/gcc.rake b/tasks/toolchains/gcc.rake
index 7edf93642..fb1455812 100644
--- a/tasks/toolchains/gcc.rake
+++ b/tasks/toolchains/gcc.rake
@@ -1,7 +1,7 @@
MRuby::Toolchain.new(:gcc) do |conf|
[conf.cc, conf.objc, conf.asm].each do |cc|
cc.command = ENV['CC'] || 'gcc'
- cc.flags = [ENV['CFLAGS'] || %w(-g -std=gnu99 -O3 -Wall -Werror-implicit-function-declaration -Wdeclaration-after-statement)]
+ cc.flags = [ENV['CFLAGS'] || %w(-g -std=gnu99 -O3 -Wall -Werror-implicit-function-declaration -Wdeclaration-after-statement -Wwrite-strings)]
cc.defines = %w(DISABLE_GEMS)
cc.option_include_path = '-I%s'
cc.option_define = '-D%s'
diff --git a/tasks/toolchains/visualcpp.rake b/tasks/toolchains/visualcpp.rake
index 8838f8a41..eaf013068 100644
--- a/tasks/toolchains/visualcpp.rake
+++ b/tasks/toolchains/visualcpp.rake
@@ -11,7 +11,7 @@ MRuby::Toolchain.new(:visualcpp) do |conf|
[conf.cxx].each do |cxx|
cxx.command = ENV['CXX'] || 'cl.exe'
- cxx.flags = [ENV['CXXFLAGS'] || ENV['CFLAGS'] || %w(/c /nologo /W3 /Zi /MD /O2 /EHsc /D_CRT_SECURE_NO_WARNINGS)]
+ cxx.flags = [ENV['CXXFLAGS'] || ENV['CFLAGS'] || %w(/c /nologo /W3 /Zi /MD /O2 /EHs /D_CRT_SECURE_NO_WARNINGS)]
cxx.defines = %w(DISABLE_GEMS MRB_STACK_EXTEND_DOUBLING)
cxx.option_include_path = '/I%s'
cxx.option_define = '/D%s'