xot 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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