#!/bin/env ruby require 'rubygems' require 'thor' require 'gettext' require 'rbconfig' require 'fileutils' require 'delegate' $GIT_REPO_MRUBY="git://github.com/mruby/mruby.git" $HG_REPO_SDL2= { # 'SDL' => "http://hg.libsdl.org/SDL", 'SDL' => 'http://www.libsdl.org/release/SDL2-2.0.1.tar.gz', # 'SDL_image' => "http://hg.libsdl.org/SDL_image/", 'SDL_image' => 'http://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.0.tar.gz', # 'SDL_mixer' => "http://hg.libsdl.org/SDL_mixer/", 'SDL_mixer' => 'http://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.0.tar.gz', # 'SDL_ttf' => "http://hg.libsdl.org/SDL_ttf/" 'SDL_ttf' => 'http://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.12.tar.gz' } module CacheDir def cache_directory(basename) local_file = File.join(cache_path, basename) Dir.mkdir(cache_path) unless File.exists?(cache_path) yield(local_file) end end class Curl < SimpleDelegator include CacheDir def clone(dir, url, options = "") cache_directory(File.basename(url)) { |local_file| run("curl -C - %s -o %s %s" % [url, local_file, options]) run("tar -xzf %s" % [local_file]) run("mv %s %s" % [File.basename(url, ".tar.gz"), dir]) } end def pull(dir) end end class Git < SimpleDelegator include CacheDir def clone(dir, url, options = "") cache_directory(File.basename(dir)) {|local_path| run("git clone %s %s %s" % [url, options, local_path]) run("git clone %s %s %s" % [local_path, options, dir]) } end def pull(dir) Dir.chdir(dir) do run("git pull") end end end class Hg < SimpleDelegator include CacheDir def clone(dir, url, options = {}) cache_directory(File.basename(dir)) {|local_path| run("hg clone %s %s %s" % [url, options, local_path]) run("hg clone %s %s %s" % [url, options, dir]) } end def pull(dir) run("hg pull %s" % [dir]) end end module Build #directory for build code for the host def build_host_path File.join(app_path(), 'core', 'build_host') end def build_android_path File.join(app_path(), 'core', 'build_android') end def core_path File.join(app_path(), 'core') end def _configure_mruby(app, mruby_path) gems_common = [ 'mrbgems/mruby-math', 'mrbgems/mruby-enum-ext', 'mrbgems/mruby-random', 'mrbgems/mruby-proc-ext', 'mrbgems/mruby-exit', 'mrbgems/mruby-fiber', 'mrbgems/mruby-struct', 'mrbgems/mruby-sprintf', 'mrbgems/mruby-string-ext', 'mrbgems/mruby-object-ext', 'mrbgems/mruby-array-ext', 'mrbgems/mruby-hash-ext', 'mrbgems/mruby-symbol-ext', 'mrbgems/mruby-eval' ] gems_base = [ { :github => 'pichurriaj/mruby-sdl2', :branch => 'master', :cc => { 'cc.include_paths' => [File.join(build_host_path, 'include')], 'linker.libraries' => ['SDL2'], 'linker.library_paths' => [File.join(build_host_path, 'lib')] } }, 'mrbgems/mruby-print', 'mrbgems/mruby-bin-mirb', 'mrbgems/mruby-bin-mruby' ] | gems_common | [ { :github => 'iij/mruby-dir', :branch => 'master' }, { :github => 'iij/mruby-io', :branch => 'master' }, { :github => 'iij/mruby-tempfile', :branch => 'master' }, { :github => 'iij/mruby-require', :branch => 'master' } ] gems_android = [ { :github => 'pichurriaj/mruby-sdl2', :branch => 'master', :cc => { 'cc.include_paths' => [File.join(build_host_path, 'include'), File.join(ENV['ANDROID_NDK_HOME'], 'sources/android/support/include/'), ], #'linker.libraries' => [%w(SDL2)], #'linker.library_paths' => [File.join(build_android_path, 'libs', 'armeabi')] }, }, { :github => 'pichurriaj/mruby-print-android', :branch => 'master' } ] | gems_common _configure_mruby_host(mruby_path, gems_base) _configure_mruby_android(mruby_path, gems_android) if options[:build_android] inside(mruby_path) do run("rake clean && rake") end end #changes name logo and personalize the engine def _personalize_android(app, package) android_manifest_path = File.join(build_android_path, 'AndroidManifest.xml') gsub_file android_manifest_path, 'package="com.pichurriajuegos.muruby"', "package=\"%s\"" % package android_values_path = File.join(build_android_path, 'res', 'values', 'strings.xml') gsub_file android_values_path 'muruby', '%s' % app end def _configure_mruby_host(mruby_path, gems_base) _mruby_update_build_conf(mruby_path, gems_base, "MRuby::Build.new do |conf|\n", "#AUTOMATIC MRBGEMS --NO EDIT--\n") _mruby_update_build_conf(mruby_path, gems_base, "MRuby::Build.new('host-debug') do |conf|\n", "#AUTOMATIC MRBGEMS DEBUG --NO EDIT--\n") end def _configure_mruby_android(mruby_path, gems_base) key_to_append = "#AUTOMATIC GEMS ANDROID --NO EDIT--\n" insert_into_file File.join(mruby_path, 'build_config.rb'), :after => "# Define cross build settings\n" do out = "#AUTOMATIC CROSSBUILD ANDROID\n" out += "MRuby::CrossBuild.new('androideabi') do |conf|\n" out += "toolchain :androideabi\n" out += "conf.cc.defines = %w(DISABLE_STDIO)\n" out += "conf.bins = []\n" out += key_to_append out += "end\n" out end _mruby_update_build_conf(mruby_path, gems_base, key_to_append, "#AUTOMATIC ANDROID MBRGEMS\n") #copy skel android projct #@todo how do recursive?? run("rm -rf %s" % build_android_path) run("cp -ra %s %s" % [_skel_root('android-project'), build_android_path]) sdl_android_path = File.join(build_android_path, 'jni', 'SDL') repo('curl').clone(sdl_android_path, $HG_REPO_SDL2['SDL']) unless File.directory?(sdl_android_path) if options[:enable_sdl_image] sdl_image_android_path = File.join(build_android_path, 'jni', 'SDL_image') repo('curl').clone(sdl_image_android_path, $HG_REPO_SDL2['SDL_image']) unless File.directory?(sdl_image_android_path) sdl_image_android_path_mk = File.join(sdl_image_android_path, 'Android.mk') gsub_file sdl_image_android_path_mk, "SUPPORT_WEBP := true", "SUPPORT_WEBP := false" end if options[:enable_sdl_ttf] sdl_ttf_android_path = File.join(build_android_path, 'jni', 'SDL_ttf') repo('curl').clone(sdl_ttf_android_path, $HG_REPO_SDL2['SDL_ttf']) unless File.directory?(sdl_ttf_android_path) sdl_ttf_android_path_mk = File.join(sdl_ttf_android_path, 'Android.mk') gsub_file sdl_ttf_android_path_mk, "SUPPORT_JPG := true", "SUPPORT_JPG := false" end if options[:enable_sdl_mixer] sdl_mixer_android_path = File.join(build_android_path, 'jni', 'SDL_mixer') repo('curl').clone(sdl_mixer_android_path, $HG_REPO_SDL2['SDL_mixer']) unless File.directory?(sdl_mixer_android_path) sdl_mixer_android_path_mk = File.join(sdl_mixer_android_path, 'Android.mk') gsub_file sdl_mixer_android_path_mk, "SUPPORT_MOD_MODPLUG := true", "SUPPORT_MOD_MODPLUG := false" gsub_file sdl_mixer_android_path_mk, "SUPPORT_MOD_MIKMOD := true", "SUPPORT_MOD_MIKMOD := false" gsub_file sdl_mixer_android_path_mk, "SUPPORT_MP3_SMPEG := true", "SUPPORT_MP3_SMPEG := false" end end def _mruby_update_build_conf(mruby_path, gems_base, after, tag = "") insert_into_file File.join(mruby_path,"build_config.rb"), :after => after do gems_base.map do |gem| case gem when Hash out = tag out += "\nconf.gem :github => '%s', :branch => '%s' " % [gem[:github], gem[:branch]] if gem[:cc] out += "do |g|\n" out += gem[:cc].map{|k,v| case v when Array v.map{|vc| "\tg.#{k} << '#{vc}'"}.join("\n") else "\tg.#{k} = '#{v}'" end }.join("\n") out += "\nend\n" end out when String "conf.gem '%s'" % gem end end.join("\n") + "\n" end end def _configure_sdl2(app, sdl_path) #compile for host say("compiling %s for host" % sdl_path) @sdl_path = sdl_path sdl_lib_path = File.join(build_host_path, 'lib', 'libSDL2.so') if File.exists?(sdl_lib_path) say("Skipping SDL2...") return end inside(sdl_path) do #simulate system install run("mkdir include/SDL2") run("cp -ra include/* include/SDL2/") run("./configure --prefix=%s" % build_host_path, :capture => false) run("make") run("make install") run("make clean") end if !File.exists?(sdl_lib_path) raise RuntimeError, "Failed Compiling SDL2, build manually %s" % sdl_path end end def _configure_sdl2_image(app, sdl_path, sdl_image_path) #compile for host say("compiling %s for host" % sdl_image_path) sdl_image_lib_path = File.join(build_host_path, 'lib', 'libSDL2_image.so') if File.exists?(sdl_image_lib_path) say("Skipping SDL2 image..") return end inside(sdl_image_path) do run("./autogen.sh") run("./configure --prefix=%s --with-sdl-prefix=%s" % [build_host_path, build_host_path], :capture => false) run("make") run("make install") run("make clean") end if !File.exists?(sdl_image_lib_path) raise RuntimeError, "Failed Compiling SDL2 image, build manually %s" % sdl_image_path end end def _configure_sdl2_ttf(app, sdl_path, sdl_ttf_path) #compile for host say("compiling %s for host" % sdl_ttf_path) sdl_ttf_lib_path = File.join(build_host_path, 'lib', 'libSDL2_ttf.so') if File.exists?(sdl_ttf_lib_path) say("Skipping SDL2 ttf...") return end inside(sdl_ttf_path) do run("./autogen.sh") run("./configure --prefix=%s --with-sdl-prefix=%s" % [build_host_path, build_host_path], :capture => false) run("make") run("make install") run("make clean") end if !File.exists?(sdl_ttf_lib_path) raise RuntimeError, "Failed Compiling SDL2 ttf build manually %s" % sdl_ttf_path end end def _configure_sdl2_mixer(app, sdl_path, sdl_mixer_path) #compile for host say("compiling %s for host" % sdl_mixer_path) sdl_mixer_lib_path = File.join(build_host_path, 'lib', 'libSDL2_mixer.so') if File.exists?(sdl_mixer_lib_path) say("Skipping SDL2 mixer...") return end inside(sdl_mixer_path) do run("./autogen.sh") run("./configure --prefix=%s --with-sdl-prefix=%s" % [build_host_path, build_host_path], :capture => false) run("make") run("make install") end if !File.exists?(sdl_mixer_lib_path) raise RuntimeError, "Failed Compiling SDL2 mixer, build manually %s" % sdl_mixer_path end end end module Muruby class Game < Thor include Thor::Actions include Build @@app_path = nil def self.source_root File.dirname(__FILE__) end class_option :enable_sdl_mixer, :type => :boolean, :default => false, :desc => "Not Implemented yet" class_option :enable_sdl_ttf, :type => :boolean, :default => false, :desc => "Not implemented yet" class_option :enable_sdl_image, :type => :boolean, :default => false, :desc => "Not implemented yet" class_option :mruby_unstable, :type => :boolean, :default => true, :desc => "Use the master of mruby" class_option :build_android, :type => :boolean, :default => true, :desc => "Build android" method_option :package, :type => :string, :default => 'com.pichurriajuegos.muruby', :required => true, :banner => 'ej: com.pichurriajuegos.muruby the package' desc 'create ', "Create a directory structure with everything need for creating games for Android, and GNU/Linux. " def create(name) if options[:build_android] abort "Need enviroment variable ANDROID_NDK_HOME" unless ENV["ANDROID_NDK_HOME"] end @@app_path = File.absolute_path File.join(".", name) source_paths << _skel_root() _create_app(name) _create_core(name) end no_commands { def app_path @@app_path end def cache_path File.join(Dir.home, ".muruby") end def repo(type) case type when 'hg' Hg.new(self) when 'git' Git.new(self) when 'curl' Curl.new(self) else raise RuntimeError, "Invalid Cloner %s\n" % [type] end end } private def _create_app(name) empty_directory "#{name}/app" empty_directory "#{name}/app/game" copy_file "doc/README_game.md", "#{name}/app/game/README.md" copy_file "game/runtime.rb", "#{name}/app/game/runtime.rb" copy_file "Rakefile", "#{name}/app/Rakefile" copy_file "Gemfile", "#{name}/app/Gemfile" copy_file ".gitignore.tmpl", "#{name}/app/.gitignore" empty_directory "#{name}/app/resources" copy_file "doc/README_resources.md", "#{name}/app/resources/README.md" empty_directory "#{name}/app/deploy" copy_file "doc/README_deploy.md", "#{name}/app/deploy/README.md" end def _create_core(name) empty_directory "#{name}/core" #download sources sdl_path = "#{name}/core/SDL2" repo('curl').clone(sdl_path, $HG_REPO_SDL2['SDL']) unless File.directory?(sdl_path) sdl_image_path = "#{name}/core/SDL2_image" repo('curl').clone(sdl_image_path, $HG_REPO_SDL2['SDL_image']) unless File.directory?(sdl_image_path) if options[:enable_sdl_image] sdl_ttf_path = "#{name}/core/SDL2_ttf" repo('curl').clone(sdl_ttf_path, $HG_REPO_SDL2['SDL_ttf']) unless File.directory?(sdl_ttf_path) if options[:enable_sdl_ttf] sdl_mixer_path = "#{name}/core/SDL2_mixer" repo('curl').clone(sdl_mixer_path, $HG_REPO_SDL2['SDL_mixer']) unless File.directory?(sdl_mixer_path) if options[:enable_sdl_mixer] mruby_path = "#{name}/core/mruby" unless File.directory?(mruby_path) repo('git').clone(mruby_path, $GIT_REPO_MRUBY) end inside(mruby_path) do unless options[:mruby_unstable] run("git checkout 1.1.0") else run("git checkout master") end end #mruby-android #mruby-require #configure apps _configure_sdl2(name, sdl_path) _configure_sdl2_image(name, sdl_path, sdl_image_path) if options[:enable_sdl_image] _configure_sdl2_ttf(name, sdl_path, sdl_ttf_path) if options[:enable_sdl_ttf] _configure_sdl2_mixer(name, sdl_path, sdl_mixer_path) if options[:enable_sdl_mixer] _configure_mruby(name, mruby_path) end def _skel_root(path = nil) spec = Gem::Specification.find_by_name("muruby") spec.gem_dir unless path if path File.join(spec.gem_dir, 'skel', path) else File.join(spec.gem_dir, 'skel') end end end class Android < Thor include Thor::Actions def self.source_root File.dirname(__FILE__) end end class Gnu < Thor include Thor::Actions def self.source_root File.dirname(__FILE__) end end end Muruby::Game.start()