pkg-config 1.1.3 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/setup.rb DELETED
@@ -1,1586 +0,0 @@
1
- #
2
- # setup.rb
3
- #
4
- # Copyright (c) 2000-2005 Minero Aoki
5
- #
6
- # This program is free software.
7
- # You can distribute/modify this program under the terms of
8
- # the GNU LGPL, Lesser General Public License version 2.1.
9
- #
10
-
11
- unless Enumerable.method_defined?(:map) # Ruby 1.4.6
12
- module Enumerable
13
- alias map collect
14
- end
15
- end
16
-
17
- unless File.respond_to?(:read) # Ruby 1.6
18
- def File.read(fname)
19
- open(fname) {|f|
20
- return f.read
21
- }
22
- end
23
- end
24
-
25
- unless Errno.const_defined?(:ENOTEMPTY) # Windows?
26
- module Errno
27
- class ENOTEMPTY
28
- # We do not raise this exception, implementation is not needed.
29
- end
30
- end
31
- end
32
-
33
- def File.binread(fname)
34
- open(fname, 'rb') {|f|
35
- return f.read
36
- }
37
- end
38
-
39
- # for corrupted Windows' stat(2)
40
- def File.dir?(path)
41
- File.directory?((path[-1,1] == '/') ? path : path + '/')
42
- end
43
-
44
-
45
- class ConfigTable
46
-
47
- include Enumerable
48
-
49
- def initialize(rbconfig)
50
- @rbconfig = rbconfig
51
- @items = []
52
- @table = {}
53
- # options
54
- @install_prefix = nil
55
- @config_opt = nil
56
- @verbose = true
57
- @no_harm = false
58
- end
59
-
60
- attr_accessor :install_prefix
61
- attr_accessor :config_opt
62
-
63
- attr_writer :verbose
64
-
65
- def verbose?
66
- @verbose
67
- end
68
-
69
- attr_writer :no_harm
70
-
71
- def no_harm?
72
- @no_harm
73
- end
74
-
75
- def [](key)
76
- lookup(key).resolve(self)
77
- end
78
-
79
- def []=(key, val)
80
- lookup(key).set val
81
- end
82
-
83
- def names
84
- @items.map {|i| i.name }
85
- end
86
-
87
- def each(&block)
88
- @items.each(&block)
89
- end
90
-
91
- def key?(name)
92
- @table.key?(name)
93
- end
94
-
95
- def lookup(name)
96
- @table[name] or setup_rb_error "no such config item: #{name}"
97
- end
98
-
99
- def add(item)
100
- @items.push item
101
- @table[item.name] = item
102
- end
103
-
104
- def remove(name)
105
- item = lookup(name)
106
- @items.delete_if {|i| i.name == name }
107
- @table.delete_if {|name, i| i.name == name }
108
- item
109
- end
110
-
111
- def load_script(path, inst = nil)
112
- if File.file?(path)
113
- MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
114
- end
115
- end
116
-
117
- def savefile
118
- '.config'
119
- end
120
-
121
- def load_savefile
122
- begin
123
- File.foreach(savefile()) do |line|
124
- k, v = *line.split(/=/, 2)
125
- self[k] = v.strip
126
- end
127
- rescue Errno::ENOENT
128
- setup_rb_error $!.message + "\n#{File.basename($0)} config first"
129
- end
130
- end
131
-
132
- def save
133
- @items.each {|i| i.value }
134
- File.open(savefile(), 'w') {|f|
135
- @items.each do |i|
136
- f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
137
- end
138
- }
139
- end
140
-
141
- def load_standard_entries
142
- standard_entries(@rbconfig).each do |ent|
143
- add ent
144
- end
145
- end
146
-
147
- def standard_entries(rbconfig)
148
- c = rbconfig
149
-
150
- rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT'])
151
-
152
- major = c['MAJOR'].to_i
153
- minor = c['MINOR'].to_i
154
- teeny = c['TEENY'].to_i
155
- version = "#{major}.#{minor}"
156
-
157
- # ruby ver. >= 1.4.4?
158
- newpath_p = ((major >= 2) or
159
- ((major == 1) and
160
- ((minor >= 5) or
161
- ((minor == 4) and (teeny >= 4)))))
162
-
163
- if c['rubylibdir']
164
- # V > 1.6.3
165
- libruby = "#{c['prefix']}/lib/ruby"
166
- librubyver = c['rubylibdir']
167
- librubyverarch = c['archdir']
168
- siteruby = c['sitedir']
169
- siterubyver = c['sitelibdir']
170
- siterubyverarch = c['sitearchdir']
171
- elsif newpath_p
172
- # 1.4.4 <= V <= 1.6.3
173
- libruby = "#{c['prefix']}/lib/ruby"
174
- librubyver = "#{c['prefix']}/lib/ruby/#{version}"
175
- librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
176
- siteruby = c['sitedir']
177
- siterubyver = "$siteruby/#{version}"
178
- siterubyverarch = "$siterubyver/#{c['arch']}"
179
- else
180
- # V < 1.4.4
181
- libruby = "#{c['prefix']}/lib/ruby"
182
- librubyver = "#{c['prefix']}/lib/ruby/#{version}"
183
- librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
184
- siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
185
- siterubyver = siteruby
186
- siterubyverarch = "$siterubyver/#{c['arch']}"
187
- end
188
- parameterize = lambda {|path|
189
- path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
190
- }
191
-
192
- if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
193
- makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
194
- else
195
- makeprog = 'make'
196
- end
197
-
198
- [
199
- ExecItem.new('installdirs', 'std/site/home',
200
- 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\
201
- {|val, table|
202
- case val
203
- when 'std'
204
- table['rbdir'] = '$librubyver'
205
- table['sodir'] = '$librubyverarch'
206
- when 'site'
207
- table['rbdir'] = '$siterubyver'
208
- table['sodir'] = '$siterubyverarch'
209
- when 'home'
210
- setup_rb_error '$HOME was not set' unless ENV['HOME']
211
- table['prefix'] = ENV['HOME']
212
- table['rbdir'] = '$libdir/ruby'
213
- table['sodir'] = '$libdir/ruby'
214
- end
215
- },
216
- PathItem.new('prefix', 'path', c['prefix'],
217
- 'path prefix of target environment'),
218
- PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
219
- 'the directory for commands'),
220
- PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
221
- 'the directory for libraries'),
222
- PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
223
- 'the directory for shared data'),
224
- PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
225
- 'the directory for man pages'),
226
- PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
227
- 'the directory for system configuration files'),
228
- PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),
229
- 'the directory for local state data'),
230
- PathItem.new('libruby', 'path', libruby,
231
- 'the directory for ruby libraries'),
232
- PathItem.new('librubyver', 'path', librubyver,
233
- 'the directory for standard ruby libraries'),
234
- PathItem.new('librubyverarch', 'path', librubyverarch,
235
- 'the directory for standard ruby extensions'),
236
- PathItem.new('siteruby', 'path', siteruby,
237
- 'the directory for version-independent aux ruby libraries'),
238
- PathItem.new('siterubyver', 'path', siterubyver,
239
- 'the directory for aux ruby libraries'),
240
- PathItem.new('siterubyverarch', 'path', siterubyverarch,
241
- 'the directory for aux ruby binaries'),
242
- PathItem.new('rbdir', 'path', '$siterubyver',
243
- 'the directory for ruby scripts'),
244
- PathItem.new('sodir', 'path', '$siterubyverarch',
245
- 'the directory for ruby extentions'),
246
- PathItem.new('rubypath', 'path', rubypath,
247
- 'the path to set to #! line'),
248
- ProgramItem.new('rubyprog', 'name', rubypath,
249
- 'the ruby program using for installation'),
250
- ProgramItem.new('makeprog', 'name', makeprog,
251
- 'the make program to compile ruby extentions'),
252
- SelectItem.new('shebang', 'all/ruby/never', 'ruby',
253
- 'shebang line (#!) editing mode'),
254
- BoolItem.new('without-ext', 'yes/no', 'no',
255
- 'does not compile/install ruby extentions')
256
- ]
257
- end
258
- private :standard_entries
259
-
260
- def load_multipackage_entries
261
- multipackage_entries().each do |ent|
262
- add ent
263
- end
264
- end
265
-
266
- def multipackage_entries
267
- [
268
- PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
269
- 'package names that you want to install'),
270
- PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
271
- 'package names that you do not want to install')
272
- ]
273
- end
274
- private :multipackage_entries
275
-
276
- ALIASES = {
277
- 'std-ruby' => 'librubyver',
278
- 'stdruby' => 'librubyver',
279
- 'rubylibdir' => 'librubyver',
280
- 'archdir' => 'librubyverarch',
281
- 'site-ruby-common' => 'siteruby', # For backward compatibility
282
- 'site-ruby' => 'siterubyver', # For backward compatibility
283
- 'bin-dir' => 'bindir',
284
- 'bin-dir' => 'bindir',
285
- 'rb-dir' => 'rbdir',
286
- 'so-dir' => 'sodir',
287
- 'data-dir' => 'datadir',
288
- 'ruby-path' => 'rubypath',
289
- 'ruby-prog' => 'rubyprog',
290
- 'ruby' => 'rubyprog',
291
- 'make-prog' => 'makeprog',
292
- 'make' => 'makeprog'
293
- }
294
-
295
- def fixup
296
- ALIASES.each do |ali, name|
297
- @table[ali] = @table[name]
298
- end
299
- end
300
-
301
- def options_re
302
- /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
303
- end
304
-
305
- def parse_opt(opt)
306
- m = options_re().match(opt) or setup_rb_error "config: unknown option #{opt}"
307
- m.to_a[1,2]
308
- end
309
-
310
- def dllext
311
- @rbconfig['DLEXT']
312
- end
313
-
314
- def value_config?(name)
315
- lookup(name).value?
316
- end
317
-
318
- class Item
319
- def initialize(name, template, default, desc)
320
- @name = name.freeze
321
- @template = template
322
- @value = default
323
- @default = default
324
- @description = desc
325
- end
326
-
327
- attr_reader :name
328
- attr_reader :description
329
-
330
- attr_accessor :default
331
- alias help_default default
332
-
333
- def help_opt
334
- "--#{@name}=#{@template}"
335
- end
336
-
337
- def value?
338
- true
339
- end
340
-
341
- def value
342
- @value
343
- end
344
-
345
- def resolve(table)
346
- @value.gsub(%r<\$([^/]+)>) { table[$1] }
347
- end
348
-
349
- def set(val)
350
- @value = check(val)
351
- end
352
-
353
- private
354
-
355
- def check(val)
356
- setup_rb_error "config: --#{name} requires argument" unless val
357
- val
358
- end
359
- end
360
-
361
- class BoolItem < Item
362
- def config_type
363
- 'bool'
364
- end
365
-
366
- def help_opt
367
- "--#{@name}"
368
- end
369
-
370
- private
371
-
372
- def check(val)
373
- return 'yes' unless val
374
- case val
375
- when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes'
376
- when /\An(o)?\z/i, /\Af(alse)\z/i then 'no'
377
- else
378
- setup_rb_error "config: --#{@name} accepts only yes/no for argument"
379
- end
380
- end
381
- end
382
-
383
- class PathItem < Item
384
- def config_type
385
- 'path'
386
- end
387
-
388
- private
389
-
390
- def check(path)
391
- setup_rb_error "config: --#{@name} requires argument" unless path
392
- path[0,1] == '$' ? path : File.expand_path(path)
393
- end
394
- end
395
-
396
- class ProgramItem < Item
397
- def config_type
398
- 'program'
399
- end
400
- end
401
-
402
- class SelectItem < Item
403
- def initialize(name, selection, default, desc)
404
- super
405
- @ok = selection.split('/')
406
- end
407
-
408
- def config_type
409
- 'select'
410
- end
411
-
412
- private
413
-
414
- def check(val)
415
- unless @ok.include?(val.strip)
416
- setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
417
- end
418
- val.strip
419
- end
420
- end
421
-
422
- class ExecItem < Item
423
- def initialize(name, selection, desc, &block)
424
- super name, selection, nil, desc
425
- @ok = selection.split('/')
426
- @action = block
427
- end
428
-
429
- def config_type
430
- 'exec'
431
- end
432
-
433
- def value?
434
- false
435
- end
436
-
437
- def resolve(table)
438
- setup_rb_error "$#{name()} wrongly used as option value"
439
- end
440
-
441
- undef set
442
-
443
- def evaluate(val, table)
444
- v = val.strip.downcase
445
- unless @ok.include?(v)
446
- setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})"
447
- end
448
- @action.call v, table
449
- end
450
- end
451
-
452
- class PackageSelectionItem < Item
453
- def initialize(name, template, default, help_default, desc)
454
- super name, template, default, desc
455
- @help_default = help_default
456
- end
457
-
458
- attr_reader :help_default
459
-
460
- def config_type
461
- 'package'
462
- end
463
-
464
- private
465
-
466
- def check(val)
467
- unless File.dir?("packages/#{val}")
468
- setup_rb_error "config: no such package: #{val}"
469
- end
470
- val
471
- end
472
- end
473
-
474
- class MetaConfigEnvironment
475
- def initialize(config, installer)
476
- @config = config
477
- @installer = installer
478
- end
479
-
480
- def config_names
481
- @config.names
482
- end
483
-
484
- def config?(name)
485
- @config.key?(name)
486
- end
487
-
488
- def bool_config?(name)
489
- @config.lookup(name).config_type == 'bool'
490
- end
491
-
492
- def path_config?(name)
493
- @config.lookup(name).config_type == 'path'
494
- end
495
-
496
- def value_config?(name)
497
- @config.lookup(name).config_type != 'exec'
498
- end
499
-
500
- def add_config(item)
501
- @config.add item
502
- end
503
-
504
- def add_bool_config(name, default, desc)
505
- @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
506
- end
507
-
508
- def add_path_config(name, default, desc)
509
- @config.add PathItem.new(name, 'path', default, desc)
510
- end
511
-
512
- def set_config_default(name, default)
513
- @config.lookup(name).default = default
514
- end
515
-
516
- def remove_config(name)
517
- @config.remove(name)
518
- end
519
-
520
- # For only multipackage
521
- def packages
522
- raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
523
- @installer.packages
524
- end
525
-
526
- # For only multipackage
527
- def declare_packages(list)
528
- raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer
529
- @installer.packages = list
530
- end
531
- end
532
-
533
- end # class ConfigTable
534
-
535
-
536
- # This module requires: #verbose?, #no_harm?
537
- module FileOperations
538
-
539
- def mkdir_p(dirname, prefix = nil)
540
- dirname = prefix + File.expand_path(dirname) if prefix
541
- $stderr.puts "mkdir -p #{dirname}" if verbose?
542
- return if no_harm?
543
-
544
- # Does not check '/', it's too abnormal.
545
- dirs = File.expand_path(dirname).split(%r<(?=/)>)
546
- if /\A[a-z]:\z/i =~ dirs[0]
547
- disk = dirs.shift
548
- dirs[0] = disk + dirs[0]
549
- end
550
- dirs.each_index do |idx|
551
- path = dirs[0..idx].join('')
552
- Dir.mkdir path unless File.dir?(path)
553
- end
554
- end
555
-
556
- def rm_f(path)
557
- $stderr.puts "rm -f #{path}" if verbose?
558
- return if no_harm?
559
- force_remove_file path
560
- end
561
-
562
- def rm_rf(path)
563
- $stderr.puts "rm -rf #{path}" if verbose?
564
- return if no_harm?
565
- remove_tree path
566
- end
567
-
568
- def remove_tree(path)
569
- if File.symlink?(path)
570
- remove_file path
571
- elsif File.dir?(path)
572
- remove_tree0 path
573
- else
574
- force_remove_file path
575
- end
576
- end
577
-
578
- def remove_tree0(path)
579
- Dir.foreach(path) do |ent|
580
- next if ent == '.'
581
- next if ent == '..'
582
- entpath = "#{path}/#{ent}"
583
- if File.symlink?(entpath)
584
- remove_file entpath
585
- elsif File.dir?(entpath)
586
- remove_tree0 entpath
587
- else
588
- force_remove_file entpath
589
- end
590
- end
591
- begin
592
- Dir.rmdir path
593
- rescue Errno::ENOTEMPTY
594
- # directory may not be empty
595
- end
596
- end
597
-
598
- def move_file(src, dest)
599
- force_remove_file dest
600
- begin
601
- File.rename src, dest
602
- rescue
603
- File.open(dest, 'wb') {|f|
604
- f.write File.binread(src)
605
- }
606
- File.chmod File.stat(src).mode, dest
607
- File.unlink src
608
- end
609
- end
610
-
611
- def force_remove_file(path)
612
- begin
613
- remove_file path
614
- rescue
615
- end
616
- end
617
-
618
- def remove_file(path)
619
- File.chmod 0777, path
620
- File.unlink path
621
- end
622
-
623
- def install(from, dest, mode, prefix = nil)
624
- $stderr.puts "install #{from} #{dest}" if verbose?
625
- return if no_harm?
626
-
627
- realdest = prefix ? prefix + File.expand_path(dest) : dest
628
- realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
629
- str = File.binread(from)
630
- if diff?(str, realdest)
631
- verbose_off {
632
- rm_f realdest if File.exist?(realdest)
633
- }
634
- File.open(realdest, 'wb') {|f|
635
- f.write str
636
- }
637
- File.chmod mode, realdest
638
-
639
- File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
640
- if prefix
641
- f.puts realdest.sub(prefix, '')
642
- else
643
- f.puts realdest
644
- end
645
- }
646
- end
647
- end
648
-
649
- def diff?(new_content, path)
650
- return true unless File.exist?(path)
651
- new_content != File.binread(path)
652
- end
653
-
654
- def command(*args)
655
- $stderr.puts args.join(' ') if verbose?
656
- system(*args) or raise RuntimeError,
657
- "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
658
- end
659
-
660
- def ruby(*args)
661
- command config('rubyprog'), *args
662
- end
663
-
664
- def make(task = nil)
665
- command(*[config('makeprog'), task].compact)
666
- end
667
-
668
- def extdir?(dir)
669
- File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
670
- end
671
-
672
- def files_of(dir)
673
- Dir.open(dir) {|d|
674
- return d.select {|ent| File.file?("#{dir}/#{ent}") }
675
- }
676
- end
677
-
678
- DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
679
-
680
- def directories_of(dir)
681
- Dir.open(dir) {|d|
682
- return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
683
- }
684
- end
685
-
686
- end
687
-
688
-
689
- # This module requires: #srcdir_root, #objdir_root, #relpath
690
- module HookScriptAPI
691
-
692
- def get_config(key)
693
- @config[key]
694
- end
695
-
696
- alias config get_config
697
-
698
- # obsolete: use metaconfig to change configuration
699
- def set_config(key, val)
700
- @config[key] = val
701
- end
702
-
703
- #
704
- # srcdir/objdir (works only in the package directory)
705
- #
706
-
707
- def curr_srcdir
708
- "#{srcdir_root()}/#{relpath()}"
709
- end
710
-
711
- def curr_objdir
712
- "#{objdir_root()}/#{relpath()}"
713
- end
714
-
715
- def srcfile(path)
716
- "#{curr_srcdir()}/#{path}"
717
- end
718
-
719
- def srcexist?(path)
720
- File.exist?(srcfile(path))
721
- end
722
-
723
- def srcdirectory?(path)
724
- File.dir?(srcfile(path))
725
- end
726
-
727
- def srcfile?(path)
728
- File.file?(srcfile(path))
729
- end
730
-
731
- def srcentries(path = '.')
732
- Dir.open("#{curr_srcdir()}/#{path}") {|d|
733
- return d.to_a - %w(. ..)
734
- }
735
- end
736
-
737
- def srcfiles(path = '.')
738
- srcentries(path).select {|fname|
739
- File.file?(File.join(curr_srcdir(), path, fname))
740
- }
741
- end
742
-
743
- def srcdirectories(path = '.')
744
- srcentries(path).select {|fname|
745
- File.dir?(File.join(curr_srcdir(), path, fname))
746
- }
747
- end
748
-
749
- end
750
-
751
-
752
- class ToplevelInstaller
753
-
754
- Version = '3.4.1'
755
- Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
756
-
757
- TASKS = [
758
- [ 'all', 'do config, setup, then install' ],
759
- [ 'config', 'saves your configurations' ],
760
- [ 'show', 'shows current configuration' ],
761
- [ 'setup', 'compiles ruby extentions and others' ],
762
- [ 'install', 'installs files' ],
763
- [ 'test', 'run all tests in test/' ],
764
- [ 'clean', "does `make clean' for each extention" ],
765
- [ 'distclean',"does `make distclean' for each extention" ]
766
- ]
767
-
768
- def ToplevelInstaller.invoke
769
- config = ConfigTable.new(load_rbconfig())
770
- config.load_standard_entries
771
- config.load_multipackage_entries if multipackage?
772
- config.fixup
773
- klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
774
- klass.new(File.dirname($0), config).invoke
775
- end
776
-
777
- def ToplevelInstaller.multipackage?
778
- File.dir?(File.dirname($0) + '/packages')
779
- end
780
-
781
- def ToplevelInstaller.load_rbconfig
782
- if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
783
- ARGV.delete(arg)
784
- load File.expand_path(arg.split(/=/, 2)[1])
785
- $".push 'rbconfig.rb'
786
- else
787
- require 'rbconfig'
788
- end
789
- ::Config::CONFIG
790
- end
791
-
792
- def initialize(ardir_root, config)
793
- @ardir = File.expand_path(ardir_root)
794
- @config = config
795
- # cache
796
- @valid_task_re = nil
797
- end
798
-
799
- def config(key)
800
- @config[key]
801
- end
802
-
803
- def inspect
804
- "#<#{self.class} #{__id__()}>"
805
- end
806
-
807
- def invoke
808
- run_metaconfigs
809
- case task = parsearg_global()
810
- when nil, 'all'
811
- parsearg_config
812
- init_installers
813
- exec_config
814
- exec_setup
815
- exec_install
816
- else
817
- case task
818
- when 'config', 'test'
819
- ;
820
- when 'clean', 'distclean'
821
- @config.load_savefile if File.exist?(@config.savefile)
822
- else
823
- @config.load_savefile
824
- end
825
- __send__ "parsearg_#{task}"
826
- init_installers
827
- __send__ "exec_#{task}"
828
- end
829
- end
830
-
831
- def run_metaconfigs
832
- @config.load_script "#{@ardir}/metaconfig"
833
- end
834
-
835
- def init_installers
836
- @installer = Installer.new(@config, @ardir, File.expand_path('.'))
837
- end
838
-
839
- #
840
- # Hook Script API bases
841
- #
842
-
843
- def srcdir_root
844
- @ardir
845
- end
846
-
847
- def objdir_root
848
- '.'
849
- end
850
-
851
- def relpath
852
- '.'
853
- end
854
-
855
- #
856
- # Option Parsing
857
- #
858
-
859
- def parsearg_global
860
- while arg = ARGV.shift
861
- case arg
862
- when /\A\w+\z/
863
- setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
864
- return arg
865
- when '-q', '--quiet'
866
- @config.verbose = false
867
- when '--verbose'
868
- @config.verbose = true
869
- when '--help'
870
- print_usage $stdout
871
- exit 0
872
- when '--version'
873
- puts "#{File.basename($0)} version #{Version}"
874
- exit 0
875
- when '--copyright'
876
- puts Copyright
877
- exit 0
878
- else
879
- setup_rb_error "unknown global option '#{arg}'"
880
- end
881
- end
882
- nil
883
- end
884
-
885
- def valid_task?(t)
886
- valid_task_re() =~ t
887
- end
888
-
889
- def valid_task_re
890
- @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
891
- end
892
-
893
- def parsearg_no_options
894
- unless ARGV.empty?
895
- task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
896
- setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
897
- end
898
- end
899
-
900
- alias parsearg_show parsearg_no_options
901
- alias parsearg_setup parsearg_no_options
902
- alias parsearg_test parsearg_no_options
903
- alias parsearg_clean parsearg_no_options
904
- alias parsearg_distclean parsearg_no_options
905
-
906
- def parsearg_config
907
- evalopt = []
908
- set = []
909
- @config.config_opt = []
910
- while i = ARGV.shift
911
- if /\A--?\z/ =~ i
912
- @config.config_opt = ARGV.dup
913
- break
914
- end
915
- name, value = *@config.parse_opt(i)
916
- if @config.value_config?(name)
917
- @config[name] = value
918
- else
919
- evalopt.push [name, value]
920
- end
921
- set.push name
922
- end
923
- evalopt.each do |name, value|
924
- @config.lookup(name).evaluate value, @config
925
- end
926
- # Check if configuration is valid
927
- set.each do |n|
928
- @config[n] if @config.value_config?(n)
929
- end
930
- end
931
-
932
- def parsearg_install
933
- @config.no_harm = false
934
- @config.install_prefix = ''
935
- while a = ARGV.shift
936
- case a
937
- when '--no-harm'
938
- @config.no_harm = true
939
- when /\A--prefix=/
940
- path = a.split(/=/, 2)[1]
941
- path = File.expand_path(path) unless path[0,1] == '/'
942
- @config.install_prefix = path
943
- else
944
- setup_rb_error "install: unknown option #{a}"
945
- end
946
- end
947
- end
948
-
949
- def print_usage(out)
950
- out.puts 'Typical Installation Procedure:'
951
- out.puts " $ ruby #{File.basename $0} config"
952
- out.puts " $ ruby #{File.basename $0} setup"
953
- out.puts " # ruby #{File.basename $0} install (may require root privilege)"
954
- out.puts
955
- out.puts 'Detailed Usage:'
956
- out.puts " ruby #{File.basename $0} <global option>"
957
- out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
958
-
959
- fmt = " %-24s %s\n"
960
- out.puts
961
- out.puts 'Global options:'
962
- out.printf fmt, '-q,--quiet', 'suppress message outputs'
963
- out.printf fmt, ' --verbose', 'output messages verbosely'
964
- out.printf fmt, ' --help', 'print this message'
965
- out.printf fmt, ' --version', 'print version and quit'
966
- out.printf fmt, ' --copyright', 'print copyright and quit'
967
- out.puts
968
- out.puts 'Tasks:'
969
- TASKS.each do |name, desc|
970
- out.printf fmt, name, desc
971
- end
972
-
973
- fmt = " %-24s %s [%s]\n"
974
- out.puts
975
- out.puts 'Options for CONFIG or ALL:'
976
- @config.each do |item|
977
- out.printf fmt, item.help_opt, item.description, item.help_default
978
- end
979
- out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
980
- out.puts
981
- out.puts 'Options for INSTALL:'
982
- out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
983
- out.printf fmt, '--prefix=path', 'install path prefix', ''
984
- out.puts
985
- end
986
-
987
- #
988
- # Task Handlers
989
- #
990
-
991
- def exec_config
992
- @installer.exec_config
993
- @config.save # must be final
994
- end
995
-
996
- def exec_setup
997
- @installer.exec_setup
998
- end
999
-
1000
- def exec_install
1001
- @installer.exec_install
1002
- end
1003
-
1004
- def exec_test
1005
- @installer.exec_test
1006
- end
1007
-
1008
- def exec_show
1009
- @config.each do |i|
1010
- printf "%-20s %s\n", i.name, i.value if i.value?
1011
- end
1012
- end
1013
-
1014
- def exec_clean
1015
- @installer.exec_clean
1016
- end
1017
-
1018
- def exec_distclean
1019
- @installer.exec_distclean
1020
- end
1021
-
1022
- end # class ToplevelInstaller
1023
-
1024
-
1025
- class ToplevelInstallerMulti < ToplevelInstaller
1026
-
1027
- include FileOperations
1028
-
1029
- def initialize(ardir_root, config)
1030
- super
1031
- @packages = directories_of("#{@ardir}/packages")
1032
- raise 'no package exists' if @packages.empty?
1033
- @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
1034
- end
1035
-
1036
- def run_metaconfigs
1037
- @config.load_script "#{@ardir}/metaconfig", self
1038
- @packages.each do |name|
1039
- @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
1040
- end
1041
- end
1042
-
1043
- attr_reader :packages
1044
-
1045
- def packages=(list)
1046
- raise 'package list is empty' if list.empty?
1047
- list.each do |name|
1048
- raise "directory packages/#{name} does not exist"\
1049
- unless File.dir?("#{@ardir}/packages/#{name}")
1050
- end
1051
- @packages = list
1052
- end
1053
-
1054
- def init_installers
1055
- @installers = {}
1056
- @packages.each do |pack|
1057
- @installers[pack] = Installer.new(@config,
1058
- "#{@ardir}/packages/#{pack}",
1059
- "packages/#{pack}")
1060
- end
1061
- with = extract_selection(config('with'))
1062
- without = extract_selection(config('without'))
1063
- @selected = @installers.keys.select {|name|
1064
- (with.empty? or with.include?(name)) \
1065
- and not without.include?(name)
1066
- }
1067
- end
1068
-
1069
- def extract_selection(list)
1070
- a = list.split(/,/)
1071
- a.each do |name|
1072
- setup_rb_error "no such package: #{name}" unless @installers.key?(name)
1073
- end
1074
- a
1075
- end
1076
-
1077
- def print_usage(f)
1078
- super
1079
- f.puts 'Inluded packages:'
1080
- f.puts ' ' + @packages.sort.join(' ')
1081
- f.puts
1082
- end
1083
-
1084
- #
1085
- # Task Handlers
1086
- #
1087
-
1088
- def exec_config
1089
- run_hook 'pre-config'
1090
- each_selected_installers {|inst| inst.exec_config }
1091
- run_hook 'post-config'
1092
- @config.save # must be final
1093
- end
1094
-
1095
- def exec_setup
1096
- run_hook 'pre-setup'
1097
- each_selected_installers {|inst| inst.exec_setup }
1098
- run_hook 'post-setup'
1099
- end
1100
-
1101
- def exec_install
1102
- run_hook 'pre-install'
1103
- each_selected_installers {|inst| inst.exec_install }
1104
- run_hook 'post-install'
1105
- end
1106
-
1107
- def exec_test
1108
- run_hook 'pre-test'
1109
- each_selected_installers {|inst| inst.exec_test }
1110
- run_hook 'post-test'
1111
- end
1112
-
1113
- def exec_clean
1114
- rm_f @config.savefile
1115
- run_hook 'pre-clean'
1116
- each_selected_installers {|inst| inst.exec_clean }
1117
- run_hook 'post-clean'
1118
- end
1119
-
1120
- def exec_distclean
1121
- rm_f @config.savefile
1122
- run_hook 'pre-distclean'
1123
- each_selected_installers {|inst| inst.exec_distclean }
1124
- run_hook 'post-distclean'
1125
- end
1126
-
1127
- #
1128
- # lib
1129
- #
1130
-
1131
- def each_selected_installers
1132
- Dir.mkdir 'packages' unless File.dir?('packages')
1133
- @selected.each do |pack|
1134
- $stderr.puts "Processing the package `#{pack}' ..." if verbose?
1135
- Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
1136
- Dir.chdir "packages/#{pack}"
1137
- yield @installers[pack]
1138
- Dir.chdir '../..'
1139
- end
1140
- end
1141
-
1142
- def run_hook(id)
1143
- @root_installer.run_hook id
1144
- end
1145
-
1146
- # module FileOperations requires this
1147
- def verbose?
1148
- @config.verbose?
1149
- end
1150
-
1151
- # module FileOperations requires this
1152
- def no_harm?
1153
- @config.no_harm?
1154
- end
1155
-
1156
- end # class ToplevelInstallerMulti
1157
-
1158
-
1159
- class Installer
1160
-
1161
- FILETYPES = %w( bin lib ext data conf man )
1162
-
1163
- include FileOperations
1164
- include HookScriptAPI
1165
-
1166
- def initialize(config, srcroot, objroot)
1167
- @config = config
1168
- @srcdir = File.expand_path(srcroot)
1169
- @objdir = File.expand_path(objroot)
1170
- @currdir = '.'
1171
- end
1172
-
1173
- def inspect
1174
- "#<#{self.class} #{File.basename(@srcdir)}>"
1175
- end
1176
-
1177
- def noop(rel)
1178
- end
1179
-
1180
- #
1181
- # Hook Script API base methods
1182
- #
1183
-
1184
- def srcdir_root
1185
- @srcdir
1186
- end
1187
-
1188
- def objdir_root
1189
- @objdir
1190
- end
1191
-
1192
- def relpath
1193
- @currdir
1194
- end
1195
-
1196
- #
1197
- # Config Access
1198
- #
1199
-
1200
- # module FileOperations requires this
1201
- def verbose?
1202
- @config.verbose?
1203
- end
1204
-
1205
- # module FileOperations requires this
1206
- def no_harm?
1207
- @config.no_harm?
1208
- end
1209
-
1210
- def verbose_off
1211
- begin
1212
- save, @config.verbose = @config.verbose?, false
1213
- yield
1214
- ensure
1215
- @config.verbose = save
1216
- end
1217
- end
1218
-
1219
- #
1220
- # TASK config
1221
- #
1222
-
1223
- def exec_config
1224
- exec_task_traverse 'config'
1225
- end
1226
-
1227
- alias config_dir_bin noop
1228
- alias config_dir_lib noop
1229
-
1230
- def config_dir_ext(rel)
1231
- extconf if extdir?(curr_srcdir())
1232
- end
1233
-
1234
- alias config_dir_data noop
1235
- alias config_dir_conf noop
1236
- alias config_dir_man noop
1237
-
1238
- def extconf
1239
- ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
1240
- end
1241
-
1242
- #
1243
- # TASK setup
1244
- #
1245
-
1246
- def exec_setup
1247
- exec_task_traverse 'setup'
1248
- end
1249
-
1250
- def setup_dir_bin(rel)
1251
- files_of(curr_srcdir()).each do |fname|
1252
- update_shebang_line "#{curr_srcdir()}/#{fname}"
1253
- end
1254
- end
1255
-
1256
- alias setup_dir_lib noop
1257
-
1258
- def setup_dir_ext(rel)
1259
- make if extdir?(curr_srcdir())
1260
- end
1261
-
1262
- alias setup_dir_data noop
1263
- alias setup_dir_conf noop
1264
- alias setup_dir_man noop
1265
-
1266
- def update_shebang_line(path)
1267
- return if no_harm?
1268
- return if config('shebang') == 'never'
1269
- old = Shebang.load(path)
1270
- if old
1271
- $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1
1272
- new = new_shebang(old)
1273
- return if new.to_s == old.to_s
1274
- else
1275
- return unless config('shebang') == 'all'
1276
- new = Shebang.new(config('rubypath'))
1277
- end
1278
- $stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
1279
- open_atomic_writer(path) {|output|
1280
- File.open(path, 'rb') {|f|
1281
- f.gets if old # discard
1282
- output.puts new.to_s
1283
- output.print f.read
1284
- }
1285
- }
1286
- end
1287
-
1288
- def new_shebang(old)
1289
- if /\Aruby/ =~ File.basename(old.cmd)
1290
- Shebang.new(config('rubypath'), old.args)
1291
- elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
1292
- Shebang.new(config('rubypath'), old.args[1..-1])
1293
- else
1294
- return old unless config('shebang') == 'all'
1295
- Shebang.new(config('rubypath'))
1296
- end
1297
- end
1298
-
1299
- def open_atomic_writer(path, &block)
1300
- tmpfile = File.basename(path) + '.tmp'
1301
- begin
1302
- File.open(tmpfile, 'wb', &block)
1303
- File.rename tmpfile, File.basename(path)
1304
- ensure
1305
- File.unlink tmpfile if File.exist?(tmpfile)
1306
- end
1307
- end
1308
-
1309
- class Shebang
1310
- def Shebang.load(path)
1311
- line = nil
1312
- File.open(path) {|f|
1313
- line = f.gets
1314
- }
1315
- return nil unless /\A#!/ =~ line
1316
- parse(line)
1317
- end
1318
-
1319
- def Shebang.parse(line)
1320
- cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
1321
- new(cmd, args)
1322
- end
1323
-
1324
- def initialize(cmd, args = [])
1325
- @cmd = cmd
1326
- @args = args
1327
- end
1328
-
1329
- attr_reader :cmd
1330
- attr_reader :args
1331
-
1332
- def to_s
1333
- "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
1334
- end
1335
- end
1336
-
1337
- #
1338
- # TASK install
1339
- #
1340
-
1341
- def exec_install
1342
- rm_f 'InstalledFiles'
1343
- exec_task_traverse 'install'
1344
- end
1345
-
1346
- def install_dir_bin(rel)
1347
- install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
1348
- end
1349
-
1350
- def install_dir_lib(rel)
1351
- install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644
1352
- end
1353
-
1354
- def install_dir_ext(rel)
1355
- return unless extdir?(curr_srcdir())
1356
- install_files rubyextentions('.'),
1357
- "#{config('sodir')}/#{File.dirname(rel)}",
1358
- 0555
1359
- end
1360
-
1361
- def install_dir_data(rel)
1362
- install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
1363
- end
1364
-
1365
- def install_dir_conf(rel)
1366
- # FIXME: should not remove current config files
1367
- # (rename previous file to .old/.org)
1368
- install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
1369
- end
1370
-
1371
- def install_dir_man(rel)
1372
- install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
1373
- end
1374
-
1375
- def install_files(list, dest, mode)
1376
- mkdir_p dest, @config.install_prefix
1377
- list.each do |fname|
1378
- install fname, dest, mode, @config.install_prefix
1379
- end
1380
- end
1381
-
1382
- def libfiles
1383
- glob_reject(%w(*.y *.output), targetfiles())
1384
- end
1385
-
1386
- def rubyextentions(dir)
1387
- ents = glob_select("*.#{@config.dllext}", targetfiles())
1388
- if ents.empty?
1389
- setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
1390
- end
1391
- ents
1392
- end
1393
-
1394
- def targetfiles
1395
- mapdir(existfiles() - hookfiles())
1396
- end
1397
-
1398
- def mapdir(ents)
1399
- ents.map {|ent|
1400
- if File.exist?(ent)
1401
- then ent # objdir
1402
- else "#{curr_srcdir()}/#{ent}" # srcdir
1403
- end
1404
- }
1405
- end
1406
-
1407
- # picked up many entries from cvs-1.11.1/src/ignore.c
1408
- JUNK_FILES = %w(
1409
- core RCSLOG tags TAGS .make.state
1410
- .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1411
- *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1412
-
1413
- *.org *.in .*
1414
- )
1415
-
1416
- def existfiles
1417
- glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
1418
- end
1419
-
1420
- def hookfiles
1421
- %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1422
- %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1423
- }.flatten
1424
- end
1425
-
1426
- def glob_select(pat, ents)
1427
- re = globs2re([pat])
1428
- ents.select {|ent| re =~ ent }
1429
- end
1430
-
1431
- def glob_reject(pats, ents)
1432
- re = globs2re(pats)
1433
- ents.reject {|ent| re =~ ent }
1434
- end
1435
-
1436
- GLOB2REGEX = {
1437
- '.' => '\.',
1438
- '$' => '\$',
1439
- '#' => '\#',
1440
- '*' => '.*'
1441
- }
1442
-
1443
- def globs2re(pats)
1444
- /\A(?:#{
1445
- pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
1446
- })\z/
1447
- end
1448
-
1449
- #
1450
- # TASK test
1451
- #
1452
-
1453
- TESTDIR = 'test'
1454
-
1455
- def exec_test
1456
- unless File.directory?('test')
1457
- $stderr.puts 'no test in this package' if verbose?
1458
- return
1459
- end
1460
- $stderr.puts 'Running tests...' if verbose?
1461
- begin
1462
- require 'test/unit'
1463
- rescue LoadError
1464
- setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.'
1465
- end
1466
- runner = Test::Unit::AutoRunner.new(true)
1467
- runner.to_run << TESTDIR
1468
- runner.run
1469
- end
1470
-
1471
- #
1472
- # TASK clean
1473
- #
1474
-
1475
- def exec_clean
1476
- exec_task_traverse 'clean'
1477
- rm_f @config.savefile
1478
- rm_f 'InstalledFiles'
1479
- end
1480
-
1481
- alias clean_dir_bin noop
1482
- alias clean_dir_lib noop
1483
- alias clean_dir_data noop
1484
- alias clean_dir_conf noop
1485
- alias clean_dir_man noop
1486
-
1487
- def clean_dir_ext(rel)
1488
- return unless extdir?(curr_srcdir())
1489
- make 'clean' if File.file?('Makefile')
1490
- end
1491
-
1492
- #
1493
- # TASK distclean
1494
- #
1495
-
1496
- def exec_distclean
1497
- exec_task_traverse 'distclean'
1498
- rm_f @config.savefile
1499
- rm_f 'InstalledFiles'
1500
- end
1501
-
1502
- alias distclean_dir_bin noop
1503
- alias distclean_dir_lib noop
1504
-
1505
- def distclean_dir_ext(rel)
1506
- return unless extdir?(curr_srcdir())
1507
- make 'distclean' if File.file?('Makefile')
1508
- end
1509
-
1510
- alias distclean_dir_data noop
1511
- alias distclean_dir_conf noop
1512
- alias distclean_dir_man noop
1513
-
1514
- #
1515
- # Traversing
1516
- #
1517
-
1518
- def exec_task_traverse(task)
1519
- run_hook "pre-#{task}"
1520
- FILETYPES.each do |type|
1521
- if type == 'ext' and config('without-ext') == 'yes'
1522
- $stderr.puts 'skipping ext/* by user option' if verbose?
1523
- next
1524
- end
1525
- traverse task, type, "#{task}_dir_#{type}"
1526
- end
1527
- run_hook "post-#{task}"
1528
- end
1529
-
1530
- def traverse(task, rel, mid)
1531
- dive_into(rel) {
1532
- run_hook "pre-#{task}"
1533
- __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1534
- directories_of(curr_srcdir()).each do |d|
1535
- traverse task, "#{rel}/#{d}", mid
1536
- end
1537
- run_hook "post-#{task}"
1538
- }
1539
- end
1540
-
1541
- def dive_into(rel)
1542
- return unless File.dir?("#{@srcdir}/#{rel}")
1543
-
1544
- dir = File.basename(rel)
1545
- Dir.mkdir dir unless File.dir?(dir)
1546
- prevdir = Dir.pwd
1547
- Dir.chdir dir
1548
- $stderr.puts '---> ' + rel if verbose?
1549
- @currdir = rel
1550
- yield
1551
- Dir.chdir prevdir
1552
- $stderr.puts '<--- ' + rel if verbose?
1553
- @currdir = File.dirname(rel)
1554
- end
1555
-
1556
- def run_hook(id)
1557
- path = [ "#{curr_srcdir()}/#{id}",
1558
- "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
1559
- return unless path
1560
- begin
1561
- instance_eval File.read(path), path, 1
1562
- rescue
1563
- raise if $DEBUG
1564
- setup_rb_error "hook #{path} failed:\n" + $!.message
1565
- end
1566
- end
1567
-
1568
- end # class Installer
1569
-
1570
-
1571
- class SetupError < StandardError; end
1572
-
1573
- def setup_rb_error(msg)
1574
- raise SetupError, msg
1575
- end
1576
-
1577
- if $0 == __FILE__
1578
- begin
1579
- ToplevelInstaller.invoke
1580
- rescue SetupError
1581
- raise if $DEBUG
1582
- $stderr.puts $!.message
1583
- $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1584
- exit 1
1585
- end
1586
- end