summaryrefslogtreecommitdiffhomepage
path: root/tasks/mruby_build.rake
blob: de9e556b44fe8cea7396aaa2346fbb70aa3200ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
module MRuby
  class << self
    attr_accessor :build

    def targets
      @targets ||= {}
    end

    def each_target(&block)
      @targets.each do |key, target|
        target.instance_eval(&block)
      end
    end
  end

  class Build
    include Rake::DSL
    attr_accessor :name
    attr_accessor :cc, :cflags, :includes
    attr_accessor :ld, :ldflags, :libs
    attr_accessor :ar
    attr_writer :cxx, :cxxflags
    attr_writer :objcc, :objcflags
    attr_writer :asm, :asmflags
    attr_accessor :bins
    attr_accessor :gperf, :yacc
    attr_accessor :cat, :git
    attr_reader :root, :gems
    attr_reader :libmruby

    def initialize(&block)
      @name ||= 'host'
      @root = File.expand_path("#{File.dirname(__FILE__)}/..")
      @cc, @cflags, @includes = 'gcc', %W(-DDISABLE_GEMS -MMD), %W(#{@root}/include)
      @ldflags, @libs = [], %w(-lm)
      @ar = 'ar'
      @cxxflags, @objccflags, @asmflags = [], [], []

      @yacc, @gperf = 'bison', 'gperf'
      @cat, @git = 'cat', 'git'

      @bins = %w(mruby mrbc mirb)

      @gems, @libmruby = [], []

      MRuby.targets[name.to_s] = self
      MRuby.build = self
      instance_eval(&block)
    end

    def cxx; @cxx || cc; end
    def cxxflags; !@cxxflags || @cxxflags.empty? ? cflags : @cxxflags; end

    def objcc; @objcc || cc; end
    def objcflags; !@objcflags || @objcflags.empty? ? cflags : @objcflags; end

    def asm; @asm || cc; end
    def asmflags; !@asmflags || @asmflags.empty? ? cflags : @asmflags; end

    def ld; @ld || cc; end

    def gem(gemdir)
      gemdir = load_external_gem(gemdir) if gemdir.is_a?(Hash)

      [@cflags, @cxxflags, @objcflags, @asmflags].each do |f|
        f.delete '-DDISABLE_GEMS' if f
      end
      Gem::processing_path = gemdir
      load File.join(gemdir, "mrbgem.rake")
    end

    def load_external_gem(params)
      if params[:github]
        params[:git] = "[email protected]:#{params[:github]}.git"
      end

      if params[:git]
        url = params[:git]
        gemdir = "build/mrbgems/#{url.match(/([-_\w]+)(\.[-_\w]+|)$/).to_a[1]}"
        return gemdir if File.exists?(gemdir)
        options = []
        options << "--branch \"#{params[:branch]}\"" if params[:branch]
        run_git_clone gemdir, url, options
        gemdir
      else
        fail "unknown gem option #{params}"
      end
    end

    def enable_gems?
      [email protected]?
    end

    def gemlibs
      enable_gems? ? ["#{build_dir}/mrbgems/gem_init.o"] + @gems.map{ |g| g.lib } : []
    end

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

    def mrbcfile
      @mrbcfile ||= exefile("build/host/bin/mrbc")
    end

    def compile_c(outfile, infile, flags=[], includes=[])
      FileUtils.mkdir_p File.dirname(outfile)
      flags = [cflags, gems.map { |g| g.mruby_cflags }, flags]
      flags << [self.includes, gems.map { |g| g.mruby_includes }, includes].flatten.map { |f| "-I#{filename f}" }
      sh "#{filename cc} #{flags.flatten.join(' ')} -o #{filename outfile} -c #{filename infile}"
    end
    
    def compile_cxx(outfile, infile, flags=[], includes=[])
      FileUtils.mkdir_p File.dirname(outfile)
      flags = [cxxflags, gems.map { |g| g.mruby_cflags }, flags]
      flags << [self.includes, gems.map { |g| g.mruby_includes }, includes].flatten.map { |f| "-I#{filename f}" }
      sh "#{filename cxx} #{flags.flatten.join(' ')} -o #{filename outfile} -c #{filename infile}"
    end
    
    def compile_objc(outfile, infile, flags=[], includes=[])
      FileUtils.mkdir_p File.dirname(outfile)
      flags = [objcflags, gems.map { |g| g.mruby_cflags }, flags]
      flags << [self.includes, gems.map { |g| g.mruby_includes }, includes].flatten.map { |f| "-I#{filename f}" }
      sh "#{filename objcc} #{flags.flatten.join(' ')} -o #{filename outfile} -c #{filename infile}"
    end
    
    def compile_asm(outfile, infile, flags=[], includes=[])
      FileUtils.mkdir_p File.dirname(outfile)
      flags = [asmflags, gems.map { |g| g.mruby_cflags }, flags]
      flags << [self.includes, gems.map { |g| g.mruby_includes }, includes].flatten.map { |f| "-I#{filename f}" }
      sh "#{filename asm} #{flags.flatten.join(' ')} -o #{filename outfile} -c #{filename infile}"
    end
    
    def compile_mruby(outfile, infiles, funcname)
      cmd = "#{cat} #{filenames [infiles]} | #{filename mrbcfile} -B#{funcname}"
      if outfile.is_a?(IO)
        IO.popen("#{cmd} -o- -", 'r') do |f|
          outfile.puts f.read
        end
      else
        FileUtils.mkdir_p File.dirname(outfile)
        sh "#{cmd} -o#{filename outfile} -"
      end
    end
    
    def link(outfile, objfiles, flags=[], libs=[])
      FileUtils.mkdir_p File.dirname(outfile)
      flags = [ldflags, flags]
      libs = [libs, self.libs]
      sh "#{filename ld} -o #{filename outfile} #{flags.join(' ')} #{filenames objfiles} #{libs.flatten.join(' ')}"
    end
    
    def archive(outfile, options, objfiles)
      FileUtils.mkdir_p File.dirname(outfile)
      sh "#{filename ar} #{options} #{filename outfile} #{filenames objfiles}"
    end

    def run_yacc(outfile, infile)
      FileUtils.mkdir_p File.dirname(outfile)
      sh "#{filename yacc} -o #{filename outfile} #{filename infile}"
    end

    def run_gperf(outfile, infile)
      FileUtils.mkdir_p File.dirname(outfile)
      sh %Q[#{filename gperf} -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" #{filename infile} > #{filename outfile}]
    end

    def run_git_clone(gemdir, giturl, options=[])
      sh "#{filename git} clone #{options.join(' ')} #{filename giturl} #{filename gemdir}"
    end


  end # Build

  class CrossBuild < Build
    def initialize(name, &block)
      @name ||= name
      super(&block)
    end
  end # CrossBuild
end # MRuby