mruby_build.rake 4.49 KB
Newer Older
1 2 3
load 'tasks/mruby_build_gem.rake'
load 'tasks/mruby_build_commands.rake'

4 5 6
module MRuby
  class << self
    def targets
7
      @targets ||= {}
8 9 10
    end

    def each_target(&block)
11
      @targets.each do |key, target|
12 13 14 15 16
        target.instance_eval(&block)
      end
    end
  end

17 18 19 20
  class Toolchain
    class << self
      attr_accessor :toolchains
    end
21

22 23 24 25 26
    def initialize(name, &block)
      @name, @initializer = name.to_s, block
      MRuby::Toolchain.toolchains ||= {}
      MRuby::Toolchain.toolchains[@name] = self
    end
27

28 29 30
    def setup(conf)
      conf.instance_eval(&@initializer)
    end
31

32 33 34 35 36 37 38
    def self.load
      Dir.glob("#{File.dirname(__FILE__)}/toolchains/*.rake").each do |file|
        Kernel.load file
      end
    end
  end
  Toolchain.load
39

40 41 42 43 44 45 46 47
  class Build
    class << self
      attr_accessor :current
    end
    include Rake::DSL
    include LoadGems
    attr_accessor :name, :bins, :exts, :file_separator
    attr_reader :root, :libmruby, :gems
48

49 50 51
    COMPILERS = %w(cc cxx objc asm)
    COMMANDS = COMPILERS + %w(linker archiver yacc gperf git exts mrbc)
    attr_block MRuby::Build::COMMANDS
52

53
    Exts = Struct.new(:object, :executable, :library)
54

55
    def initialize(name='host', &block)
56
      @name = name.to_s
57

58 59
      unless MRuby.targets[@name]
        @root = File.expand_path("#{File.dirname(__FILE__)}/..")
60

61 62
        if ENV['OS'] == 'Windows_NT'
          @exts = Exts.new('.o', '.exe', '.a')
63
        else
64
          @exts = Exts.new('.o', '', '.a')
65
        end
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80

        @file_separator = '/'
        @cc = Command::Compiler.new(self, %w(.c))
        @cxx = Command::Compiler.new(self, %w(.cc .cxx .cpp))
        @objc = Command::Compiler.new(self, %w(.m))
        @asm = Command::Compiler.new(self, %w(.S .asm))
        @linker = Command::Linker.new(self)
        @archiver = Command::Archiver.new(self)
        @yacc = Command::Yacc.new(self)
        @gperf = Command::Gperf.new(self)
        @git = Command::Git.new(self)
        @mrbc = Command::Mrbc.new(self)

        @bins = %w(mruby mrbc mirb)
        @gems, @libmruby = [], []
81
        @build_mrbtest_lib_only = false
82 83

        MRuby.targets[@name] = self
84
      end
85

86 87
      MRuby::Build.current = MRuby.targets[@name]
      MRuby.targets[@name].instance_eval(&block)
88 89
    end

90
    def toolchain(name)
91 92 93
      tc = Toolchain.toolchains[name.to_s]
      fail "Unknown #{name} toolchain" unless tc
      tc.setup(self)
94 95 96 97 98 99 100
    end

    def build_dir
      "build/#{self.name}"
    end

    def mrbcfile
Yuichiro MASUI's avatar
Yuichiro MASUI committed
101
      MRuby.targets['host'].exefile("build/host/bin/mrbc")
102
    end
103 104 105 106 107

    def compilers
      COMPILERS.map do |c|
        instance_variable_get("@#{c}")
      end
108 109
    end

110 111
    def define_rules
      compilers.each do |compiler|
Yukihiro Matz Matsumoto's avatar
Yukihiro Matz Matsumoto committed
112 113 114 115 116
        if respond_to?(:enable_gems?) && enable_gems?
          compiler.defines -= %w(DISABLE_GEMS) 
        else
          compiler.defines += %w(DISABLE_GEMS) 
        end
117 118 119 120
        compiler.define_rules build_dir
      end
    end

121 122
    def filename(name)
      if name.is_a?(Array)
123
        name.flatten.map { |n| filename(n) }
124 125 126
      else
        '"%s"' % name.gsub('/', file_separator)
      end
127 128
    end

129 130
    def exefile(name)
      if name.is_a?(Array)
131
        name.flatten.map { |n| exefile(n) }
132 133 134
      else
        "#{name}#{exts.executable}"
      end
135 136
    end

137 138
    def objfile(name)
      if name.is_a?(Array)
139
        name.flatten.map { |n| objfile(n) }
140 141 142
      else
        "#{name}#{exts.object}"
      end
143 144
    end

145 146
    def libfile(name)
      if name.is_a?(Array)
147
        name.flatten.map { |n| libfile(n) }
148 149 150 151
      else
        "#{name}#{exts.library}"
      end
    end
152

153 154 155 156 157 158 159 160
    def build_mrbtest_lib_only
      @build_mrbtest_lib_only = true
    end

    def build_mrbtest_lib_only?
      @build_mrbtest_lib_only
    end

161 162 163 164 165 166
    def run_test
      puts ">>> Test #{name} <<<"
      mrbtest = exefile("#{build_dir}/test/mrbtest")
      sh "#{filename mrbtest}"
      puts 
    end
167 168 169 170 171 172

    def print_build_summary
      puts "================================================"
      puts "      Config Name: #{@name}"
      puts " Output Directory: #{self.build_dir}"
      puts "         Binaries: #{@bins.join(', ')}" unless @bins.empty?
mattn's avatar
mattn committed
173 174
      unless @gems.empty?
        puts "    Included Gems:"
Davide D'Agostino's avatar
Davide D'Agostino committed
175
        @gems.map(&:name).each do |name|
mattn's avatar
mattn committed
176 177 178
          puts "             #{name}"
        end
      end
179 180 181
      puts "================================================"
      puts
    end
182 183 184
  end # Build

  class CrossBuild < Build
185 186 187 188
    def run_test
      mrbtest = exefile("#{build_dir}/test/mrbtest")
      puts "You should run #{mrbtest} on target device."
      puts 
189 190 191
    end
  end # CrossBuild
end # MRuby