1# -*- coding: us-ascii -*-
2# frozen-string-literal: false
3# module to create Makefile for extension modules
4# invoke like: ruby -r mkmf extconf.rb
5
6require 'rbconfig'
7require 'fileutils'
8require 'shellwords'
9
10class String
11  # :stopdoc:
12
13  # Wraps a string in escaped quotes if it contains whitespace.
14  def quote
15    /\s/ =~ self ? "\"#{self}\"" : "#{self}"
16  end
17
18  # Escape whitespaces for Makefile.
19  def unspace
20    gsub(/\s/, '\\\\\\&')
21  end
22
23  # Generates a string used as cpp macro name.
24  def tr_cpp
25    strip.upcase.tr_s("^A-Z0-9_*", "_").tr_s("*", "P")
26  end
27
28  def funcall_style
29    /\)\z/ =~ self ? dup : "#{self}()"
30  end
31
32  def sans_arguments
33    self[/\A[^()]+/]
34  end
35
36  # :startdoc:
37end
38
39class Array
40  # :stopdoc:
41
42  # Wraps all strings in escaped quotes if they contain whitespace.
43  def quote
44    map {|s| s.quote}
45  end
46
47  # :startdoc:
48end
49
50##
51# mkmf.rb is used by Ruby C extensions to generate a Makefile which will
52# correctly compile and link the C extension to Ruby and a third-party
53# library.
54module MakeMakefile
55  #### defer until this module become global-state free.
56  # def self.extended(obj)
57  #   obj.init_mkmf
58  #   super
59  # end
60  #
61  # def initialize(*args, rbconfig: RbConfig, **rest)
62  #   init_mkmf(rbconfig::MAKEFILE_CONFIG, rbconfig::CONFIG)
63  #   super(*args, **rest)
64  # end
65
66  ##
67  # The makefile configuration using the defaults from when Ruby was built.
68
69  CONFIG = RbConfig::MAKEFILE_CONFIG
70  ORIG_LIBPATH = ENV['LIB']
71
72  ##
73  # Extensions for files compiled with a C compiler
74
75  C_EXT = %w[c m]
76
77  ##
78  # Extensions for files complied with a C++ compiler
79
80  CXX_EXT = %w[cc mm cxx cpp]
81  unless File.exist?(File.join(*File.split(__FILE__).tap {|d, b| b.swapcase}))
82    CXX_EXT.concat(%w[C])
83  end
84
85  ##
86  # Extensions for source files
87
88  SRC_EXT = C_EXT + CXX_EXT
89
90  ##
91  # Extensions for header files
92
93  HDR_EXT = %w[h hpp]
94  $static = nil
95  $config_h = '$(arch_hdrdir)/ruby/config.h'
96  $default_static = $static
97
98  unless defined? $configure_args
99    $configure_args = {}
100    args = CONFIG["configure_args"]
101    if ENV["CONFIGURE_ARGS"]
102      args << " " << ENV["CONFIGURE_ARGS"]
103    end
104    for arg in Shellwords::shellwords(args)
105      arg, val = arg.split('=', 2)
106      next unless arg
107      arg.tr!('_', '-')
108      if arg.sub!(/^(?!--)/, '--')
109        val or next
110        arg.downcase!
111      end
112      next if /^--(?:top|topsrc|src|cur)dir$/ =~ arg
113      $configure_args[arg] = val || true
114    end
115    for arg in ARGV
116      arg, val = arg.split('=', 2)
117      next unless arg
118      arg.tr!('_', '-')
119      if arg.sub!(/^(?!--)/, '--')
120        val or next
121        arg.downcase!
122      end
123      $configure_args[arg] = val || true
124    end
125  end
126
127  $libdir = CONFIG["libdir"]
128  $rubylibdir = CONFIG["rubylibdir"]
129  $archdir = CONFIG["archdir"]
130  $sitedir = CONFIG["sitedir"]
131  $sitelibdir = CONFIG["sitelibdir"]
132  $sitearchdir = CONFIG["sitearchdir"]
133  $vendordir = CONFIG["vendordir"]
134  $vendorlibdir = CONFIG["vendorlibdir"]
135  $vendorarchdir = CONFIG["vendorarchdir"]
136
137  $mswin = /mswin/ =~ RUBY_PLATFORM
138  $mingw = /mingw/ =~ RUBY_PLATFORM
139  $cygwin = /cygwin/ =~ RUBY_PLATFORM
140  $netbsd = /netbsd/ =~ RUBY_PLATFORM
141  $haiku = /haiku/ =~ RUBY_PLATFORM
142  $solaris = /solaris/ =~ RUBY_PLATFORM
143  $universal = /universal/ =~ RUBY_PLATFORM
144  $dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
145
146  # :stopdoc:
147
148  def config_string(key, config = CONFIG)
149    s = config[key] and !s.empty? and block_given? ? yield(s) : s
150  end
151  module_function :config_string
152
153  def dir_re(dir)
154    Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$(?:\(target_prefix\)|\{target_prefix\}))?')
155  end
156  module_function :dir_re
157
158  def relative_from(path, base)
159    dir = File.join(path, "")
160    if File.expand_path(dir) == File.expand_path(dir, base)
161      path
162    else
163      File.join(base, path)
164    end
165  end
166
167  INSTALL_DIRS = [
168    [dir_re('commondir'), "$(RUBYCOMMONDIR)"],
169    [dir_re('sitedir'), "$(RUBYCOMMONDIR)"],
170    [dir_re('vendordir'), "$(RUBYCOMMONDIR)"],
171    [dir_re('rubylibdir'), "$(RUBYLIBDIR)"],
172    [dir_re('archdir'), "$(RUBYARCHDIR)"],
173    [dir_re('sitelibdir'), "$(RUBYLIBDIR)"],
174    [dir_re('vendorlibdir'), "$(RUBYLIBDIR)"],
175    [dir_re('sitearchdir'), "$(RUBYARCHDIR)"],
176    [dir_re('vendorarchdir'), "$(RUBYARCHDIR)"],
177    [dir_re('rubyhdrdir'), "$(RUBYHDRDIR)"],
178    [dir_re('sitehdrdir'), "$(SITEHDRDIR)"],
179    [dir_re('vendorhdrdir'), "$(VENDORHDRDIR)"],
180    [dir_re('bindir'), "$(BINDIR)"],
181  ]
182
183  def install_dirs(target_prefix = nil)
184    if $extout and $extmk
185      dirs = [
186        ['BINDIR',        '$(extout)/bin'],
187        ['RUBYCOMMONDIR', '$(extout)/common'],
188        ['RUBYLIBDIR',    '$(RUBYCOMMONDIR)$(target_prefix)'],
189        ['RUBYARCHDIR',   '$(extout)/$(arch)$(target_prefix)'],
190        ['HDRDIR',        '$(extout)/include/ruby$(target_prefix)'],
191        ['ARCHHDRDIR',    '$(extout)/include/$(arch)/ruby$(target_prefix)'],
192        ['extout',        "#$extout"],
193        ['extout_prefix', "#$extout_prefix"],
194      ]
195    elsif $extmk
196      dirs = [
197        ['BINDIR',        '$(bindir)'],
198        ['RUBYCOMMONDIR', '$(rubylibdir)'],
199        ['RUBYLIBDIR',    '$(rubylibdir)$(target_prefix)'],
200        ['RUBYARCHDIR',   '$(archdir)$(target_prefix)'],
201        ['HDRDIR',        '$(rubyhdrdir)/ruby$(target_prefix)'],
202        ['ARCHHDRDIR',    '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
203      ]
204    elsif $configure_args.has_key?('--vendor')
205      dirs = [
206        ['BINDIR',        '$(bindir)'],
207        ['RUBYCOMMONDIR', '$(vendordir)$(target_prefix)'],
208        ['RUBYLIBDIR',    '$(vendorlibdir)$(target_prefix)'],
209        ['RUBYARCHDIR',   '$(vendorarchdir)$(target_prefix)'],
210        ['HDRDIR',        '$(rubyhdrdir)/ruby$(target_prefix)'],
211        ['ARCHHDRDIR',    '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
212      ]
213    else
214      dirs = [
215        ['BINDIR',        '$(bindir)'],
216        ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'],
217        ['RUBYLIBDIR',    '$(sitelibdir)$(target_prefix)'],
218        ['RUBYARCHDIR',   '$(sitearchdir)$(target_prefix)'],
219        ['HDRDIR',        '$(rubyhdrdir)/ruby$(target_prefix)'],
220        ['ARCHHDRDIR',    '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
221      ]
222    end
223    dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")]
224    dirs
225  end
226
227  def map_dir(dir, map = nil)
228    map ||= INSTALL_DIRS
229    map.inject(dir) {|d, (orig, new)| d.gsub(orig, new)}
230  end
231
232  topdir = File.dirname(File.dirname(__FILE__))
233  path = File.expand_path($0)
234  until (dir = File.dirname(path)) == path
235    if File.identical?(dir, topdir)
236      $extmk = true if %r"\A(?:ext|enc|tool|test)\z" =~ File.basename(path)
237      break
238    end
239    path = dir
240  end
241  $extmk ||= false
242  if not $extmk and File.exist?(($hdrdir = RbConfig::CONFIG["rubyhdrdir"]) + "/ruby/ruby.h")
243    $topdir = $hdrdir + "/" + "#{CONFIG['arch']}/ruby/"
244    $top_srcdir = $hdrdir
245    $arch_hdrdir = RbConfig::CONFIG["rubyarchhdrdir"]
246  elsif File.exist?(($hdrdir = ($top_srcdir ||= topdir) + "/include")  + "/ruby.h")
247    $topdir ||= RbConfig::CONFIG["topdir"]
248    $arch_hdrdir = "$(extout)/include/$(arch)"
249  else
250    abort <<MESSAGE
251mkmf.rb can't find header files for ruby at #{$hdrdir}/ruby.h
252
253You might have to install separate package for the ruby development
254environment, ruby-dev or ruby-devel for example.
255MESSAGE
256  end
257
258  CONFTEST = "conftest".freeze
259  CONFTEST_C = "#{CONFTEST}.c"
260
261  OUTFLAG = CONFIG['OUTFLAG']
262  COUTFLAG = CONFIG['COUTFLAG']
263  CSRCFLAG = CONFIG['CSRCFLAG']
264  CPPOUTFILE = config_string('CPPOUTFILE') {|str| str.sub(/\bconftest\b/, CONFTEST)}
265
266  def rm_f(*files)
267    opt = (Hash === files.last ? [files.pop] : [])
268    FileUtils.rm_f(Dir[*files.flatten], *opt)
269  end
270  module_function :rm_f
271
272  def rm_rf(*files)
273    opt = (Hash === files.last ? [files.pop] : [])
274    FileUtils.rm_rf(Dir[*files.flatten], *opt)
275  end
276  module_function :rm_rf
277
278  # Returns time stamp of the +target+ file if it exists and is newer than or
279  # equal to all of +times+.
280  def modified?(target, times)
281    (t = File.mtime(target)) rescue return nil
282    Array === times or times = [times]
283    t if times.all? {|n| n <= t}
284  end
285
286  def split_libs(*strs)
287    strs.map {|s| s.split(/\s+(?=-|\z)/)}.flatten
288  end
289
290  def merge_libs(*libs)
291    libs.inject([]) do |x, y|
292      y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e}
293      y.each_with_index do |v, yi|
294        if xi = x.rindex(v)
295          x[(xi+1)..-1] = merge_libs(y[(yi+1)..-1], x[(xi+1)..-1])
296          x[xi, 0] = y[0...yi]
297          break
298        end
299      end and x.concat(y)
300      x
301    end
302  end
303
304  # This is a custom logging module. It generates an mkmf.log file when you
305  # run your extconf.rb script. This can be useful for debugging unexpected
306  # failures.
307  #
308  # This module and its associated methods are meant for internal use only.
309  #
310  module Logging
311    @log = nil
312    @logfile = 'mkmf.log'
313    @orgerr = $stderr.dup
314    @orgout = $stdout.dup
315    @postpone = 0
316    @quiet = $extmk
317
318    def self::log_open
319      @log ||= File::open(@logfile, 'wb')
320      @log.sync = true
321    end
322
323    def self::log_opened?
324      @log and not @log.closed?
325    end
326
327    def self::open
328      log_open
329      $stderr.reopen(@log)
330      $stdout.reopen(@log)
331      yield
332    ensure
333      $stderr.reopen(@orgerr)
334      $stdout.reopen(@orgout)
335    end
336
337    def self::message(*s)
338      log_open
339      @log.printf(*s)
340    end
341
342    def self::logfile file
343      @logfile = file
344      log_close
345    end
346
347    def self::log_close
348      if @log and not @log.closed?
349        @log.flush
350        @log.close
351        @log = nil
352      end
353    end
354
355    def self::postpone
356      tmplog = "mkmftmp#{@postpone += 1}.log"
357      open do
358        log, *save = @log, @logfile, @orgout, @orgerr
359        @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
360        begin
361          log.print(open {yield @log})
362        ensure
363          @log.close if @log and not @log.closed?
364          File::open(tmplog) {|t| FileUtils.copy_stream(t, log)} if File.exist?(tmplog)
365          @log, @logfile, @orgout, @orgerr = log, *save
366          @postpone -= 1
367          MakeMakefile.rm_f tmplog
368        end
369      end
370    end
371
372    class << self
373      attr_accessor :quiet
374    end
375  end
376
377  def libpath_env
378    # used only if native compiling
379    if libpathenv = config_string("LIBPATHENV")
380      pathenv = ENV[libpathenv]
381      libpath = RbConfig.expand($DEFLIBPATH.join(File::PATH_SEPARATOR))
382      {libpathenv => [libpath, pathenv].compact.join(File::PATH_SEPARATOR)}
383    else
384      {}
385    end
386  end
387
388  def xsystem command, opts = nil
389    varpat = /\$\((\w+)\)|\$\{(\w+)\}/
390    if varpat =~ command
391      vars = Hash.new {|h, k| h[k] = ENV[k]}
392      command = command.dup
393      nil while command.gsub!(varpat) {vars[$1||$2]}
394    end
395    Logging::open do
396      puts command.quote
397      if opts and opts[:werror]
398        result = nil
399        Logging.postpone do |log|
400          output = IO.popen(libpath_env, command, &:read)
401          result = ($?.success? and File.zero?(log.path))
402          output
403        end
404        result
405      else
406        system(libpath_env, command)
407      end
408    end
409  end
410
411  def xpopen command, *mode, &block
412    Logging::open do
413      case mode[0]
414      when nil, /^r/
415        puts "#{command} |"
416      else
417        puts "| #{command}"
418      end
419      IO.popen(libpath_env, command, *mode, &block)
420    end
421  end
422
423  def log_src(src, heading="checked program was")
424    src = src.split(/^/)
425    fmt = "%#{src.size.to_s.size}d: %s"
426    Logging::message <<"EOM"
427#{heading}:
428/* begin */
429EOM
430    src.each_with_index {|line, no| Logging::message fmt, no+1, line}
431    Logging::message <<"EOM"
432/* end */
433
434EOM
435  end
436
437  def create_tmpsrc(src)
438    src = "#{COMMON_HEADERS}\n#{src}"
439    src = yield(src) if block_given?
440    src.gsub!(/[ \t]+$/, '')
441    src.gsub!(/\A\n+|^\n+$/, '')
442    src.sub!(/[^\n]\z/, "\\&\n")
443    count = 0
444    begin
445      open(CONFTEST_C, "wb") do |cfile|
446        cfile.print src
447      end
448    rescue Errno::EACCES
449      if (count += 1) < 5
450        sleep 0.2
451        retry
452      end
453    end
454    src
455  end
456
457  def have_devel?
458    unless defined? $have_devel
459      $have_devel = true
460      $have_devel = try_link(MAIN_DOES_NOTHING)
461    end
462    $have_devel
463  end
464
465  def try_do(src, command, *opts, &b)
466    unless have_devel?
467      raise <<MSG
468The compiler failed to generate an executable file.
469You have to install development tools first.
470MSG
471    end
472    begin
473      src = create_tmpsrc(src, &b)
474      xsystem(command, *opts)
475    ensure
476      log_src(src)
477    end
478  end
479
480  def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
481    librubyarg = $extmk ? $LIBRUBYARG_STATIC : "$(LIBRUBYARG)"
482    conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote,
483                                  'src' => "#{CONFTEST_C}",
484                                  'arch_hdrdir' => $arch_hdrdir.quote,
485                                  'top_srcdir' => $top_srcdir.quote,
486                                  'INCFLAGS' => "#$INCFLAGS",
487                                  'CPPFLAGS' => "#$CPPFLAGS",
488                                  'CFLAGS' => "#$CFLAGS",
489                                  'ARCH_FLAG' => "#$ARCH_FLAG",
490                                  'LDFLAGS' => "#$LDFLAGS #{ldflags}",
491                                  'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs",
492                                  'LIBS' => "#{librubyarg} #{opt} #$LIBS")
493    conf['LIBPATH'] = libpathflag(libpath.map {|s| RbConfig::expand(s.dup, conf)})
494    RbConfig::expand(TRY_LINK.dup, conf)
495  end
496
497  def cc_command(opt="")
498    conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
499                                  'arch_hdrdir' => $arch_hdrdir.quote,
500                                  'top_srcdir' => $top_srcdir.quote)
501    RbConfig::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}",
502                     conf)
503  end
504
505  def cpp_command(outfile, opt="")
506    conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
507                                  'arch_hdrdir' => $arch_hdrdir.quote,
508                                  'top_srcdir' => $top_srcdir.quote)
509    if $universal and (arch_flag = conf['ARCH_FLAG']) and !arch_flag.empty?
510      conf['ARCH_FLAG'] = arch_flag.gsub(/(?:\G|\s)-arch\s+\S+/, '')
511    end
512    RbConfig::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
513                     conf)
514  end
515
516  def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
517    libpath.map{|x|
518      case x
519      when "$(topdir)", /\A\./
520        LIBPATHFLAG
521      else
522        LIBPATHFLAG+RPATHFLAG
523      end % x.quote
524    }.join
525  end
526
527  def with_werror(opt, opts = nil)
528    if opts
529      if opts[:werror] and config_string("WERRORFLAG") {|flag| opt = opt ? "#{opt} #{flag}" : flag}
530        (opts = opts.dup).delete(:werror)
531      end
532      yield(opt, opts)
533    else
534      yield(opt)
535    end
536  end
537
538  def try_link0(src, opt="", *opts, &b) # :nodoc:
539    exe = CONFTEST+$EXEEXT
540    cmd = link_command("", opt)
541    if $universal
542      require 'tmpdir'
543      Dir.mktmpdir("mkmf_", oldtmpdir = ENV["TMPDIR"]) do |tmpdir|
544        begin
545          ENV["TMPDIR"] = tmpdir
546          try_do(src, cmd, *opts, &b)
547        ensure
548          ENV["TMPDIR"] = oldtmpdir
549        end
550      end
551    else
552      try_do(src, cmd, *opts, &b)
553    end and File.executable?(exe) or return nil
554    exe
555  ensure
556    MakeMakefile.rm_rf(*Dir["#{CONFTEST}*"]-[exe])
557  end
558
559  # Returns whether or not the +src+ can be compiled as a C source and linked
560  # with its depending libraries successfully.  +opt+ is passed to the linker
561  # as options. Note that +$CFLAGS+ and +$LDFLAGS+ are also passed to the
562  # linker.
563  #
564  # If a block given, it is called with the source before compilation. You can
565  # modify the source in the block.
566  #
567  # [+src+] a String which contains a C source
568  # [+opt+] a String which contains linker options
569  def try_link(src, opt="", *opts, &b)
570    exe = try_link0(src, opt, *opts, &b) or return false
571    MakeMakefile.rm_f exe
572    true
573  end
574
575  # Returns whether or not the +src+ can be compiled as a C source.  +opt+ is
576  # passed to the C compiler as options. Note that +$CFLAGS+ is also passed to
577  # the compiler.
578  #
579  # If a block given, it is called with the source before compilation. You can
580  # modify the source in the block.
581  #
582  # [+src+] a String which contains a C source
583  # [+opt+] a String which contains compiler options
584  def try_compile(src, opt="", *opts, &b)
585    with_werror(opt, *opts) {|_opt, *| try_do(src, cc_command(_opt), *opts, &b)} and
586      File.file?("#{CONFTEST}.#{$OBJEXT}")
587  ensure
588    MakeMakefile.rm_f "#{CONFTEST}*"
589  end
590
591  # Returns whether or not the +src+ can be preprocessed with the C
592  # preprocessor.  +opt+ is passed to the preprocessor as options. Note that
593  # +$CFLAGS+ is also passed to the preprocessor.
594  #
595  # If a block given, it is called with the source before preprocessing. You
596  # can modify the source in the block.
597  #
598  # [+src+] a String which contains a C source
599  # [+opt+] a String which contains preprocessor options
600  def try_cpp(src, opt="", *opts, &b)
601    try_do(src, cpp_command(CPPOUTFILE, opt), *opts, &b) and
602      File.file?("#{CONFTEST}.i")
603  ensure
604    MakeMakefile.rm_f "#{CONFTEST}*"
605  end
606
607  alias_method :try_header, (config_string('try_header') || :try_cpp)
608
609  def cpp_include(header)
610    if header
611      header = [header] unless header.kind_of? Array
612      header.map {|h| String === h ? "#include <#{h}>\n" : h}.join
613    else
614      ""
615    end
616  end
617
618  def with_cppflags(flags)
619    cppflags = $CPPFLAGS
620    $CPPFLAGS = flags.dup
621    ret = yield
622  ensure
623    $CPPFLAGS = cppflags unless ret
624  end
625
626  def try_cppflags(flags, opts = {})
627    try_header(MAIN_DOES_NOTHING, flags, {:werror => true}.update(opts))
628  end
629
630  def append_cppflags(flags, *opts)
631    Array(flags).each do |flag|
632      if checking_for("whether #{flag} is accepted as CPPFLAGS") {
633           try_cppflags(flag, *opts)
634         }
635        $CPPFLAGS << " " << flag
636      end
637    end
638  end
639
640  def with_cflags(flags)
641    cflags = $CFLAGS
642    $CFLAGS = flags.dup
643    ret = yield
644  ensure
645    $CFLAGS = cflags unless ret
646  end
647
648  def try_cflags(flags, opts = {})
649    try_compile(MAIN_DOES_NOTHING, flags, {:werror => true}.update(opts))
650  end
651
652  def append_cflags(flags, *opts)
653    Array(flags).each do |flag|
654      if checking_for("whether #{flag} is accepted as CFLAGS") {
655           try_cflags(flag, *opts)
656         }
657        $CFLAGS << " " << flag
658      end
659    end
660  end
661
662  def with_ldflags(flags)
663    ldflags = $LDFLAGS
664    $LDFLAGS = flags.dup
665    ret = yield
666  ensure
667    $LDFLAGS = ldflags unless ret
668  end
669
670  def try_ldflags(flags, opts = {})
671    opts = {:werror => true}.update(opts) if $mswin
672    try_link(MAIN_DOES_NOTHING, flags, opts)
673  end
674
675  def append_ldflags(flags, *opts)
676    Array(flags).each do |flag|
677      if checking_for("whether #{flag} is accepted as LDFLAGS") {
678           try_ldflags(flag, *opts)
679         }
680        $LDFLAGS << " " << flag
681      end
682    end
683  end
684
685  def try_static_assert(expr, headers = nil, opt = "", &b)
686    headers = cpp_include(headers)
687    try_compile(<<SRC, opt, &b)
688#{headers}
689/*top*/
690int conftest_const[(#{expr}) ? 1 : -1];
691SRC
692  end
693
694  def try_constant(const, headers = nil, opt = "", &b)
695    includes = cpp_include(headers)
696    neg = try_static_assert("#{const} < 0", headers, opt)
697    if CROSS_COMPILING
698      if neg
699        const = "-(#{const})"
700      elsif try_static_assert("#{const} > 0", headers, opt)
701        # positive constant
702      elsif try_static_assert("#{const} == 0", headers, opt)
703        return 0
704      else
705        # not a constant
706        return nil
707      end
708      upper = 1
709      until try_static_assert("#{const} <= #{upper}", headers, opt)
710        lower = upper
711        upper <<= 1
712      end
713      return nil unless lower
714      while upper > lower + 1
715        mid = (upper + lower) / 2
716        if try_static_assert("#{const} > #{mid}", headers, opt)
717          lower = mid
718        else
719          upper = mid
720        end
721      end
722      upper = -upper if neg
723      return upper
724    else
725      src = %{#{includes}
726#include <stdio.h>
727/*top*/
728typedef#{neg ? '' : ' unsigned'}
729#ifdef PRI_LL_PREFIX
730#define PRI_CONFTEST_PREFIX PRI_LL_PREFIX
731LONG_LONG
732#else
733#define PRI_CONFTEST_PREFIX "l"
734long
735#endif
736conftest_type;
737conftest_type conftest_const = (conftest_type)(#{const});
738int main() {printf("%"PRI_CONFTEST_PREFIX"#{neg ? 'd' : 'u'}\\n", conftest_const); return 0;}
739}
740      begin
741        if try_link0(src, opt, &b)
742          xpopen("./#{CONFTEST}") do |f|
743            return Integer(f.gets)
744          end
745        end
746      ensure
747        MakeMakefile.rm_f "#{CONFTEST}#{$EXEEXT}"
748      end
749    end
750    nil
751  end
752
753  # You should use +have_func+ rather than +try_func+.
754  #
755  # [+func+] a String which contains a symbol name
756  # [+libs+] a String which contains library names.
757  # [+headers+] a String or an Array of strings which contains names of header
758  #             files.
759  def try_func(func, libs, headers = nil, opt = "", &b)
760    headers = cpp_include(headers)
761    case func
762    when /^&/
763      decltype = proc {|x|"const volatile void *#{x}"}
764    when /\)$/
765      call = func
766    when nil
767      call = ""
768    else
769      call = "#{func}()"
770      decltype = proc {|x| "void ((*#{x})())"}
771    end
772    if opt and !opt.empty?
773      [[:to_str], [:join, " "], [:to_s]].each do |meth, *args|
774        if opt.respond_to?(meth)
775          break opt = opt.send(meth, *args)
776        end
777      end
778      opt = "#{opt} #{libs}"
779    else
780      opt = libs
781    end
782    decltype && try_link(<<"SRC", opt, &b) or
783#{headers}
784/*top*/
785extern int t(void);
786#{MAIN_DOES_NOTHING 't'}
787int t(void) { #{decltype["volatile p"]}; p = (#{decltype[]})#{func}; return !p; }
788SRC
789    call && try_link(<<"SRC", opt, &b)
790#{headers}
791/*top*/
792extern int t(void);
793#{MAIN_DOES_NOTHING 't'}
794#{"extern void #{call};" if decltype}
795int t(void) { #{call}; return 0; }
796SRC
797  end
798
799  # You should use +have_var+ rather than +try_var+.
800  def try_var(var, headers = nil, opt = "", &b)
801    headers = cpp_include(headers)
802    try_compile(<<"SRC", opt, &b)
803#{headers}
804/*top*/
805extern int t(void);
806#{MAIN_DOES_NOTHING 't'}
807int t(void) { const volatile void *volatile p; p = &(&#{var})[0]; return !p; }
808SRC
809  end
810
811  # Returns whether or not the +src+ can be preprocessed with the C
812  # preprocessor and matches with +pat+.
813  #
814  # If a block given, it is called with the source before compilation. You can
815  # modify the source in the block.
816  #
817  # [+pat+] a Regexp or a String
818  # [+src+] a String which contains a C source
819  # [+opt+] a String which contains preprocessor options
820  #
821  # NOTE: When pat is a Regexp the matching will be checked in process,
822  # otherwise egrep(1) will be invoked to check it.
823  def egrep_cpp(pat, src, opt = "", &b)
824    src = create_tmpsrc(src, &b)
825    xpopen(cpp_command('', opt)) do |f|
826      if Regexp === pat
827        puts("    ruby -ne 'print if #{pat.inspect}'")
828        f.grep(pat) {|l|
829          puts "#{f.lineno}: #{l}"
830          return true
831        }
832        false
833      else
834        puts("    egrep '#{pat}'")
835        begin
836          stdin = $stdin.dup
837          $stdin.reopen(f)
838          system("egrep", pat)
839        ensure
840          $stdin.reopen(stdin)
841        end
842      end
843    end
844  ensure
845    MakeMakefile.rm_f "#{CONFTEST}*"
846    log_src(src)
847  end
848
849  # This is used internally by the have_macro? method.
850  def macro_defined?(macro, src, opt = "", &b)
851    src = src.sub(/[^\n]\z/, "\\&\n")
852    try_compile(src + <<"SRC", opt, &b)
853/*top*/
854#ifndef #{macro}
855# error
856|:/ === #{macro} undefined === /:|
857#endif
858SRC
859  end
860
861  # Returns whether or not:
862  # * the +src+ can be compiled as a C source,
863  # * the result object can be linked with its depending libraries
864  #   successfully,
865  # * the linked file can be invoked as an executable
866  # * and the executable exits successfully
867  #
868  # +opt+ is passed to the linker as options. Note that +$CFLAGS+ and
869  # +$LDFLAGS+ are also passed to the linker.
870  #
871  # If a block given, it is called with the source before compilation. You can
872  # modify the source in the block.
873  #
874  # [+src+] a String which contains a C source
875  # [+opt+] a String which contains linker options
876  #
877  # Returns true when the executable exits successfully, false when it fails,
878  # or nil when preprocessing, compilation or link fails.
879  def try_run(src, opt = "", &b)
880    raise "cannot run test program while cross compiling" if CROSS_COMPILING
881    if try_link0(src, opt, &b)
882      xsystem("./#{CONFTEST}")
883    else
884      nil
885    end
886  ensure
887    MakeMakefile.rm_f "#{CONFTEST}*"
888  end
889
890  def install_files(mfile, ifiles, map = nil, srcprefix = nil)
891    ifiles or return
892    ifiles.empty? and return
893    srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
894    RbConfig::expand(srcdir = srcprefix.dup)
895    dirs = []
896    path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]}
897    ifiles.each do |files, dir, prefix|
898      dir = map_dir(dir, map)
899      prefix &&= %r|\A#{Regexp.quote(prefix)}/?|
900      if /\A\.\// =~ files
901        # install files which are in current working directory.
902        files = files[2..-1]
903        len = nil
904      else
905        # install files which are under the $(srcdir).
906        files = File.join(srcdir, files)
907        len = srcdir.size
908      end
909      f = nil
910      Dir.glob(files) do |fx|
911        f = fx
912        f[0..len] = "" if len
913        case File.basename(f)
914        when *$NONINSTALLFILES
915          next
916        end
917        d = File.dirname(f)
918        d.sub!(prefix, "") if prefix
919        d = (d.empty? || d == ".") ? dir : File.join(dir, d)
920        f = File.join(srcprefix, f) if len
921        path[d] << f
922      end
923      unless len or f
924        d = File.dirname(files)
925        d.sub!(prefix, "") if prefix
926        d = (d.empty? || d == ".") ? dir : File.join(dir, d)
927        path[d] << files
928      end
929    end
930    dirs
931  end
932
933  def install_rb(mfile, dest, srcdir = nil)
934    install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir)
935  end
936
937  def append_library(libs, lib) # :no-doc:
938    format(LIBARG, lib) + " " + libs
939  end
940
941  def message(*s)
942    unless Logging.quiet and not $VERBOSE
943      printf(*s)
944      $stdout.flush
945    end
946  end
947
948  # This emits a string to stdout that allows users to see the results of the
949  # various have* and find* methods as they are tested.
950  #
951  # Internal use only.
952  #
953  def checking_for(m, fmt = nil)
954    f = caller[0][/in `([^<].*)'$/, 1] and f << ": " #` for vim #'
955    m = "checking #{/\Acheck/ =~ f ? '' : 'for '}#{m}... "
956    message "%s", m
957    a = r = nil
958    Logging::postpone do
959      r = yield
960      a = (fmt ? "#{fmt % r}" : r ? "yes" : "no")
961      "#{f}#{m}-------------------- #{a}\n\n"
962    end
963    message "%s\n", a
964    Logging::message "--------------------\n\n"
965    r
966  end
967
968  def checking_message(target, place = nil, opt = nil)
969    [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)|
970      if noun
971        [[:to_str], [:join, ","], [:to_s]].each do |meth, *args|
972          if noun.respond_to?(meth)
973            break noun = noun.send(meth, *args)
974          end
975        end
976        unless noun.empty?
977          msg << " #{pre} " unless msg.empty?
978          msg << noun
979        end
980      end
981      msg
982    end
983  end
984
985  # :startdoc:
986
987  # Returns whether or not +macro+ is defined either in the common header
988  # files or within any +headers+ you provide.
989  #
990  # Any options you pass to +opt+ are passed along to the compiler.
991  #
992  def have_macro(macro, headers = nil, opt = "", &b)
993    checking_for checking_message(macro, headers, opt) do
994      macro_defined?(macro, cpp_include(headers), opt, &b)
995    end
996  end
997
998  # Returns whether or not the given entry point +func+ can be found within
999  # +lib+.  If +func+ is +nil+, the <code>main()</code> entry point is used by
1000  # default.  If found, it adds the library to list of libraries to be used
1001  # when linking your extension.
1002  #
1003  # If +headers+ are provided, it will include those header files as the
1004  # header files it looks in when searching for +func+.
1005  #
1006  # The real name of the library to be linked can be altered by
1007  # <code>--with-FOOlib</code> configuration option.
1008  #
1009  def have_library(lib, func = nil, headers = nil, opt = "", &b)
1010    lib = with_config(lib+'lib', lib)
1011    checking_for checking_message(func && func.funcall_style, LIBARG%lib, opt) do
1012      if COMMON_LIBS.include?(lib)
1013        true
1014      else
1015        libs = append_library($libs, lib)
1016        if try_func(func, libs, headers, opt, &b)
1017          $libs = libs
1018          true
1019        else
1020          false
1021        end
1022      end
1023    end
1024  end
1025
1026  # Returns whether or not the entry point +func+ can be found within the
1027  # library +lib+ in one of the +paths+ specified, where +paths+ is an array
1028  # of strings.  If +func+ is +nil+ , then the <code>main()</code> function is
1029  # used as the entry point.
1030  #
1031  # If +lib+ is found, then the path it was found on is added to the list of
1032  # library paths searched and linked against.
1033  #
1034  def find_library(lib, func, *paths, &b)
1035    lib = with_config(lib+'lib', lib)
1036    paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
1037    checking_for checking_message(func && func.funcall_style, LIBARG%lib) do
1038      libpath = $LIBPATH
1039      libs = append_library($libs, lib)
1040      begin
1041        until r = try_func(func, libs, &b) or paths.empty?
1042          $LIBPATH = libpath | [paths.shift]
1043        end
1044        if r
1045          $libs = libs
1046          libpath = nil
1047        end
1048      ensure
1049        $LIBPATH = libpath if libpath
1050      end
1051      r
1052    end
1053  end
1054
1055  # Returns whether or not the function +func+ can be found in the common
1056  # header files, or within any +headers+ that you provide.  If found, a macro
1057  # is passed as a preprocessor constant to the compiler using the function
1058  # name, in uppercase, prepended with +HAVE_+.
1059  #
1060  # To check functions in an additional library, you need to check that
1061  # library first using <code>have_library()</code>.  The +func+ shall be
1062  # either mere function name or function name with arguments.
1063  #
1064  # For example, if <code>have_func('foo')</code> returned +true+, then the
1065  # +HAVE_FOO+ preprocessor macro would be passed to the compiler.
1066  #
1067  def have_func(func, headers = nil, opt = "", &b)
1068    checking_for checking_message(func.funcall_style, headers, opt) do
1069      if try_func(func, $libs, headers, opt, &b)
1070        $defs << "-DHAVE_#{func.sans_arguments.tr_cpp}"
1071        true
1072      else
1073        false
1074      end
1075    end
1076  end
1077
1078  # Returns whether or not the variable +var+ can be found in the common
1079  # header files, or within any +headers+ that you provide.  If found, a macro
1080  # is passed as a preprocessor constant to the compiler using the variable
1081  # name, in uppercase, prepended with +HAVE_+.
1082  #
1083  # To check variables in an additional library, you need to check that
1084  # library first using <code>have_library()</code>.
1085  #
1086  # For example, if <code>have_var('foo')</code> returned true, then the
1087  # +HAVE_FOO+ preprocessor macro would be passed to the compiler.
1088  #
1089  def have_var(var, headers = nil, opt = "", &b)
1090    checking_for checking_message(var, headers, opt) do
1091      if try_var(var, headers, opt, &b)
1092        $defs.push(format("-DHAVE_%s", var.tr_cpp))
1093        true
1094      else
1095        false
1096      end
1097    end
1098  end
1099
1100  # Returns whether or not the given +header+ file can be found on your system.
1101  # If found, a macro is passed as a preprocessor constant to the compiler
1102  # using the header file name, in uppercase, prepended with +HAVE_+.
1103  #
1104  # For example, if <code>have_header('foo.h')</code> returned true, then the
1105  # +HAVE_FOO_H+ preprocessor macro would be passed to the compiler.
1106  #
1107  def have_header(header, preheaders = nil, opt = "", &b)
1108    checking_for header do
1109      if try_header(cpp_include(preheaders)+cpp_include(header), opt, &b)
1110        $defs.push(format("-DHAVE_%s", header.tr_cpp))
1111        true
1112      else
1113        false
1114      end
1115    end
1116  end
1117
1118  # Returns whether or not the given +framework+ can be found on your system.
1119  # If found, a macro is passed as a preprocessor constant to the compiler
1120  # using the framework name, in uppercase, prepended with +HAVE_FRAMEWORK_+.
1121  #
1122  # For example, if <code>have_framework('Ruby')</code> returned true, then
1123  # the +HAVE_FRAMEWORK_RUBY+ preprocessor macro would be passed to the
1124  # compiler.
1125  #
1126  # If +fw+ is a pair of the framework name and its header file name
1127  # that header file is checked, instead of the normally used header
1128  # file which is named same as the framework.
1129  def have_framework(fw, &b)
1130    if Array === fw
1131      fw, header = *fw
1132    else
1133      header = "#{fw}.h"
1134    end
1135    checking_for fw do
1136      src = cpp_include("#{fw}/#{header}") << "\n" "int main(void){return 0;}"
1137      opt = " -framework #{fw}"
1138      if try_link(src, opt, &b) or (objc = try_link(src, "-ObjC#{opt}", &b))
1139        $defs.push(format("-DHAVE_FRAMEWORK_%s", fw.tr_cpp))
1140        # TODO: non-worse way than this hack, to get rid of separating
1141        # option and its argument.
1142        $LDFLAGS << " -ObjC" if objc and /(\A|\s)-ObjC(\s|\z)/ !~ $LDFLAGS
1143        $LIBS << opt
1144        true
1145      else
1146        false
1147      end
1148    end
1149  end
1150
1151  # Instructs mkmf to search for the given +header+ in any of the +paths+
1152  # provided, and returns whether or not it was found in those paths.
1153  #
1154  # If the header is found then the path it was found on is added to the list
1155  # of included directories that are sent to the compiler (via the
1156  # <code>-I</code> switch).
1157  #
1158  def find_header(header, *paths)
1159    message = checking_message(header, paths)
1160    header = cpp_include(header)
1161    checking_for message do
1162      if try_header(header)
1163        true
1164      else
1165        found = false
1166        paths.each do |dir|
1167          opt = "-I#{dir}".quote
1168          if try_header(header, opt)
1169            $INCFLAGS << " " << opt
1170            found = true
1171            break
1172          end
1173        end
1174        found
1175      end
1176    end
1177  end
1178
1179  # Returns whether or not the struct of type +type+ contains +member+.  If
1180  # it does not, or the struct type can't be found, then false is returned.
1181  # You may optionally specify additional +headers+ in which to look for the
1182  # struct (in addition to the common header files).
1183  #
1184  # If found, a macro is passed as a preprocessor constant to the compiler
1185  # using the type name and the member name, in uppercase, prepended with
1186  # +HAVE_+.
1187  #
1188  # For example, if <code>have_struct_member('struct foo', 'bar')</code>
1189  # returned true, then the +HAVE_STRUCT_FOO_BAR+ preprocessor macro would be
1190  # passed to the compiler.
1191  #
1192  # +HAVE_ST_BAR+ is also defined for backward compatibility.
1193  #
1194  def have_struct_member(type, member, headers = nil, opt = "", &b)
1195    checking_for checking_message("#{type}.#{member}", headers) do
1196      if try_compile(<<"SRC", opt, &b)
1197#{cpp_include(headers)}
1198/*top*/
1199int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
1200#{MAIN_DOES_NOTHING}
1201SRC
1202        $defs.push(format("-DHAVE_%s_%s", type.tr_cpp, member.tr_cpp))
1203        $defs.push(format("-DHAVE_ST_%s", member.tr_cpp)) # backward compatibility
1204        true
1205      else
1206        false
1207      end
1208    end
1209  end
1210
1211  # Returns whether or not the static type +type+ is defined.
1212  #
1213  # See also +have_type+
1214  #
1215  def try_type(type, headers = nil, opt = "", &b)
1216    if try_compile(<<"SRC", opt, &b)
1217#{cpp_include(headers)}
1218/*top*/
1219typedef #{type} conftest_type;
1220int conftestval[sizeof(conftest_type)?1:-1];
1221SRC
1222      $defs.push(format("-DHAVE_TYPE_%s", type.tr_cpp))
1223      true
1224    else
1225      false
1226    end
1227  end
1228
1229  # Returns whether or not the static type +type+ is defined.  You may
1230  # optionally pass additional +headers+ to check against in addition to the
1231  # common header files.
1232  #
1233  # You may also pass additional flags to +opt+ which are then passed along to
1234  # the compiler.
1235  #
1236  # If found, a macro is passed as a preprocessor constant to the compiler
1237  # using the type name, in uppercase, prepended with +HAVE_TYPE_+.
1238  #
1239  # For example, if <code>have_type('foo')</code> returned true, then the
1240  # +HAVE_TYPE_FOO+ preprocessor macro would be passed to the compiler.
1241  #
1242  def have_type(type, headers = nil, opt = "", &b)
1243    checking_for checking_message(type, headers, opt) do
1244      try_type(type, headers, opt, &b)
1245    end
1246  end
1247
1248  # Returns where the static type +type+ is defined.
1249  #
1250  # You may also pass additional flags to +opt+ which are then passed along to
1251  # the compiler.
1252  #
1253  # See also +have_type+.
1254  #
1255  def find_type(type, opt, *headers, &b)
1256    opt ||= ""
1257    fmt = "not found"
1258    def fmt.%(x)
1259      x ? x.respond_to?(:join) ? x.join(",") : x : self
1260    end
1261    checking_for checking_message(type, nil, opt), fmt do
1262      headers.find do |h|
1263        try_type(type, h, opt, &b)
1264      end
1265    end
1266  end
1267
1268  # Returns whether or not the constant +const+ is defined.
1269  #
1270  # See also +have_const+
1271  #
1272  def try_const(const, headers = nil, opt = "", &b)
1273    const, type = *const
1274    if try_compile(<<"SRC", opt, &b)
1275#{cpp_include(headers)}
1276/*top*/
1277typedef #{type || 'int'} conftest_type;
1278conftest_type conftestval = #{type ? '' : '(int)'}#{const};
1279SRC
1280      $defs.push(format("-DHAVE_CONST_%s", const.tr_cpp))
1281      true
1282    else
1283      false
1284    end
1285  end
1286
1287  # Returns whether or not the constant +const+ is defined.  You may
1288  # optionally pass the +type+ of +const+ as <code>[const, type]</code>,
1289  # such as:
1290  #
1291  #   have_const(%w[PTHREAD_MUTEX_INITIALIZER pthread_mutex_t], "pthread.h")
1292  #
1293  # You may also pass additional +headers+ to check against in addition to the
1294  # common header files, and additional flags to +opt+ which are then passed
1295  # along to the compiler.
1296  #
1297  # If found, a macro is passed as a preprocessor constant to the compiler
1298  # using the type name, in uppercase, prepended with +HAVE_CONST_+.
1299  #
1300  # For example, if <code>have_const('foo')</code> returned true, then the
1301  # +HAVE_CONST_FOO+ preprocessor macro would be passed to the compiler.
1302  #
1303  def have_const(const, headers = nil, opt = "", &b)
1304    checking_for checking_message([*const].compact.join(' '), headers, opt) do
1305      try_const(const, headers, opt, &b)
1306    end
1307  end
1308
1309  # :stopdoc:
1310  STRING_OR_FAILED_FORMAT = "%s"
1311  def STRING_OR_FAILED_FORMAT.%(x) # :nodoc:
1312    x ? super : "failed"
1313  end
1314
1315  def typedef_expr(type, headers)
1316    typename, member = type.split('.', 2)
1317    prelude = cpp_include(headers).split(/$/)
1318    prelude << "typedef #{typename} rbcv_typedef_;\n"
1319    return "rbcv_typedef_", member, prelude
1320  end
1321
1322  def try_signedness(type, member, headers = nil, opts = nil)
1323    raise ArgumentError, "don't know how to tell signedness of members" if member
1324    if try_static_assert("(#{type})-1 < 0", headers, opts)
1325      return -1
1326    elsif try_static_assert("(#{type})-1 > 0", headers, opts)
1327      return +1
1328    end
1329  end
1330
1331  # :startdoc:
1332
1333  # Returns the size of the given +type+.  You may optionally specify
1334  # additional +headers+ to search in for the +type+.
1335  #
1336  # If found, a macro is passed as a preprocessor constant to the compiler
1337  # using the type name, in uppercase, prepended with +SIZEOF_+, followed by
1338  # the type name, followed by <code>=X</code> where "X" is the actual size.
1339  #
1340  # For example, if <code>check_sizeof('mystruct')</code> returned 12, then
1341  # the <code>SIZEOF_MYSTRUCT=12</code> preprocessor macro would be passed to
1342  # the compiler.
1343  #
1344  def check_sizeof(type, headers = nil, opts = "", &b)
1345    typedef, member, prelude = typedef_expr(type, headers)
1346    prelude << "#{typedef} *rbcv_ptr_;\n"
1347    prelude = [prelude]
1348    expr = "sizeof((*rbcv_ptr_)#{"." << member if member})"
1349    fmt = STRING_OR_FAILED_FORMAT
1350    checking_for checking_message("size of #{type}", headers), fmt do
1351      if size = try_constant(expr, prelude, opts, &b)
1352        $defs.push(format("-DSIZEOF_%s=%s", type.tr_cpp, size))
1353        size
1354      end
1355    end
1356  end
1357
1358  # Returns the signedness of the given +type+.  You may optionally specify
1359  # additional +headers+ to search in for the +type+.
1360  #
1361  # If the +type+ is found and is a numeric type, a macro is passed as a
1362  # preprocessor constant to the compiler using the +type+ name, in uppercase,
1363  # prepended with +SIGNEDNESS_OF_+, followed by the +type+ name, followed by
1364  # <code>=X</code> where "X" is positive integer if the +type+ is unsigned
1365  # and a negative integer if the +type+ is signed.
1366  #
1367  # For example, if +size_t+ is defined as unsigned, then
1368  # <code>check_signedness('size_t')</code> would return +1 and the
1369  # <code>SIGNEDNESS_OF_SIZE_T=+1</code> preprocessor macro would be passed to
1370  # the compiler.  The <code>SIGNEDNESS_OF_INT=-1</code> macro would be set
1371  # for <code>check_signedness('int')</code>
1372  #
1373  def check_signedness(type, headers = nil, opts = nil, &b)
1374    typedef, member, prelude = typedef_expr(type, headers)
1375    signed = nil
1376    checking_for("signedness of #{type}", STRING_OR_FAILED_FORMAT) do
1377      signed = try_signedness(typedef, member, [prelude], opts, &b) or next nil
1378      $defs.push("-DSIGNEDNESS_OF_%s=%+d" % [type.tr_cpp, signed])
1379      signed < 0 ? "signed" : "unsigned"
1380    end
1381    signed
1382  end
1383
1384  # Returns the convertible integer type of the given +type+.  You may
1385  # optionally specify additional +headers+ to search in for the +type+.
1386  # _convertible_ means actually the same type, or typedef'd from the same
1387  # type.
1388  #
1389  # If the +type+ is an integer type and the _convertible_ type is found,
1390  # the following macros are passed as preprocessor constants to the compiler
1391  # using the +type+ name, in uppercase.
1392  #
1393  # * +TYPEOF_+, followed by the +type+ name, followed by <code>=X</code>
1394  #   where "X" is the found _convertible_ type name.
1395  # * +TYP2NUM+ and +NUM2TYP+,
1396  #   where +TYP+ is the +type+ name in uppercase with replacing an +_t+
1397  #   suffix with "T", followed by <code>=X</code> where "X" is the macro name
1398  #   to convert +type+ to an Integer object, and vice versa.
1399  #
1400  # For example, if +foobar_t+ is defined as unsigned long, then
1401  # <code>convertible_int("foobar_t")</code> would return "unsigned long", and
1402  # define these macros:
1403  #
1404  #   #define TYPEOF_FOOBAR_T unsigned long
1405  #   #define FOOBART2NUM ULONG2NUM
1406  #   #define NUM2FOOBART NUM2ULONG
1407  #
1408  def convertible_int(type, headers = nil, opts = nil, &b)
1409    type, macname = *type
1410    checking_for("convertible type of #{type}", STRING_OR_FAILED_FORMAT) do
1411      if UNIVERSAL_INTS.include?(type)
1412        type
1413      else
1414        typedef, member, prelude = typedef_expr(type, headers, &b)
1415        if member
1416          prelude << "static rbcv_typedef_ rbcv_var;"
1417          compat = UNIVERSAL_INTS.find {|t|
1418            try_static_assert("sizeof(rbcv_var.#{member}) == sizeof(#{t})", [prelude], opts, &b)
1419          }
1420        else
1421          next unless signed = try_signedness(typedef, member, [prelude])
1422          u = "unsigned " if signed > 0
1423          prelude << "extern rbcv_typedef_ foo();"
1424          compat = UNIVERSAL_INTS.find {|t|
1425            try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, :werror=>true, &b)
1426          }
1427        end
1428        if compat
1429          macname ||= type.sub(/_(?=t\z)/, '').tr_cpp
1430          conv = (compat == "long long" ? "LL" : compat.upcase)
1431          compat = "#{u}#{compat}"
1432          typename = type.tr_cpp
1433          $defs.push(format("-DSIZEOF_%s=SIZEOF_%s", typename, compat.tr_cpp))
1434          $defs.push(format("-DTYPEOF_%s=%s", typename, compat.quote))
1435          $defs.push(format("-DPRI_%s_PREFIX=PRI_%s_PREFIX", macname, conv))
1436          conv = (u ? "U" : "") + conv
1437          $defs.push(format("-D%s2NUM=%s2NUM", macname, conv))
1438          $defs.push(format("-DNUM2%s=NUM2%s", macname, conv))
1439          compat
1440        end
1441      end
1442    end
1443  end
1444  # :stopdoc:
1445
1446  # Used internally by the what_type? method to determine if +type+ is a scalar
1447  # pointer.
1448  def scalar_ptr_type?(type, member = nil, headers = nil, &b)
1449    try_compile(<<"SRC", &b)   # pointer
1450#{cpp_include(headers)}
1451/*top*/
1452volatile #{type} conftestval;
1453extern int t(void);
1454#{MAIN_DOES_NOTHING 't'}
1455int t(void) {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
1456SRC
1457  end
1458
1459  # Used internally by the what_type? method to determine if +type+ is a scalar
1460  # pointer.
1461  def scalar_type?(type, member = nil, headers = nil, &b)
1462    try_compile(<<"SRC", &b)   # pointer
1463#{cpp_include(headers)}
1464/*top*/
1465volatile #{type} conftestval;
1466extern int t(void);
1467#{MAIN_DOES_NOTHING 't'}
1468int t(void) {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
1469SRC
1470  end
1471
1472  # Used internally by the what_type? method to check if the _typeof_ GCC
1473  # extension is available.
1474  def have_typeof?
1475    return $typeof if defined?($typeof)
1476    $typeof = %w[__typeof__ typeof].find do |t|
1477      try_compile(<<SRC)
1478int rbcv_foo;
1479#{t}(rbcv_foo) rbcv_bar;
1480SRC
1481    end
1482  end
1483
1484  def what_type?(type, member = nil, headers = nil, &b)
1485    m = "#{type}"
1486    var = val = "*rbcv_var_"
1487    func = "rbcv_func_(void)"
1488    if member
1489      m << "." << member
1490    else
1491      type, member = type.split('.', 2)
1492    end
1493    if member
1494      val = "(#{var}).#{member}"
1495    end
1496    prelude = [cpp_include(headers).split(/^/)]
1497    prelude << ["typedef #{type} rbcv_typedef_;\n",
1498                "extern rbcv_typedef_ *#{func};\n",
1499                "rbcv_typedef_ #{var};\n",
1500               ]
1501    type = "rbcv_typedef_"
1502    fmt = member && !(typeof = have_typeof?) ? "seems %s" : "%s"
1503    if typeof
1504      var = "*rbcv_member_"
1505      func = "rbcv_mem_func_(void)"
1506      member = nil
1507      type = "rbcv_mem_typedef_"
1508      prelude[-1] << "typedef #{typeof}(#{val}) #{type};\n"
1509      prelude[-1] << "extern #{type} *#{func};\n"
1510      prelude[-1] << "#{type} #{var};\n"
1511      val = var
1512    end
1513    def fmt.%(x)
1514      x ? super : "unknown"
1515    end
1516    checking_for checking_message(m, headers), fmt do
1517      if scalar_ptr_type?(type, member, prelude, &b)
1518        if try_static_assert("sizeof(*#{var}) == 1", prelude)
1519          return "string"
1520        end
1521        ptr = "*"
1522      elsif scalar_type?(type, member, prelude, &b)
1523        unless member and !typeof or try_static_assert("(#{type})-1 < 0", prelude)
1524          unsigned = "unsigned"
1525        end
1526        ptr = ""
1527      else
1528        next
1529      end
1530      type = UNIVERSAL_INTS.find do |t|
1531        pre = prelude
1532        unless member
1533          pre += [["#{unsigned} #{t} #{ptr}#{var};\n",
1534                   "extern #{unsigned} #{t} #{ptr}*#{func};\n"]]
1535        end
1536        try_static_assert("sizeof(#{ptr}#{val}) == sizeof(#{unsigned} #{t})", pre)
1537      end
1538      type or next
1539      [unsigned, type, ptr].join(" ").strip
1540    end
1541  end
1542
1543  # This method is used internally by the find_executable method.
1544  #
1545  # Internal use only.
1546  #
1547  def find_executable0(bin, path = nil)
1548    executable_file = proc do |name|
1549      begin
1550        stat = File.stat(name)
1551      rescue SystemCallError
1552      else
1553        next name if stat.file? and stat.executable?
1554      end
1555    end
1556
1557    exts = config_string('EXECUTABLE_EXTS') {|s| s.split} || config_string('EXEEXT') {|s| [s]}
1558    if File.expand_path(bin) == bin
1559      return bin if executable_file.call(bin)
1560      if exts
1561        exts.each {|ext| executable_file.call(file = bin + ext) and return file}
1562      end
1563      return nil
1564    end
1565    if path ||= ENV['PATH']
1566      path = path.split(File::PATH_SEPARATOR)
1567    else
1568      path = %w[/usr/local/bin /usr/ucb /usr/bin /bin]
1569    end
1570    file = nil
1571    path.each do |dir|
1572      dir.sub!(/\A"(.*)"\z/m, '\1') if $mswin or $mingw
1573      return file if executable_file.call(file = File.join(dir, bin))
1574      if exts
1575        exts.each {|ext| executable_file.call(ext = file + ext) and return ext}
1576      end
1577    end
1578    nil
1579  end
1580
1581  # :startdoc:
1582
1583  # Searches for the executable +bin+ on +path+.  The default path is your
1584  # +PATH+ environment variable. If that isn't defined, it will resort to
1585  # searching /usr/local/bin, /usr/ucb, /usr/bin and /bin.
1586  #
1587  # If found, it will return the full path, including the executable name, of
1588  # where it was found.
1589  #
1590  # Note that this method does not actually affect the generated Makefile.
1591  #
1592  def find_executable(bin, path = nil)
1593    checking_for checking_message(bin, path) do
1594      find_executable0(bin, path)
1595    end
1596  end
1597
1598  # :stopdoc:
1599
1600  def arg_config(config, default=nil, &block)
1601    $arg_config << [config, default]
1602    defaults = []
1603    if default
1604      defaults << default
1605    elsif !block
1606      defaults << nil
1607    end
1608    $configure_args.fetch(config.tr('_', '-'), *defaults, &block)
1609  end
1610
1611  # :startdoc:
1612
1613  # Tests for the presence of a <tt>--with-</tt>_config_ or
1614  # <tt>--without-</tt>_config_ option.  Returns +true+ if the with option is
1615  # given, +false+ if the without option is given, and the default value
1616  # otherwise.
1617  #
1618  # This can be useful for adding custom definitions, such as debug
1619  # information.
1620  #
1621  # Example:
1622  #
1623  #    if with_config("debug")
1624  #       $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1625  #    end
1626  #
1627  def with_config(config, default=nil)
1628    config = config.sub(/^--with[-_]/, '')
1629    val = arg_config("--with-"+config) do
1630      if arg_config("--without-"+config)
1631        false
1632      elsif block_given?
1633        yield(config, default)
1634      else
1635        break default
1636      end
1637    end
1638    case val
1639    when "yes"
1640      true
1641    when "no"
1642      false
1643    else
1644      val
1645    end
1646  end
1647
1648  # Tests for the presence of an <tt>--enable-</tt>_config_ or
1649  # <tt>--disable-</tt>_config_ option. Returns +true+ if the enable option is
1650  # given, +false+ if the disable option is given, and the default value
1651  # otherwise.
1652  #
1653  # This can be useful for adding custom definitions, such as debug
1654  # information.
1655  #
1656  # Example:
1657  #
1658  #    if enable_config("debug")
1659  #       $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1660  #    end
1661  #
1662  def enable_config(config, default=nil)
1663    if arg_config("--enable-"+config)
1664      true
1665    elsif arg_config("--disable-"+config)
1666      false
1667    elsif block_given?
1668      yield(config, default)
1669    else
1670      return default
1671    end
1672  end
1673
1674  # Generates a header file consisting of the various macro definitions
1675  # generated by other methods such as have_func and have_header. These are
1676  # then wrapped in a custom <code>#ifndef</code> based on the +header+ file
1677  # name, which defaults to "extconf.h".
1678  #
1679  # For example:
1680  #
1681  #   # extconf.rb
1682  #   require 'mkmf'
1683  #   have_func('realpath')
1684  #   have_header('sys/utime.h')
1685  #   create_header
1686  #   create_makefile('foo')
1687  #
1688  # The above script would generate the following extconf.h file:
1689  #
1690  #   #ifndef EXTCONF_H
1691  #   #define EXTCONF_H
1692  #   #define HAVE_REALPATH 1
1693  #   #define HAVE_SYS_UTIME_H 1
1694  #   #endif
1695  #
1696  # Given that the create_header method generates a file based on definitions
1697  # set earlier in your extconf.rb file, you will probably want to make this
1698  # one of the last methods you call in your script.
1699  #
1700  def create_header(header = "extconf.h")
1701    message "creating %s\n", header
1702    sym = header.tr_cpp
1703    hdr = ["#ifndef #{sym}\n#define #{sym}\n"]
1704    for line in $defs
1705      case line
1706      when /^-D([^=]+)(?:=(.*))?/
1707        hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0].gsub(/(?=\t+)/, "\\\n") : 1}\n"
1708      when /^-U(.*)/
1709        hdr << "#undef #$1\n"
1710      end
1711    end
1712    hdr << "#endif\n"
1713    hdr = hdr.join("")
1714    log_src(hdr, "#{header} is")
1715    unless (IO.read(header) == hdr rescue false)
1716      open(header, "wb") do |hfile|
1717        hfile.write(hdr)
1718      end
1719    end
1720    $extconf_h = header
1721  end
1722
1723  # call-seq:
1724  #   dir_config(target)
1725  #   dir_config(target, prefix)
1726  #   dir_config(target, idefault, ldefault)
1727  #
1728  # Sets a +target+ name that the user can then use to configure
1729  # various "with" options with on the command line by using that
1730  # name.  For example, if the target is set to "foo", then the user
1731  # could use the <code>--with-foo-dir=prefix</code>,
1732  # <code>--with-foo-include=dir</code> and
1733  # <code>--with-foo-lib=dir</code> command line options to tell where
1734  # to search for header/library files.
1735  #
1736  # You may pass along additional parameters to specify default
1737  # values.  If one is given it is taken as default +prefix+, and if
1738  # two are given they are taken as "include" and "lib" defaults in
1739  # that order.
1740  #
1741  # In any case, the return value will be an array of determined
1742  # "include" and "lib" directories, either of which can be nil if no
1743  # corresponding command line option is given when no default value
1744  # is specified.
1745  #
1746  # Note that dir_config only adds to the list of places to search for
1747  # libraries and include files.  It does not link the libraries into your
1748  # application.
1749  #
1750  def dir_config(target, idefault=nil, ldefault=nil)
1751    if dir = with_config(target + "-dir", (idefault unless ldefault))
1752      defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR)
1753      idefault = ldefault = nil
1754    end
1755
1756    idir = with_config(target + "-include", idefault)
1757    $arg_config.last[1] ||= "${#{target}-dir}/include"
1758    ldir = with_config(target + "-lib", ldefault)
1759    $arg_config.last[1] ||= "${#{target}-dir}/#{_libdir_basename}"
1760
1761    idirs = idir ? Array === idir ? idir.dup : idir.split(File::PATH_SEPARATOR) : []
1762    if defaults
1763      idirs.concat(defaults.collect {|d| d + "/include"})
1764      idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR)
1765    end
1766    unless idirs.empty?
1767      idirs.collect! {|d| "-I" + d}
1768      idirs -= Shellwords.shellwords($CPPFLAGS)
1769      unless idirs.empty?
1770        $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ")
1771      end
1772    end
1773
1774    ldirs = ldir ? Array === ldir ? ldir.dup : ldir.split(File::PATH_SEPARATOR) : []
1775    if defaults
1776      ldirs.concat(defaults.collect {|d| "#{d}/#{_libdir_basename}"})
1777      ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR)
1778    end
1779    $LIBPATH = ldirs | $LIBPATH
1780
1781    [idir, ldir]
1782  end
1783
1784  # Returns compile/link information about an installed library in a
1785  # tuple of <code>[cflags, ldflags, libs]</code>, by using the
1786  # command found first in the following commands:
1787  #
1788  # 1. If <code>--with-{pkg}-config={command}</code> is given via
1789  #    command line option: <code>{command} {option}</code>
1790  #
1791  # 2. <code>{pkg}-config {option}</code>
1792  #
1793  # 3. <code>pkg-config {option} {pkg}</code>
1794  #
1795  # Where {option} is, for instance, <code>--cflags</code>.
1796  #
1797  # The values obtained are appended to +$CFLAGS+, +$LDFLAGS+ and
1798  # +$libs+.
1799  #
1800  # If an <code>option</code> argument is given, the config command is
1801  # invoked with the option and a stripped output string is returned
1802  # without modifying any of the global values mentioned above.
1803  def pkg_config(pkg, option=nil)
1804    if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
1805      # iff package specific config command is given
1806    elsif ($PKGCONFIG ||=
1807           (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
1808           find_executable0(pkgconfig) && pkgconfig) and
1809        xsystem("#{$PKGCONFIG} --exists #{pkg}")
1810      # default to pkg-config command
1811      pkgconfig = $PKGCONFIG
1812      get = proc {|opt|
1813        opt = xpopen("#{$PKGCONFIG} --#{opt} #{pkg}", err:[:child, :out], &:read)
1814        Logging.open {puts opt.each_line.map{|s|"=> #{s.inspect}"}}
1815        opt.strip if $?.success?
1816      }
1817    elsif find_executable0(pkgconfig = "#{pkg}-config")
1818      # default to package specific config command, as a last resort.
1819    else
1820      pkgconfig = nil
1821    end
1822    if pkgconfig
1823      get ||= proc {|opt|
1824        opt = xpopen("#{pkgconfig} --#{opt}", err:[:child, :out], &:read)
1825        Logging.open {puts opt.each_line.map{|s|"=> #{s.inspect}"}}
1826        opt.strip if $?.success?
1827      }
1828    end
1829    orig_ldflags = $LDFLAGS
1830    if get and option
1831      get[option]
1832    elsif get and try_ldflags(ldflags = get['libs'])
1833      if incflags = get['cflags-only-I']
1834        $INCFLAGS << " " << incflags
1835        cflags = get['cflags-only-other']
1836      else
1837        cflags = get['cflags']
1838      end
1839      libs = get['libs-only-l']
1840      if cflags
1841        $CFLAGS += " " << cflags
1842        $CXXFLAGS += " " << cflags
1843      end
1844      if libs
1845        ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ")
1846      else
1847        libs, ldflags = Shellwords.shellwords(ldflags).partition {|s| s =~ /-l([^ ]+)/ }.map {|l|l.quote.join(" ")}
1848      end
1849      $libs += " " << libs
1850
1851      $LDFLAGS = [orig_ldflags, ldflags].join(' ')
1852      Logging::message "package configuration for %s\n", pkg
1853      Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n",
1854                       cflags, ldflags, libs
1855      [cflags, ldflags, libs]
1856    else
1857      Logging::message "package configuration for %s is not found\n", pkg
1858      nil
1859    end
1860  end
1861
1862  # :stopdoc:
1863
1864  def with_destdir(dir)
1865    dir = dir.sub($dest_prefix_pattern, '')
1866    /\A\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir
1867  end
1868
1869  # Converts forward slashes to backslashes. Aimed at MS Windows.
1870  #
1871  # Internal use only.
1872  #
1873  def winsep(s)
1874    s.tr('/', '\\')
1875  end
1876
1877  # Converts native path to format acceptable in Makefile
1878  #
1879  # Internal use only.
1880  #
1881  if !CROSS_COMPILING
1882    case CONFIG['build_os']
1883    when 'mingw32'
1884      def mkintpath(path)
1885        # mingw uses make from msys and it needs special care
1886        # converts from C:\some\path to /C/some/path
1887        path = path.dup
1888        path.tr!('\\', '/')
1889        path.sub!(/\A([A-Za-z]):(?=\/)/, '/\1')
1890        path
1891      end
1892    when 'cygwin'
1893      if CONFIG['target_os'] != 'cygwin'
1894        def mkintpath(path)
1895          IO.popen(["cygpath", "-u", path], &:read).chomp
1896        end
1897      end
1898    end
1899  end
1900  unless method_defined?(:mkintpath)
1901    def mkintpath(path)
1902      path
1903    end
1904  end
1905
1906  def configuration(srcdir)
1907    mk = []
1908    vpath = $VPATH.dup
1909    CONFIG["hdrdir"] ||= $hdrdir
1910    mk << %{
1911SHELL = /bin/sh
1912
1913# V=0 quiet, V=1 verbose.  other values don't work.
1914V = 0
1915Q1 = $(V:1=)
1916Q = $(Q1:0=@)
1917ECHO1 = $(V:1=@ #{CONFIG['NULLCMD']})
1918ECHO = $(ECHO1:0=@ echo)
1919NULLCMD = #{CONFIG['NULLCMD']}
1920
1921#### Start of system configuration section. ####
1922#{"top_srcdir = " + $top_srcdir.sub(%r"\A#{Regexp.quote($topdir)}/", "$(topdir)/") if $extmk}
1923srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {mkintpath(CONFIG[$1||$2]).unspace}}
1924topdir = #{mkintpath(topdir = $extmk ? CONFIG["topdir"] : $topdir).unspace}
1925hdrdir = #{(hdrdir = CONFIG["hdrdir"]) == topdir ? "$(topdir)" : mkintpath(hdrdir).unspace}
1926arch_hdrdir = #{$arch_hdrdir.quote}
1927PATH_SEPARATOR = #{CONFIG['PATH_SEPARATOR']}
1928VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
1929}
1930    if $extmk
1931      mk << "RUBYLIB =\n""RUBYOPT = -\n"
1932    end
1933    prefix = mkintpath(CONFIG["prefix"])
1934    if destdir = prefix[$dest_prefix_pattern, 1]
1935      mk << "\nDESTDIR = #{destdir}\n"
1936      prefix = prefix[destdir.size..-1]
1937    end
1938    mk << "prefix = #{with_destdir(prefix).unspace}\n"
1939    CONFIG.each do |key, var|
1940      mk << "#{key} = #{with_destdir(mkintpath(var)).unspace}\n" if /.prefix$/ =~ key
1941    end
1942    CONFIG.each do |key, var|
1943      next if /^abs_/ =~ key
1944      next if /^(?:src|top(?:_src)?|build|hdr)dir$/ =~ key
1945      next unless /dir$/ =~ key
1946      mk << "#{key} = #{with_destdir(var)}\n"
1947    end
1948    if !$extmk and !$configure_args.has_key?('--ruby') and
1949        sep = config_string('BUILD_FILE_SEPARATOR')
1950      sep = ":/=#{sep}"
1951    else
1952      sep = ""
1953    end
1954    possible_command = (proc {|s| s if /top_srcdir/ !~ s} unless $extmk)
1955    extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ") << " "
1956    headers = %w[
1957      $(hdrdir)/ruby.h
1958      $(hdrdir)/ruby/backward.h
1959      $(hdrdir)/ruby/ruby.h
1960      $(hdrdir)/ruby/defines.h
1961      $(hdrdir)/ruby/missing.h
1962      $(hdrdir)/ruby/intern.h
1963      $(hdrdir)/ruby/st.h
1964      $(hdrdir)/ruby/subst.h
1965    ]
1966    headers += $headers
1967    if RULE_SUBST
1968      headers.each {|h| h.sub!(/.*/, &RULE_SUBST.method(:%))}
1969    end
1970    headers << $config_h
1971    headers << '$(RUBY_EXTCONF_H)' if $extconf_h
1972    mk << %{
1973
1974CC_WRAPPER = #{CONFIG['CC_WRAPPER']}
1975CC = #{CONFIG['CC']}
1976CXX = #{CONFIG['CXX']}
1977LIBRUBY = #{CONFIG['LIBRUBY']}
1978LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
1979LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
1980LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC
1981empty =
1982OUTFLAG = #{OUTFLAG}$(empty)
1983COUTFLAG = #{COUTFLAG}$(empty)
1984CSRCFLAG = #{CSRCFLAG}$(empty)
1985
1986RUBY_EXTCONF_H = #{$extconf_h}
1987cflags   = #{CONFIG['cflags']}
1988cxxflags = #{CONFIG['cxxflags']}
1989optflags = #{CONFIG['optflags']}
1990debugflags = #{CONFIG['debugflags']}
1991warnflags = #{$warnflags}
1992cppflags = #{CONFIG['cppflags']}
1993CCDLFLAGS = #{$static ? '' : CONFIG['CCDLFLAGS']}
1994CFLAGS   = $(CCDLFLAGS) #$CFLAGS $(ARCH_FLAG)
1995INCFLAGS = -I. #$INCFLAGS
1996DEFS     = #{CONFIG['DEFS']}
1997CPPFLAGS = #{extconf_h}#{$CPPFLAGS}
1998CXXFLAGS = $(CCDLFLAGS) #$CXXFLAGS $(ARCH_FLAG)
1999ldflags  = #{$LDFLAGS}
2000dldflags = #{$DLDFLAGS} #{CONFIG['EXTDLDFLAGS']}
2001ARCH_FLAG = #{$ARCH_FLAG}
2002DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
2003LDSHARED = #{CONFIG['LDSHARED']}
2004LDSHAREDXX = #{config_string('LDSHAREDXX') || '$(LDSHARED)'}
2005AR = #{CONFIG['AR']}
2006EXEEXT = #{CONFIG['EXEEXT']}
2007
2008}
2009    CONFIG.each do |key, val|
2010      mk << "#{key} = #{val}\n" if /^RUBY.*NAME/ =~ key
2011    end
2012    mk << %{
2013arch = #{CONFIG['arch']}
2014sitearch = #{CONFIG['sitearch']}
2015ruby_version = #{RbConfig::CONFIG['ruby_version']}
2016ruby = #{$ruby.sub(%r[\A#{Regexp.quote(RbConfig::CONFIG['bindir'])}(?=/|\z)]) {'$(bindir)'}}
2017RUBY = $(ruby#{sep})
2018ruby_headers = #{headers.join(' ')}
2019
2020RM = #{config_string('RM', &possible_command) || '$(RUBY) -run -e rm -- -f'}
2021RM_RF = #{'$(RUBY) -run -e rm -- -rf'}
2022RMDIRS = #{config_string('RMDIRS', &possible_command) || '$(RUBY) -run -e rmdir -- -p'}
2023MAKEDIRS = #{config_string('MAKEDIRS', &possible_command) || '@$(RUBY) -run -e mkdir -- -p'}
2024INSTALL = #{config_string('INSTALL', &possible_command) || '@$(RUBY) -run -e install -- -vp'}
2025INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'}
2026INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'}
2027COPY = #{config_string('CP', &possible_command) || '@$(RUBY) -run -e cp -- -v'}
2028TOUCH = exit >
2029
2030#### End of system configuration section. ####
2031
2032preload = #{defined?($preload) && $preload ? $preload.join(' ') : ''}
2033}
2034    mk
2035  end
2036
2037  def timestamp_file(name, target_prefix = nil)
2038    pat = {}
2039    name = '$(RUBYARCHDIR)' if name == '$(TARGET_SO_DIR)'
2040    install_dirs.each do |n, d|
2041      pat[n] = $` if /\$\(target_prefix\)\z/ =~ d
2042    end
2043    name = name.gsub(/\$\((#{pat.keys.join("|")})\)/) {pat[$1]+target_prefix}
2044    name.sub!(/(\$\((?:site)?arch\))\/*/, '')
2045    arch = $1 || ''
2046    name.chomp!('/')
2047    name = name.gsub(/(\$[({]|[})])|(\/+)|[^-.\w]+/) {$1 ? "" : $2 ? ".-." : "_"}
2048    File.join("$(TIMESTAMP_DIR)", arch, "#{name.sub(/\A(?=.)/, '.')}.time")
2049  end
2050  # :startdoc:
2051
2052  # creates a stub Makefile.
2053  #
2054  def dummy_makefile(srcdir)
2055    configuration(srcdir) << <<RULES << CLEANINGS
2056CLEANFILES = #{$cleanfiles.join(' ')}
2057DISTCLEANFILES = #{$distcleanfiles.join(' ')}
2058
2059all install static install-so install-rb: Makefile
2060	@$(NULLCMD)
2061.PHONY: all install static install-so install-rb
2062.PHONY: clean clean-so clean-static clean-rb
2063
2064RULES
2065  end
2066
2067  def each_compile_rules # :nodoc:
2068    vpath_splat = /\$\(\*VPATH\*\)/
2069    COMPILE_RULES.each do |rule|
2070      if vpath_splat =~ rule
2071        $VPATH.each do |path|
2072          yield rule.sub(vpath_splat) {path}
2073        end
2074      else
2075        yield rule
2076      end
2077    end
2078  end
2079
2080  # Processes the data contents of the "depend" file.  Each line of this file
2081  # is expected to be a file name.
2082  #
2083  # Returns the output of findings, in Makefile format.
2084  #
2085  def depend_rules(depend)
2086    suffixes = []
2087    depout = []
2088    cont = implicit = nil
2089    impconv = proc do
2090      each_compile_rules {|rule| depout << (rule % implicit[0]) << implicit[1]}
2091      implicit = nil
2092    end
2093    ruleconv = proc do |line|
2094      if implicit
2095        if /\A\t/ =~ line
2096          implicit[1] << line
2097          next
2098        else
2099          impconv[]
2100        end
2101      end
2102      if m = /\A\.(\w+)\.(\w+)(?:\s*:)/.match(line)
2103        suffixes << m[1] << m[2]
2104        implicit = [[m[1], m[2]], [m.post_match]]
2105        next
2106      elsif RULE_SUBST and /\A(?!\s*\w+\s*=)[$\w][^#]*:/ =~ line
2107        line.sub!(/\s*\#.*$/, '')
2108        comment = $&
2109        line.gsub!(%r"(\s)(?!\.)([^$(){}+=:\s\\,]+)(?=\s|\z)") {$1 + RULE_SUBST % $2}
2110        line = line.chomp + comment + "\n" if comment
2111      end
2112      depout << line
2113    end
2114    depend.each_line do |line|
2115      line.gsub!(/\.o\b/, ".#{$OBJEXT}")
2116      line.gsub!(/\{\$\(VPATH\)\}/, "") unless $nmake
2117      line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h)
2118      line.gsub!(%r"\$\(hdrdir\)/(?!ruby(?![^:;/\s]))(?=[-\w]+\.h)", '\&ruby/')
2119      if $nmake && /\A\s*\$\(RM|COPY\)/ =~ line
2120        line.gsub!(%r"[-\w\./]{2,}"){$&.tr("/", "\\")}
2121        line.gsub!(/(\$\((?!RM|COPY)[^:)]+)(?=\))/, '\1:/=\\')
2122      end
2123      if /(?:^|[^\\])(?:\\\\)*\\$/ =~ line
2124        (cont ||= []) << line
2125        next
2126      elsif cont
2127        line = (cont << line).join
2128        cont = nil
2129      end
2130      ruleconv.call(line)
2131    end
2132    if cont
2133      ruleconv.call(cont.join)
2134    elsif implicit
2135      impconv.call
2136    end
2137    unless suffixes.empty?
2138      depout.unshift(".SUFFIXES: ." + suffixes.uniq.join(" .") + "\n\n")
2139    end
2140    if $extconf_h
2141      depout.unshift("$(OBJS): $(RUBY_EXTCONF_H)\n\n")
2142      depout.unshift("$(OBJS): $(hdrdir)/ruby/win32.h\n\n") if $mswin or $mingw
2143    end
2144    depout.flatten!
2145    depout
2146  end
2147
2148  # Generates the Makefile for your extension, passing along any options and
2149  # preprocessor constants that you may have generated through other methods.
2150  #
2151  # The +target+ name should correspond the name of the global function name
2152  # defined within your C extension, minus the +Init_+.  For example, if your
2153  # C extension is defined as +Init_foo+, then your target would simply be
2154  # "foo".
2155  #
2156  # If any "/" characters are present in the target name, only the last name
2157  # is interpreted as the target name, and the rest are considered toplevel
2158  # directory names, and the generated Makefile will be altered accordingly to
2159  # follow that directory structure.
2160  #
2161  # For example, if you pass "test/foo" as a target name, your extension will
2162  # be installed under the "test" directory.  This means that in order to
2163  # load the file within a Ruby program later, that directory structure will
2164  # have to be followed, e.g. <code>require 'test/foo'</code>.
2165  #
2166  # The +srcprefix+ should be used when your source files are not in the same
2167  # directory as your build script. This will not only eliminate the need for
2168  # you to manually copy the source files into the same directory as your
2169  # build script, but it also sets the proper +target_prefix+ in the generated
2170  # Makefile.
2171  #
2172  # Setting the +target_prefix+ will, in turn, install the generated binary in
2173  # a directory under your <code>RbConfig::CONFIG['sitearchdir']</code> that
2174  # mimics your local filesystem when you run <code>make install</code>.
2175  #
2176  # For example, given the following file tree:
2177  #
2178  #   ext/
2179  #     extconf.rb
2180  #     test/
2181  #       foo.c
2182  #
2183  # And given the following code:
2184  #
2185  #   create_makefile('test/foo', 'test')
2186  #
2187  # That will set the +target_prefix+ in the generated Makefile to "test".
2188  # That, in turn, will create the following file tree when installed via the
2189  # <code>make install</code> command:
2190  #
2191  #   /path/to/ruby/sitearchdir/test/foo.so
2192  #
2193  # It is recommended that you use this approach to generate your makefiles,
2194  # instead of copying files around manually, because some third party
2195  # libraries may depend on the +target_prefix+ being set properly.
2196  #
2197  # The +srcprefix+ argument can be used to override the default source
2198  # directory, i.e. the current directory.  It is included as part of the
2199  # +VPATH+ and added to the list of +INCFLAGS+.
2200  #
2201  def create_makefile(target, srcprefix = nil)
2202    $target = target
2203    libpath = $DEFLIBPATH|$LIBPATH
2204    message "creating Makefile\n"
2205    MakeMakefile.rm_f "#{CONFTEST}*"
2206    if CONFIG["DLEXT"] == $OBJEXT
2207      for lib in libs = $libs.split
2208        lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
2209      end
2210      $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
2211    end
2212
2213    if target.include?('/')
2214      target_prefix, target = File.split(target)
2215      target_prefix[0,0] = '/'
2216    else
2217      target_prefix = ""
2218    end
2219
2220    srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
2221    RbConfig.expand(srcdir = srcprefix.dup)
2222
2223    ext = ".#{$OBJEXT}"
2224    orig_srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")].sort
2225    if not $objs
2226      srcs = $srcs || orig_srcs
2227      $objs = []
2228      objs = srcs.inject(Hash.new {[]}) {|h, f|
2229        h.key?(o = File.basename(f, ".*") << ext) or $objs << o
2230        h[o] <<= f
2231        h
2232      }
2233      unless objs.delete_if {|b, f| f.size == 1}.empty?
2234        dups = objs.sort.map {|b, f|
2235          "#{b[/.*\./]}{#{f.collect {|n| n[/([^.]+)\z/]}.join(',')}}"
2236        }
2237        abort "source files duplication - #{dups.join(", ")}"
2238      end
2239    else
2240      $objs.collect! {|o| File.basename(o, ".*") << ext} unless $OBJEXT == "o"
2241      srcs = $srcs || $objs.collect {|o| o.chomp(ext) << ".c"}
2242    end
2243    $srcs = srcs
2244
2245    hdrs = Dir[File.join(srcdir, "*.{#{HDR_EXT.join(%q{,})}}")]
2246
2247    target = nil if $objs.empty?
2248
2249    if target and EXPORT_PREFIX
2250      if File.exist?(File.join(srcdir, target + '.def'))
2251        deffile = "$(srcdir)/$(TARGET).def"
2252        unless EXPORT_PREFIX.empty?
2253          makedef = %{$(RUBY) -pe "$$_.sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i" #{deffile}}
2254        end
2255      else
2256        makedef = %{(echo EXPORTS && echo $(TARGET_ENTRY))}
2257      end
2258      if makedef
2259        $cleanfiles << '$(DEFFILE)'
2260        origdef = deffile
2261        deffile = "$(TARGET)-$(arch).def"
2262      end
2263    end
2264    origdef ||= ''
2265
2266    if $extout and $INSTALLFILES
2267      $cleanfiles.concat($INSTALLFILES.collect {|files, dir|File.join(dir, files.delete_prefix('./'))})
2268      $distcleandirs.concat($INSTALLFILES.collect {|files, dir| dir})
2269    end
2270
2271    if $extmk and $static
2272      $defs << "-DRUBY_EXPORT=1"
2273    end
2274
2275    if $extmk and not $extconf_h
2276      create_header
2277    end
2278
2279    libpath = libpathflag(libpath)
2280
2281    dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
2282    staticlib = target ? "$(TARGET).#$LIBEXT" : ""
2283    conf = configuration(srcprefix)
2284    conf << "\
2285libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")}
2286LIBPATH = #{libpath}
2287DEFFILE = #{deffile}
2288
2289CLEANFILES = #{$cleanfiles.join(' ')}
2290DISTCLEANFILES = #{$distcleanfiles.join(' ')}
2291DISTCLEANDIRS = #{$distcleandirs.join(' ')}
2292
2293extout = #{$extout && $extout.quote}
2294extout_prefix = #{$extout_prefix}
2295target_prefix = #{target_prefix}
2296LOCAL_LIBS = #{$LOCAL_LIBS}
2297LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
2298ORIG_SRCS = #{orig_srcs.collect(&File.method(:basename)).join(' ')}
2299SRCS = $(ORIG_SRCS) #{(srcs - orig_srcs).collect(&File.method(:basename)).join(' ')}
2300OBJS = #{$objs.join(" ")}
2301HDRS = #{hdrs.map{|h| '$(srcdir)/' + File.basename(h)}.join(' ')}
2302LOCAL_HDRS = #{$headers.join(' ')}
2303TARGET = #{target}
2304TARGET_NAME = #{target && target[/\A\w+/]}
2305TARGET_ENTRY = #{EXPORT_PREFIX || ''}Init_$(TARGET_NAME)
2306DLLIB = #{dllib}
2307EXTSTATIC = #{$static || ""}
2308STATIC_LIB = #{staticlib unless $static.nil?}
2309#{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
2310TIMESTAMP_DIR = #{$extout && $extmk ? '$(extout)/.timestamp' : '.'}
2311" #"
2312    # TODO: fixme
2313    install_dirs.each {|d| conf << ("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
2314    sodir = $extout ? '$(TARGET_SO_DIR)' : '$(RUBYARCHDIR)'
2315    n = '$(TARGET_SO_DIR)$(TARGET)'
2316    conf << "\
2317TARGET_SO_DIR =#{$extout ? " $(RUBYARCHDIR)/" : ''}
2318TARGET_SO     = $(TARGET_SO_DIR)$(DLLIB)
2319CLEANLIBS     = #{'$(TARGET_SO) ' if target}#{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
2320CLEANOBJS     = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")} if target} *.bak
2321" #"
2322
2323    conf = yield(conf) if block_given?
2324    mfile = open("Makefile", "wb")
2325    mfile.puts(conf)
2326    mfile.print "
2327all:    #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
2328static: #{$extmk && !$static ? "all" : "$(STATIC_LIB)#{$extout ? " install-rb" : ""}"}
2329.PHONY: all install static install-so install-rb
2330.PHONY: clean clean-so clean-static clean-rb
2331" #"
2332    mfile.print CLEANINGS
2333    fsep = config_string('BUILD_FILE_SEPARATOR') {|s| s unless s == "/"}
2334    if fsep
2335      sep = ":/=#{fsep}"
2336      fseprepl = proc {|s|
2337        s = s.gsub("/", fsep)
2338        s = s.gsub(/(\$\(\w+)(\))/) {$1+sep+$2}
2339        s.gsub(/(\$\{\w+)(\})/) {$1+sep+$2}
2340      }
2341      rsep = ":#{fsep}=/"
2342    else
2343      fseprepl = proc {|s| s}
2344      sep = ""
2345      rsep = ""
2346    end
2347    dirs = []
2348    mfile.print "install: install-so install-rb\n\n"
2349    dir = sodir.dup
2350    mfile.print("install-so: ")
2351    if target
2352      f = "$(DLLIB)"
2353      dest = "$(TARGET_SO)"
2354      stamp = timestamp_file(dir, target_prefix)
2355      if $extout
2356        mfile.puts dest
2357        mfile.print "clean-so::\n"
2358        mfile.print "\t-$(Q)$(RM) #{fseprepl[dest]} #{fseprepl[stamp]}\n"
2359        mfile.print "\t-$(Q)$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n"
2360      else
2361        mfile.print "#{f} #{stamp}\n"
2362        mfile.print "\t$(INSTALL_PROG) #{fseprepl[f]} #{dir}\n"
2363        if defined?($installed_list)
2364          mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
2365        end
2366      end
2367      mfile.print "clean-static::\n"
2368      mfile.print "\t-$(Q)$(RM) $(STATIC_LIB)\n"
2369    else
2370      mfile.puts "Makefile"
2371    end
2372    mfile.print("install-rb: pre-install-rb do-install-rb install-rb-default\n")
2373    mfile.print("install-rb-default: pre-install-rb-default do-install-rb-default\n")
2374    mfile.print("pre-install-rb: Makefile\n")
2375    mfile.print("pre-install-rb-default: Makefile\n")
2376    mfile.print("do-install-rb:\n")
2377    mfile.print("do-install-rb-default:\n")
2378    for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]]
2379      files = install_files(mfile, i, nil, srcprefix) or next
2380      for dir, *files in files
2381        unless dirs.include?(dir)
2382          dirs << dir
2383          mfile.print "pre-install-rb#{sfx}: #{timestamp_file(dir, target_prefix)}\n"
2384        end
2385        for f in files
2386          dest = "#{dir}/#{File.basename(f)}"
2387          mfile.print("do-install-rb#{sfx}: #{dest}\n")
2388          mfile.print("#{dest}: #{f} #{timestamp_file(dir, target_prefix)}\n")
2389          mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D)\n")
2390          if defined?($installed_list) and !$extout
2391            mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
2392          end
2393          if $extout
2394            mfile.print("clean-rb#{sfx}::\n")
2395            mfile.print("\t-$(Q)$(RM) #{fseprepl[dest]}\n")
2396          end
2397        end
2398      end
2399      mfile.print "pre-install-rb#{sfx}:\n"
2400      if files.empty?
2401        mfile.print("\t@$(NULLCMD)\n")
2402      else
2403        q = "$(MAKE) -q do-install-rb#{sfx}"
2404        if $nmake
2405          mfile.print "!if \"$(Q)\" == \"@\"\n\t@#{q} || \\\n!endif\n\t"
2406        else
2407          mfile.print "\t$(Q1:0=@#{q} || )"
2408        end
2409        mfile.print "$(ECHO1:0=echo) installing#{sfx.sub(/^-/, " ")} #{target} libraries\n"
2410      end
2411      if $extout
2412        dirs.uniq!
2413        unless dirs.empty?
2414          mfile.print("clean-rb#{sfx}::\n")
2415          for dir in dirs.sort_by {|d| -d.count('/')}
2416            stamp = timestamp_file(dir, target_prefix)
2417            mfile.print("\t-$(Q)$(RM) #{fseprepl[stamp]}\n")
2418            mfile.print("\t-$(Q)$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n")
2419          end
2420        end
2421      end
2422    end
2423    dirs.unshift(sodir) if target and !dirs.include?(sodir)
2424    dirs.each do |d|
2425      t = timestamp_file(d, target_prefix)
2426      mfile.print "#{t}:\n\t$(Q) $(MAKEDIRS) $(@D) #{d}\n\t$(Q) $(TOUCH) $@\n"
2427    end
2428
2429    mfile.print <<-SITEINSTALL
2430
2431site-install: site-install-so site-install-rb
2432site-install-so: install-so
2433site-install-rb: install-rb
2434
2435    SITEINSTALL
2436
2437    return unless target
2438
2439    mfile.print ".SUFFIXES: .#{(SRC_EXT + [$OBJEXT, $ASMEXT]).compact.join(' .')}\n"
2440    mfile.print "\n"
2441
2442    compile_command = "\n\t$(ECHO) compiling $(<#{rsep})\n\t$(Q) %s\n\n"
2443    command = compile_command % COMPILE_CXX
2444    asm_command = compile_command.sub(/compiling/, 'translating') % ASSEMBLE_CXX
2445    CXX_EXT.each do |e|
2446      each_compile_rules do |rule|
2447        mfile.printf(rule, e, $OBJEXT)
2448        mfile.print(command)
2449        mfile.printf(rule, e, $ASMEXT)
2450        mfile.print(asm_command)
2451      end
2452    end
2453    command = compile_command % COMPILE_C
2454    asm_command = compile_command.sub(/compiling/, 'translating') % ASSEMBLE_C
2455    C_EXT.each do |e|
2456      each_compile_rules do |rule|
2457        mfile.printf(rule, e, $OBJEXT)
2458        mfile.print(command)
2459        mfile.printf(rule, e, $ASMEXT)
2460        mfile.print(asm_command)
2461      end
2462    end
2463
2464    mfile.print "$(TARGET_SO): "
2465    mfile.print "$(DEFFILE) " if makedef
2466    mfile.print "$(OBJS) Makefile"
2467    mfile.print " #{timestamp_file(sodir, target_prefix)}" if $extout
2468    mfile.print "\n"
2469    mfile.print "\t$(ECHO) linking shared-object #{target_prefix.sub(/\A\/(.*)/, '\1/')}$(DLLIB)\n"
2470    mfile.print "\t-$(Q)$(RM) $(@#{sep})\n"
2471    link_so = LINK_SO.gsub(/^/, "\t$(Q) ")
2472    if srcs.any?(&%r"\.(?:#{CXX_EXT.join('|')})\z".method(:===))
2473      link_so = link_so.sub(/\bLDSHARED\b/, '\&XX')
2474    end
2475    mfile.print link_so, "\n\n"
2476    unless $static.nil?
2477      mfile.print "$(STATIC_LIB): $(OBJS)\n\t-$(Q)$(RM) $(@#{sep})\n\t"
2478      mfile.print "$(ECHO) linking static-library $(@#{rsep})\n\t$(Q) "
2479      mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
2480      config_string('RANLIB') do |ranlib|
2481        mfile.print "\n\t-$(Q)#{ranlib} $(@) 2> /dev/null || true"
2482      end
2483    end
2484    mfile.print "\n\n"
2485    if makedef
2486      mfile.print "$(DEFFILE): #{origdef}\n"
2487      mfile.print "\t$(ECHO) generating $(@#{rsep})\n"
2488      mfile.print "\t$(Q) #{makedef} > $@\n\n"
2489    end
2490
2491    depend = File.join(srcdir, "depend")
2492    if File.exist?(depend)
2493      mfile.print("###\n", *depend_rules(File.read(depend)))
2494    else
2495      mfile.print "$(OBJS): $(HDRS) $(ruby_headers)\n"
2496    end
2497
2498    $makefile_created = true
2499  ensure
2500    mfile.close if mfile
2501  end
2502
2503  # :stopdoc:
2504
2505  def init_mkmf(config = CONFIG, rbconfig = RbConfig::CONFIG)
2506    $makefile_created = false
2507    $arg_config = []
2508    $enable_shared = config['ENABLE_SHARED'] == 'yes'
2509    $defs = []
2510    $extconf_h = nil
2511    if $warnflags = CONFIG['warnflags'] and CONFIG['GCC'] == 'yes'
2512      # turn warnings into errors only for bundled extensions.
2513      config['warnflags'] = $warnflags.gsub(/(\A|\s)-Werror[-=]/, '\1-W')
2514      if /icc\z/ =~ config['CC']
2515        config['warnflags'].gsub!(/(\A|\s)-W(?:division-by-zero|deprecated-declarations)/, '\1')
2516      end
2517      RbConfig.expand(rbconfig['warnflags'] = config['warnflags'].dup)
2518      config.each do |key, val|
2519        RbConfig.expand(rbconfig[key] = val.dup) if /warnflags/ =~ val
2520      end
2521      $warnflags = config['warnflags'] unless $extmk
2522    end
2523    if (w = rbconfig['CC_WRAPPER']) and !w.empty? and !File.executable?(w)
2524      rbconfig['CC_WRAPPER'] = config['CC_WRAPPER'] = ''
2525    end
2526    $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup
2527    $CXXFLAGS = (with_config("cxxflags", arg_config("CXXFLAGS", config["CXXFLAGS"]))||'').dup
2528    $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup
2529    $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup
2530    $LDFLAGS = with_config("ldflags", arg_config("LDFLAGS", config["LDFLAGS"])).dup
2531    $INCFLAGS = "-I$(arch_hdrdir)"
2532    $INCFLAGS << " -I$(hdrdir)/ruby/backward" unless $extmk
2533    $INCFLAGS << " -I$(hdrdir) -I$(srcdir)"
2534    $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
2535    $LIBEXT = config['LIBEXT'].dup
2536    $OBJEXT = config["OBJEXT"].dup
2537    $EXEEXT = config["EXEEXT"].dup
2538    $ASMEXT = config_string('ASMEXT', &:dup) || 'S'
2539    $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}"
2540    $LIBRUBYARG = ""
2541    $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC']
2542    $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED']
2543    $DEFLIBPATH = [$extmk ? "$(topdir)" : "$(#{config["libdirname"] || "libdir"})"]
2544    $DEFLIBPATH.unshift(".")
2545    $LIBPATH = []
2546    $INSTALLFILES = []
2547    $NONINSTALLFILES = [/~\z/, /\A#.*#\z/, /\A\.#/, /\.bak\z/i, /\.orig\z/, /\.rej\z/, /\.l[ao]\z/, /\.o\z/]
2548    $VPATH = %w[$(srcdir) $(arch_hdrdir)/ruby $(hdrdir)/ruby]
2549
2550    $objs = nil
2551    $srcs = nil
2552    $headers = []
2553    $libs = ""
2554    if $enable_shared or RbConfig.expand(config["LIBRUBY"].dup) != RbConfig.expand(config["LIBRUBY_A"].dup)
2555      $LIBRUBYARG = config['LIBRUBYARG']
2556    end
2557
2558    $LOCAL_LIBS = ""
2559
2560    $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || []
2561    $cleanfiles << "mkmf.log"
2562    $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || []
2563    $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || []
2564
2565    $extout ||= nil
2566    $extout_prefix ||= nil
2567
2568    $arg_config.clear
2569    dir_config("opt")
2570  end
2571
2572  FailedMessage = <<MESSAGE
2573Could not create Makefile due to some reason, probably lack of necessary
2574libraries and/or headers.  Check the mkmf.log file for more details.  You may
2575need configuration options.
2576
2577Provided configuration options:
2578MESSAGE
2579
2580  # Returns whether or not the Makefile was successfully generated. If not,
2581  # the script will abort with an error message.
2582  #
2583  # Internal use only.
2584  #
2585  def mkmf_failed(path)
2586    unless $makefile_created or File.exist?("Makefile")
2587      opts = $arg_config.collect {|t, n| "\t#{t}#{n ? "=#{n}" : ""}\n"}
2588      abort "*** #{path} failed ***\n" + FailedMessage + opts.join
2589    end
2590  end
2591
2592  private
2593
2594  def _libdir_basename
2595    @libdir_basename ||= config_string("libdir") {|name| name[/\A\$\(exec_prefix\)\/(.*)/, 1]} || "lib"
2596  end
2597
2598  def MAIN_DOES_NOTHING(*refs)
2599    src = MAIN_DOES_NOTHING
2600    unless refs.empty?
2601      src = src.sub(/\{/) do
2602        $& +
2603          "\n  if (argc > 1000000) {\n" +
2604          refs.map {|n|"    int (* volatile #{n}p)(void)=(int (*)(void))&#{n};\n"}.join("") +
2605          refs.map {|n|"    printf(\"%d\", (*#{n}p)());\n"}.join("") +
2606          "  }\n"
2607      end
2608    end
2609    src
2610  end
2611
2612  extend self
2613  init_mkmf
2614
2615  $make = with_config("make-prog", ENV["MAKE"] || "make")
2616  make, = Shellwords.shellwords($make)
2617  $nmake = nil
2618  case
2619  when $mswin
2620    $nmake = ?m if /nmake/i =~ make
2621  end
2622  $ignore_error = $nmake ? '' : ' 2> /dev/null || true'
2623
2624  RbConfig::CONFIG["srcdir"] = CONFIG["srcdir"] =
2625    $srcdir = arg_config("--srcdir", File.dirname($0))
2626  $configure_args["--topsrcdir"] ||= $srcdir
2627  if $curdir = arg_config("--curdir")
2628    RbConfig.expand(curdir = $curdir.dup)
2629  else
2630    curdir = $curdir = "."
2631  end
2632  unless File.expand_path(RbConfig::CONFIG["topdir"]) == File.expand_path(curdir)
2633    CONFIG["topdir"] = $curdir
2634    RbConfig::CONFIG["topdir"] = curdir
2635  end
2636  $configure_args["--topdir"] ||= $curdir
2637  $ruby = arg_config("--ruby", File.join(RbConfig::CONFIG["bindir"], CONFIG["ruby_install_name"]))
2638
2639  RbConfig.expand(CONFIG["RUBY_SO_NAME"])
2640
2641  # :startdoc:
2642
2643  split = Shellwords.method(:shellwords).to_proc
2644
2645  EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip}
2646
2647  hdr = ['#include "ruby.h"' "\n"]
2648  config_string('COMMON_MACROS') do |s|
2649    Shellwords.shellwords(s).each do |w|
2650      w, v = w.split(/=/, 2)
2651      hdr << "#ifndef #{w}"
2652      hdr << "#define #{[w, v].compact.join(" ")}"
2653      hdr << "#endif /* #{w} */"
2654    end
2655  end
2656  config_string('COMMON_HEADERS') do |s|
2657    Shellwords.shellwords(s).each {|w| hdr << "#include <#{w}>"}
2658  end
2659
2660  ##
2661  # Common headers for Ruby C extensions
2662
2663  COMMON_HEADERS = hdr.join("\n")
2664
2665  ##
2666  # Common libraries for Ruby C extensions
2667
2668  COMMON_LIBS = config_string('COMMON_LIBS', &split) || []
2669
2670  ##
2671  # make compile rules
2672
2673  COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:]
2674  RULE_SUBST = config_string('RULE_SUBST')
2675
2676  ##
2677  # Command which will compile C files in the generated Makefile
2678
2679  COMPILE_C = config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<'
2680
2681  ##
2682  # Command which will compile C++ files in the generated Makefile
2683
2684  COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<'
2685
2686  ##
2687  # Command which will translate C files to assembler sources in the generated Makefile
2688
2689  ASSEMBLE_C = config_string('ASSEMBLE_C') || COMPILE_C.sub(/(?<=\s)-c(?=\s)/, '-S')
2690
2691  ##
2692  # Command which will translate C++ files to assembler sources in the generated Makefile
2693
2694  ASSEMBLE_CXX = config_string('ASSEMBLE_CXX') || COMPILE_CXX.sub(/(?<=\s)-c(?=\s)/, '-S')
2695
2696  ##
2697  # Command which will compile a program in order to test linking a library
2698
2699  TRY_LINK = config_string('TRY_LINK') ||
2700    "$(CC) #{OUTFLAG}#{CONFTEST}#{$EXEEXT} $(INCFLAGS) $(CPPFLAGS) " \
2701    "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
2702
2703  ##
2704  # Command which will link a shared library
2705
2706  LINK_SO = (config_string('LINK_SO') || "").sub(/^$/) do
2707    if CONFIG["DLEXT"] == $OBJEXT
2708      "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
2709    else
2710      "$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \
2711      "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)"
2712    end
2713  end
2714
2715  ##
2716  # Argument which will add a library path to the linker
2717
2718  LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L%s'
2719  RPATHFLAG = config_string('RPATHFLAG') || ''
2720
2721  ##
2722  # Argument which will add a library to the linker
2723
2724  LIBARG = config_string('LIBARG') || '-l%s'
2725
2726  ##
2727  # A C main function which does no work
2728
2729  MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || "int main(int argc, char **argv)\n{\n  return 0;\n}"
2730  UNIVERSAL_INTS = config_string('UNIVERSAL_INTS') {|s| Shellwords.shellwords(s)} ||
2731    %w[int short long long\ long]
2732
2733  sep = config_string('BUILD_FILE_SEPARATOR') {|s| ":/=#{s}" if s != "/"} || ""
2734
2735  ##
2736  # Makefile rules that will clean the extension build directory
2737
2738  CLEANINGS = "
2739clean-static::
2740clean-rb-default::
2741clean-rb::
2742clean-so::
2743clean: clean-so clean-static clean-rb-default clean-rb
2744\t\t-$(Q)$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep}) .*.time
2745
2746distclean-rb-default::
2747distclean-rb::
2748distclean-so::
2749distclean-static::
2750distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb
2751\t\t-$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) #{CONFTEST}.* mkmf.log
2752\t\t-$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
2753\t\t-$(Q)$(RMDIRS) $(DISTCLEANDIRS#{sep})#{$ignore_error}
2754
2755realclean: distclean
2756"
2757end
2758
2759include MakeMakefile
2760
2761if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
2762  END {mkmf_failed($0)}
2763end
2764