xot 0.1.12 → 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
 
4
- require 'erb'
5
4
  require 'rbconfig'
6
- require 'pp'
5
+ require 'rake/loaders/makefile'
6
+ require 'rake/testtask'
7
+ require 'xot/rake/alias_task'
8
+ require 'xot/rake/util'
9
+ require 'xot/rake/escalation'
7
10
 
8
11
 
9
12
  module Xot
@@ -12,142 +15,337 @@ module Xot
12
15
  module Rake
13
16
 
14
17
 
15
- def empty_task (*names)
16
- names.each do |name|
17
- task name => '.'
18
- end
18
+ def srcs_map ()
19
+ paths = glob("#{src_dir}/**/*.{#{src_exts.join ','}}") +
20
+ erbs_map.values.grep(/\.(#{src_exts.join '|'})$/)
21
+ paths.reject! {|path| excluded? path}
22
+ paths.reject! {|path| path =~ %r(/win32/)} unless win32?
23
+ paths.reject! {|path| path =~ %r(/osx/)} unless osx?
24
+ paths.reject! {|path| path =~ %r(/ios/)} unless ios?
25
+ make_path_map paths, src_ext_map
19
26
  end
20
27
 
21
- def glob (*patterns)
22
- paths = []
23
- patterns.each do |pattern|
24
- paths.concat Dir.glob(pattern)
25
- end
26
- paths
28
+ def erbs_map ()
29
+ paths = glob *[inc_dir, src_dir].map {|s| "#{s}/**/*.erb"}
30
+ paths.reject! {|path| excluded? path}
31
+ make_path_map paths, {".erb" => ""}
27
32
  end
28
33
 
29
- def erb (str)
30
- ERB.new(str, nil, '%').result binding
34
+ def vendor_srcs_map (*dirs)
35
+ dirs = src_dirs if dirs.empty?
36
+ paths = dirs.map {|dir| glob "#{dir}/**/*.{#{src_exts.join ','}}"}.flatten
37
+ paths.reject! {|path| excluded? path}
38
+ make_path_map paths.flatten, src_ext_map
31
39
  end
32
40
 
33
- def compile (path, out)
34
- open(path) do |input|
35
- open(out, 'w') do |output|
36
- output.write erb(input.read)
37
- end
38
- end
39
- #rescue
41
+ def src_ext_map (to = '.o')
42
+ Hash[*src_exts.map {|ext| [".#{ext}", to]}.flatten]
43
+ end
44
+
45
+ def defs ()
46
+ env_array :DEFS, []
47
+ end
48
+
49
+ def test_alones ()
50
+ env :TESTS_ALONE, []
40
51
  end
41
52
 
42
- def params (max, sep = '', &block)
43
- raise 'block not given.' unless block
44
- return '' if max == 0
45
- (1..max).map(&block).join(sep)
53
+ def test_excludes ()
54
+ env :TESTS_EXCLUDE, []
46
55
  end
47
56
 
48
- def convertions (paths, convs)
49
- raise 'empty conversion.' if convs.empty?
50
- paths = paths.map do |path|
51
- convpath = path
52
- convs.each do |from, to|
53
- convpath = convpath.sub(/#{from.gsub('.', '\.')}$/, to)
57
+ def build_native_library ()
58
+ outname = "lib#{target_name}.a"
59
+ out = File.join lib_dir, outname
60
+ erbs = erbs_map
61
+ srcs = srcs_map
62
+ depend = 'depend.mf'
63
+
64
+ alias_task :erb => 'lib:erb'
65
+ alias_task :lib => out
66
+ alias_task :clean => 'lib:clean'
67
+
68
+ namespace :lib do
69
+ desc "compile sources"
70
+ alias_task :compile => srcs.values
71
+
72
+ desc "convert erb sources"
73
+ alias_task :erb => erbs.values
74
+
75
+ desc "link #{out}"
76
+ file out => srcs.values do
77
+ next if srcs.values.empty?
78
+ objs = srcs.values + vendor_srcs_map.values
79
+ sh %( rm -f #{out} )
80
+ sh %( #{ar} #{arflags} #{out} #{objs.join " "} )
81
+ end
82
+
83
+ desc "create #{depend}"
84
+ file depend => erbs.values do
85
+ sh %( #{cxx} -M #{cppflags} #{srcs.keys.join ' '} > #{depend} )
86
+ input = open(depend) {|f| f.read}
87
+ open(depend, 'w') do |output|
88
+ output << input.gsub(/\w+\.o/, src_dir + '/\0')
89
+ end
90
+ end
91
+
92
+ import depend if File.exist? depend
93
+
94
+ srcs.each do |src, obj|
95
+ desc "compile #{src}"
96
+ file obj => [:vendor, depend, src] + erbs.values do
97
+ sh %( #{cxx} -c #{cppflags} #{cxxflags} -o #{obj} #{src} )
98
+ end
99
+ end
100
+
101
+ erbs.each do |erb, to|
102
+ desc "compile #{erb}"
103
+ file to => erb do
104
+ print "#{erb}: compiling to #{to} ..."
105
+ compile_erb erb, to
106
+ puts "ok"
107
+ end
108
+ end
109
+
110
+ task :clean do
111
+ tmps = srcs.values + erbs.values
112
+ sh %( rm -rf #{out} #{depend} #{tmps.join ' '} )
54
113
  end
55
- [path, convpath]
56
114
  end
57
- Hash[*paths.flatten]
58
115
  end
59
116
 
60
- def env (name, defval = nil, to = nil)
61
- case val = (ENV[name.to_s] || Object.const_get(name) rescue defval)
62
- when /^\d+$/ then val.to_i
63
- when 'true', true then true
64
- when 'false', false then false
65
- when nil then nil
66
- when Numeric then val
67
- else
68
- val = val.split /\s+/ if to == :array && val.respond_to?(:split)
69
- val.dup
117
+ def build_ruby_extension (dlname: 'native', dlext: 'so')
118
+ dlname = env :DLNAME, dlname
119
+ dlext = env :DLEXT, RbConfig::CONFIG['DLEXT'] || dlext
120
+
121
+ extconf = File.join ext_dir, 'extconf.rb'
122
+ makefile = File.join ext_dir, 'Makefile'
123
+ depend = File.join ext_dir, 'depend.mf'
124
+
125
+ outname = "#{dlname}.#{dlext}"
126
+ extout = File.join ext_dir, outname
127
+ libout = File.join ext_lib_dir, outname
128
+
129
+ srcs = FileList["#{ext_dir}/**/*.cpp"]
130
+ libs = modules.map {|m| m.name.downcase}.map {|s| "../#{s}/lib/lib#{s}.a"}
131
+
132
+ alias_task :ext => libout
133
+ alias_task :clean => 'ext:clean'
134
+ alias_task :clobber => 'ext:clobber'
135
+
136
+ namespace :ext do
137
+ desc "build #{libout}"
138
+ file libout => extout do
139
+ sh %( cp #{extout} #{libout} )
140
+ end
141
+
142
+ desc "build #{extout}"
143
+ file extout => [:lib, makefile] do
144
+ sh %( cd #{ext_dir} && make )
145
+ end
146
+
147
+ desc "create #{makefile}"
148
+ file makefile => [extconf, depend] + libs do
149
+ sh %( cd #{ext_dir} && ruby #{File.basename extconf} )
150
+ end
151
+
152
+ desc "create #{depend}"
153
+ file depend => srcs do
154
+ inc = inc_dirs.map {|s| " -I#{s}"}.join
155
+ src = srcs.map {|cpp| File.basename cpp}.join ' '
156
+ dep = File.basename depend
157
+ sh %( cd #{ext_dir} && #{cxx} -M #{cppflags} #{inc} #{src} > #{dep} )
158
+ end
159
+
160
+ task :clean do
161
+ sh %( cd #{ext_dir} && make clean ) if File.exist? makefile
162
+ sh %( rm -rf #{libout} )
163
+ end
164
+
165
+ task :clobber do
166
+ sh %( cd #{ext_dir} && make distclean ) if File.exist? makefile
167
+ sh %( rm -rf #{makefile} #{depend} )
168
+ end
70
169
  end
71
170
  end
72
171
 
73
- def ruby_incdirs ()
74
- root = RbConfig::CONFIG['rubyhdrdir']
75
- [root, RbConfig::CONFIG['rubyarchhdrdir'] || "#{root}/#{RUBY_PLATFORM}"]
76
- end
172
+ def test_ruby_extension ()
173
+ alias_task :test => [:ext, 'test:full', 'test:alones']
77
174
 
78
- def cppflags (flags = '', defs = [], incdirs = [])
79
- s = flags.dup
80
- s << cppflags_defs(defs) .map {|s| " -D#{s}"}.join
81
- s << cppflags_incdirs(incdirs).map {|s| " -I#{s}"}.join
82
- s
83
- end
175
+ namespace :test do
176
+ ::Rake::TestTask.new :full do |t|
177
+ t.libs << lib_dir
178
+ t.test_files = FileList["#{test_dir}/test_*.rb"] - test_alones - test_excludes
179
+ t.verbose = true
180
+ end
84
181
 
85
- def cppflags_defs (defs = [])
86
- a = defs
87
- a << $~[0].upcase if RUBY_PLATFORM =~ /mswin|ming|cygwin|darwin/i
88
- a << (debug? ? '_DEBUG' : 'NDEBUG')
89
- a << 'WIN32' if win32?
90
- a << 'OSX' if osx?
91
- a << 'IOS' if ios?
92
- a
182
+ task :alones do
183
+ test_alones.each do |rb|
184
+ next if test_excludes.include? rb
185
+ sh %( ruby #{rb} )
186
+ end
187
+ end
188
+ end
93
189
  end
94
190
 
95
- def cppflags_incdirs (dirs = [])
96
- a = dirs.dup
97
- a += ruby_incdirs
98
- a
99
- end
191
+ def build_ruby_gem ()
192
+ gemspec = "#{target_name}.gemspec"
193
+ gemname = env :GEMNAME, target_name
194
+ gemver = env :GEMVERSION, target.version
195
+ gemfile = "#{gemname}-#{gemver}.gem"
196
+
197
+ alias_task :gem => gemfile
198
+ alias_task :clean => 'gem:clean'
199
+ alias_task :install => 'gem:install'
200
+ alias_task :uninstall => 'gem:uninstall'
201
+ alias_task :upload => 'gem:upload'
202
+
203
+ namespace :gem do
204
+ file gemfile => [:ext, :doc, gemspec] do
205
+ sh %( gem build #{gemspec} )
206
+ end
100
207
 
101
- def cflags (flags = '')
102
- s = flags.dup
103
- s << ' -Wno-unknown-pragmas'
104
- s << ' ' << RbConfig::CONFIG['debugflags'] if debug?
105
- s << ' -stdlib=libc++ -mmacosx-version-min=10.7' if clang?
106
- s.gsub! /-O\d?/, '-O0' if debug?
107
- s
108
- end
208
+ desc "test gem"
209
+ alias_task :test => [:install, :uninstall]
109
210
 
110
- def ldflags (flags = '', libdirs = [], frameworks = [])
111
- s = flags.dup
112
- s << libdirs.map {|s| " -L#{s}"}.join
113
- s << frameworks.map {|s| " -framework #{s}"}.join
114
- s
115
- end
211
+ desc "install gem"
212
+ task :install => gemfile do
213
+ sh %( gem install #{gemfile} )
214
+ end
116
215
 
117
- def header (mod)
118
- puts "-- #{mod.to_s.capitalize} " + '-' * 50
119
- end
216
+ desc "uninstall gem"
217
+ task :uninstall do
218
+ sh %( gem uninstall -x --version #{gemver} #{gemname} )
219
+ end
120
220
 
121
- def debug? ()
122
- env :DEBUG, false
123
- end
221
+ desc "upload gem"
222
+ task :upload => :install do
223
+ sh %( gem push #{gemfile} )
224
+ end
124
225
 
125
- def win32? ()
126
- RUBY_PLATFORM =~ /mswin|ming|cygwin/
226
+ task :clean do
227
+ sh %( rm -f #{gemfile} )
228
+ end
229
+ end
127
230
  end
128
231
 
129
- def mswin? ()
130
- RUBY_PLATFORM =~ /mswin/
131
- end
232
+ def build_application ()
233
+ bindir = env :BINDIR, 'bin'
234
+ bin = "#{bindir}/#{target_name}"
235
+ appdir = "#{target.name}.app"
236
+ appbindir = "#{appdir}/Contents/MacOS"
237
+ out = "#{appbindir}/#{target.name}"
238
+ tmps = [appdir]
132
239
 
133
- def ming? ()
134
- RUBY_PLATFORM =~ /ming/
135
- end
240
+ alias_task :app => out
241
+ alias_task :clean => 'app:clean'
242
+
243
+ namespace :app do
244
+ task :run => :app do
245
+ sh %( ruby #{bin} )
246
+ end
247
+
248
+ file out => [bin, appbindir] do
249
+ sh %( cp #{bin} #{appbindir} )
250
+ end
251
+
252
+ directory appbindir
136
253
 
137
- def cygwin? ()
138
- RUBY_PLATFORM =~ /cygwin/
254
+ task :clean do
255
+ sh %( rm -rf #{tmps.join ' '} )
256
+ end
257
+ end
139
258
  end
140
259
 
141
- def osx? ()
142
- RUBY_PLATFORM =~ /darwin/
260
+ def use_external_library (
261
+ repos, branch: nil, tag: nil,
262
+ incdir: nil, srcdir: nil, excludes: [],
263
+ submodules: [], post_submodules: nil)
264
+
265
+ excludes = [excludes].flatten
266
+
267
+ name = repos[%r{/([^/]+?)(:?\.git)?$}, 1]
268
+ dir = "#{vendor_dir}/#{name}"
269
+ incdir = dir + (incdir ? "/#{incdir}" : '')
270
+ srcdir = dir + (srcdir ? "/#{srcdir}" : '')
271
+
272
+ append_env 'INCDIRS', incdir
273
+ append_env 'SRCDIRS', srcdir
274
+ append_env 'EXCLUDES', excludes unless excludes.empty?
275
+
276
+ alias_task :vendor => "vendor:#{name}"
277
+ alias_task :clobber => "vendor:#{name}:clobber"
278
+
279
+ namespace :vendor do
280
+ desc "setup #{name} library"
281
+ alias_task name => dir
282
+
283
+ namespace name do
284
+ desc "clone #{name}"
285
+ file dir do
286
+ opts = '--depth=1'
287
+ opts += " --branch=#{branch || tag}" if branch || tag
288
+ opts += " --recursive" if submodules.empty?
289
+ sh %( git clone #{opts} #{repos} #{dir} )
290
+ unless submodules.empty?
291
+ Dir.chdir dir do
292
+ submodules.each do |path|
293
+ sh %( git submodule init #{path} )
294
+ end
295
+ sh %( git submodule update --depth=1 )
296
+ sh post_submodules if post_submodules
297
+ end
298
+ end
299
+ vendor_srcs_map(srcdir).each do |src, obj|
300
+ sh %( #{cxx} -c #{cppflags} #{cxxflags} -o #{obj} #{src} )
301
+ end
302
+ end
303
+
304
+ desc "update #{name} library"
305
+ task :update => ["vendor:#{name}:clobber", "vendor:#{name}"]
306
+
307
+ desc "delete #{name} library"
308
+ task :clobber do
309
+ sh %( rm -rf #{dir} )
310
+ end
311
+ end
312
+ end
143
313
  end
144
314
 
145
- def ios? ()
146
- false
315
+ def use_boost_library (modules = [], branch: nil, tag: nil)
316
+ default_modules = %w[tools/build libs/config]
317
+ use_external_library 'https://github.com/boostorg/boost',
318
+ branch: branch,
319
+ tag: tag,
320
+ srcdir: 'NOSRC',
321
+ submodules: default_modules | modules.map {|mod| "libs/#{mod}"},
322
+ post_submodules: './bootstrap.sh && ./b2 headers'
147
323
  end
148
324
 
149
- def clang? ()
150
- RbConfig::CONFIG['CXX'] =~ /clang/
325
+ def define_placeholder_tasks ()
326
+ desc "delete temporary files"
327
+ alias_task :clean
328
+
329
+ desc "delete all generated files"
330
+ alias_task :clobber => :clean
331
+
332
+ desc "build native library"
333
+ alias_task :lib
334
+
335
+ desc "build ruby extension"
336
+ alias_task :ext
337
+
338
+ desc "build ruby gem"
339
+ alias_task :gem
340
+
341
+ desc "generate documentations"
342
+ alias_task :doc
343
+
344
+ desc "run all tests"
345
+ alias_task :test
346
+
347
+ desc "setup all external libraries"
348
+ alias_task :vendor
151
349
  end
152
350
 
153
351
 
@@ -157,29 +355,6 @@ module Xot
157
355
  end# Xot
158
356
 
159
357
 
160
- if Kernel.const_defined? :Rake
161
- module Rake
162
- class Application
163
- alias invoke_task_org invoke_task
358
+ include Xot::Rake
164
359
 
165
- def invoke_task (*args, &block)
166
- invoke_task_org *args, &block
167
- rescue RuntimeError => e
168
- if e.message =~ /don't\s+know\s+.*\s+task\s+/i
169
- escalate_tasks
170
- else
171
- raise
172
- end
173
- end
174
-
175
- def escalate_tasks ()
176
- Dir.chdir '..' do
177
- cmd = "rake #{ARGV.join ' '}"
178
- $stderr.puts "(in #{Dir.pwd}) #{cmd}"
179
- system cmd
180
- end
181
- exit 0
182
- end
183
- end
184
- end
185
- end
360
+ define_placeholder_tasks