mkmfmf 0.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/mkmfmf.rb ADDED
@@ -0,0 +1,2112 @@
1
+ # -*- indent-tabs-mode: t -*-
2
+ # module to create Makefile for extension modules
3
+ # invoke like: ruby -r mkmf extconf.rb
4
+
5
+ require 'rbconfig'
6
+ require 'fileutils'
7
+ require 'shellwords'
8
+
9
+ CONFIG = RbConfig::MAKEFILE_CONFIG
10
+ CONFIG['CC'] = ENV['CC'] if ENV['CC']
11
+ ORIG_LIBPATH = ENV['LIB']
12
+
13
+ CXX_EXT = %w[cc cxx cpp]
14
+ if File::FNM_SYSCASE.zero?
15
+ CXX_EXT.concat(%w[C])
16
+ end
17
+ SRC_EXT = %w[c m].concat(CXX_EXT)
18
+ $static = nil
19
+ $config_h = '$(arch_hdrdir)/ruby/config.h'
20
+ $default_static = $static
21
+
22
+ unless defined? $configure_args
23
+ $configure_args = {}
24
+ args = CONFIG["configure_args"]
25
+ if ENV["CONFIGURE_ARGS"]
26
+ args << " " << ENV["CONFIGURE_ARGS"]
27
+ end
28
+ for arg in Shellwords::shellwords(args)
29
+ arg, val = arg.split('=', 2)
30
+ next unless arg
31
+ arg.tr!('_', '-')
32
+ if arg.sub!(/^(?!--)/, '--')
33
+ val or next
34
+ arg.downcase!
35
+ end
36
+ next if /^--(?:top|topsrc|src|cur)dir$/ =~ arg
37
+ $configure_args[arg] = val || true
38
+ end
39
+ for arg in ARGV
40
+ arg, val = arg.split('=', 2)
41
+ next unless arg
42
+ arg.tr!('_', '-')
43
+ if arg.sub!(/^(?!--)/, '--')
44
+ val or next
45
+ arg.downcase!
46
+ end
47
+ $configure_args[arg] = val || true
48
+ end
49
+ end
50
+
51
+ $libdir = CONFIG["libdir"]
52
+ $rubylibdir = CONFIG["rubylibdir"]
53
+ $archdir = CONFIG["archdir"]
54
+ $sitedir = CONFIG["sitedir"]
55
+ $sitelibdir = CONFIG["sitelibdir"]
56
+ $sitearchdir = CONFIG["sitearchdir"]
57
+ $vendordir = CONFIG["vendordir"]
58
+ $vendorlibdir = CONFIG["vendorlibdir"]
59
+ $vendorarchdir = CONFIG["vendorarchdir"]
60
+
61
+ $mswin = /mswin/ =~ RUBY_PLATFORM
62
+ $bccwin = /bccwin/ =~ RUBY_PLATFORM
63
+ $mingw = /mingw/ =~ RUBY_PLATFORM
64
+ $cygwin = /cygwin/ =~ RUBY_PLATFORM
65
+ $netbsd = /netbsd/ =~ RUBY_PLATFORM
66
+ $os2 = /os2/ =~ RUBY_PLATFORM
67
+ $beos = /beos/ =~ RUBY_PLATFORM
68
+ $haiku = /haiku/ =~ RUBY_PLATFORM
69
+ $solaris = /solaris/ =~ RUBY_PLATFORM
70
+ $universal = /universal/ =~ RUBY_PLATFORM
71
+ $dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
72
+
73
+ # :stopdoc:
74
+
75
+ def config_string(key, config = CONFIG)
76
+ s = config[key] and !s.empty? and block_given? ? yield(s) : s
77
+ end
78
+
79
+ def dir_re(dir)
80
+ Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$(?:\(target_prefix\)|\{target_prefix\}))?')
81
+ end
82
+
83
+ def relative_from(path, base)
84
+ dir = File.join(path, "")
85
+ if File.expand_path(dir) == File.expand_path(dir, base)
86
+ path
87
+ else
88
+ File.join(base, path)
89
+ end
90
+ end
91
+
92
+ INSTALL_DIRS = [
93
+ [dir_re('commondir'), "$(RUBYCOMMONDIR)"],
94
+ [dir_re('sitedir'), "$(RUBYCOMMONDIR)"],
95
+ [dir_re('vendordir'), "$(RUBYCOMMONDIR)"],
96
+ [dir_re('rubylibdir'), "$(RUBYLIBDIR)"],
97
+ [dir_re('archdir'), "$(RUBYARCHDIR)"],
98
+ [dir_re('sitelibdir'), "$(RUBYLIBDIR)"],
99
+ [dir_re('vendorlibdir'), "$(RUBYLIBDIR)"],
100
+ [dir_re('sitearchdir'), "$(RUBYARCHDIR)"],
101
+ [dir_re('vendorarchdir'), "$(RUBYARCHDIR)"],
102
+ [dir_re('rubyhdrdir'), "$(RUBYHDRDIR)"],
103
+ [dir_re('sitehdrdir'), "$(SITEHDRDIR)"],
104
+ [dir_re('vendorhdrdir'), "$(VENDORHDRDIR)"],
105
+ [dir_re('bindir'), "$(BINDIR)"],
106
+ ]
107
+
108
+ def install_dirs(target_prefix = nil)
109
+ if $extout
110
+ dirs = [
111
+ ['BINDIR', '$(extout)/bin'],
112
+ ['RUBYCOMMONDIR', '$(extout)/common'],
113
+ ['RUBYLIBDIR', '$(RUBYCOMMONDIR)$(target_prefix)'],
114
+ ['RUBYARCHDIR', '$(extout)/$(arch)$(target_prefix)'],
115
+ ['HDRDIR', '$(extout)/include/ruby$(target_prefix)'],
116
+ ['ARCHHDRDIR', '$(extout)/include/$(arch)/ruby$(target_prefix)'],
117
+ ['extout', "#$extout"],
118
+ ['extout_prefix', "#$extout_prefix"],
119
+ ]
120
+ elsif $extmk
121
+ dirs = [
122
+ ['BINDIR', '$(bindir)'],
123
+ ['RUBYCOMMONDIR', '$(rubylibdir)'],
124
+ ['RUBYLIBDIR', '$(rubylibdir)$(target_prefix)'],
125
+ ['RUBYARCHDIR', '$(archdir)$(target_prefix)'],
126
+ ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
127
+ ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
128
+ ]
129
+ elsif $configure_args.has_key?('--vendor')
130
+ dirs = [
131
+ ['BINDIR', '$(bindir)'],
132
+ ['RUBYCOMMONDIR', '$(vendordir)$(target_prefix)'],
133
+ ['RUBYLIBDIR', '$(vendorlibdir)$(target_prefix)'],
134
+ ['RUBYARCHDIR', '$(vendorarchdir)$(target_prefix)'],
135
+ ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
136
+ ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
137
+ ]
138
+ else
139
+ dirs = [
140
+ ['BINDIR', '$(bindir)'],
141
+ ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'],
142
+ ['RUBYLIBDIR', '$(sitelibdir)$(target_prefix)'],
143
+ ['RUBYARCHDIR', '$(sitearchdir)$(target_prefix)'],
144
+ ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
145
+ ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
146
+ ]
147
+ end
148
+ dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")]
149
+ dirs
150
+ end
151
+
152
+ def map_dir(dir, map = nil)
153
+ map ||= INSTALL_DIRS
154
+ map.inject(dir) {|d, (orig, new)| d.gsub(orig, new)}
155
+ end
156
+
157
+ topdir = File.dirname(libdir = File.dirname(__FILE__))
158
+ extdir = File.expand_path("ext", topdir)
159
+ path = File.expand_path($0)
160
+ $extmk = path[0, topdir.size+1] == topdir+"/"
161
+ $extmk &&= %r"\A(?:ext|enc|tool|test(?:/.+))\z" =~ File.dirname(path[topdir.size+1..-1])
162
+ $extmk &&= true
163
+ if not $extmk and File.exist?(($hdrdir = RbConfig::CONFIG["rubyhdrdir"]) + "/ruby/ruby.h")
164
+ $topdir = $hdrdir
165
+ $top_srcdir = $hdrdir
166
+ $arch_hdrdir = $hdrdir + "/$(arch)"
167
+ elsif File.exist?(($hdrdir = ($top_srcdir ||= topdir) + "/include") + "/ruby.h")
168
+ $topdir ||= RbConfig::CONFIG["topdir"]
169
+ $arch_hdrdir = "$(extout)/include/$(arch)"
170
+ else
171
+ abort "mkmf.rb can't find header files for ruby at #{$hdrdir}/ruby.h"
172
+ end
173
+
174
+ OUTFLAG = CONFIG['OUTFLAG']
175
+ COUTFLAG = CONFIG['COUTFLAG']
176
+ CPPOUTFILE = CONFIG['CPPOUTFILE']
177
+
178
+ CONFTEST_C = "conftest.c".freeze
179
+
180
+ class String
181
+ # Wraps a string in escaped quotes if it contains whitespace.
182
+ def quote
183
+ /\s/ =~ self ? "\"#{self}\"" : "#{self}"
184
+ end
185
+
186
+ # Generates a string used as cpp macro name.
187
+ def tr_cpp
188
+ strip.upcase.tr_s("^A-Z0-9_", "_")
189
+ end
190
+ end
191
+ class Array
192
+ # Wraps all strings in escaped quotes if they contain whitespace.
193
+ def quote
194
+ map {|s| s.quote}
195
+ end
196
+ end
197
+
198
+ def rm_f(*files)
199
+ opt = (Hash === files.last ? [files.pop] : [])
200
+ FileUtils.rm_f(Dir[*files.flatten], *opt)
201
+ end
202
+
203
+ def rm_rf(*files)
204
+ opt = (Hash === files.last ? [files.pop] : [])
205
+ FileUtils.rm_rf(Dir[*files.flatten], *opt)
206
+ end
207
+
208
+ # Returns time stamp of the +target+ file if it exists and is newer
209
+ # than or equal to all of +times+.
210
+ def modified?(target, times)
211
+ (t = File.mtime(target)) rescue return nil
212
+ Array === times or times = [times]
213
+ t if times.all? {|n| n <= t}
214
+ end
215
+
216
+ def merge_libs(*libs)
217
+ libs.inject([]) do |x, y|
218
+ xy = x & y
219
+ xn = yn = 0
220
+ y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e}
221
+ y.each_with_index do |v, yi|
222
+ if xy.include?(v)
223
+ xi = [x.index(v), xn].max()
224
+ x[xi, 1] = y[yn..yi]
225
+ xn, yn = xi + (yi - yn + 1), yi + 1
226
+ end
227
+ end
228
+ x.concat(y[yn..-1] || [])
229
+ end
230
+ end
231
+
232
+ # This is a custom logging module. It generates an mkmf.log file when you
233
+ # run your extconf.rb script. This can be useful for debugging unexpected
234
+ # failures.
235
+ #
236
+ # This module and its associated methods are meant for internal use only.
237
+ #
238
+ module Logging
239
+ @log = nil
240
+ @logfile = 'mkmf.log'
241
+ @orgerr = $stderr.dup
242
+ @orgout = $stdout.dup
243
+ @postpone = 0
244
+ @quiet = $extmk
245
+
246
+ def self::log_open
247
+ @log ||= File::open(@logfile, 'wb')
248
+ @log.sync = true
249
+ end
250
+
251
+ def self::open
252
+ log_open
253
+ $stderr.reopen(@log)
254
+ $stdout.reopen(@log)
255
+ yield
256
+ ensure
257
+ $stderr.reopen(@orgerr)
258
+ $stdout.reopen(@orgout)
259
+ end
260
+
261
+ def self::message(*s)
262
+ log_open
263
+ @log.printf(*s)
264
+ end
265
+
266
+ def self::logfile file
267
+ @logfile = file
268
+ if @log and not @log.closed?
269
+ @log.flush
270
+ @log.close
271
+ @log = nil
272
+ end
273
+ end
274
+
275
+ def self::postpone
276
+ tmplog = "mkmftmp#{@postpone += 1}.log"
277
+ open do
278
+ log, *save = @log, @logfile, @orgout, @orgerr
279
+ @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
280
+ begin
281
+ log.print(open {yield})
282
+ ensure
283
+ @log.close
284
+ File::open(tmplog) {|t| FileUtils.copy_stream(t, log)}
285
+ @log, @logfile, @orgout, @orgerr = log, *save
286
+ @postpone -= 1
287
+ rm_f tmplog
288
+ end
289
+ end
290
+ end
291
+
292
+ class << self
293
+ attr_accessor :quiet
294
+ end
295
+ end
296
+
297
+ def xsystem command
298
+ varpat = /\$\((\w+)\)|\$\{(\w+)\}/
299
+ if varpat =~ command
300
+ vars = Hash.new {|h, k| h[k] = ''; ENV[k]}
301
+ command = command.dup
302
+ nil while command.gsub!(varpat) {vars[$1||$2]}
303
+ end
304
+ Logging::open do
305
+ puts command.quote
306
+ system(command)
307
+ end
308
+ end
309
+
310
+ def xpopen command, *mode, &block
311
+ Logging::open do
312
+ case mode[0]
313
+ when nil, /^r/
314
+ puts "#{command} |"
315
+ else
316
+ puts "| #{command}"
317
+ end
318
+ IO.popen(command, *mode, &block)
319
+ end
320
+ end
321
+
322
+ def log_src(src)
323
+ src = src.split(/^/)
324
+ fmt = "%#{src.size.to_s.size}d: %s"
325
+ Logging::message <<"EOM"
326
+ checked program was:
327
+ /* begin */
328
+ EOM
329
+ src.each_with_index {|line, no| Logging::message fmt, no+1, line}
330
+ Logging::message <<"EOM"
331
+ /* end */
332
+
333
+ EOM
334
+ end
335
+
336
+ def create_tmpsrc(src)
337
+ src = "#{COMMON_HEADERS}\n#{src}"
338
+ src = yield(src) if block_given?
339
+ src.gsub!(/[ \t]+$/, '')
340
+ src.gsub!(/\A\n+|^\n+$/, '')
341
+ src.sub!(/[^\n]\z/, "\\&\n")
342
+ count = 0
343
+ begin
344
+ open(CONFTEST_C, "wb") do |cfile|
345
+ cfile.print src
346
+ end
347
+ rescue Errno::EACCES
348
+ if (count += 1) < 5
349
+ sleep 0.2
350
+ retry
351
+ end
352
+ end
353
+ src
354
+ end
355
+
356
+ def have_devel?
357
+ unless defined? $have_devel
358
+ $have_devel = true
359
+ $have_devel = try_link(MAIN_DOES_NOTHING)
360
+ end
361
+ $have_devel
362
+ end
363
+
364
+ def try_do(src, command, &b)
365
+ unless have_devel?
366
+ raise <<MSG
367
+ The complier failed to generate an executable file.
368
+ You have to install development tools first.
369
+ MSG
370
+ end
371
+ begin
372
+ src = create_tmpsrc(src, &b)
373
+ xsystem(command)
374
+ ensure
375
+ log_src(src)
376
+ rm_rf 'conftest.dSYM'
377
+ end
378
+ end
379
+
380
+ def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
381
+ conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote,
382
+ 'src' => "#{CONFTEST_C}",
383
+ 'arch_hdrdir' => "#$arch_hdrdir",
384
+ 'top_srcdir' => $top_srcdir.quote,
385
+ 'INCFLAGS' => "#$INCFLAGS",
386
+ 'CPPFLAGS' => "#$CPPFLAGS",
387
+ 'CFLAGS' => "#$CFLAGS",
388
+ 'ARCH_FLAG' => "#$ARCH_FLAG",
389
+ 'LDFLAGS' => "#$LDFLAGS #{ldflags}",
390
+ 'LIBPATH' => libpathflag(libpath),
391
+ 'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs",
392
+ 'LIBS' => "#$LIBRUBYARG_STATIC #{opt} #$LIBS")
393
+ RbConfig::expand(TRY_LINK.dup, conf)
394
+ end
395
+
396
+ def cc_command(opt="")
397
+ conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
398
+ 'arch_hdrdir' => "#$arch_hdrdir",
399
+ 'top_srcdir' => $top_srcdir.quote)
400
+ RbConfig::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}",
401
+ conf)
402
+ end
403
+
404
+ def cpp_command(outfile, opt="")
405
+ conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
406
+ 'arch_hdrdir' => "#$arch_hdrdir",
407
+ 'top_srcdir' => $top_srcdir.quote)
408
+ RbConfig::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
409
+ conf)
410
+ end
411
+
412
+ def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
413
+ libpath.map{|x|
414
+ case x
415
+ when "$(topdir)", /\A\./
416
+ LIBPATHFLAG
417
+ else
418
+ LIBPATHFLAG+RPATHFLAG
419
+ end % x.quote
420
+ }.join
421
+ end
422
+
423
+ def try_link0(src, opt="", &b)
424
+ cmd = link_command("", opt)
425
+ if $universal
426
+ require 'tmpdir'
427
+ Dir.mktmpdir("mkmf_", oldtmpdir = ENV["TMPDIR"]) do |tmpdir|
428
+ begin
429
+ ENV["TMPDIR"] = tmpdir
430
+ try_do(src, cmd, &b)
431
+ ensure
432
+ ENV["TMPDIR"] = oldtmpdir
433
+ end
434
+ end
435
+ else
436
+ try_do(src, cmd, &b)
437
+ end
438
+ end
439
+
440
+ def try_link(src, opt="", &b)
441
+ try_link0(src, opt, &b)
442
+ ensure
443
+ rm_f "conftest*", "c0x32*"
444
+ end
445
+
446
+ def try_compile(src, opt="", &b)
447
+ try_do(src, cc_command(opt), &b)
448
+ ensure
449
+ rm_f "conftest*"
450
+ end
451
+
452
+ def try_cpp(src, opt="", &b)
453
+ try_do(src, cpp_command(CPPOUTFILE, opt), &b)
454
+ ensure
455
+ rm_f "conftest*"
456
+ end
457
+
458
+ class Object
459
+ alias_method :try_header, (config_string('try_header') || :try_cpp)
460
+ end
461
+
462
+ def cpp_include(header)
463
+ if header
464
+ header = [header] unless header.kind_of? Array
465
+ header.map {|h| String === h ? "#include <#{h}>\n" : h}.join
466
+ else
467
+ ""
468
+ end
469
+ end
470
+
471
+ def with_cppflags(flags)
472
+ cppflags = $CPPFLAGS
473
+ $CPPFLAGS = flags
474
+ ret = yield
475
+ ensure
476
+ $CPPFLAGS = cppflags unless ret
477
+ end
478
+
479
+ def with_cflags(flags)
480
+ cflags = $CFLAGS
481
+ $CFLAGS = flags
482
+ ret = yield
483
+ ensure
484
+ $CFLAGS = cflags unless ret
485
+ end
486
+
487
+ def with_ldflags(flags)
488
+ ldflags = $LDFLAGS
489
+ $LDFLAGS = flags
490
+ ret = yield
491
+ ensure
492
+ $LDFLAGS = ldflags unless ret
493
+ end
494
+
495
+ def try_static_assert(expr, headers = nil, opt = "", &b)
496
+ headers = cpp_include(headers)
497
+ try_compile(<<SRC, opt, &b)
498
+ #{headers}
499
+ /*top*/
500
+ int conftest_const[(#{expr}) ? 1 : -1];
501
+ SRC
502
+ end
503
+
504
+ def try_constant(const, headers = nil, opt = "", &b)
505
+ includes = cpp_include(headers)
506
+ if CROSS_COMPILING
507
+ if try_static_assert("#{const} > 0", headers, opt)
508
+ # positive constant
509
+ elsif try_static_assert("#{const} < 0", headers, opt)
510
+ neg = true
511
+ const = "-(#{const})"
512
+ elsif try_static_assert("#{const} == 0", headers, opt)
513
+ return 0
514
+ else
515
+ # not a constant
516
+ return nil
517
+ end
518
+ upper = 1
519
+ lower = 0
520
+ until try_static_assert("#{const} <= #{upper}", headers, opt)
521
+ lower = upper
522
+ upper <<= 1
523
+ end
524
+ return nil unless lower
525
+ while upper > lower + 1
526
+ mid = (upper + lower) / 2
527
+ if try_static_assert("#{const} > #{mid}", headers, opt)
528
+ lower = mid
529
+ else
530
+ upper = mid
531
+ end
532
+ end
533
+ upper = -upper if neg
534
+ return upper
535
+ else
536
+ src = %{#{includes}
537
+ #include <stdio.h>
538
+ /*top*/
539
+ int conftest_const = (int)(#{const});
540
+ int main() {printf("%d\\n", conftest_const); return 0;}
541
+ }
542
+ if try_link0(src, opt, &b)
543
+ xpopen("./conftest") do |f|
544
+ return Integer(f.gets)
545
+ end
546
+ end
547
+ end
548
+ nil
549
+ end
550
+
551
+ def try_func(func, libs, headers = nil, &b)
552
+ headers = cpp_include(headers)
553
+ try_link(<<"SRC", libs, &b) or
554
+ #{headers}
555
+ /*top*/
556
+ #{MAIN_DOES_NOTHING}
557
+ int t() { void ((*volatile p)()); p = (void ((*)()))#{func}; return 0; }
558
+ SRC
559
+ try_link(<<"SRC", libs, &b)
560
+ #{headers}
561
+ /*top*/
562
+ #{MAIN_DOES_NOTHING}
563
+ int t() { #{func}(); return 0; }
564
+ SRC
565
+ end
566
+
567
+ def try_var(var, headers = nil, &b)
568
+ headers = cpp_include(headers)
569
+ try_compile(<<"SRC", &b)
570
+ #{headers}
571
+ /*top*/
572
+ #{MAIN_DOES_NOTHING}
573
+ int t() { const volatile void *volatile p; p = &(&#{var})[0]; return 0; }
574
+ SRC
575
+ end
576
+
577
+ def egrep_cpp(pat, src, opt = "", &b)
578
+ src = create_tmpsrc(src, &b)
579
+ xpopen(cpp_command('', opt)) do |f|
580
+ if Regexp === pat
581
+ puts(" ruby -ne 'print if #{pat.inspect}'")
582
+ f.grep(pat) {|l|
583
+ puts "#{f.lineno}: #{l}"
584
+ return true
585
+ }
586
+ false
587
+ else
588
+ puts(" egrep '#{pat}'")
589
+ begin
590
+ stdin = $stdin.dup
591
+ $stdin.reopen(f)
592
+ system("egrep", pat)
593
+ ensure
594
+ $stdin.reopen(stdin)
595
+ end
596
+ end
597
+ end
598
+ ensure
599
+ rm_f "conftest*"
600
+ log_src(src)
601
+ end
602
+
603
+ # This is used internally by the have_macro? method.
604
+ def macro_defined?(macro, src, opt = "", &b)
605
+ src = src.sub(/[^\n]\z/, "\\&\n")
606
+ try_compile(src + <<"SRC", opt, &b)
607
+ /*top*/
608
+ #ifndef #{macro}
609
+ # error
610
+ >>>>>> #{macro} undefined <<<<<<
611
+ #endif
612
+ SRC
613
+ end
614
+
615
+ def try_run(src, opt = "", &b)
616
+ if try_link0(src, opt, &b)
617
+ xsystem("./conftest")
618
+ else
619
+ nil
620
+ end
621
+ ensure
622
+ rm_f "conftest*"
623
+ end
624
+
625
+ def install_files(mfile, ifiles, map = nil, srcprefix = nil)
626
+ ifiles or return
627
+ ifiles.empty? and return
628
+ srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
629
+ RbConfig::expand(srcdir = srcprefix.dup)
630
+ dirs = []
631
+ path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]}
632
+ ifiles.each do |files, dir, prefix|
633
+ dir = map_dir(dir, map)
634
+ prefix &&= %r|\A#{Regexp.quote(prefix)}/?|
635
+ if /\A\.\// =~ files
636
+ # install files which are in current working directory.
637
+ files = files[2..-1]
638
+ len = nil
639
+ else
640
+ # install files which are under the $(srcdir).
641
+ files = File.join(srcdir, files)
642
+ len = srcdir.size
643
+ end
644
+ f = nil
645
+ Dir.glob(files) do |fx|
646
+ f = fx
647
+ f[0..len] = "" if len
648
+ case File.basename(f)
649
+ when *$NONINSTALLFILES
650
+ next
651
+ end
652
+ d = File.dirname(f)
653
+ d.sub!(prefix, "") if prefix
654
+ d = (d.empty? || d == ".") ? dir : File.join(dir, d)
655
+ f = File.join(srcprefix, f) if len
656
+ path[d] << f
657
+ end
658
+ unless len or f
659
+ d = File.dirname(files)
660
+ d.sub!(prefix, "") if prefix
661
+ d = (d.empty? || d == ".") ? dir : File.join(dir, d)
662
+ path[d] << files
663
+ end
664
+ end
665
+ dirs
666
+ end
667
+
668
+ def install_rb(mfile, dest, srcdir = nil)
669
+ install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir)
670
+ end
671
+
672
+ def append_library(libs, lib) # :no-doc:
673
+ format(LIBARG, lib) + " " + libs
674
+ end
675
+
676
+ def message(*s)
677
+ unless Logging.quiet and not $VERBOSE
678
+ printf(*s)
679
+ $stdout.flush
680
+ end
681
+ end
682
+
683
+ # This emits a string to stdout that allows users to see the results of the
684
+ # various have* and find* methods as they are tested.
685
+ #
686
+ # Internal use only.
687
+ #
688
+ def checking_for(m, fmt = nil)
689
+ f = caller[0][/in `([^<].*)'$/, 1] and f << ": " #` for vim #'
690
+ m = "checking #{/\Acheck/ =~ f ? '' : 'for '}#{m}... "
691
+ message "%s", m
692
+ a = r = nil
693
+ Logging::postpone do
694
+ r = yield
695
+ a = (fmt ? fmt % r : r ? "yes" : "no") << "\n"
696
+ "#{f}#{m}-------------------- #{a}\n"
697
+ end
698
+ message(a)
699
+ Logging::message "--------------------\n\n"
700
+ r
701
+ end
702
+
703
+ def checking_message(target, place = nil, opt = nil)
704
+ [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)|
705
+ if noun
706
+ [[:to_str], [:join, ","], [:to_s]].each do |meth, *args|
707
+ if noun.respond_to?(meth)
708
+ break noun = noun.send(meth, *args)
709
+ end
710
+ end
711
+ msg << " #{pre} #{noun}" unless noun.empty?
712
+ end
713
+ msg
714
+ end
715
+ end
716
+
717
+ # :startdoc:
718
+
719
+ # Returns whether or not +macro+ is defined either in the common header
720
+ # files or within any +headers+ you provide.
721
+ #
722
+ # Any options you pass to +opt+ are passed along to the compiler.
723
+ #
724
+ def have_macro(macro, headers = nil, opt = "", &b)
725
+ checking_for checking_message(macro, headers, opt) do
726
+ macro_defined?(macro, cpp_include(headers), opt, &b)
727
+ end
728
+ end
729
+
730
+ # Returns whether or not the given entry point +func+ can be found within
731
+ # +lib+. If +func+ is nil, the 'main()' entry point is used by default.
732
+ # If found, it adds the library to list of libraries to be used when linking
733
+ # your extension.
734
+ #
735
+ # If +headers+ are provided, it will include those header files as the
736
+ # header files it looks in when searching for +func+.
737
+ #
738
+ # The real name of the library to be linked can be altered by
739
+ # '--with-FOOlib' configuration option.
740
+ #
741
+ def have_library(lib, func = nil, headers = nil, &b)
742
+ func = "main" if !func or func.empty?
743
+ lib = with_config(lib+'lib', lib)
744
+ checking_for checking_message("#{func}()", LIBARG%lib) do
745
+ if COMMON_LIBS.include?(lib)
746
+ true
747
+ else
748
+ libs = append_library($libs, lib)
749
+ if try_func(func, libs, headers, &b)
750
+ $libs = libs
751
+ true
752
+ else
753
+ false
754
+ end
755
+ end
756
+ end
757
+ end
758
+
759
+ # Returns whether or not the entry point +func+ can be found within the library
760
+ # +lib+ in one of the +paths+ specified, where +paths+ is an array of strings.
761
+ # If +func+ is nil , then the main() function is used as the entry point.
762
+ #
763
+ # If +lib+ is found, then the path it was found on is added to the list of
764
+ # library paths searched and linked against.
765
+ #
766
+ def find_library(lib, func, *paths, &b)
767
+ func = "main" if !func or func.empty?
768
+ lib = with_config(lib+'lib', lib)
769
+ paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
770
+ checking_for "#{func}() in #{LIBARG%lib}" do
771
+ libpath = $LIBPATH
772
+ libs = append_library($libs, lib)
773
+ begin
774
+ until r = try_func(func, libs, &b) or paths.empty?
775
+ $LIBPATH = libpath | [paths.shift]
776
+ end
777
+ if r
778
+ $libs = libs
779
+ libpath = nil
780
+ end
781
+ ensure
782
+ $LIBPATH = libpath if libpath
783
+ end
784
+ r
785
+ end
786
+ end
787
+
788
+ # Returns whether or not the function +func+ can be found in the common
789
+ # header files, or within any +headers+ that you provide. If found, a
790
+ # macro is passed as a preprocessor constant to the compiler using the
791
+ # function name, in uppercase, prepended with 'HAVE_'.
792
+ #
793
+ # For example, if have_func('foo') returned true, then the HAVE_FOO
794
+ # preprocessor macro would be passed to the compiler.
795
+ #
796
+ def have_func(func, headers = nil, &b)
797
+ checking_for checking_message("#{func}()", headers) do
798
+ if try_func(func, $libs, headers, &b)
799
+ $defs.push(format("-DHAVE_%s", func.tr_cpp))
800
+ true
801
+ else
802
+ false
803
+ end
804
+ end
805
+ end
806
+
807
+ # Returns whether or not the variable +var+ can be found in the common
808
+ # header files, or within any +headers+ that you provide. If found, a
809
+ # macro is passed as a preprocessor constant to the compiler using the
810
+ # variable name, in uppercase, prepended with 'HAVE_'.
811
+ #
812
+ # For example, if have_var('foo') returned true, then the HAVE_FOO
813
+ # preprocessor macro would be passed to the compiler.
814
+ #
815
+ def have_var(var, headers = nil, &b)
816
+ checking_for checking_message(var, headers) do
817
+ if try_var(var, headers, &b)
818
+ $defs.push(format("-DHAVE_%s", var.tr_cpp))
819
+ true
820
+ else
821
+ false
822
+ end
823
+ end
824
+ end
825
+
826
+ # Returns whether or not the given +header+ file can be found on your system.
827
+ # If found, a macro is passed as a preprocessor constant to the compiler using
828
+ # the header file name, in uppercase, prepended with 'HAVE_'.
829
+ #
830
+ # For example, if have_header('foo.h') returned true, then the HAVE_FOO_H
831
+ # preprocessor macro would be passed to the compiler.
832
+ #
833
+ def have_header(header, preheaders = nil, &b)
834
+ checking_for header do
835
+ if try_header(cpp_include(preheaders)+cpp_include(header), &b)
836
+ $defs.push(format("-DHAVE_%s", header.tr_cpp))
837
+ true
838
+ else
839
+ false
840
+ end
841
+ end
842
+ end
843
+
844
+ # Instructs mkmf to search for the given +header+ in any of the +paths+
845
+ # provided, and returns whether or not it was found in those paths.
846
+ #
847
+ # If the header is found then the path it was found on is added to the list
848
+ # of included directories that are sent to the compiler (via the -I switch).
849
+ #
850
+ def find_header(header, *paths)
851
+ message = checking_message(header, paths)
852
+ header = cpp_include(header)
853
+ checking_for message do
854
+ if try_header(header)
855
+ true
856
+ else
857
+ found = false
858
+ paths.each do |dir|
859
+ opt = "-I#{dir}".quote
860
+ if try_header(header, opt)
861
+ $INCFLAGS << " " << opt
862
+ found = true
863
+ break
864
+ end
865
+ end
866
+ found
867
+ end
868
+ end
869
+ end
870
+
871
+ # Returns whether or not the struct of type +type+ contains +member+. If
872
+ # it does not, or the struct type can't be found, then false is returned. You
873
+ # may optionally specify additional +headers+ in which to look for the struct
874
+ # (in addition to the common header files).
875
+ #
876
+ # If found, a macro is passed as a preprocessor constant to the compiler using
877
+ # the type name and the member name, in uppercase, prepended with 'HAVE_'.
878
+ #
879
+ # For example, if have_struct_member('struct foo', 'bar') returned true, then the
880
+ # HAVE_STRUCT_FOO_BAR preprocessor macro would be passed to the compiler.
881
+ #
882
+ # HAVE_ST_BAR is also defined for backward compatibility.
883
+ #
884
+ def have_struct_member(type, member, headers = nil, &b)
885
+ checking_for checking_message("#{type}.#{member}", headers) do
886
+ if try_compile(<<"SRC", &b)
887
+ #{cpp_include(headers)}
888
+ /*top*/
889
+ #{MAIN_DOES_NOTHING}
890
+ int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
891
+ SRC
892
+ $defs.push(format("-DHAVE_%s_%s", type.tr_cpp, member.tr_cpp))
893
+ $defs.push(format("-DHAVE_ST_%s", member.tr_cpp)) # backward compatibility
894
+ true
895
+ else
896
+ false
897
+ end
898
+ end
899
+ end
900
+
901
+ def try_type(type, headers = nil, opt = "", &b)
902
+ if try_compile(<<"SRC", opt, &b)
903
+ #{cpp_include(headers)}
904
+ /*top*/
905
+ typedef #{type} conftest_type;
906
+ int conftestval[sizeof(conftest_type)?1:-1];
907
+ SRC
908
+ $defs.push(format("-DHAVE_TYPE_%s", type.tr_cpp))
909
+ true
910
+ else
911
+ false
912
+ end
913
+ end
914
+
915
+ # Returns whether or not the static type +type+ is defined. You may
916
+ # optionally pass additional +headers+ to check against in addition to the
917
+ # common header files.
918
+ #
919
+ # You may also pass additional flags to +opt+ which are then passed along to
920
+ # the compiler.
921
+ #
922
+ # If found, a macro is passed as a preprocessor constant to the compiler using
923
+ # the type name, in uppercase, prepended with 'HAVE_TYPE_'.
924
+ #
925
+ # For example, if have_type('foo') returned true, then the HAVE_TYPE_FOO
926
+ # preprocessor macro would be passed to the compiler.
927
+ #
928
+ def have_type(type, headers = nil, opt = "", &b)
929
+ checking_for checking_message(type, headers, opt) do
930
+ try_type(type, headers, opt, &b)
931
+ end
932
+ end
933
+
934
+ # Returns where the static type +type+ is defined.
935
+ #
936
+ # You may also pass additional flags to +opt+ which are then passed along to
937
+ # the compiler.
938
+ #
939
+ # See also +have_type+.
940
+ #
941
+ def find_type(type, opt, *headers, &b)
942
+ opt ||= ""
943
+ fmt = "not found"
944
+ def fmt.%(x)
945
+ x ? x.respond_to?(:join) ? x.join(",") : x : self
946
+ end
947
+ checking_for checking_message(type, nil, opt), fmt do
948
+ headers.find do |h|
949
+ try_type(type, h, opt, &b)
950
+ end
951
+ end
952
+ end
953
+
954
+ def try_const(const, headers = nil, opt = "", &b)
955
+ const, type = *const
956
+ if try_compile(<<"SRC", opt, &b)
957
+ #{cpp_include(headers)}
958
+ /*top*/
959
+ typedef #{type || 'int'} conftest_type;
960
+ conftest_type conftestval = #{type ? '' : '(int)'}#{const};
961
+ SRC
962
+ $defs.push(format("-DHAVE_CONST_%s", const.tr_cpp))
963
+ true
964
+ else
965
+ false
966
+ end
967
+ end
968
+
969
+ # Returns whether or not the constant +const+ is defined. You may
970
+ # optionally pass the +type+ of +const+ as <code>[const, type]</code>,
971
+ # like as:
972
+ #
973
+ # have_const(%w[PTHREAD_MUTEX_INITIALIZER pthread_mutex_t], "pthread.h")
974
+ #
975
+ # You may also pass additional +headers+ to check against in addition
976
+ # to the common header files, and additional flags to +opt+ which are
977
+ # then passed along to the compiler.
978
+ #
979
+ # If found, a macro is passed as a preprocessor constant to the compiler using
980
+ # the type name, in uppercase, prepended with 'HAVE_CONST_'.
981
+ #
982
+ # For example, if have_const('foo') returned true, then the HAVE_CONST_FOO
983
+ # preprocessor macro would be passed to the compiler.
984
+ #
985
+ def have_const(const, headers = nil, opt = "", &b)
986
+ checking_for checking_message([*const].compact.join(' '), headers, opt) do
987
+ try_const(const, headers, opt, &b)
988
+ end
989
+ end
990
+
991
+ STRING_OR_FAILED_FORMAT = "%s"
992
+ # :stopdoc:
993
+ def STRING_OR_FAILED_FORMAT.%(x)
994
+ x ? super : "failed"
995
+ end
996
+ # :startdoc:
997
+
998
+ # Returns the size of the given +type+. You may optionally specify additional
999
+ # +headers+ to search in for the +type+.
1000
+ #
1001
+ # If found, a macro is passed as a preprocessor constant to the compiler using
1002
+ # the type name, in uppercase, prepended with 'SIZEOF_', followed by the type
1003
+ # name, followed by '=X' where 'X' is the actual size.
1004
+ #
1005
+ # For example, if check_sizeof('mystruct') returned 12, then the
1006
+ # SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to the compiler.
1007
+ #
1008
+ def check_sizeof(type, headers = nil, opts = "", &b)
1009
+ typename, member = type.split('.', 2)
1010
+ prelude = cpp_include(headers).split(/$/)
1011
+ prelude << "typedef #{typename} rbcv_typedef_;\n"
1012
+ prelude << "static rbcv_typedef_ *rbcv_ptr_;\n"
1013
+ prelude = [prelude]
1014
+ expr = "sizeof((*rbcv_ptr_)#{"." << member if member})"
1015
+ fmt = STRING_OR_FAILED_FORMAT
1016
+ checking_for checking_message("size of #{type}", headers), fmt do
1017
+ if UNIVERSAL_INTS.include?(type)
1018
+ type
1019
+ elsif size = UNIVERSAL_INTS.find {|t|
1020
+ try_static_assert("#{expr} == sizeof(#{t})", prelude, opts, &b)
1021
+ }
1022
+ $defs.push(format("-DSIZEOF_%s=SIZEOF_%s", type.tr_cpp, size.tr_cpp))
1023
+ size
1024
+ elsif size = try_constant(expr, prelude, opts, &b)
1025
+ $defs.push(format("-DSIZEOF_%s=%s", type.tr_cpp, size))
1026
+ size
1027
+ end
1028
+ end
1029
+ end
1030
+
1031
+ # Returns the signedness of the given +type+. You may optionally
1032
+ # specify additional +headers+ to search in for the +type+.
1033
+ #
1034
+ # If the +type+ is found and is a numeric type, a macro is passed as a
1035
+ # preprocessor constant to the compiler using the +type+ name, in
1036
+ # uppercase, prepended with 'SIGNEDNESS_OF_', followed by the +type+
1037
+ # name, followed by '=X' where 'X' is positive integer if the +type+ is
1038
+ # unsigned, or negative integer if the +type+ is signed.
1039
+ #
1040
+ # For example, if size_t is defined as unsigned, then
1041
+ # check_signedness('size_t') would returned +1 and the
1042
+ # SIGNEDNESS_OF_SIZE_T=+1 preprocessor macro would be passed to the
1043
+ # compiler, and SIGNEDNESS_OF_INT=-1 if check_signedness('int') is
1044
+ # done.
1045
+ #
1046
+ def check_signedness(type, headers = nil)
1047
+ signed = nil
1048
+ checking_for("signedness of #{type}", STRING_OR_FAILED_FORMAT) do
1049
+ if try_static_assert("(#{type})-1 < 0")
1050
+ signed = -1
1051
+ elsif try_static_assert("(#{type})-1 > 0")
1052
+ signed = +1
1053
+ else
1054
+ next nil
1055
+ end
1056
+ $defs.push("-DSIGNEDNESS_OF_%s=%+d" % [type.tr_cpp, signed])
1057
+ signed < 0 ? "signed" : "unsigned"
1058
+ end
1059
+ signed
1060
+ end
1061
+
1062
+ # :stopdoc:
1063
+
1064
+ # Used internally by the what_type? method to determine if +type+ is a scalar
1065
+ # pointer.
1066
+ def scalar_ptr_type?(type, member = nil, headers = nil, &b)
1067
+ try_compile(<<"SRC", &b) # pointer
1068
+ #{cpp_include(headers)}
1069
+ /*top*/
1070
+ volatile #{type} conftestval;
1071
+ #{MAIN_DOES_NOTHING}
1072
+ int t() {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
1073
+ SRC
1074
+ end
1075
+
1076
+ # Used internally by the what_type? method to determine if +type+ is a scalar
1077
+ # pointer.
1078
+ def scalar_type?(type, member = nil, headers = nil, &b)
1079
+ try_compile(<<"SRC", &b) # pointer
1080
+ #{cpp_include(headers)}
1081
+ /*top*/
1082
+ volatile #{type} conftestval;
1083
+ #{MAIN_DOES_NOTHING}
1084
+ int t() {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
1085
+ SRC
1086
+ end
1087
+
1088
+ # Used internally by the what_type? method to check if _typeof_ GCC
1089
+ # extension is available.
1090
+ def have_typeof?
1091
+ return $typeof if defined?($typeof)
1092
+ $typeof = %w[__typeof__ typeof].find do |t|
1093
+ try_compile(<<SRC)
1094
+ int rbcv_foo;
1095
+ #{t}(rbcv_foo) rbcv_bar;
1096
+ SRC
1097
+ end
1098
+ end
1099
+
1100
+ def what_type?(type, member = nil, headers = nil, &b)
1101
+ m = "#{type}"
1102
+ var = val = "*rbcv_var_"
1103
+ func = "rbcv_func_(void)"
1104
+ if member
1105
+ m << "." << member
1106
+ else
1107
+ type, member = type.split('.', 2)
1108
+ end
1109
+ if member
1110
+ val = "(#{var}).#{member}"
1111
+ end
1112
+ prelude = [cpp_include(headers).split(/^/)]
1113
+ prelude << ["typedef #{type} rbcv_typedef_;\n",
1114
+ "extern rbcv_typedef_ *#{func};\n",
1115
+ "static rbcv_typedef_ #{var};\n",
1116
+ ]
1117
+ type = "rbcv_typedef_"
1118
+ fmt = member && !(typeof = have_typeof?) ? "seems %s" : "%s"
1119
+ if typeof
1120
+ var = "*rbcv_member_"
1121
+ func = "rbcv_mem_func_(void)"
1122
+ member = nil
1123
+ type = "rbcv_mem_typedef_"
1124
+ prelude[-1] << "typedef #{typeof}(#{val}) #{type};\n"
1125
+ prelude[-1] << "extern #{type} *#{func};\n"
1126
+ prelude[-1] << "static #{type} #{var};\n"
1127
+ val = var
1128
+ end
1129
+ def fmt.%(x)
1130
+ x ? super : "unknown"
1131
+ end
1132
+ checking_for checking_message(m, headers), fmt do
1133
+ if scalar_ptr_type?(type, member, prelude, &b)
1134
+ if try_static_assert("sizeof(*#{var}) == 1", prelude)
1135
+ return "string"
1136
+ end
1137
+ ptr = "*"
1138
+ elsif scalar_type?(type, member, prelude, &b)
1139
+ unless member and !typeof or try_static_assert("(#{type})-1 < 0", prelude)
1140
+ unsigned = "unsigned"
1141
+ end
1142
+ ptr = ""
1143
+ else
1144
+ next
1145
+ end
1146
+ type = UNIVERSAL_INTS.find do |t|
1147
+ pre = prelude
1148
+ unless member
1149
+ pre += [["static #{unsigned} #{t} #{ptr}#{var};\n",
1150
+ "extern #{unsigned} #{t} #{ptr}*#{func};\n"]]
1151
+ end
1152
+ try_static_assert("sizeof(#{ptr}#{val}) == sizeof(#{unsigned} #{t})", pre)
1153
+ end
1154
+ type or next
1155
+ [unsigned, type, ptr].join(" ").strip
1156
+ end
1157
+ end
1158
+
1159
+ # This method is used internally by the find_executable method.
1160
+ #
1161
+ # Internal use only.
1162
+ #
1163
+ def find_executable0(bin, path = nil)
1164
+ exts = config_string('EXECUTABLE_EXTS') {|s| s.split} || config_string('EXEEXT') {|s| [s]}
1165
+ if File.expand_path(bin) == bin
1166
+ return bin if File.executable?(bin)
1167
+ if exts
1168
+ exts.each {|ext| File.executable?(file = bin + ext) and return file}
1169
+ end
1170
+ return nil
1171
+ end
1172
+ if path ||= ENV['PATH']
1173
+ path = path.split(File::PATH_SEPARATOR)
1174
+ else
1175
+ path = %w[/usr/local/bin /usr/ucb /usr/bin /bin]
1176
+ end
1177
+ file = nil
1178
+ path.each do |dir|
1179
+ return file if File.executable?(file = File.join(dir, bin))
1180
+ if exts
1181
+ exts.each {|ext| File.executable?(ext = file + ext) and return ext}
1182
+ end
1183
+ end
1184
+ nil
1185
+ end
1186
+
1187
+ # :startdoc:
1188
+
1189
+ # Searches for the executable +bin+ on +path+. The default path is your
1190
+ # PATH environment variable. If that isn't defined, it will resort to
1191
+ # searching /usr/local/bin, /usr/ucb, /usr/bin and /bin.
1192
+ #
1193
+ # If found, it will return the full path, including the executable name,
1194
+ # of where it was found.
1195
+ #
1196
+ # Note that this method does not actually affect the generated Makefile.
1197
+ #
1198
+ def find_executable(bin, path = nil)
1199
+ checking_for checking_message(bin, path) do
1200
+ find_executable0(bin, path)
1201
+ end
1202
+ end
1203
+
1204
+ # :stopdoc:
1205
+
1206
+ def arg_config(config, default=nil, &block)
1207
+ $arg_config << [config, default]
1208
+ defaults = []
1209
+ if default
1210
+ defaults << default
1211
+ elsif !block
1212
+ defaults << nil
1213
+ end
1214
+ $configure_args.fetch(config.tr('_', '-'), *defaults, &block)
1215
+ end
1216
+
1217
+ # :startdoc:
1218
+
1219
+ # Tests for the presence of a --with-<tt>config</tt> or --without-<tt>config</tt>
1220
+ # option. Returns true if the with option is given, false if the without
1221
+ # option is given, and the default value otherwise.
1222
+ #
1223
+ # This can be useful for adding custom definitions, such as debug information.
1224
+ #
1225
+ # Example:
1226
+ #
1227
+ # if with_config("debug")
1228
+ # $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1229
+ # end
1230
+ #
1231
+ def with_config(config, default=nil)
1232
+ config = config.sub(/^--with[-_]/, '')
1233
+ val = arg_config("--with-"+config) do
1234
+ if arg_config("--without-"+config)
1235
+ false
1236
+ elsif block_given?
1237
+ yield(config, default)
1238
+ else
1239
+ break default
1240
+ end
1241
+ end
1242
+ case val
1243
+ when "yes"
1244
+ true
1245
+ when "no"
1246
+ false
1247
+ else
1248
+ val
1249
+ end
1250
+ end
1251
+
1252
+ # Tests for the presence of an --enable-<tt>config</tt> or
1253
+ # --disable-<tt>config</tt> option. Returns true if the enable option is given,
1254
+ # false if the disable option is given, and the default value otherwise.
1255
+ #
1256
+ # This can be useful for adding custom definitions, such as debug information.
1257
+ #
1258
+ # Example:
1259
+ #
1260
+ # if enable_config("debug")
1261
+ # $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1262
+ # end
1263
+ #
1264
+ def enable_config(config, default=nil)
1265
+ if arg_config("--enable-"+config)
1266
+ true
1267
+ elsif arg_config("--disable-"+config)
1268
+ false
1269
+ elsif block_given?
1270
+ yield(config, default)
1271
+ else
1272
+ return default
1273
+ end
1274
+ end
1275
+
1276
+ # Generates a header file consisting of the various macro definitions generated
1277
+ # by other methods such as have_func and have_header. These are then wrapped in
1278
+ # a custom #ifndef based on the +header+ file name, which defaults to
1279
+ # 'extconf.h'.
1280
+ #
1281
+ # For example:
1282
+ #
1283
+ # # extconf.rb
1284
+ # require 'mkmf'
1285
+ # have_func('realpath')
1286
+ # have_header('sys/utime.h')
1287
+ # create_header
1288
+ # create_makefile('foo')
1289
+ #
1290
+ # The above script would generate the following extconf.h file:
1291
+ #
1292
+ # #ifndef EXTCONF_H
1293
+ # #define EXTCONF_H
1294
+ # #define HAVE_REALPATH 1
1295
+ # #define HAVE_SYS_UTIME_H 1
1296
+ # #endif
1297
+ #
1298
+ # Given that the create_header method generates a file based on definitions
1299
+ # set earlier in your extconf.rb file, you will probably want to make this
1300
+ # one of the last methods you call in your script.
1301
+ #
1302
+ def create_header(header = "extconf.h")
1303
+ message "creating %s\n", header
1304
+ sym = header.tr_cpp
1305
+ hdr = ["#ifndef #{sym}\n#define #{sym}\n"]
1306
+ for line in $defs
1307
+ case line
1308
+ when /^-D([^=]+)(?:=(.*))?/
1309
+ hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0].gsub(/(?=\t+)/, "\\\n") : 1}\n"
1310
+ when /^-U(.*)/
1311
+ hdr << "#undef #$1\n"
1312
+ end
1313
+ end
1314
+ hdr << "#endif\n"
1315
+ hdr = hdr.join
1316
+ unless (IO.read(header) == hdr rescue false)
1317
+ open(header, "wb") do |hfile|
1318
+ hfile.write(hdr)
1319
+ end
1320
+ end
1321
+ $extconf_h = header
1322
+ end
1323
+
1324
+ # Sets a +target+ name that the user can then use to configure various 'with'
1325
+ # options with on the command line by using that name. For example, if the
1326
+ # target is set to "foo", then the user could use the --with-foo-dir command
1327
+ # line option.
1328
+ #
1329
+ # You may pass along additional 'include' or 'lib' defaults via the +idefault+
1330
+ # and +ldefault+ parameters, respectively.
1331
+ #
1332
+ # Note that dir_config only adds to the list of places to search for libraries
1333
+ # and include files. It does not link the libraries into your application.
1334
+ #
1335
+ def dir_config(target, idefault=nil, ldefault=nil)
1336
+ if dir = with_config(target + "-dir", (idefault unless ldefault))
1337
+ defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR)
1338
+ idefault = ldefault = nil
1339
+ end
1340
+
1341
+ idir = with_config(target + "-include", idefault)
1342
+ $arg_config.last[1] ||= "${#{target}-dir}/include"
1343
+ ldir = with_config(target + "-lib", ldefault)
1344
+ $arg_config.last[1] ||= "${#{target}-dir}/lib"
1345
+
1346
+ idirs = idir ? Array === idir ? idir.dup : idir.split(File::PATH_SEPARATOR) : []
1347
+ if defaults
1348
+ idirs.concat(defaults.collect {|d| d + "/include"})
1349
+ idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR)
1350
+ end
1351
+ unless idirs.empty?
1352
+ idirs.collect! {|d| "-I" + d}
1353
+ idirs -= Shellwords.shellwords($CPPFLAGS)
1354
+ unless idirs.empty?
1355
+ $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ")
1356
+ end
1357
+ end
1358
+
1359
+ ldirs = ldir ? Array === ldir ? ldir.dup : ldir.split(File::PATH_SEPARATOR) : []
1360
+ if defaults
1361
+ ldirs.concat(defaults.collect {|d| d + "/lib"})
1362
+ ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR)
1363
+ end
1364
+ $LIBPATH = ldirs | $LIBPATH
1365
+
1366
+ [idir, ldir]
1367
+ end
1368
+
1369
+ # :stopdoc:
1370
+
1371
+ # Handles meta information about installed libraries. Uses your platform's
1372
+ # pkg-config program if it has one.
1373
+ def pkg_config(pkg)
1374
+ if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
1375
+ # iff package specific config command is given
1376
+ get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
1377
+ elsif ($PKGCONFIG ||=
1378
+ (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
1379
+ find_executable0(pkgconfig) && pkgconfig) and
1380
+ system("#{$PKGCONFIG} --exists #{pkg}")
1381
+ # default to pkg-config command
1382
+ get = proc {|opt| `#{$PKGCONFIG} --#{opt} #{pkg}`.chomp}
1383
+ elsif find_executable0(pkgconfig = "#{pkg}-config")
1384
+ # default to package specific config command, as a last resort.
1385
+ get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
1386
+ end
1387
+ if get
1388
+ cflags = get['cflags']
1389
+ ldflags = get['libs']
1390
+ libs = get['libs-only-l']
1391
+ ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ")
1392
+ $CFLAGS += " " << cflags
1393
+ $LDFLAGS += " " << ldflags
1394
+ $libs += " " << libs
1395
+ Logging::message "package configuration for %s\n", pkg
1396
+ Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n",
1397
+ cflags, ldflags, libs
1398
+ [cflags, ldflags, libs]
1399
+ else
1400
+ Logging::message "package configuration for %s is not found\n", pkg
1401
+ nil
1402
+ end
1403
+ end
1404
+
1405
+ def with_destdir(dir)
1406
+ dir = dir.sub($dest_prefix_pattern, '')
1407
+ /\A\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir
1408
+ end
1409
+
1410
+ # Converts forward slashes to backslashes. Aimed at MS Windows.
1411
+ #
1412
+ # Internal use only.
1413
+ #
1414
+ def winsep(s)
1415
+ s.tr('/', '\\')
1416
+ end
1417
+
1418
+ # Converts native path to format acceptable in Makefile
1419
+ #
1420
+ # Internal use only.
1421
+ #
1422
+ if !CROSS_COMPILING
1423
+ case CONFIG['build_os']
1424
+ when 'mingw32'
1425
+ def mkintpath(path)
1426
+ # mingw uses make from msys and it needs special care
1427
+ # converts from C:\some\path to /C/some/path
1428
+ path = path.dup
1429
+ path.tr!('\\', '/')
1430
+ path.sub!(/\A([A-Za-z]):(?=\/)/, '/\1')
1431
+ return File.expand_path( path ) unless $use_relative_paths
1432
+ return path
1433
+ end
1434
+ end
1435
+ end
1436
+ unless defined?(mkintpath)
1437
+ def mkintpath(path)
1438
+ return File.expand_path( path ) unless $use_relative_paths
1439
+ return path
1440
+ end
1441
+ end
1442
+
1443
+ def configuration(srcdir)
1444
+ mk = []
1445
+ vpath = $VPATH.dup
1446
+ if !CROSS_COMPILING
1447
+ case CONFIG['build_os']
1448
+ when 'cygwin'
1449
+ if CONFIG['target_os'] != 'cygwin'
1450
+ vpath = vpath.map {|p| p.sub(/.*/, '$(shell cygpath -u \&)')}
1451
+ end
1452
+ end
1453
+ end
1454
+ CONFIG["hdrdir"] ||= $hdrdir
1455
+ mk << %{
1456
+ SHELL = /bin/sh
1457
+
1458
+ #### Start of system configuration section. ####
1459
+ #{"top_srcdir = " + $top_srcdir.sub(%r"\A#{Regexp.quote($topdir)}/", "$(topdir)/") if $extmk}
1460
+ srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {mkintpath(CONFIG[$1||$2])}.quote}
1461
+ topdir = #{mkintpath($extmk ? CONFIG["topdir"] : $topdir).quote}
1462
+ hdrdir = #{mkintpath(CONFIG["hdrdir"]).quote}
1463
+ arch_hdrdir = #{$arch_hdrdir}
1464
+ VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}:#{$file_directories.collect{ |directory| File.expand_path( directory )}.join(':')}
1465
+ }
1466
+ if $extmk
1467
+ mk << "RUBYLIB = -\nRUBYOPT = -r$(top_srcdir)/ext/purelib.rb\n"
1468
+ end
1469
+ if destdir = CONFIG["prefix"][$dest_prefix_pattern, 1]
1470
+ mk << "\nDESTDIR = #{destdir}\n"
1471
+ end
1472
+ CONFIG.each do |key, var|
1473
+ next unless /prefix$/ =~ key
1474
+ mk << "#{key} = #{with_destdir(var)}\n"
1475
+ end
1476
+ CONFIG.each do |key, var|
1477
+ next if /^abs_/ =~ key
1478
+ next if /^(?:src|top|hdr)dir$/ =~ key
1479
+ next unless /dir$/ =~ key
1480
+ mk << "#{key} = #{with_destdir(var)}\n"
1481
+ end
1482
+ if !$extmk and !$configure_args.has_key?('--ruby') and
1483
+ sep = config_string('BUILD_FILE_SEPARATOR')
1484
+ sep = ":/=#{sep}"
1485
+ else
1486
+ sep = ""
1487
+ end
1488
+ possible_command = (proc {|s| s if /top_srcdir/ !~ s} unless $extmk)
1489
+ extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ") << " "
1490
+ mk << %{
1491
+ CC = #{CONFIG['CC']}
1492
+ CXX = #{CONFIG['CXX']}
1493
+ LIBRUBY = #{CONFIG['LIBRUBY']}
1494
+ LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
1495
+ LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
1496
+ LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC
1497
+ OUTFLAG = #{OUTFLAG}
1498
+ COUTFLAG = #{COUTFLAG}
1499
+
1500
+ RUBY_EXTCONF_H = #{$extconf_h}
1501
+ cflags = #{CONFIG['cflags']}
1502
+ optflags = #{CONFIG['optflags']}
1503
+ debugflags = #{CONFIG['debugflags']}
1504
+ warnflags = #{CONFIG['warnflags']}
1505
+ CFLAGS = #{$static ? '' : CONFIG['CCDLFLAGS']} #$CFLAGS #$ARCH_FLAG
1506
+ INCFLAGS = -I. #$INCFLAGS#{$include_directories.collect{ |directory| ' -I' + directory}.join(' ')}
1507
+ DEFS = #{CONFIG['DEFS']}
1508
+ CPPFLAGS = #{extconf_h}#{$CPPFLAGS}
1509
+ CXXFLAGS = $(CFLAGS) #{CONFIG['CXXFLAGS']}
1510
+ ldflags = #{$LDFLAGS}
1511
+ dldflags = #{$DLDFLAGS}
1512
+ ARCH_FLAG = #{$ARCH_FLAG}
1513
+ DLDFLAGS = $(ldflags) $(dldflags)
1514
+ LDSHARED = #{CONFIG['LDSHARED']}
1515
+ LDSHAREDXX = #{config_string('LDSHAREDXX') || '$(LDSHARED)'}
1516
+ AR = #{CONFIG['AR']}
1517
+ EXEEXT = #{CONFIG['EXEEXT']}
1518
+
1519
+ RUBY_BASE_NAME = #{CONFIG['RUBY_BASE_NAME']}
1520
+ RUBY_INSTALL_NAME = #{CONFIG['RUBY_INSTALL_NAME']}
1521
+ RUBY_SO_NAME = #{CONFIG['RUBY_SO_NAME']}
1522
+ arch = #{CONFIG['arch']}
1523
+ sitearch = #{CONFIG['sitearch']}
1524
+ ruby_version = #{RbConfig::CONFIG['ruby_version']}
1525
+ ruby = #{$ruby}
1526
+ RUBY = $(ruby#{sep})
1527
+ RM = #{config_string('RM', &possible_command) || '$(RUBY) -run -e rm -- -f'}
1528
+ RM_RF = #{'$(RUBY) -run -e rm -- -rf'}
1529
+ RMDIRS = #{config_string('RMDIRS', &possible_command) || '$(RUBY) -run -e rmdir -- -p'}
1530
+ MAKEDIRS = #{config_string('MAKEDIRS', &possible_command) || '@$(RUBY) -run -e mkdir -- -p'}
1531
+ INSTALL = #{config_string('INSTALL', &possible_command) || '@$(RUBY) -run -e install -- -vp'}
1532
+ INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'}
1533
+ INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'}
1534
+ COPY = #{config_string('CP', &possible_command) || '@$(RUBY) -run -e cp -- -v'}
1535
+
1536
+ #### End of system configuration section. ####
1537
+
1538
+ preload = #{defined?($preload) && $preload ? $preload.join(' ') : ''}
1539
+ }
1540
+ if $nmake == ?b
1541
+ mk.each do |x|
1542
+ x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do
1543
+ "!ifndef " + $1 + "\n" +
1544
+ $& +
1545
+ "!endif\n"
1546
+ end
1547
+ end
1548
+ end
1549
+ mk
1550
+ end
1551
+ # :startdoc:
1552
+
1553
+ def dummy_makefile(srcdir)
1554
+ configuration(srcdir) << <<RULES << CLEANINGS
1555
+ CLEANFILES = #{$cleanfiles.join(' ')}
1556
+ DISTCLEANFILES = #{$distcleanfiles.join(' ')}
1557
+
1558
+ all install static install-so install-rb: Makefile
1559
+ .PHONY: all install static install-so install-rb
1560
+ .PHONY: clean clean-so clean-rb
1561
+
1562
+ RULES
1563
+ end
1564
+
1565
+ def depend_rules(depend)
1566
+ suffixes = []
1567
+ depout = []
1568
+ cont = implicit = nil
1569
+ impconv = proc do
1570
+ COMPILE_RULES.each {|rule| depout << (rule % implicit[0]) << implicit[1]}
1571
+ implicit = nil
1572
+ end
1573
+ ruleconv = proc do |line|
1574
+ if implicit
1575
+ if /\A\t/ =~ line
1576
+ implicit[1] << line
1577
+ next
1578
+ else
1579
+ impconv[]
1580
+ end
1581
+ end
1582
+ if m = /\A\.(\w+)\.(\w+)(?:\s*:)/.match(line)
1583
+ suffixes << m[1] << m[2]
1584
+ implicit = [[m[1], m[2]], [m.post_match]]
1585
+ next
1586
+ elsif RULE_SUBST and /\A(?!\s*\w+\s*=)[$\w][^#]*:/ =~ line
1587
+ line.gsub!(%r"(\s)(?!\.)([^$(){}+=:\s\/\\,]+)(?=\s|\z)") {$1 + RULE_SUBST % $2}
1588
+ end
1589
+ depout << line
1590
+ end
1591
+ depend.each_line do |line|
1592
+ line.gsub!(/\.o\b/, ".#{$OBJEXT}")
1593
+ line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h)
1594
+ line.gsub!(%r"\$\(hdrdir\)/(?!ruby(?![^:;/\s]))(?=[-\w]+\.h)", '\&ruby/')
1595
+ if $nmake && /\A\s*\$\(RM|COPY\)/ =~ line
1596
+ line.gsub!(%r"[-\w\./]{2,}"){$&.tr("/", "\\")}
1597
+ line.gsub!(/(\$\((?!RM|COPY)[^:)]+)(?=\))/, '\1:/=\\')
1598
+ end
1599
+ if /(?:^|[^\\])(?:\\\\)*\\$/ =~ line
1600
+ (cont ||= []) << line
1601
+ next
1602
+ elsif cont
1603
+ line = (cont << line).join
1604
+ cont = nil
1605
+ end
1606
+ ruleconv.call(line)
1607
+ end
1608
+ if cont
1609
+ ruleconv.call(cont.join)
1610
+ elsif implicit
1611
+ impconv.call
1612
+ end
1613
+ unless suffixes.empty?
1614
+ depout.unshift(".SUFFIXES: ." + suffixes.uniq.join(" .") + "\n\n")
1615
+ end
1616
+ depout.unshift("$(OBJS): $(RUBY_EXTCONF_H)\n\n") if $extconf_h
1617
+ depout.flatten!
1618
+ depout
1619
+ end
1620
+
1621
+ def use_relative_paths
1622
+ $use_relative_paths = true
1623
+ yield if block_given?
1624
+ end
1625
+
1626
+ def all_headers_files_and_directories_with_subdirectories_for( directory )
1627
+
1628
+ headers = Dir.glob( directory + '/**/*.h' )
1629
+ files = Array.new
1630
+ SRC_EXT.each do |this_ext|
1631
+ files.concat( Dir.glob( directory + '/**/*.' + this_ext ) )
1632
+ end
1633
+
1634
+ include_directories = headers.collect { |file| File.dirname( file ) }.uniq
1635
+ file_directories = files.collect { |file| File.dirname( file ) }.uniq
1636
+
1637
+ [ headers, files, include_directories ].each do |this_pathset|
1638
+ this_pathset.collect { |path| File.expand_path( path ) }
1639
+ end
1640
+
1641
+ return headers, files, file_directories, include_directories
1642
+
1643
+ end
1644
+
1645
+ # Generates the Makefile for your extension, passing along any options and
1646
+ # preprocessor constants that you may have generated through other methods.
1647
+ #
1648
+ # The +target+ name should correspond the name of the global function name
1649
+ # defined within your C extension, minus the 'Init_'. For example, if your
1650
+ # C extension is defined as 'Init_foo', then your target would simply be 'foo'.
1651
+ #
1652
+ # If any '/' characters are present in the target name, only the last name
1653
+ # is interpreted as the target name, and the rest are considered toplevel
1654
+ # directory names, and the generated Makefile will be altered accordingly to
1655
+ # follow that directory structure.
1656
+ #
1657
+ # For example, if you pass 'test/foo' as a target name, your extension will
1658
+ # be installed under the 'test' directory. This means that in order to
1659
+ # load the file within a Ruby program later, that directory structure will
1660
+ # have to be followed, e.g. "require 'test/foo'".
1661
+ #
1662
+ # The +srcprefix+ should be used when your source files are not in the same
1663
+ # directory as your build script. This will not only eliminate the need for
1664
+ # you to manually copy the source files into the same directory as your build
1665
+ # script, but it also sets the proper +target_prefix+ in the generated
1666
+ # Makefile.
1667
+ #
1668
+ # Setting the +target_prefix+ will, in turn, install the generated binary in
1669
+ # a directory under your RbConfig::CONFIG['sitearchdir'] that mimics your local
1670
+ # filesystem when you run 'make install'.
1671
+ #
1672
+ # For example, given the following file tree:
1673
+ #
1674
+ # ext/
1675
+ # extconf.rb
1676
+ # test/
1677
+ # foo.c
1678
+ #
1679
+ # And given the following code:
1680
+ #
1681
+ # create_makefile('test/foo', 'test')
1682
+ #
1683
+ # That will set the +target_prefix+ in the generated Makefile to 'test'. That,
1684
+ # in turn, will create the following file tree when installed via the
1685
+ # 'make install' command:
1686
+ #
1687
+ # /path/to/ruby/sitearchdir/test/foo.so
1688
+ #
1689
+ # It is recommended that you use this approach to generate your makefiles,
1690
+ # instead of copying files around manually, because some third party
1691
+ # libraries may depend on the +target_prefix+ being set properly.
1692
+ #
1693
+ # The +srcprefix+ argument can be used to override the default source
1694
+ # directory, i.e. the current directory . It is included as part of the VPATH
1695
+ # and added to the list of INCFLAGS.
1696
+ #
1697
+ def create_makefile(target, srcprefix = nil)
1698
+ $target = target
1699
+ libpath = $DEFLIBPATH|$LIBPATH
1700
+ message "creating Makefile\n"
1701
+ rm_f "conftest*"
1702
+ if CONFIG["DLEXT"] == $OBJEXT
1703
+ for lib in libs = $libs.split
1704
+ lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
1705
+ end
1706
+ $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
1707
+ end
1708
+
1709
+ if target.include?('/')
1710
+ target_prefix, target = File.split(target)
1711
+ target_prefix[0,0] = '/'
1712
+ else
1713
+ target_prefix = ""
1714
+ end
1715
+
1716
+ srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
1717
+ RbConfig.expand(srcdir = srcprefix.dup)
1718
+
1719
+ ext = ".#{$OBJEXT}"
1720
+ if not $objs
1721
+ # get sources - we want anything with our SRC_EXT in ext/target or any subdirectory
1722
+
1723
+ headers, files, $file_directories, $include_directories = all_headers_files_and_directories_with_subdirectories_for( srcdir )
1724
+ srcs = $srcs || files
1725
+
1726
+ # srcs = $srcs || Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
1727
+
1728
+ objs = srcs.inject(Hash.new {[]}) {|h, f| h[File.dirname( f ) + '/' + File.basename(f, ".*") << ext] <<= f; h}
1729
+ $objs = objs.keys
1730
+ # unless objs.delete_if {|b, f| f.size == 1}.empty?
1731
+ # dups = objs.sort.map {|b, f|
1732
+ # "#{b[/.*\./]}{#{f.collect {|n| n[/([^.]+)\z/]}.join(',')}}"
1733
+ # }
1734
+ # abort "source files duplication - #{dups.join(", ")}"
1735
+ # end
1736
+ else
1737
+ $objs.collect! {|o| File.basename(o, ".*") << ext} unless $OBJEXT == "o"
1738
+ srcs = $srcs || $objs.collect {|o| o.chomp(ext) << ".c"}
1739
+ end
1740
+ $srcs = srcs
1741
+
1742
+ target = nil if $objs.empty?
1743
+
1744
+ if target and EXPORT_PREFIX
1745
+ if File.exist?(File.join(srcdir, target + '.def'))
1746
+ deffile = "$(srcdir)/$(TARGET).def"
1747
+ unless EXPORT_PREFIX.empty?
1748
+ makedef = %{-pe "$_.sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i"}
1749
+ end
1750
+ else
1751
+ makedef = %{-e "puts 'EXPORTS', '#{EXPORT_PREFIX}Init_$(TARGET)'"}
1752
+ end
1753
+ if makedef
1754
+ $cleanfiles << '$(DEFFILE)'
1755
+ origdef = deffile
1756
+ deffile = "$(TARGET)-$(arch).def"
1757
+ end
1758
+ end
1759
+ origdef ||= ''
1760
+
1761
+ if $extout and $INSTALLFILES
1762
+ $cleanfiles.concat($INSTALLFILES.collect {|files, dir|File.join(dir, files.sub(/\A\.\//, ''))})
1763
+ $distcleandirs.concat($INSTALLFILES.collect {|files, dir| dir})
1764
+ end
1765
+
1766
+ if $extmk and not $extconf_h
1767
+ create_header
1768
+ end
1769
+
1770
+ libpath = libpathflag(libpath)
1771
+
1772
+ dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
1773
+ staticlib = target ? "$(TARGET).#$LIBEXT" : ""
1774
+ mfile = open("Makefile", "wb")
1775
+ conf = configuration(srcprefix)
1776
+ conf = yield(conf) if block_given?
1777
+ mfile.puts(conf)
1778
+ mfile.print "
1779
+ libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")}
1780
+ LIBPATH = #{libpath}
1781
+ DEFFILE = #{deffile}
1782
+
1783
+ CLEANFILES = #{$cleanfiles.join(' ')}
1784
+ DISTCLEANFILES = #{$distcleanfiles.join(' ')}
1785
+ DISTCLEANDIRS = #{$distcleandirs.join(' ')}
1786
+
1787
+ extout = #{$extout && $extout.quote}
1788
+ extout_prefix = #{$extout_prefix}
1789
+ target_prefix = #{target_prefix}
1790
+ LOCAL_LIBS = #{$LOCAL_LIBS}
1791
+ LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
1792
+ SRCS = #{srcs.collect(&File.method(:basename)).join(' ')}
1793
+ OBJS = #{$objs.collect(&File.method(:basename)).join(' ')}
1794
+ TARGET = #{target}
1795
+ DLLIB = #{dllib}
1796
+ EXTSTATIC = #{$static || ""}
1797
+ STATIC_LIB = #{staticlib unless $static.nil?}
1798
+ #{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
1799
+ " #"
1800
+ # TODO: fixme
1801
+ install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
1802
+ n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET)'
1803
+ mfile.print "
1804
+ TARGET_SO = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
1805
+ CLEANLIBS = #{n}.#{CONFIG['DLEXT']} #{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
1806
+ CLEANOBJS = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")} if target} *.bak
1807
+
1808
+ all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
1809
+ static: $(STATIC_LIB)#{$extout ? " install-rb" : ""}
1810
+ .PHONY: all install static install-so install-rb
1811
+ .PHONY: clean clean-so clean-rb
1812
+ "
1813
+ mfile.print CLEANINGS
1814
+ fsep = config_string('BUILD_FILE_SEPARATOR') {|s| s unless s == "/"}
1815
+ if fsep
1816
+ sep = ":/=#{fsep}"
1817
+ fseprepl = proc {|s|
1818
+ s = s.gsub("/", fsep)
1819
+ s = s.gsub(/(\$\(\w+)(\))/) {$1+sep+$2}
1820
+ s = s.gsub(/(\$\{\w+)(\})/) {$1+sep+$2}
1821
+ }
1822
+ else
1823
+ fseprepl = proc {|s| s}
1824
+ sep = ""
1825
+ end
1826
+ dirs = []
1827
+ mfile.print "install: install-so install-rb\n\n"
1828
+ sodir = (dir = "$(RUBYARCHDIR)").dup
1829
+ mfile.print("install-so: ")
1830
+ if target
1831
+ f = "$(DLLIB)"
1832
+ dest = "#{dir}/#{f}"
1833
+ mfile.puts dir, "install-so: #{dest}"
1834
+ if $extout
1835
+ mfile.print "clean-so::\n"
1836
+ mfile.print "\t@-$(RM) #{fseprepl[dest]}\n"
1837
+ mfile.print "\t@-$(RMDIRS) #{fseprepl[dir]}\n"
1838
+ else
1839
+ mfile.print "#{dest}: #{f}\n\t@-$(MAKEDIRS) $(@D#{sep})\n"
1840
+ mfile.print "\t$(INSTALL_PROG) #{fseprepl[f]} $(@D#{sep})\n"
1841
+ if defined?($installed_list)
1842
+ mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
1843
+ end
1844
+ end
1845
+ else
1846
+ mfile.puts "Makefile"
1847
+ end
1848
+ mfile.print("install-rb: pre-install-rb install-rb-default\n")
1849
+ mfile.print("install-rb-default: pre-install-rb-default\n")
1850
+ mfile.print("pre-install-rb: Makefile\n")
1851
+ mfile.print("pre-install-rb-default: Makefile\n")
1852
+ for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]]
1853
+ files = install_files(mfile, i, nil, srcprefix) or next
1854
+ for dir, *files in files
1855
+ unless dirs.include?(dir)
1856
+ dirs << dir
1857
+ mfile.print "pre-install-rb#{sfx}: #{dir}\n"
1858
+ end
1859
+ for f in files
1860
+ dest = "#{dir}/#{File.basename(f)}"
1861
+ mfile.print("install-rb#{sfx}: #{dest}\n")
1862
+ mfile.print("#{dest}: #{f}\n\t@-$(MAKEDIRS) $(@D#{sep})\n")
1863
+ mfile.print("\t$(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D#{sep})\n")
1864
+ if defined?($installed_list) and !$extout
1865
+ mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
1866
+ end
1867
+ if $extout
1868
+ mfile.print("clean-rb#{sfx}::\n")
1869
+ mfile.print("\t@-$(RM) #{fseprepl[dest]}\n")
1870
+ end
1871
+ end
1872
+ end
1873
+ if $extout
1874
+ dirs.uniq!
1875
+ unless dirs.empty?
1876
+ mfile.print("clean-rb#{sfx}::\n")
1877
+ for dir in dirs.sort_by {|d| -d.count('/')}
1878
+ mfile.print("\t@-$(RMDIRS) #{fseprepl[dir]}\n")
1879
+ end
1880
+ end
1881
+ end
1882
+ end
1883
+ dirs.unshift(sodir) if target and !dirs.include?(sodir)
1884
+ dirs.each {|d| mfile.print "#{d}:\n\t$(MAKEDIRS) $@\n"}
1885
+
1886
+ mfile.print <<-SITEINSTALL
1887
+
1888
+ site-install: site-install-so site-install-rb
1889
+ site-install-so: install-so
1890
+ site-install-rb: install-rb
1891
+
1892
+ SITEINSTALL
1893
+
1894
+ return unless target
1895
+
1896
+ mfile.puts SRC_EXT.collect {|e| ".path.#{e} = $(VPATH)"} if $nmake == ?b
1897
+ mfile.print ".SUFFIXES: .#{SRC_EXT.join(' .')} .#{$OBJEXT}\n"
1898
+ mfile.print "\n"
1899
+
1900
+ CXX_EXT.each do |e|
1901
+ COMPILE_RULES.each do |rule|
1902
+ mfile.printf(rule, e, $OBJEXT)
1903
+ mfile.printf("\n\t%s\n\n", COMPILE_CXX)
1904
+ end
1905
+ end
1906
+ %w[c].each do |e|
1907
+ COMPILE_RULES.each do |rule|
1908
+ mfile.printf(rule, e, $OBJEXT)
1909
+ mfile.printf("\n\t%s\n\n", COMPILE_C)
1910
+ end
1911
+ end
1912
+
1913
+ mfile.print "$(RUBYARCHDIR)/" if $extout
1914
+ mfile.print "$(DLLIB): "
1915
+ mfile.print "$(DEFFILE) " if makedef
1916
+ mfile.print "$(OBJS) Makefile\n"
1917
+ mfile.print "\t@-$(RM) $(@#{sep})\n"
1918
+ mfile.print "\t@-$(MAKEDIRS) $(@D)\n" if $extout
1919
+ link_so = LINK_SO.gsub(/^/, "\t")
1920
+ if srcs.any?(&%r"\.(?:#{CXX_EXT.join('|')})\z".method(:===))
1921
+ link_so = link_so.sub(/\bLDSHARED\b/, '\&XX')
1922
+ end
1923
+ mfile.print link_so, "\n\n"
1924
+ unless $static.nil?
1925
+ mfile.print "$(STATIC_LIB): $(OBJS)\n\t@-$(RM) $(@#{sep})\n\t"
1926
+ mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
1927
+ config_string('RANLIB') do |ranlib|
1928
+ mfile.print "\n\t@-#{ranlib} $(DLLIB) 2> /dev/null || true"
1929
+ end
1930
+ end
1931
+ mfile.print "\n\n"
1932
+ if makedef
1933
+ mfile.print "$(DEFFILE): #{origdef}\n"
1934
+ mfile.print "\t$(RUBY) #{makedef} #{origdef} > $@\n\n"
1935
+ end
1936
+
1937
+ depend = File.join(srcdir, "depend")
1938
+ if File.exist?(depend)
1939
+ mfile.print("###\n", *depend_rules(File.read(depend)))
1940
+ else
1941
+ headers = %w[$(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h]
1942
+ if RULE_SUBST
1943
+ headers.each {|h| h.sub!(/.*/, &RULE_SUBST.method(:%))}
1944
+ end
1945
+ headers << $config_h
1946
+ headers << '$(RUBY_EXTCONF_H)' if $extconf_h
1947
+ mfile.print "$(OBJS): ", headers.join(' '), "\n"
1948
+ end
1949
+
1950
+ $makefile_created = true
1951
+ ensure
1952
+ mfile.close if mfile
1953
+ end
1954
+
1955
+ # :stopdoc:
1956
+
1957
+ def init_mkmf(config = CONFIG)
1958
+ $makefile_created = false
1959
+ $arg_config = []
1960
+ $enable_shared = config['ENABLE_SHARED'] == 'yes'
1961
+ $defs = []
1962
+ $extconf_h = nil
1963
+ $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup
1964
+ $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup
1965
+ $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup
1966
+ $LDFLAGS = with_config("ldflags", arg_config("LDFLAGS", config["LDFLAGS"])).dup
1967
+ $INCFLAGS = "-I$(arch_hdrdir)"
1968
+ $INCFLAGS << " -I$(hdrdir)/ruby/backward" unless $extmk
1969
+ $INCFLAGS << " -I$(hdrdir) -I$(srcdir)"
1970
+ $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
1971
+ $LIBEXT = config['LIBEXT'].dup
1972
+ $OBJEXT = config["OBJEXT"].dup
1973
+ $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}"
1974
+ $LIBRUBYARG = ""
1975
+ $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC']
1976
+ $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED']
1977
+ $DEFLIBPATH = [$extmk ? "$(topdir)" : "$(libdir)"]
1978
+ $DEFLIBPATH.unshift(".")
1979
+ $LIBPATH = []
1980
+ $INSTALLFILES = []
1981
+ $NONINSTALLFILES = [/~\z/, /\A#.*#\z/, /\A\.#/, /\.bak\z/i, /\.orig\z/, /\.rej\z/, /\.l[ao]\z/, /\.o\z/]
1982
+ $VPATH = %w[$(srcdir) $(arch_hdrdir)/ruby $(hdrdir)/ruby]
1983
+
1984
+ $objs = nil
1985
+ $srcs = nil
1986
+ $libs = ""
1987
+ if $enable_shared or RbConfig.expand(config["LIBRUBY"].dup) != RbConfig.expand(config["LIBRUBY_A"].dup)
1988
+ $LIBRUBYARG = config['LIBRUBYARG']
1989
+ end
1990
+
1991
+ $LOCAL_LIBS = ""
1992
+
1993
+ $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || []
1994
+ $cleanfiles << "mkmf.log"
1995
+ $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || []
1996
+ $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || []
1997
+
1998
+ $extout ||= nil
1999
+ $extout_prefix ||= nil
2000
+
2001
+ $arg_config.clear
2002
+ dir_config("opt")
2003
+ end
2004
+
2005
+ FailedMessage = <<MESSAGE
2006
+ Could not create Makefile due to some reason, probably lack of
2007
+ necessary libraries and/or headers. Check the mkmf.log file for more
2008
+ details. You may need configuration options.
2009
+
2010
+ Provided configuration options:
2011
+ MESSAGE
2012
+
2013
+ # Returns whether or not the Makefile was successfully generated. If not,
2014
+ # the script will abort with an error message.
2015
+ #
2016
+ # Internal use only.
2017
+ #
2018
+ def mkmf_failed(path)
2019
+ unless $makefile_created or File.exist?("Makefile")
2020
+ opts = $arg_config.collect {|t, n| "\t#{t}#{n ? "=#{n}" : ""}\n"}
2021
+ abort "*** #{path} failed ***\n" + FailedMessage + opts.join
2022
+ end
2023
+ end
2024
+
2025
+ # :startdoc:
2026
+
2027
+ init_mkmf
2028
+
2029
+ $make = with_config("make-prog", ENV["MAKE"] || "make")
2030
+ make, = Shellwords.shellwords($make)
2031
+ $nmake = nil
2032
+ case
2033
+ when $mswin
2034
+ $nmake = ?m if /nmake/i =~ make
2035
+ when $bccwin
2036
+ $nmake = ?b if /Borland/i =~ `#{make} -h`
2037
+ end
2038
+
2039
+ RbConfig::CONFIG["srcdir"] = CONFIG["srcdir"] =
2040
+ $srcdir = arg_config("--srcdir", File.dirname($0))
2041
+ $configure_args["--topsrcdir"] ||= $srcdir
2042
+ if $curdir = arg_config("--curdir")
2043
+ RbConfig.expand(curdir = $curdir.dup)
2044
+ else
2045
+ curdir = $curdir = "."
2046
+ end
2047
+ unless File.expand_path(RbConfig::CONFIG["topdir"]) == File.expand_path(curdir)
2048
+ CONFIG["topdir"] = $curdir
2049
+ RbConfig::CONFIG["topdir"] = curdir
2050
+ end
2051
+ $configure_args["--topdir"] ||= $curdir
2052
+ $ruby = arg_config("--ruby", File.join(RbConfig::CONFIG["bindir"], CONFIG["ruby_install_name"]))
2053
+
2054
+ split = Shellwords.method(:shellwords).to_proc
2055
+
2056
+ EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip}
2057
+
2058
+ hdr = ['#include "ruby.h"' "\n"]
2059
+ config_string('COMMON_MACROS') do |s|
2060
+ Shellwords.shellwords(s).each do |w|
2061
+ hdr << "#define " + w.split(/=/, 2).join(" ")
2062
+ end
2063
+ end
2064
+ config_string('COMMON_HEADERS') do |s|
2065
+ Shellwords.shellwords(s).each {|w| hdr << "#include <#{w}>"}
2066
+ end
2067
+ COMMON_HEADERS = hdr.join("\n")
2068
+ COMMON_LIBS = config_string('COMMON_LIBS', &split) || []
2069
+
2070
+ COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:]
2071
+ RULE_SUBST = config_string('RULE_SUBST')
2072
+ COMPILE_C = config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<'
2073
+ COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<'
2074
+ TRY_LINK = config_string('TRY_LINK') ||
2075
+ "$(CC) #{OUTFLAG}conftest $(INCFLAGS) $(CPPFLAGS) " \
2076
+ "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
2077
+ LINK_SO = config_string('LINK_SO') ||
2078
+ if CONFIG["DLEXT"] == $OBJEXT
2079
+ "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
2080
+ else
2081
+ "$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \
2082
+ "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)"
2083
+ end
2084
+ LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L"%s"'
2085
+ RPATHFLAG = config_string('RPATHFLAG') || ''
2086
+ LIBARG = config_string('LIBARG') || '-l%s'
2087
+ MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || 'int main() {return 0;}'
2088
+ UNIVERSAL_INTS = config_string('UNIVERSAL_INTS') {|s| Shellwords.shellwords(s)} ||
2089
+ %w[int short long long\ long]
2090
+
2091
+ sep = config_string('BUILD_FILE_SEPARATOR') {|s| ":/=#{s}" if s != "/"} || ""
2092
+ CLEANINGS = "
2093
+ clean-rb-default::
2094
+ clean-rb::
2095
+ clean-so::
2096
+ clean: clean-so clean-rb-default clean-rb
2097
+ \t\t@-$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep})
2098
+
2099
+ distclean-rb-default::
2100
+ distclean-rb::
2101
+ distclean-so::
2102
+ distclean: clean distclean-so distclean-rb-default distclean-rb
2103
+ \t\t@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
2104
+ \t\t@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
2105
+ \t\t@-$(RMDIRS) $(DISTCLEANDIRS#{sep})
2106
+
2107
+ realclean: distclean
2108
+ "
2109
+
2110
+ if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
2111
+ END {mkmf_failed($0)}
2112
+ end