source: EcnlProtoTool/trunk/mruby-1.2.0/tasks/mruby_build_commands.rake@ 281

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

mrbc.jsをemscriptenでビルド出来るようmrubyのビルドファイルを更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 11.8 KB
Line 
1require 'forwardable'
2require 'digest/md5'
3
4module MRuby
5 class Command
6 include Rake::DSL
7 extend Forwardable
8 def_delegators :@build, :filename, :objfile, :libfile, :exefile, :cygwin_filename
9 attr_accessor :build, :command
10
11 def initialize(build)
12 @build = build
13 end
14
15 # clone is deep clone without @build
16 def clone
17 target = super
18 excepts = %w(@build)
19 instance_variables.each do |attr|
20 unless excepts.include?(attr.to_s)
21 val = Marshal::load(Marshal.dump(instance_variable_get(attr))) # deep clone
22 target.instance_variable_set(attr, val)
23 end
24 end
25 target
26 end
27
28 NotFoundCommands = {}
29
30 private
31 def _run(options, params={})
32 return sh command + ' ' + ( options % params ) if NotFoundCommands.key? @command
33 begin
34 sh build.filename(command) + ' ' + ( options % params )
35 rescue RuntimeError
36 NotFoundCommands[@command] = true
37 _run options, params
38 end
39 end
40 end
41
42 class Command::Compiler < Command
43 attr_accessor :flags, :include_paths, :defines, :source_exts
44 attr_accessor :compile_options, :option_define, :option_include_path, :out_ext
45
46 def initialize(build, source_exts=[])
47 super(build)
48 @command = ENV['CC'] || 'cc'
49 @flags = [ENV['CFLAGS'] || []]
50 @source_exts = source_exts
51 @include_paths = ["#{MRUBY_ROOT}/include"]
52 @defines = %w()
53 @option_include_path = '-I%s'
54 @option_define = '-D%s'
55 @compile_options = '%{flags} -o %{outfile} -c %{infile}'
56 end
57
58 alias header_search_paths include_paths
59 def search_header_path(name)
60 header_search_paths.find do |v|
61 File.exist? build.filename("#{v}/#{name}").sub(/^"(.*)"$/, '\1')
62 end
63 end
64
65 def search_header(name)
66 path = search_header_path name
67 path && build.filename("#{path}/#{name}").sub(/^"(.*)"$/, '\1')
68 end
69
70 def all_flags(_defineds=[], _include_paths=[], _flags=[])
71 define_flags = [defines, _defineds].flatten.map{ |d| option_define % d }
72 include_path_flags = [include_paths, _include_paths].flatten.map do |f|
73 if MRUBY_BUILD_HOST_IS_CYGWIN
74 option_include_path % cygwin_filename(f)
75 else
76 option_include_path % filename(f)
77 end
78 end
79 [flags, define_flags, include_path_flags, _flags].flatten.join(' ')
80 end
81
82 def run(outfile, infile, _defineds=[], _include_paths=[], _flags=[])
83 FileUtils.mkdir_p File.dirname(outfile)
84 _pp "CC", infile.relative_path, outfile.relative_path
85 if MRUBY_BUILD_HOST_IS_CYGWIN
86 _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags),
87 :infile => cygwin_filename(infile), :outfile => cygwin_filename(outfile),
88 :outdir => File.dirname(outfile), :outfilebase => File.basename(outfile, ".*") }
89 else
90 _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags),
91 :infile => filename(infile), :outfile => filename(outfile),
92 :outdir => File.dirname(outfile), :outfilebase => File.basename(outfile, ".*") }
93 end
94 end
95
96 def define_rules(build_dir, source_dir='')
97 @out_ext = build.exts.object
98 gemrake = File.join(source_dir, "mrbgem.rake")
99 rakedep = File.exist?(gemrake) ? [ gemrake ] : []
100
101 if build_dir.include? "mrbgems/"
102 generated_file_matcher = Regexp.new("^#{Regexp.escape build_dir}/(.*)#{Regexp.escape out_ext}$")
103 else
104 generated_file_matcher = Regexp.new("^#{Regexp.escape build_dir}/(?!mrbgems/.+/)(.*)#{Regexp.escape out_ext}$")
105 end
106 source_exts.each do |ext, compile|
107 rule generated_file_matcher => [
108 proc { |file|
109 file.sub(generated_file_matcher, "#{source_dir}/\\1#{ext}")
110 },
111 proc { |file|
112 get_dependencies(file) + rakedep
113 }
114 ] do |t|
115 run t.name, t.prerequisites.first
116 end
117
118 rule generated_file_matcher => [
119 proc { |file|
120 file.sub(generated_file_matcher, "#{build_dir}/\\1#{ext}")
121 },
122 proc { |file|
123 get_dependencies(file) + rakedep
124 }
125 ] do |t|
126 run t.name, t.prerequisites.first
127 end
128 end
129 end
130
131 private
132 def get_dependencies(file)
133 file = file.ext('d') unless File.extname(file) == '.d'
134 if File.exist?(file)
135 File.read(file).gsub("\\\n ", "").scan(/^\S+:\s+(.+)$/).flatten.map {|s| s.split(' ') }.flatten
136 else
137 []
138 end + [ MRUBY_CONFIG ]
139 end
140 end
141
142 class Command::Linker < Command
143 attr_accessor :flags, :library_paths, :flags_before_libraries, :libraries, :flags_after_libraries
144 attr_accessor :link_options, :option_library, :option_library_path
145
146 def initialize(build)
147 super
148 @command = ENV['LD'] || 'ld'
149 @flags = (ENV['LDFLAGS'] || [])
150 @flags_before_libraries, @flags_after_libraries = [], []
151 @libraries = []
152 @library_paths = []
153 @option_library = '-l%s'
154 @option_library_path = '-L%s'
155 @link_options = "%{flags} -o %{outfile} %{objs} %{flags_before_libraries} %{libs} %{flags_after_libraries}"
156 end
157
158 def all_flags(_library_paths=[], _flags=[])
159 library_path_flags = [library_paths, _library_paths].flatten.map do |f|
160 if MRUBY_BUILD_HOST_IS_CYGWIN
161 option_library_path % cygwin_filename(f)
162 else
163 option_library_path % filename(f)
164 end
165 end
166 [flags, library_path_flags, _flags].flatten.join(' ')
167 end
168
169 def library_flags(_libraries)
170 [libraries, _libraries].flatten.map{ |d| option_library % d }.join(' ')
171 end
172
173 def run(outfile, objfiles, _libraries=[], _library_paths=[], _flags=[], _flags_before_libraries=[], _flags_after_libraries=[])
174 FileUtils.mkdir_p File.dirname(outfile)
175 library_flags = [libraries, _libraries].flatten.map { |d| option_library % d }
176
177 _pp "LD", outfile.relative_path
178 if MRUBY_BUILD_HOST_IS_CYGWIN
179 _run link_options, { :flags => all_flags(_library_paths, _flags),
180 :outfile => cygwin_filename(outfile) , :objs => cygwin_filename(objfiles).join(' '),
181 :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '),
182 :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '),
183 :libs => library_flags.join(' '),
184 :outdir => File.dirname(outfile), :outfilebase => File.basename(outfile, ".*") }
185 else
186 _run link_options, { :flags => all_flags(_library_paths, _flags),
187 :outfile => filename(outfile) , :objs => filename(objfiles).join(' '),
188 :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '),
189 :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '),
190 :libs => library_flags.join(' '),
191 :outdir => File.dirname(outfile), :outfilebase => File.basename(outfile, ".*") }
192 end
193 end
194 end
195
196 class Command::Archiver < Command
197 attr_accessor :archive_options
198
199 def initialize(build)
200 super
201 @command = ENV['AR'] || 'ar'
202 @archive_options = 'rs %{outfile} %{objs}'
203 end
204
205 def run(outfile, objfiles)
206 FileUtils.mkdir_p File.dirname(outfile)
207 _pp "AR", outfile.relative_path
208
209 # reference from emar.py
210 outfilebase = File.dirname(outfile)
211 to_delete = []
212 newargs = []
213 objfiles.each do |orig_name|
214 dir_name = File.dirname(orig_name)
215 dir_name = dir_name.relative_path_from(Dir.pwd)
216 base_name = File.basename(orig_name)
217 parts = base_name.split('.')
218 # h = Digest::MD5.new.update(orig_name).to_s
219 h = Digest::MD5.new.update(orig_name).to_s.slice(0,4)
220 parts[0] += '_' + h
221 newname = parts.join('.')
222 full_newname = File.join(dir_name, newname)
223 if not File.exists?(full_newname)
224 begin # it is ok to fail here, we just don't get hashing
225 FileUtils.cp(orig_name, full_newname)
226 newargs << full_newname
227 to_delete << full_newname
228 rescue
229 end
230 end
231 end
232
233 if MRUBY_BUILD_HOST_IS_CYGWIN
234 _run archive_options, { :outfile => cygwin_filename(outfile), :objs => cygwin_filename(newargs).join(' '), :outdir => File.dirname(outfile), :outfilebase => File.basename(outfile, ".*") }
235 else
236 _run archive_options, { :outfile => filename(outfile), :objs => filename(newargs).join(' '), :outdir => File.dirname(outfile), :outfilebase => File.basename(outfile, ".*") }
237 end
238
239 to_delete.each do |d|
240 FileUtils.rm(d)
241 end
242 end
243 end
244
245 class Command::Yacc < Command
246 attr_accessor :compile_options
247
248 def initialize(build)
249 super
250 @command = 'bison'
251 @compile_options = '-o %{outfile} %{infile}'
252 end
253
254 def run(outfile, infile)
255 FileUtils.mkdir_p File.dirname(outfile)
256 _pp "YACC", infile.relative_path, outfile.relative_path
257 _run compile_options, { :outfile => filename(outfile) , :infile => filename(infile) }
258 end
259 end
260
261 class Command::Gperf < Command
262 attr_accessor :compile_options
263
264 def initialize(build)
265 super
266 @command = 'gperf'
267 @compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}'
268 end
269
270 def run(outfile, infile)
271 FileUtils.mkdir_p File.dirname(outfile)
272 _pp "GPERF", infile.relative_path, outfile.relative_path
273 _run compile_options, { :outfile => filename(outfile) , :infile => filename(infile) }
274 end
275 end
276
277 class Command::Git < Command
278 attr_accessor :flags
279 attr_accessor :clone_options, :pull_options, :checkout_options
280
281 def initialize(build)
282 super
283 @command = 'git'
284 @flags = %w[]
285 @clone_options = "clone %{flags} %{url} %{dir}"
286 @pull_options = "pull"
287 @checkout_options = "checkout %{checksum_hash}"
288 end
289
290 def run_clone(dir, url, _flags = [])
291 _pp "GIT", url, dir.relative_path
292 _run clone_options, { :flags => [flags, _flags].flatten.join(' '), :url => url, :dir => filename(dir) }
293 end
294
295 def run_pull(dir, url)
296 root = Dir.pwd
297 Dir.chdir dir
298 _pp "GIT PULL", url, dir.relative_path
299 _run pull_options
300 Dir.chdir root
301 end
302
303 def run_checkout(dir, checksum_hash)
304 root = Dir.pwd
305 Dir.chdir dir
306 _pp "GIT CHECKOUT", checksum_hash
307 _run checkout_options, { :checksum_hash => checksum_hash }
308 Dir.chdir root
309 end
310 end
311
312 class Command::Mrbc < Command
313 attr_accessor :compile_options
314
315 def initialize(build)
316 super
317 @command = nil
318 @compile_options = "-B%{funcname} -o-"
319 end
320
321 def run(out, infiles, funcname)
322 @command ||= @build.mrbcfile
323 infiles = [infiles].flatten
324 infiles.each do |f|
325 _pp "MRBC", f.relative_path, nil, :indent => 2
326 end
327 IO.popen("#{filename @command} #{@compile_options % {:funcname => funcname}} #{filename(infiles).join(' ')}", 'r+') do |io|
328 out.puts io.read
329 end
330 # if mrbc execution fail, drop the file
331 if $?.exitstatus != 0
332 File.delete(out.path)
333 exit(-1)
334 end
335 end
336 end
337
338 class Command::CrossTestRunner < Command
339 attr_accessor :runner_options
340 attr_accessor :verbose_flag
341 attr_accessor :flags
342
343 def initialize(build)
344 super
345 @command = nil
346 @runner_options = '%{flags} %{infile}'
347 @verbose_flag = ''
348 @flags = []
349 end
350
351 def run(testbinfile)
352 puts "TEST for " + @build.name
353 _run runner_options, { :flags => [flags, verbose_flag].flatten.join(' '), :infile => testbinfile }
354 end
355 end
356
357end
Note: See TracBrowser for help on using the repository browser.