source: EcnlProtoTool/trunk/mruby-2.1.1/lib/mruby/build.rb@ 439

Last change on this file since 439 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 11.0 KB
Line 
1require "mruby-core-ext"
2require "mruby/build/load_gems"
3require "mruby/build/command"
4
5module MRuby
6 autoload :Gem, "mruby/gem"
7 autoload :Lockfile, "mruby/lockfile"
8
9 class << self
10 def targets
11 @targets ||= {}
12 end
13
14 def each_target(&block)
15 return to_enum(:each_target) if block.nil?
16 @targets.each do |key, target|
17 target.instance_eval(&block)
18 end
19 end
20 end
21
22 class Toolchain
23 class << self
24 attr_accessor :toolchains
25 end
26
27 def initialize(name, &block)
28 @name, @initializer = name.to_s, block
29 MRuby::Toolchain.toolchains[@name] = self
30 end
31
32 def setup(conf,params={})
33 conf.instance_exec(conf, params, &@initializer)
34 end
35
36 self.toolchains = {}
37 end
38
39 class Build
40 class << self
41 attr_accessor :current
42 end
43 include Rake::DSL
44 include LoadGems
45 attr_accessor :name, :bins, :exts, :file_separator, :build_dir, :gem_clone_dir
46 attr_reader :libmruby_objs, :gems, :toolchains, :gem_dir_to_repo_url
47 attr_writer :enable_bintest, :enable_test
48
49 alias libmruby libmruby_objs
50
51 COMPILERS = %w(cc cxx objc asm)
52 COMMANDS = COMPILERS + %w(linker archiver yacc gperf git exts mrbc)
53 attr_block MRuby::Build::COMMANDS
54
55 Exts = Struct.new(:object, :executable, :library)
56
57 def initialize(name='host', build_dir=nil, &block)
58 @name = name.to_s
59
60 unless MRuby.targets[@name]
61 if ENV['OS'] == 'Windows_NT'
62 @exts = Exts.new('.o', '.exe', '.a')
63 else
64 @exts = Exts.new('.o', '', '.a')
65 end
66
67 build_dir = build_dir || ENV['MRUBY_BUILD_DIR'] || "#{MRUBY_ROOT}/build"
68
69 @file_separator = '/'
70 @build_dir = "#{build_dir}/#{@name}"
71 @gem_clone_dir = "#{build_dir}/repos/#{@name}"
72 @cc = Command::Compiler.new(self, %w(.c))
73 @cxx = Command::Compiler.new(self, %w(.cc .cxx .cpp))
74 @objc = Command::Compiler.new(self, %w(.m))
75 @asm = Command::Compiler.new(self, %w(.S .asm))
76 @linker = Command::Linker.new(self)
77 @archiver = Command::Archiver.new(self)
78 @yacc = Command::Yacc.new(self)
79 @gperf = Command::Gperf.new(self)
80 @git = Command::Git.new(self)
81 @mrbc = Command::Mrbc.new(self)
82
83 @bins = []
84 @gems, @libmruby_objs = MRuby::Gem::List.new, []
85 @build_mrbtest_lib_only = false
86 @cxx_exception_enabled = false
87 @cxx_exception_disabled = false
88 @cxx_abi_enabled = false
89 @enable_bintest = false
90 @enable_test = false
91 @enable_lock = true
92 @toolchains = []
93 @gem_dir_to_repo_url = {}
94
95 MRuby.targets[@name] = self
96 end
97
98 MRuby::Build.current = MRuby.targets[@name]
99 MRuby.targets[@name].instance_eval(&block)
100
101 build_mrbc_exec if name == 'host'
102 build_mrbtest if test_enabled?
103 end
104
105 def debug_enabled?
106 @enable_debug
107 end
108
109 def enable_debug
110 compilers.each do |c|
111 c.defines += %w(MRB_DEBUG)
112 if toolchains.any? { |toolchain| toolchain == "gcc" }
113 c.flags += %w(-g3 -O0)
114 end
115 if toolchains.any? { |toolchain| toolchain == "visualcpp" }
116 c.flags = c.flags.collect{ |a| a.collect{ |f|
117 case f
118 when "/DNDEBUG"
119 "/D_DEBUG"
120 when "/MD"
121 "/MDd"
122 when "/O2"
123 "/Od"
124 when "/Zi"
125 "/ZI"
126 else
127 f
128 end
129 }.flatten }.flatten
130 c.flags += %w(/JMC /RTC1 /Gy)
131 end
132 end
133 if toolchains.any? { |toolchain| toolchain == "visualcpp" }
134 linker.flags = linker.flags.collect{ |a| a.collect{ |f|
135 case f
136 when "/OPT:REF"
137 ""
138 when "/OPT:ICF"
139 ""
140 when "/INCREMENTAL:NO"
141 "/INCREMENTAL"
142 when "/LTCG:incremental"
143 ""
144 else
145 f
146 end
147 }.flatten }.flatten
148 end
149 @mrbc.compile_options += ' -g'
150
151 @enable_debug = true
152 end
153
154 def disable_lock
155 @enable_lock = false
156 end
157
158 def lock_enabled?
159 Lockfile.enabled? && @enable_lock
160 end
161
162 def disable_cxx_exception
163 if @cxx_exception_enabled or @cxx_abi_enabled
164 raise "cxx_exception already enabled"
165 end
166 @cxx_exception_disabled = true
167 end
168
169 def enable_cxx_exception
170 return if @cxx_exception_enabled
171 return if @cxx_abi_enabled
172 if @cxx_exception_disabled
173 raise "cxx_exception disabled"
174 end
175 @cxx_exception_enabled = true
176 compilers.each { |c|
177 c.defines += %w(MRB_ENABLE_CXX_EXCEPTION)
178 c.flags << c.cxx_exception_flag
179 }
180 linker.command = cxx.command if toolchains.find { |v| v == 'gcc' }
181 end
182
183 def cxx_exception_enabled?
184 @cxx_exception_enabled
185 end
186
187 def cxx_abi_enabled?
188 @cxx_abi_enabled
189 end
190
191 def enable_cxx_abi
192 return if @cxx_abi_enabled
193 if @cxx_exception_enabled
194 raise "cxx_exception already enabled"
195 end
196 compilers.each { |c|
197 c.defines += %w(MRB_ENABLE_CXX_EXCEPTION MRB_ENABLE_CXX_ABI)
198 c.flags << c.cxx_compile_flag
199 c.flags = c.flags.flatten - c.cxx_invalid_flags.flatten
200 }
201 linker.command = cxx.command if toolchains.find { |v| v == 'gcc' }
202 @cxx_abi_enabled = true
203 end
204
205 def compile_as_cxx src, cxx_src, obj = nil, includes = []
206 obj = objfile(cxx_src) if obj.nil?
207
208 file cxx_src => [src, __FILE__] do |t|
209 mkdir_p File.dirname t.name
210 IO.write t.name, <<EOS
211#define __STDC_CONSTANT_MACROS
212#define __STDC_LIMIT_MACROS
213
214#ifndef MRB_ENABLE_CXX_ABI
215extern "C" {
216#endif
217#include "#{File.absolute_path src}"
218#ifndef MRB_ENABLE_CXX_ABI
219}
220#endif
221EOS
222 end
223
224 file obj => cxx_src do |t|
225 cxx.run t.name, t.prerequisites.first, [], ["#{MRUBY_ROOT}/src"] + includes
226 end
227
228 obj
229 end
230
231 def enable_bintest
232 @enable_bintest = true
233 end
234
235 def bintest_enabled?
236 @enable_bintest
237 end
238
239 def toolchain(name, params={})
240 name = name.to_s
241 tc = Toolchain.toolchains[name] || begin
242 path = "#{MRUBY_ROOT}/tasks/toolchains/#{name}.rake"
243 fail "Unknown #{name} toolchain" unless File.exist?(path)
244 load path
245 Toolchain.toolchains[name]
246 end
247 tc.setup(self, params)
248 @toolchains.unshift name
249 end
250
251 def primary_toolchain
252 @toolchains.first
253 end
254
255 def root
256 MRUBY_ROOT
257 end
258
259 def enable_test
260 @enable_test = true
261 end
262
263 def test_enabled?
264 @enable_test
265 end
266
267 def build_mrbtest
268 gem :core => 'mruby-test'
269 end
270
271 def build_mrbc_exec
272 gem :core => 'mruby-bin-mrbc'
273 end
274
275 def locks
276 Lockfile.build(@name)
277 end
278
279 def mrbcfile
280 return @mrbcfile if @mrbcfile
281
282 mrbc_build = MRuby.targets['host']
283 gems.each { |v| mrbc_build = self if v.name == 'mruby-bin-mrbc' }
284 @mrbcfile = mrbc_build.exefile("#{mrbc_build.build_dir}/bin/mrbc")
285 end
286
287 def compilers
288 COMPILERS.map do |c|
289 instance_variable_get("@#{c}")
290 end
291 end
292
293 def define_rules
294 compilers.each do |compiler|
295 if respond_to?(:enable_gems?) && enable_gems?
296 compiler.defines -= %w(DISABLE_GEMS)
297 else
298 compiler.defines += %w(DISABLE_GEMS)
299 end
300 compiler.define_rules build_dir, File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
301 end
302 end
303
304 def filename(name)
305 if name.is_a?(Array)
306 name.flatten.map { |n| filename(n) }
307 else
308 name.gsub('/', file_separator)
309 end
310 end
311
312 def exefile(name)
313 if name.is_a?(Array)
314 name.flatten.map { |n| exefile(n) }
315 elsif File.extname(name).empty?
316 "#{name}#{exts.executable}"
317 else
318 # `name` sometimes have (non-standard) extension (e.g. `.bat`).
319 name
320 end
321 end
322
323 def objfile(name)
324 if name.is_a?(Array)
325 name.flatten.map { |n| objfile(n) }
326 else
327 "#{name}#{exts.object}"
328 end
329 end
330
331 def libfile(name)
332 if name.is_a?(Array)
333 name.flatten.map { |n| libfile(n) }
334 else
335 "#{name}#{exts.library}"
336 end
337 end
338
339 def build_mrbtest_lib_only
340 @build_mrbtest_lib_only = true
341 end
342
343 def build_mrbtest_lib_only?
344 @build_mrbtest_lib_only
345 end
346
347 def verbose_flag
348 Rake.verbose ? ' -v' : ''
349 end
350
351 def run_test
352 puts ">>> Test #{name} <<<"
353 mrbtest = exefile("#{build_dir}/bin/mrbtest")
354 sh "#{filename mrbtest.relative_path}#{verbose_flag}"
355 puts
356 end
357
358 def run_bintest
359 puts ">>> Bintest #{name} <<<"
360 targets = @gems.select { |v| File.directory? "#{v.dir}/bintest" }.map { |v| filename v.dir }
361 targets << filename(".") if File.directory? "./bintest"
362 sh "ruby test/bintest.rb#{verbose_flag} #{targets.join ' '}"
363 end
364
365 def print_build_summary
366 puts "================================================"
367 puts " Config Name: #{@name}"
368 puts " Output Directory: #{self.build_dir.relative_path}"
369 puts " Binaries: #{@bins.join(', ')}" unless @bins.empty?
370 unless @gems.empty?
371 puts " Included Gems:"
372 gems = @gems.sort_by { |gem| gem.name }
373 gems.each do |gem|
374 gem_version = " - #{gem.version}" if gem.version != '0.0.0'
375 gem_summary = " - #{gem.summary}" if gem.summary
376 puts " #{gem.name}#{gem_version}#{gem_summary}"
377 puts " - Binaries: #{gem.bins.join(', ')}" unless gem.bins.empty?
378 end
379 end
380 puts "================================================"
381 puts
382 end
383
384 def libmruby_static
385 libfile("#{build_dir}/lib/libmruby")
386 end
387
388 def libmruby_core_static
389 libfile("#{build_dir}/lib/libmruby_core")
390 end
391
392 def libraries
393 [libmruby_static]
394 end
395 end # Build
396
397 class CrossBuild < Build
398 attr_block %w(test_runner)
399 # cross compiling targets for building native extensions.
400 # host - arch of where the built binary will run
401 # build - arch of the machine building the binary
402 attr_accessor :host_target, :build_target
403
404 def initialize(name, build_dir=nil, &block)
405 @endian = nil
406 @test_runner = Command::CrossTestRunner.new(self)
407 super
408 end
409
410 def mrbcfile
411 MRuby.targets['host'].exefile("#{MRuby.targets['host'].build_dir}/bin/mrbc")
412 end
413
414 def run_test
415 @test_runner.runner_options << verbose_flag
416 mrbtest = exefile("#{build_dir}/bin/mrbtest")
417 if (@test_runner.command == nil)
418 puts "You should run #{mrbtest} on target device."
419 puts
420 else
421 @test_runner.run(mrbtest)
422 end
423 end
424
425 def big_endian
426 if @endian
427 puts "Endian has already specified as #{@endian}."
428 return
429 end
430 @endian = :big
431 @mrbc.compile_options += ' -E'
432 compilers.each do |c|
433 c.defines += %w(MRB_ENDIAN_BIG)
434 end
435 end
436
437 def little_endian
438 if @endian
439 puts "Endian has already specified as #{@endian}."
440 return
441 end
442 @endian = :little
443 @mrbc.compile_options += ' -e'
444 end
445 end # CrossBuild
446end # MRuby
Note: See TracBrowser for help on using the repository browser.