Develop and Download Open Source Software

Browse CVS Repository

Annotation of /exerb/exerb/setup.rb

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (hide annotations) (download)
Wed Jan 12 08:03:31 2005 UTC (19 years, 3 months ago) by yuya
Branch: MAIN
CVS Tags: release331, release330, release330p1, snapshot20050414
Branch point for: branch3xx
Changes since 1.2: +674 -649 lines
* setup.rbを3.2.4に変更

1 yuya 1.1 #
2     # setup.rb
3     #
4 yuya 1.3 # Copyright (c) 2000-2004 Minero Aoki
5 yuya 1.1 #
6 yuya 1.2 # This program is free software.
7     # You can distribute/modify this program under the terms of
8 yuya 1.3 # the GNU Lesser General Public License version 2.1.
9 yuya 1.1 #
10    
11     #
12 yuya 1.3 # For backward compatibility
13 yuya 1.1 #
14    
15 yuya 1.2 unless Enumerable.method_defined?(:map)
16     module Enumerable
17 yuya 1.1 alias map collect
18     end
19 yuya 1.2 end
20 yuya 1.1
21 yuya 1.3 unless Enumerable.method_defined?(:detect)
22     module Enumerable
23     alias detect find
24     end
25     end
26    
27 yuya 1.2 unless Enumerable.method_defined?(:select)
28     module Enumerable
29 yuya 1.1 alias select find_all
30     end
31 yuya 1.2 end
32 yuya 1.1
33 yuya 1.2 unless Enumerable.method_defined?(:reject)
34     module Enumerable
35 yuya 1.1 def reject
36     result = []
37     each do |i|
38     result.push i unless yield(i)
39     end
40     result
41     end
42     end
43 yuya 1.2 end
44 yuya 1.1
45 yuya 1.2 unless Enumerable.method_defined?(:inject)
46     module Enumerable
47     def inject(result)
48 yuya 1.1 each do |i|
49     result = yield(result, i)
50     end
51     result
52     end
53     end
54 yuya 1.2 end
55 yuya 1.1
56 yuya 1.2 unless Enumerable.method_defined?(:any?)
57     module Enumerable
58 yuya 1.1 def any?
59     each do |i|
60     return true if yield(i)
61     end
62     false
63     end
64     end
65     end
66 yuya 1.2
67     unless File.respond_to?(:read)
68     def File.read(fname)
69 yuya 1.3 open(fname) {|f|
70 yuya 1.2 return f.read
71     }
72     end
73     end
74 yuya 1.3
75 yuya 1.1 #
76 yuya 1.3 # Application independent utilities
77 yuya 1.1 #
78    
79 yuya 1.3 def File.binread(fname)
80     open(fname, 'rb') {|f|
81     return f.read
82     }
83     end
84 yuya 1.1
85 yuya 1.3 # for corrupted windows stat(2)
86     def File.dir?(path)
87     File.directory?((path[-1,1] == '/') ? path : path + '/')
88 yuya 1.2 end
89    
90 yuya 1.1 #
91 yuya 1.3 # Config
92 yuya 1.1 #
93    
94 yuya 1.3 if arg = ARGV.detect{|arg| /\A--rbconfig=/ =~ arg }
95     ARGV.delete(arg)
96     require arg.split(/=/, 2)[1]
97     $".push 'rbconfig.rb'
98 yuya 1.1 else
99     require 'rbconfig'
100     end
101    
102 yuya 1.3 def multipackage_install?
103     FileTest.directory?(File.dirname($0) + '/packages')
104     end
105    
106    
107 yuya 1.1 class ConfigTable
108    
109     c = ::Config::CONFIG
110    
111     rubypath = c['bindir'] + '/' + c['ruby_install_name']
112    
113     major = c['MAJOR'].to_i
114     minor = c['MINOR'].to_i
115     teeny = c['TEENY'].to_i
116     version = "#{major}.#{minor}"
117    
118     # ruby ver. >= 1.4.4?
119     newpath_p = ((major >= 2) or
120     ((major == 1) and
121     ((minor >= 5) or
122     ((minor == 4) and (teeny >= 4)))))
123    
124     subprefix = lambda {|path|
125 yuya 1.2 path.sub(/\A#{Regexp.quote(c['prefix'])}/o, '$prefix')
126 yuya 1.1 }
127    
128     if c['rubylibdir']
129     # V < 1.6.3
130     stdruby = subprefix.call(c['rubylibdir'])
131     siteruby = subprefix.call(c['sitedir'])
132     versite = subprefix.call(c['sitelibdir'])
133     sodir = subprefix.call(c['sitearchdir'])
134     elsif newpath_p
135     # 1.4.4 <= V <= 1.6.3
136     stdruby = "$prefix/lib/ruby/#{version}"
137     siteruby = subprefix.call(c['sitedir'])
138     versite = siteruby + '/' + version
139     sodir = "$site-ruby/#{c['arch']}"
140     else
141     # V < 1.4.4
142     stdruby = "$prefix/lib/ruby/#{version}"
143     siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
144     versite = siteruby
145     sodir = "$site-ruby/#{c['arch']}"
146     end
147    
148 yuya 1.3 if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
149     makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
150     else
151     makeprog = 'make'
152     end
153    
154 yuya 1.1 common_descripters = [
155     [ 'prefix', [ c['prefix'],
156     'path',
157     'path prefix of target environment' ] ],
158     [ 'std-ruby', [ stdruby,
159     'path',
160     'the directory for standard ruby libraries' ] ],
161     [ 'site-ruby-common', [ siteruby,
162     'path',
163     'the directory for version-independent non-standard ruby libraries' ] ],
164     [ 'site-ruby', [ versite,
165     'path',
166     'the directory for non-standard ruby libraries' ] ],
167     [ 'bin-dir', [ '$prefix/bin',
168     'path',
169     'the directory for commands' ] ],
170     [ 'rb-dir', [ '$site-ruby',
171     'path',
172     'the directory for ruby scripts' ] ],
173     [ 'so-dir', [ sodir,
174     'path',
175     'the directory for ruby extentions' ] ],
176     [ 'data-dir', [ '$prefix/share',
177     'path',
178     'the directory for shared data' ] ],
179     [ 'ruby-path', [ rubypath,
180     'path',
181     'path to set to #! line' ] ],
182     [ 'ruby-prog', [ rubypath,
183     'name',
184     'the ruby program using for installation' ] ],
185 yuya 1.3 [ 'make-prog', [ makeprog,
186 yuya 1.1 'name',
187     'the make program to compile ruby extentions' ] ],
188     [ 'without-ext', [ 'no',
189     'yes/no',
190     'does not compile/install ruby extentions' ] ]
191     ]
192     multipackage_descripters = [
193     [ 'with', [ '',
194     'name,name...',
195     'package names that you want to install',
196     'ALL' ] ],
197     [ 'without', [ '',
198     'name,name...',
199     'package names that you do not want to install',
200     'NONE' ] ]
201     ]
202     if multipackage_install?
203     DESCRIPTER = common_descripters + multipackage_descripters
204     else
205     DESCRIPTER = common_descripters
206     end
207    
208     SAVE_FILE = 'config.save'
209    
210 yuya 1.2 def ConfigTable.each_name(&block)
211 yuya 1.1 keys().each(&block)
212     end
213    
214     def ConfigTable.keys
215     DESCRIPTER.map {|name, *dummy| name }
216     end
217    
218 yuya 1.2 def ConfigTable.each_definition(&block)
219 yuya 1.1 DESCRIPTER.each(&block)
220     end
221    
222 yuya 1.2 def ConfigTable.get_entry(name)
223 yuya 1.1 name, ent = DESCRIPTER.assoc(name)
224     ent
225     end
226    
227 yuya 1.2 def ConfigTable.get_entry!(name)
228 yuya 1.1 get_entry(name) or raise ArgumentError, "no such config: #{name}"
229     end
230    
231 yuya 1.2 def ConfigTable.add_entry(name, vals)
232 yuya 1.1 ConfigTable::DESCRIPTER.push [name,vals]
233     end
234    
235 yuya 1.2 def ConfigTable.remove_entry(name)
236 yuya 1.1 get_entry(name) or raise ArgumentError, "no such config: #{name}"
237     DESCRIPTER.delete_if {|n, arr| n == name }
238     end
239    
240 yuya 1.2 def ConfigTable.config_key?(name)
241 yuya 1.1 get_entry(name) ? true : false
242     end
243    
244 yuya 1.2 def ConfigTable.bool_config?(name)
245 yuya 1.1 ent = get_entry(name) or return false
246     ent[1] == 'yes/no'
247     end
248    
249 yuya 1.2 def ConfigTable.value_config?(name)
250 yuya 1.1 ent = get_entry(name) or return false
251     ent[1] != 'yes/no'
252     end
253    
254 yuya 1.2 def ConfigTable.path_config?(name)
255 yuya 1.1 ent = get_entry(name) or return false
256     ent[1] == 'path'
257     end
258    
259    
260     class << self
261     alias newobj new
262     end
263    
264     def ConfigTable.new
265     c = newobj()
266     c.initialize_from_table
267     c
268     end
269    
270     def ConfigTable.load
271     c = newobj()
272     c.initialize_from_file
273     c
274     end
275    
276     def initialize_from_table
277     @table = {}
278     DESCRIPTER.each do |k, (default, vname, desc, default2)|
279     @table[k] = default
280     end
281     end
282    
283     def initialize_from_file
284     raise InstallError, "#{File.basename $0} config first"\
285 yuya 1.2 unless File.file?(SAVE_FILE)
286 yuya 1.1 @table = {}
287     File.foreach(SAVE_FILE) do |line|
288     k, v = line.split(/=/, 2)
289     @table[k] = v.strip
290     end
291     end
292    
293     def save
294     File.open(SAVE_FILE, 'w') {|f|
295 yuya 1.2 @table.each do |k, v|
296     f.printf "%s=%s\n", k, v if v
297     end
298 yuya 1.1 }
299     end
300    
301 yuya 1.2 def []=(k, v)
302 yuya 1.1 raise InstallError, "unknown config option #{k}"\
303 yuya 1.2 unless ConfigTable.config_key?(k)
304     @table[k] = v
305 yuya 1.1 end
306    
307 yuya 1.2 def [](key)
308 yuya 1.1 return nil unless @table[key]
309     @table[key].gsub(%r<\$([^/]+)>) { self[$1] }
310     end
311    
312 yuya 1.2 def set_raw(key, val)
313 yuya 1.1 @table[key] = val
314     end
315    
316 yuya 1.2 def get_raw(key)
317 yuya 1.1 @table[key]
318     end
319    
320     end
321    
322    
323     module MetaConfigAPI
324    
325 yuya 1.2 def eval_file_ifexist(fname)
326     instance_eval File.read(fname), fname, 1 if File.file?(fname)
327 yuya 1.1 end
328    
329     def config_names
330     ConfigTable.keys
331     end
332    
333 yuya 1.2 def config?(name)
334 yuya 1.1 ConfigTable.config_key?(name)
335     end
336    
337 yuya 1.2 def bool_config?(name)
338 yuya 1.1 ConfigTable.bool_config?(name)
339     end
340    
341 yuya 1.2 def value_config?(name)
342 yuya 1.1 ConfigTable.value_config?(name)
343     end
344    
345 yuya 1.2 def path_config?(name)
346 yuya 1.1 ConfigTable.path_config?(name)
347     end
348    
349 yuya 1.2 def add_config(name, argname, default, desc)
350 yuya 1.1 ConfigTable.add_entry name,[default,argname,desc]
351     end
352    
353 yuya 1.2 def add_path_config(name, default, desc)
354 yuya 1.1 add_config name, 'path', default, desc
355     end
356    
357 yuya 1.2 def add_bool_config(name, default, desc)
358 yuya 1.1 add_config name, 'yes/no', default ? 'yes' : 'no', desc
359     end
360    
361 yuya 1.2 def set_config_default(name, default)
362 yuya 1.1 if bool_config?(name)
363     ConfigTable.get_entry!(name)[0] = (default ? 'yes' : 'no')
364     else
365     ConfigTable.get_entry!(name)[0] = default
366     end
367     end
368    
369 yuya 1.2 def remove_config(name)
370 yuya 1.1 ent = ConfigTable.get_entry(name)
371     ConfigTable.remove_entry name
372     ent
373     end
374    
375     end
376 yuya 1.3
377 yuya 1.1 #
378 yuya 1.3 # File Operations
379 yuya 1.1 #
380    
381 yuya 1.3 module FileOperations
382    
383     def mkdir_p(dirname, prefix = nil)
384     dirname = prefix + dirname if prefix
385     $stderr.puts "mkdir -p #{dirname}" if verbose?
386     return if no_harm?
387    
388     # does not check '/'... it's too abnormal case
389     dirs = dirname.split(%r<(?=/)>)
390     if /\A[a-z]:\z/i =~ dirs[0]
391     disk = dirs.shift
392     dirs[0] = disk + dirs[0]
393     end
394     dirs.each_index do |idx|
395     path = dirs[0..idx].join('')
396     Dir.mkdir path unless File.dir?(path)
397     end
398     end
399    
400     def rm_f(fname)
401     $stderr.puts "rm -f #{fname}" if verbose?
402     return if no_harm?
403    
404     if File.exist?(fname) or File.symlink?(fname)
405     File.chmod 0777, fname
406     File.unlink fname
407     end
408     end
409    
410     def rm_rf(dn)
411     $stderr.puts "rm -rf #{dn}" if verbose?
412     return if no_harm?
413    
414     Dir.chdir dn
415     Dir.foreach('.') do |fn|
416     next if fn == '.'
417     next if fn == '..'
418     if File.dir?(fn)
419     verbose_off {
420     rm_rf fn
421     }
422     else
423     verbose_off {
424     rm_f fn
425     }
426     end
427     end
428     Dir.chdir '..'
429     Dir.rmdir dn
430     end
431    
432     def move_file(src, dest)
433     File.unlink dest if File.exist?(dest)
434     begin
435     File.rename src, dest
436     rescue
437     File.open(dest, 'wb') {|f| f.write File.binread(src) }
438     File.chmod File.stat(src).mode, dest
439     File.unlink src
440     end
441     end
442    
443     def install(from, dest, mode, prefix = nil)
444     $stderr.puts "install #{from} #{dest}" if verbose?
445     return if no_harm?
446    
447     realdest = prefix + dest if prefix
448     realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
449     str = File.binread(from)
450     if diff?(str, realdest)
451     verbose_off {
452     rm_f realdest if File.exist?(realdest)
453     }
454     File.open(realdest, 'wb') {|f|
455     f.write str
456     }
457     File.chmod mode, realdest
458    
459     File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
460     if prefix
461     f.puts realdest.sub(prefix, '')
462     else
463     f.puts realdest
464     end
465     }
466     end
467     end
468    
469     def diff?(new_content, path)
470     return true unless File.exist?(path)
471     new_content != File.binread(path)
472     end
473    
474     def command(str)
475     $stderr.puts str if verbose?
476     system str or raise RuntimeError, "'system #{str}' failed"
477     end
478    
479     def ruby(str)
480     command config('ruby-prog') + ' ' + str
481     end
482    
483     def make(task = '')
484     command config('make-prog') + ' ' + task
485     end
486    
487     def extdir?(dir)
488     File.exist?(dir + '/MANIFEST')
489     end
490    
491     def all_files_in(dirname)
492     Dir.open(dirname) {|d|
493     return d.select {|ent| File.file?("#{dirname}/#{ent}") }
494     }
495     end
496    
497     REJECT_DIRS = %w(
498     CVS SCCS RCS CVS.adm
499     )
500    
501     def all_dirs_in(dirname)
502     Dir.open(dirname) {|d|
503     return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS
504     }
505     end
506    
507     end
508 yuya 1.1
509 yuya 1.3 #
510     # Main Installer
511     #
512 yuya 1.1
513     class InstallError < StandardError; end
514    
515    
516     module HookUtils
517    
518 yuya 1.2 def run_hook(name)
519 yuya 1.1 try_run_hook "#{curr_srcdir()}/#{name}" or
520     try_run_hook "#{curr_srcdir()}/#{name}.rb"
521     end
522    
523 yuya 1.2 def try_run_hook(fname)
524     return false unless File.file?(fname)
525 yuya 1.1 begin
526 yuya 1.2 instance_eval File.read(fname), fname, 1
527 yuya 1.1 rescue
528     raise InstallError, "hook #{fname} failed:\n" + $!.message
529     end
530     true
531     end
532    
533     end
534    
535    
536     module HookScriptAPI
537    
538 yuya 1.2 def get_config(key)
539 yuya 1.1 @config[key]
540     end
541    
542     alias config get_config
543    
544 yuya 1.2 def set_config(key, val)
545 yuya 1.1 @config[key] = val
546     end
547    
548     #
549     # srcdir/objdir (works only in the package directory)
550     #
551    
552     #abstract srcdir_root
553     #abstract objdir_root
554     #abstract relpath
555    
556     def curr_srcdir
557     "#{srcdir_root()}/#{relpath()}"
558     end
559    
560     def curr_objdir
561     "#{objdir_root()}/#{relpath()}"
562     end
563    
564 yuya 1.2 def srcfile(path)
565 yuya 1.1 "#{curr_srcdir()}/#{path}"
566     end
567    
568 yuya 1.2 def srcexist?(path)
569     File.exist?(srcfile(path))
570 yuya 1.1 end
571    
572 yuya 1.2 def srcdirectory?(path)
573     File.dir?(srcfile(path))
574 yuya 1.1 end
575    
576 yuya 1.2 def srcfile?(path)
577     File.file? srcfile(path)
578 yuya 1.1 end
579    
580 yuya 1.2 def srcentries(path = '.')
581 yuya 1.1 Dir.open("#{curr_srcdir()}/#{path}") {|d|
582     return d.to_a - %w(. ..)
583     }
584     end
585    
586 yuya 1.2 def srcfiles(path = '.')
587 yuya 1.1 srcentries(path).select {|fname|
588 yuya 1.2 File.file?(File.join(curr_srcdir(), path, fname))
589 yuya 1.1 }
590     end
591    
592 yuya 1.2 def srcdirectories(path = '.')
593 yuya 1.1 srcentries(path).select {|fname|
594 yuya 1.2 File.dir?(File.join(curr_srcdir(), path, fname))
595 yuya 1.1 }
596     end
597    
598     end
599    
600    
601 yuya 1.3 class ToplevelInstaller
602 yuya 1.1
603 yuya 1.3 Version = '3.2.4'
604     Copyright = 'Copyright (c) 2000-2004 Minero Aoki'
605 yuya 1.1
606 yuya 1.3 TASKS = [
607     [ 'config', 'saves your configurations' ],
608     [ 'show', 'shows current configuration' ],
609     [ 'setup', 'compiles ruby extentions and others' ],
610     [ 'install', 'installs files' ],
611     [ 'clean', "does `make clean' for each extention" ],
612     [ 'distclean',"does `make distclean' for each extention" ]
613     ]
614 yuya 1.1
615 yuya 1.3 def ToplevelInstaller.invoke
616     instance().invoke
617 yuya 1.1 end
618    
619 yuya 1.3 @singleton = nil
620    
621     def ToplevelInstaller.instance
622     @singleton ||= new(File.dirname($0))
623     @singleton
624 yuya 1.1 end
625    
626 yuya 1.3 include MetaConfigAPI
627 yuya 1.1
628 yuya 1.3 def initialize(ardir_root)
629     @config = nil
630     @options = { 'verbose' => true }
631     @ardir = File.expand_path(ardir_root)
632 yuya 1.1 end
633    
634 yuya 1.3 def inspect
635     "#<#{self.class} #{__id__()}>"
636 yuya 1.1 end
637    
638 yuya 1.3 def invoke
639     run_metaconfigs
640     task = parsearg_global()
641     @config = load_config(task)
642     __send__ "parsearg_#{task}"
643     init_installers
644     __send__ "exec_#{task}"
645 yuya 1.1 end
646    
647 yuya 1.3 def run_metaconfigs
648     eval_file_ifexist "#{@ardir}/metaconfig"
649 yuya 1.1 end
650    
651 yuya 1.3 def load_config(task)
652     case task
653     when 'config'
654     ConfigTable.new
655     when 'clean', 'distclean'
656     if File.exist?('config.save')
657     then ConfigTable.load
658     else ConfigTable.new
659     end
660     else
661     ConfigTable.load
662     end
663 yuya 1.1 end
664    
665 yuya 1.3 def init_installers
666     @installer = Installer.new(@config, @options, @ardir, File.expand_path('.'))
667 yuya 1.1 end
668    
669     #
670 yuya 1.3 # Hook Script API bases
671 yuya 1.1 #
672    
673 yuya 1.3 def srcdir_root
674     @ardir
675 yuya 1.1 end
676    
677 yuya 1.3 def objdir_root
678     '.'
679 yuya 1.1 end
680    
681 yuya 1.3 def relpath
682     '.'
683 yuya 1.1 end
684    
685     #
686 yuya 1.3 # Option Parsing
687 yuya 1.1 #
688    
689 yuya 1.3 def parsearg_global
690     valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/
691    
692     while arg = ARGV.shift
693     case arg
694     when /\A\w+\z/
695     raise InstallError, "invalid task: #{arg}" unless valid_task =~ arg
696     return arg
697 yuya 1.1
698 yuya 1.3 when '-q', '--quiet'
699     @options['verbose'] = false
700 yuya 1.1
701 yuya 1.3 when '--verbose'
702     @options['verbose'] = true
703 yuya 1.1
704 yuya 1.3 when '-h', '--help'
705     print_usage $stdout
706     exit 0
707 yuya 1.1
708 yuya 1.3 when '-v', '--version'
709     puts "#{File.basename($0)} version #{Version}"
710     exit 0
711    
712     when '--copyright'
713     puts Copyright
714     exit 0
715 yuya 1.1
716 yuya 1.3 else
717     raise InstallError, "unknown global option '#{arg}'"
718     end
719 yuya 1.1 end
720 yuya 1.3
721     raise InstallError, <<EOS
722     No task or global option given.
723     Typical installation procedure is:
724     $ ruby #{File.basename($0)} config
725     $ ruby #{File.basename($0)} setup
726     # ruby #{File.basename($0)} install (may require root privilege)
727     EOS
728 yuya 1.1 end
729    
730    
731 yuya 1.3 def parsearg_no_options
732     raise InstallError, "#{task}: unknown options: #{ARGV.join ' '}"\
733     unless ARGV.empty?
734 yuya 1.1 end
735    
736 yuya 1.3 alias parsearg_show parsearg_no_options
737     alias parsearg_setup parsearg_no_options
738     alias parsearg_clean parsearg_no_options
739     alias parsearg_distclean parsearg_no_options
740 yuya 1.1
741 yuya 1.3 def parsearg_config
742     re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/
743     @options['config-opt'] = []
744 yuya 1.1
745 yuya 1.3 while i = ARGV.shift
746     if /\A--?\z/ =~ i
747     @options['config-opt'] = ARGV.dup
748     break
749     end
750     m = re.match(i) or raise InstallError, "config: unknown option #{i}"
751     name, value = m.to_a[1,2]
752     if value
753     if ConfigTable.bool_config?(name)
754     raise InstallError, "config: --#{name} allows only yes/no for argument"\
755     unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ value
756     value = (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
757     end
758     else
759     raise InstallError, "config: --#{name} requires argument"\
760     unless ConfigTable.bool_config?(name)
761     value = 'yes'
762     end
763     @config[name] = value
764     end
765 yuya 1.1 end
766    
767 yuya 1.3 def parsearg_install
768     @options['no-harm'] = false
769     @options['install-prefix'] = ''
770     while a = ARGV.shift
771     case a
772     when /\A--no-harm\z/
773     @options['no-harm'] = true
774     when /\A--prefix=(.*)\z/
775     path = $1
776     path = File.expand_path(path) unless path[0,1] == '/'
777     @options['install-prefix'] = path
778     else
779     raise InstallError, "install: unknown option #{a}"
780     end
781     end
782 yuya 1.1 end
783    
784 yuya 1.3 def print_usage(out)
785     out.puts 'Typical Installation Procedure:'
786     out.puts " $ ruby #{File.basename $0} config"
787     out.puts " $ ruby #{File.basename $0} setup"
788     out.puts " # ruby #{File.basename $0} install (may require root privilege)"
789     out.puts
790     out.puts 'Detailed Usage:'
791     out.puts " ruby #{File.basename $0} <global option>"
792     out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
793 yuya 1.1
794 yuya 1.3 fmt = " %-20s %s\n"
795     out.puts
796     out.puts 'Global options:'
797     out.printf fmt, '-q,--quiet', 'suppress message outputs'
798     out.printf fmt, ' --verbose', 'output messages verbosely'
799     out.printf fmt, '-h,--help', 'print this message'
800     out.printf fmt, '-v,--version', 'print version and quit'
801     out.printf fmt, ' --copyright', 'print copyright and quit'
802 yuya 1.1
803 yuya 1.3 out.puts
804     out.puts 'Tasks:'
805     TASKS.each do |name, desc|
806     out.printf " %-10s %s\n", name, desc
807     end
808 yuya 1.1
809 yuya 1.3 out.puts
810     out.puts 'Options for config:'
811     ConfigTable.each_definition do |name, (default, arg, desc, default2)|
812     out.printf " %-20s %s [%s]\n",
813     '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg),
814     desc,
815     default2 || default
816 yuya 1.1 end
817 yuya 1.3 out.printf " %-20s %s [%s]\n",
818     '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's"
819    
820     out.puts
821     out.puts 'Options for install:'
822     out.printf " %-20s %s [%s]\n",
823     '--no-harm', 'only display what to do if given', 'off'
824     out.printf " %-20s %s [%s]\n",
825     '--prefix', 'install path prefix', '$prefix'
826 yuya 1.1
827 yuya 1.3 out.puts
828 yuya 1.1 end
829    
830 yuya 1.3 #
831     # Task Handlers
832     #
833 yuya 1.1
834 yuya 1.3 def exec_config
835     @installer.exec_config
836     @config.save # must be final
837 yuya 1.1 end
838    
839 yuya 1.3 def exec_setup
840     @installer.exec_setup
841 yuya 1.1 end
842    
843 yuya 1.3 def exec_install
844     @installer.exec_install
845 yuya 1.1 end
846    
847 yuya 1.3 def exec_show
848     ConfigTable.each_name do |k|
849     v = @config.get_raw(k)
850     if not v or v.empty?
851     v = '(not specified)'
852 yuya 1.1 end
853 yuya 1.3 printf "%-10s %s\n", k, v
854     end
855 yuya 1.1 end
856    
857 yuya 1.3 def exec_clean
858     @installer.exec_clean
859 yuya 1.1 end
860    
861 yuya 1.3 def exec_distclean
862     @installer.exec_distclean
863 yuya 1.1 end
864    
865 yuya 1.3 end
866 yuya 1.1
867    
868 yuya 1.3 class ToplevelInstallerMulti < ToplevelInstaller
869 yuya 1.1
870 yuya 1.3 include HookUtils
871     include HookScriptAPI
872     include FileOperations
873 yuya 1.1
874 yuya 1.3 def initialize(ardir)
875     super
876     @packages = all_dirs_in("#{@ardir}/packages")
877     raise 'no package exists' if @packages.empty?
878 yuya 1.1 end
879    
880 yuya 1.3 def run_metaconfigs
881     eval_file_ifexist "#{@ardir}/metaconfig"
882     @packages.each do |name|
883     eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig"
884     end
885 yuya 1.1 end
886    
887 yuya 1.3 def init_installers
888     @installers = {}
889     @packages.each do |pack|
890     @installers[pack] = Installer.new(@config, @options,
891     "#{@ardir}/packages/#{pack}",
892     "packages/#{pack}")
893     end
894 yuya 1.1
895 yuya 1.3 with = extract_selection(config('with'))
896     without = extract_selection(config('without'))
897     @selected = @installers.keys.select {|name|
898     (with.empty? or with.include?(name)) \
899     and not without.include?(name)
900     }
901 yuya 1.1 end
902    
903 yuya 1.3 def extract_selection(list)
904     a = list.split(/,/)
905     a.each do |name|
906     raise InstallError, "no such package: #{name}" \
907     unless @installers.key?(name)
908     end
909     a
910 yuya 1.1 end
911    
912 yuya 1.3 def print_usage(f)
913     super
914     f.puts 'Inluded packages:'
915     f.puts ' ' + @packages.sort.join(' ')
916     f.puts
917 yuya 1.1 end
918    
919     #
920 yuya 1.3 # multi-package metaconfig API
921 yuya 1.1 #
922    
923 yuya 1.3 attr_reader :packages
924    
925     def declare_packages(list)
926     raise 'package list is empty' if list.empty?
927     list.each do |name|
928     raise "directory packages/#{name} does not exist"\
929     unless File.dir?("#{@ardir}/packages/#{name}")
930 yuya 1.1 end
931 yuya 1.3 @packages = list
932 yuya 1.1 end
933    
934 yuya 1.3 #
935     # Task Handlers
936     #
937    
938     def exec_config
939     run_hook 'pre-config'
940     each_selected_installers {|inst| inst.exec_config }
941     run_hook 'post-config'
942     @config.save # must be final
943 yuya 1.1 end
944    
945 yuya 1.3 def exec_setup
946     run_hook 'pre-setup'
947     each_selected_installers {|inst| inst.exec_setup }
948     run_hook 'post-setup'
949 yuya 1.1 end
950    
951 yuya 1.3 def exec_install
952     run_hook 'pre-install'
953     each_selected_installers {|inst| inst.exec_install }
954     run_hook 'post-install'
955 yuya 1.1 end
956    
957 yuya 1.3 def exec_clean
958     rm_f 'config.save'
959     run_hook 'pre-clean'
960     each_selected_installers {|inst| inst.exec_clean }
961     run_hook 'post-clean'
962     end
963 yuya 1.1
964 yuya 1.3 def exec_distclean
965     rm_f 'config.save'
966     run_hook 'pre-distclean'
967     each_selected_installers {|inst| inst.exec_distclean }
968     run_hook 'post-distclean'
969 yuya 1.1 end
970    
971 yuya 1.3 #
972     # lib
973     #
974 yuya 1.1
975 yuya 1.3 def each_selected_installers
976     Dir.mkdir 'packages' unless File.dir?('packages')
977     @selected.each do |pack|
978     $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose']
979     Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
980     Dir.chdir "packages/#{pack}"
981     yield @installers[pack]
982     Dir.chdir '../..'
983     end
984 yuya 1.1 end
985    
986 yuya 1.3 def verbose?
987     @options['verbose']
988 yuya 1.1 end
989    
990 yuya 1.3 def no_harm?
991     @options['no-harm']
992 yuya 1.1 end
993    
994 yuya 1.3 end
995    
996    
997     class Installer
998    
999     FILETYPES = %w( bin lib ext data )
1000    
1001     include HookScriptAPI
1002     include HookUtils
1003     include FileOperations
1004 yuya 1.1
1005 yuya 1.3 def initialize(config, opt, srcroot, objroot)
1006     @config = config
1007     @options = opt
1008     @srcdir = File.expand_path(srcroot)
1009     @objdir = File.expand_path(objroot)
1010     @currdir = '.'
1011 yuya 1.1 end
1012    
1013 yuya 1.3 def inspect
1014     "#<#{self.class} #{File.basename(@srcdir)}>"
1015 yuya 1.1 end
1016    
1017     #
1018     # Hook Script API bases
1019     #
1020    
1021     def srcdir_root
1022 yuya 1.3 @srcdir
1023 yuya 1.1 end
1024    
1025     def objdir_root
1026 yuya 1.3 @objdir
1027 yuya 1.1 end
1028    
1029     def relpath
1030 yuya 1.3 @currdir
1031 yuya 1.1 end
1032    
1033     #
1034 yuya 1.3 # configs/options
1035 yuya 1.1 #
1036    
1037 yuya 1.3 def no_harm?
1038     @options['no-harm']
1039     end
1040 yuya 1.1
1041 yuya 1.3 def verbose?
1042     @options['verbose']
1043     end
1044 yuya 1.1
1045 yuya 1.3 def verbose_off
1046     begin
1047     save, @options['verbose'] = @options['verbose'], false
1048     yield
1049     ensure
1050     @options['verbose'] = save
1051     end
1052     end
1053 yuya 1.1
1054 yuya 1.3 #
1055     # TASK config
1056     #
1057 yuya 1.1
1058 yuya 1.3 def exec_config
1059     exec_task_traverse 'config'
1060     end
1061 yuya 1.1
1062 yuya 1.3 def config_dir_bin(rel)
1063     end
1064 yuya 1.1
1065 yuya 1.3 def config_dir_lib(rel)
1066     end
1067 yuya 1.1
1068 yuya 1.3 def config_dir_ext(rel)
1069     extconf if extdir?(curr_srcdir())
1070 yuya 1.1 end
1071    
1072 yuya 1.3 def extconf
1073     opt = @options['config-opt'].join(' ')
1074     command "#{config('ruby-prog')} #{curr_srcdir()}/extconf.rb #{opt}"
1075     end
1076 yuya 1.1
1077 yuya 1.3 def config_dir_data(rel)
1078 yuya 1.1 end
1079    
1080 yuya 1.3 #
1081     # TASK setup
1082     #
1083 yuya 1.1
1084 yuya 1.3 def exec_setup
1085     exec_task_traverse 'setup'
1086     end
1087 yuya 1.1
1088 yuya 1.3 def setup_dir_bin(rel)
1089     all_files_in(curr_srcdir()).each do |fname|
1090     adjust_shebang "#{curr_srcdir()}/#{fname}"
1091 yuya 1.1 end
1092     end
1093    
1094 yuya 1.3 # modify: #!/usr/bin/ruby
1095     # modify: #! /usr/bin/ruby
1096     # modify: #!ruby
1097     # not modify: #!/usr/bin/env ruby
1098     SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
1099 yuya 1.1
1100 yuya 1.3 def adjust_shebang(path)
1101     return if no_harm?
1102 yuya 1.1
1103 yuya 1.3 tmpfile = File.basename(path) + '.tmp'
1104     begin
1105     File.open(path, 'rb') {|r|
1106     File.open(tmpfile, 'wb') {|w|
1107     first = r.gets
1108     return unless SHEBANG_RE =~ first
1109 yuya 1.1
1110 yuya 1.3 $stderr.puts "adjusting shebang: #{File.basename path}" if verbose?
1111     w.print first.sub(SHEBANG_RE, '#!' + config('ruby-path'))
1112     w.write r.read
1113     }
1114     }
1115     move_file tmpfile, File.basename(path)
1116     ensure
1117     File.unlink tmpfile if File.exist?(tmpfile)
1118 yuya 1.1 end
1119 yuya 1.3 end
1120 yuya 1.1
1121 yuya 1.3 def setup_dir_lib(rel)
1122     end
1123 yuya 1.1
1124 yuya 1.3 def setup_dir_ext(rel)
1125     make if extdir?(curr_srcdir())
1126     end
1127 yuya 1.1
1128 yuya 1.3 def setup_dir_data(rel)
1129 yuya 1.1 end
1130    
1131     #
1132 yuya 1.3 # TASK install
1133 yuya 1.1 #
1134    
1135 yuya 1.3 def exec_install
1136     exec_task_traverse 'install'
1137     end
1138    
1139     def install_dir_bin(rel)
1140     install_files collect_filenames_auto(), "#{config('bin-dir')}/#{rel}", 0755
1141 yuya 1.1 end
1142    
1143 yuya 1.3 def install_dir_lib(rel)
1144     install_files ruby_scripts(), "#{config('rb-dir')}/#{rel}", 0644
1145 yuya 1.1 end
1146    
1147 yuya 1.3 def install_dir_ext(rel)
1148     return unless extdir?(curr_srcdir())
1149     install_files ruby_extentions('.'),
1150     "#{config('so-dir')}/#{File.dirname(rel)}",
1151     0555
1152 yuya 1.1 end
1153    
1154 yuya 1.3 def install_dir_data(rel)
1155     install_files collect_filenames_auto(), "#{config('data-dir')}/#{rel}", 0644
1156 yuya 1.1 end
1157    
1158 yuya 1.3 def install_files(list, dest, mode)
1159     mkdir_p dest, @options['install-prefix']
1160     list.each do |fname|
1161     install fname, dest, mode, @options['install-prefix']
1162     end
1163 yuya 1.1 end
1164    
1165 yuya 1.3 def ruby_scripts
1166     collect_filenames_auto().select {|n| /\.rb\z/ =~ n }
1167 yuya 1.1 end
1168 yuya 1.3
1169     # picked up many entries from cvs-1.11.1/src/ignore.c
1170     reject_patterns = %w(
1171     core RCSLOG tags TAGS .make.state
1172     .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1173     *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1174 yuya 1.1
1175 yuya 1.3 *.org *.in .*
1176     )
1177     mapping = {
1178     '.' => '\.',
1179     '$' => '\$',
1180     '#' => '\#',
1181     '*' => '.*'
1182     }
1183     REJECT_PATTERNS = Regexp.new('\A(?:' +
1184     reject_patterns.map {|pat|
1185     pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] }
1186     }.join('|') +
1187     ')\z')
1188 yuya 1.1
1189 yuya 1.3 def collect_filenames_auto
1190     mapdir((existfiles() - hookfiles()).reject {|fname|
1191     REJECT_PATTERNS =~ fname
1192     })
1193     end
1194 yuya 1.1
1195 yuya 1.3 def existfiles
1196     all_files_in(curr_srcdir()) | all_files_in('.')
1197     end
1198 yuya 1.1
1199 yuya 1.3 def hookfiles
1200     %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1201     %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1202     }.flatten
1203     end
1204 yuya 1.1
1205 yuya 1.3 def mapdir(filelist)
1206     filelist.map {|fname|
1207     if File.exist?(fname) # objdir
1208     fname
1209     else # srcdir
1210     File.join(curr_srcdir(), fname)
1211     end
1212     }
1213 yuya 1.1 end
1214    
1215 yuya 1.3 def ruby_extentions(dir)
1216     _ruby_extentions(dir) or
1217     raise InstallError, "no ruby extention exists: 'ruby #{$0} setup' first"
1218 yuya 1.1 end
1219    
1220 yuya 1.3 DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/
1221 yuya 1.1
1222 yuya 1.3 def _ruby_extentions(dir)
1223     Dir.open(dir) {|d|
1224     return d.select {|fname| DLEXT =~ fname }
1225     }
1226 yuya 1.1 end
1227    
1228 yuya 1.3 #
1229     # TASK clean
1230     #
1231    
1232     def exec_clean
1233     exec_task_traverse 'clean'
1234     rm_f 'config.save'
1235     rm_f 'InstalledFiles'
1236 yuya 1.1 end
1237    
1238 yuya 1.3 def clean_dir_bin(rel)
1239 yuya 1.1 end
1240    
1241 yuya 1.3 def clean_dir_lib(rel)
1242     end
1243 yuya 1.1
1244 yuya 1.3 def clean_dir_ext(rel)
1245     return unless extdir?(curr_srcdir())
1246     make 'clean' if File.file?('Makefile')
1247     end
1248 yuya 1.1
1249 yuya 1.3 def clean_dir_data(rel)
1250 yuya 1.1 end
1251    
1252     #
1253 yuya 1.3 # TASK distclean
1254 yuya 1.1 #
1255    
1256 yuya 1.3 def exec_distclean
1257     exec_task_traverse 'distclean'
1258     rm_f 'config.save'
1259     rm_f 'InstalledFiles'
1260 yuya 1.1 end
1261    
1262 yuya 1.3 def distclean_dir_bin(rel)
1263 yuya 1.1 end
1264    
1265 yuya 1.3 def distclean_dir_lib(rel)
1266 yuya 1.1 end
1267    
1268 yuya 1.3 def distclean_dir_ext(rel)
1269     return unless extdir?(curr_srcdir())
1270     make 'distclean' if File.file?('Makefile')
1271 yuya 1.1 end
1272    
1273     #
1274     # lib
1275     #
1276    
1277 yuya 1.3 def exec_task_traverse(task)
1278     run_hook "pre-#{task}"
1279     FILETYPES.each do |type|
1280     if config('without-ext') == 'yes' and type == 'ext'
1281     $stderr.puts 'skipping ext/* by user option' if verbose?
1282     next
1283     end
1284     traverse task, type, "#{task}_dir_#{type}"
1285 yuya 1.1 end
1286 yuya 1.3 run_hook "post-#{task}"
1287 yuya 1.1 end
1288    
1289 yuya 1.3 def traverse(task, rel, mid)
1290     dive_into(rel) {
1291     run_hook "pre-#{task}"
1292     __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1293     all_dirs_in(curr_srcdir()).each do |d|
1294     traverse task, "#{rel}/#{d}", mid
1295     end
1296     run_hook "post-#{task}"
1297     }
1298 yuya 1.1 end
1299    
1300 yuya 1.3 def dive_into(rel)
1301     return unless File.dir?("#{@srcdir}/#{rel}")
1302    
1303     dir = File.basename(rel)
1304     Dir.mkdir dir unless File.dir?(dir)
1305     prevdir = Dir.pwd
1306     Dir.chdir dir
1307     $stderr.puts '---> ' + rel if verbose?
1308     @currdir = rel
1309     yield
1310     Dir.chdir prevdir
1311     $stderr.puts '<--- ' + rel if verbose?
1312     @currdir = File.dirname(rel)
1313 yuya 1.1 end
1314    
1315     end
1316    
1317 yuya 1.3
1318 yuya 1.1 if $0 == __FILE__
1319     begin
1320     if multipackage_install?
1321     ToplevelInstallerMulti.invoke
1322     else
1323     ToplevelInstaller.invoke
1324     end
1325     rescue
1326     raise if $DEBUG
1327     $stderr.puts $!.message
1328     $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1329     exit 1
1330     end
1331     end

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26