summaryrefslogtreecommitdiffhomepage
path: root/tasks
diff options
context:
space:
mode:
Diffstat (limited to 'tasks')
-rw-r--r--tasks/mrbgem_spec.rake10
-rw-r--r--tasks/mrbgems_test.rake94
-rw-r--r--tasks/mruby_build.rake31
-rw-r--r--tasks/toolchains/androidndk.rake215
4 files changed, 245 insertions, 105 deletions
diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake
index d13e7733f..4fcfc8f83 100644
--- a/tasks/mrbgem_spec.rake
+++ b/tasks/mrbgem_spec.rake
@@ -52,9 +52,9 @@ module MRuby
MRuby::Build::COMMANDS.each do |command|
instance_variable_set("@#{command}", @build.send(command).clone)
end
- @linker = LinkerConfig.new([], [], [], [])
+ @linker = LinkerConfig.new([], [], [], [], [])
- @rbfiles = Dir.glob("#{dir}/mrblib/*.rb").sort
+ @rbfiles = Dir.glob("#{dir}/mrblib/**/*.rb").sort
@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
@@ -62,7 +62,7 @@ module MRuby
@generate_functions = !(@rbfiles.empty? && @objs.empty?)
@objs << objfile("#{build_dir}/gem_init") if @generate_functions
- @test_rbfiles = Dir.glob("#{dir}/test/*.rb")
+ @test_rbfiles = Dir.glob("#{dir}/test/**/*.rb")
@test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X"))
end
@@ -103,6 +103,10 @@ module MRuby
@dependencies << {:gem => name, :requirements => requirements, :default => default_gem}
end
+ def add_test_dependency(*args)
+ add_dependency(*args) if build.test_enabled?
+ end
+
def add_conflict(name, *req)
@conflicts << {:gem => name, :requirements => req.empty? ? nil : req}
end
diff --git a/tasks/mrbgems_test.rake b/tasks/mrbgems_test.rake
deleted file mode 100644
index 0ee508360..000000000
--- a/tasks/mrbgems_test.rake
+++ /dev/null
@@ -1,94 +0,0 @@
-MRuby.each_target do
- 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).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|
- File.expand_path(g.test_preload, dir)
- }.find {|file| File.exist?(file) }
-
- f.puts %Q[/*]
- f.puts %Q[ * This file contains a test code for #{g.name} gem.]
- f.puts %Q[ *]
- f.puts %Q[ * IMPORTANT:]
- f.puts %Q[ * This file was generated!]
- f.puts %Q[ * All manual changes will get lost.]
- f.puts %Q[ */]
- if test_preload.nil?
- f.puts %Q[extern const uint8_t mrbtest_assert_irep[];]
- else
- g.build.mrbc.run f, test_preload, "gem_test_irep_#{g.funcname}_preload"
- end
- g.test_rbfiles.flatten.each_with_index do |rbfile, i|
- g.build.mrbc.run f, rbfile, "gem_test_irep_#{g.funcname}_#{i}"
- end
- f.puts %Q[void mrb_#{g.funcname}_gem_test(mrb_state *mrb);] unless g.test_objs.empty?
- dep_list.each do |d|
- f.puts %Q[void GENERATED_TMP_mrb_#{d.funcname}_gem_init(mrb_state *mrb);]
- f.puts %Q[void GENERATED_TMP_mrb_#{d.funcname}_gem_final(mrb_state *mrb);]
- end
- f.puts %Q[void mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose);]
- f.puts %Q[void mrb_t_pass_result(mrb_state *dst, mrb_state *src);]
- f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb) {]
- unless g.test_rbfiles.empty?
- f.puts %Q[ mrb_state *mrb2;]
- unless g.test_args.empty?
- f.puts %Q[ mrb_value test_args_hash;]
- end
- f.puts %Q[ int ai;]
- 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);]
- end
- f.puts %Q[ mrb_init_test_driver(mrb2, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"))));]
- if test_preload.nil?
- f.puts %Q[ mrb_load_irep(mrb2, mrbtest_assert_irep);]
- else
- f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_preload);]
- end
- f.puts %Q[ if (mrb2->exc) {]
- f.puts %Q[ mrb_print_error(mrb2);]
- f.puts %Q[ exit(EXIT_FAILURE);]
- f.puts %Q[ }]
- f.puts %Q[ mrb_const_set(mrb2, mrb_obj_value(mrb2->object_class), mrb_intern_lit(mrb2, "GEMNAME"), mrb_str_new(mrb2, "#{g.name}", #{g.name.length}));]
-
- unless g.test_args.empty?
- f.puts %Q[ test_args_hash = mrb_hash_new_capa(mrb, #{g.test_args.length}); ]
- g.test_args.each do |arg_name, arg_value|
- escaped_arg_name = arg_name.gsub('\\', '\\\\\\\\').gsub('"', '\"')
- escaped_arg_value = arg_value.gsub('\\', '\\\\\\\\').gsub('"', '\"')
- f.puts %Q[ mrb_hash_set(mrb2, test_args_hash, mrb_str_new(mrb2, "#{escaped_arg_name.to_s}", #{escaped_arg_name.to_s.length}), mrb_str_new(mrb2, "#{escaped_arg_value.to_s}", #{escaped_arg_value.to_s.length})); ]
- end
- f.puts %Q[ mrb_const_set(mrb2, mrb_obj_value(mrb2->object_class), mrb_intern_lit(mrb2, "TEST_ARGS"), test_args_hash); ]
- end
-
- f.puts %Q[ mrb_#{g.funcname}_gem_test(mrb2);] if g.custom_test_init?
-
- f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_#{i});]
- f.puts %Q[ ]
-
- f.puts %Q[ mrb_t_pass_result(mrb, mrb2);]
- f.puts %Q[ mrb_close(mrb2);]
- f.puts %Q[ mrb_gc_arena_restore(mrb, ai);]
- end
- end
- f.puts %Q[}]
- end
- end
- end
-end
diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake
index 9f8b4eda5..cff45ddf8 100644
--- a/tasks/mruby_build.rake
+++ b/tasks/mruby_build.rake
@@ -26,8 +26,8 @@ module MRuby
MRuby::Toolchain.toolchains[@name] = self
end
- def setup(conf)
- conf.instance_eval(&@initializer)
+ def setup(conf,params={})
+ conf.instance_exec(conf, params, &@initializer)
end
def self.load
@@ -46,7 +46,7 @@ module MRuby
include LoadGems
attr_accessor :name, :bins, :exts, :file_separator, :build_dir, :gem_clone_dir
attr_reader :libmruby, :gems, :toolchains
- attr_writer :enable_bintest
+ attr_writer :enable_bintest, :enable_test
COMPILERS = %w(cc cxx objc asm)
COMMANDS = COMPILERS + %w(linker archiver yacc gperf git exts mrbc)
@@ -85,6 +85,8 @@ module MRuby
@build_mrbtest_lib_only = false
@cxx_abi_enabled = false
@cxx_exception_disabled = false
+ @enable_bintest = false
+ @enable_test = false
@toolchains = []
MRuby.targets[@name] = self
@@ -94,6 +96,7 @@ module MRuby
MRuby.targets[@name].instance_eval(&block)
build_mrbc_exec if name == 'host'
+ build_mrbtest if test_enabled?
end
def enable_debug
@@ -155,10 +158,10 @@ EOS
@enable_bintest
end
- def toolchain(name)
+ def toolchain(name, params={})
tc = Toolchain.toolchains[name.to_s]
fail "Unknown #{name} toolchain" unless tc
- tc.setup(self)
+ tc.setup(self, params)
@toolchains.unshift name.to_s
end
@@ -170,6 +173,18 @@ EOS
MRUBY_ROOT
end
+ def enable_test
+ @enable_test = true
+ end
+
+ def test_enabled?
+ @enable_test
+ end
+
+ def build_mrbtest
+ gem :core => 'mruby-test'
+ end
+
def build_mrbc_exec
gem :core => 'mruby-bin-mrbc'
end
@@ -249,10 +264,10 @@ EOS
def run_test
puts ">>> Test #{name} <<<"
- mrbtest = exefile("#{build_dir}/test/mrbtest")
+ mrbtest = exefile("#{build_dir}/bin/mrbtest")
sh "#{filename mrbtest.relative_path}#{$verbose ? ' -v' : ''}"
puts
- run_bintest if @enable_bintest
+ run_bintest if bintest_enabled?
end
def run_bintest
@@ -297,7 +312,7 @@ EOS
end
def run_test
- mrbtest = exefile("#{build_dir}/test/mrbtest")
+ mrbtest = exefile("#{build_dir}/bin/mrbtest")
if (@test_runner.command == nil)
puts "You should run #{mrbtest} on target device."
puts
diff --git a/tasks/toolchains/androidndk.rake b/tasks/toolchains/androidndk.rake
new file mode 100644
index 000000000..ccf1a0c4d
--- /dev/null
+++ b/tasks/toolchains/androidndk.rake
@@ -0,0 +1,215 @@
+
+class MRuby::Toolchain::AndroidNDK
+ DEFAULT_ARCH = 'armeabi'
+ DEFAULT_PLATFORM = 'android-14'
+ DEFAULT_TOOLCHAIN = :gcc
+ DEFAULT_NDK_HOMES = %w{
+ /usr/local/opt/android-ndk
+ }
+ TOOLCHAINS = [:gcc, :clang]
+ ARCHITECTURES = %w{
+ armeabi armeabi-v7a arm64-v8a
+ mips mips64
+ x86 x86_64
+ }
+
+ class AndroidNDKHomeNotFound < StandardError
+ def message
+ <<-EOM
+Couldn't find Android NDK Home.
+Set ANDROID_NDK_HOME environment variable or set :ndk_home parameter
+ EOM
+ end
+ end
+
+ attr_reader :params
+
+ def initialize(params)
+ @params = params
+ end
+
+ def home_path
+ @home_path ||= Pathname(
+ params[:ndk_home] ||
+ ENV['ANDROID_NDK_HOME'] ||
+ DEFAULT_NDK_HOMES.find{ |path| File.directory?(path) } ||
+ raise(AndroidNDKHomeNotFound)
+ )
+ end
+
+ def arch
+ params.fetch(:arch){ DEFAULT_ARCH }
+ end
+
+ def platform
+ params.fetch(:platform){ DEFAULT_PLATFORM }
+ end
+
+ def toolchain
+ params.fetch(:toolchain){ DEFAULT_TOOLCHAIN }
+ end
+
+ def toolchain_version
+ params.fetch(:toolchain_version) do
+ test = case toolchain
+ when :gcc
+ case arch
+ when /armeabi/
+ 'arm-linux-androideabi-*'
+ when /arm64/
+ 'aarch64-linux-android-*'
+ when /mips64/
+ 'mips64el-linux-android-*'
+ when /mips/
+ 'mipsel-linux-android-*'
+ when /x86_64/
+ 'x86_64-*'
+ when /x86/
+ 'x86-*'
+ end
+ when :clang
+ 'llvm-*'
+ end
+
+ Dir[home_path.join('toolchains',test)].map{|t| t.match(/-(\d+\.\d+)$/); $1.to_f }.max
+ end
+ end
+
+ def toolchain_path
+ prefix = case toolchain
+ when :clang then 'llvm-'
+ when :gcc
+ case arch
+ when /armeabi/ then 'arm-linux-androideabi-'
+ when /arm64/ then 'aarch64-linux-android-'
+ when /x86_64/ then 'x86_64-'
+ when /x86/ then 'x86-'
+ when /mips64/ then 'mips64el-linux-android-'
+ when /mips/ then 'mipsel-linux-android-'
+ end
+ end
+ home_path.join('toolchains', prefix + toolchain_version.to_s, 'prebuilt', host_platform)
+ end
+
+ def sysroot
+ path = case arch
+ when /armeabi/ then 'arch-arm'
+ when /arm64/ then 'arch-arm64'
+ when /x86_64/ then 'arch-x86_64'
+ when /x86/ then 'arch-x86'
+ when /mips64/ then 'arch-mips64'
+ when /mips/ then 'arch-mips'
+ end
+
+ home_path.join('platforms', platform, path).to_s
+ end
+
+ def bin(command)
+ command = command.to_s
+
+ if toolchain == :gcc
+ command = case arch
+ when /armeabi/ then 'arm-linux-androideabi-'
+ when /arm64/ then 'aarch64-linux-android-'
+ when /x86_64/ then 'x86_64-linux-android-'
+ when /x86/ then 'i686-linux-android-'
+ when /mips64/ then 'mips64el-linux-android-'
+ when /mips/ then 'mipsel-linux-android-'
+ end + command
+ end
+
+ toolchain_path.join('bin',command).to_s
+ end
+
+ def cc
+ case toolchain
+ when :gcc then bin(:gcc)
+ when :clang then bin(:clang)
+ end
+ end
+
+ def cflags
+ flags = []
+
+ case toolchain
+ when :gcc
+ flags += %W(-ffunction-sections -funwind-tables -no-canonical-prefixes)
+ flags += %W(-D__android__ -mandroid --sysroot="#{sysroot}")
+ case arch
+ when /arm64/
+ flags += %W(-fpic -fstack-protector-strong)
+ when 'armeabi-v7a-hard'
+ flags += %W(-fpic -fstack-protector-strong -march=armv7-a -mhard-float -D_NDK_MATH_NO_SOFTFP=1 -mfpu=vfpv3-d16)
+ when 'armeabi-v7a'
+ flags += %W(-fpic -fstack-protector-strong -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16)
+ when /arm/
+ flags += %W(-fpic -fstack-protector-strong -march=armv5te -mtune=xscale -msoft-float)
+ when /mips/
+ flags += %W(-fpic -fno-strict-aliasing -finline-functions -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers)
+ when /x86/
+ flags += %W(-fstack-protector-strong)
+ end
+ when :clang
+ end
+
+ flags
+ end
+
+ def ld
+ cc
+ end
+
+ def ldflags
+ flags = []
+ case toolchain
+ when :gcc
+ flags += %W(-no-canonical-prefixes)
+ flags += %W(-D__android__ -mandroid --sysroot="#{sysroot}")
+ case arch
+ when 'armeabi-v7a-hard'
+ flags += %W(-march=armv7-a -Wl,--fix-cortex-a8 -Wl,--no-warn-mismatch -lm_hard)
+ when 'armeabi-v7a'
+ flags += %W(-march=armv7-a -Wl,--fix-cortex-a8)
+ end
+ end
+ end
+
+ def ar
+ case toolchain
+ when :gcc then bin(:ar)
+ when :clang then bin('llvm-ar')
+ end
+ end
+
+ def host_platform
+ case RUBY_PLATFORM
+ when /cygwin|mswin|mingw|bccwin|wince|emx/i
+ 'windows'
+ when /x86_64-darwin/i
+ 'darwin-x86_64'
+ when /darwin/i
+ 'darwin-x86'
+ when /x86_64-linux/i
+ 'linux-x86_64'
+ when /linux/i
+ 'linux-x86'
+ else
+ raise NotImplementedError, "Unknown host platform (#{RUBY_PLATFORM})"
+ end
+ end
+end
+
+MRuby::Toolchain.new(:androidndk) do |conf, params|
+ ndk = MRuby::Toolchain::AndroidNDK.new(params)
+
+ toolchain ndk.toolchain
+
+ [conf.cc, conf.cxx, conf.objc, conf.asm].each do |cc|
+ cc.command = ndk.cc
+ cc.flags = ndk.cflags
+ end
+ conf.linker.command = ndk.ld
+ conf.linker.flags = ndk.ldflags
+ conf.archiver.command = ndk.ar
+end
+