Imported File#ftype spec from rubyspecs.
[rbx.git] / lib / mkmf.rb
blob751ae8a357e0d1c28ad04fd4f428c7d1652452cd
1 # module to create Makefile for extension modules
2 # invoke like: ruby -r mkmf extconf.rb
4 require 'rbconfig'
5 require 'fileutils'
6 require 'shellwords'
8 CONFIG = Config::MAKEFILE_CONFIG
9 ORIG_LIBPATH = ENV['LIB']
11 CXX_EXT = %w[cc cxx cpp]
12 if /mswin|bccwin|mingw|msdosdjgpp|human|os2/ !~ CONFIG['build_os']
13   CXX_EXT.concat(%w[C])
14 end
15 SRC_EXT = %w[c m] << CXX_EXT
16 $static = $config_h = nil
17 $default_static = $static
19 unless defined? $configure_args
20   $configure_args = {}
21   args = CONFIG["configure_args"]
22   if ENV["CONFIGURE_ARGS"]
23     args << " " << ENV["CONFIGURE_ARGS"]
24   end
25   for arg in Shellwords::shellwords(args)
26     arg, val = arg.split('=', 2)
27     next unless arg
28     arg.tr!('_', '-')
29     if arg.sub!(/^(?!--)/, '--')
30       val or next
31       arg.downcase!
32     end
33     next if /^--(?:top|topsrc|src|cur)dir$/ =~ arg
34     $configure_args[arg] = val || true
35   end
36   for arg in ARGV
37     arg, val = arg.split('=', 2)
38     next unless arg
39     arg.tr!('_', '-')
40     if arg.sub!(/^(?!--)/, '--')
41       val or next
42       arg.downcase!
43     end
44     $configure_args[arg] = val || true
45   end
46 end
48 $libdir = CONFIG["libdir"]
49 $rubylibdir = CONFIG["rubylibdir"]
50 $archdir = CONFIG["archdir"]
51 $sitedir = CONFIG["sitedir"]
52 $sitelibdir = CONFIG["sitelibdir"]
53 $sitearchdir = CONFIG["sitearchdir"]
55 $mswin = /mswin/ =~ RUBY_PLATFORM
56 $bccwin = /bccwin/ =~ RUBY_PLATFORM
57 $mingw = /mingw/ =~ RUBY_PLATFORM
58 $cygwin = /cygwin/ =~ RUBY_PLATFORM
59 $human = /human/ =~ RUBY_PLATFORM
60 $netbsd = /netbsd/ =~ RUBY_PLATFORM
61 $os2 = /os2/ =~ RUBY_PLATFORM
62 $beos = /beos/ =~ RUBY_PLATFORM
63 $solaris = /solaris/ =~ RUBY_PLATFORM
64 $dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
66 def config_string(key, config = CONFIG)
67   s = config[key] and !s.empty? and block_given? ? yield(s) : s
68 end
70 def dir_re(dir)
71   Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$(?:\(target_prefix\)|\{target_prefix\}))?')
72 end
74 INSTALL_DIRS = [
75   [dir_re('commondir'), "$(RUBYCOMMONDIR)"],
76   [dir_re("sitedir"), "$(RUBYCOMMONDIR)"],
77   [dir_re('rubylibdir'), "$(RUBYLIBDIR)"],
78   [dir_re('archdir'), "$(RUBYARCHDIR)"],
79   [dir_re('sitelibdir'), "$(RUBYLIBDIR)"],
80   [dir_re('sitearchdir'), "$(RUBYARCHDIR)"]
83 def install_dirs(target_prefix = nil)
84   if $extout
85     dirs = [
86       ['RUBYCOMMONDIR', '$(extout)/common'],
87       ['RUBYLIBDIR',    '$(RUBYCOMMONDIR)$(target_prefix)'],
88       ['RUBYARCHDIR',   '$(extout)/$(arch)$(target_prefix)'],
89       ['extout',        "#$extout"],
90       ['extout_prefix', "#$extout_prefix"],
91     ]
92   elsif $extmk
93     dirs = [
94       ['RUBYCOMMONDIR', '$(rubylibdir)'],
95       ['RUBYLIBDIR',    '$(rubylibdir)$(target_prefix)'],
96       ['RUBYARCHDIR',   '$(archdir)$(target_prefix)'],
97     ]
98   else
99     dirs = [
100       ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'],
101       ['RUBYLIBDIR',    '$(sitelibdir)$(target_prefix)'],
102       ['RUBYARCHDIR',   '$(sitearchdir)$(target_prefix)'],
103     ]
104   end
105   dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")]
106   dirs
109 def map_dir(dir, map = nil)
110   map ||= INSTALL_DIRS
111   map.inject(dir) {|dir, (orig, new)| dir.gsub(orig, new)}
114 $topdir = topdir = File.dirname(libdir = File.dirname(__FILE__))
115 extdir = File.expand_path("ext", topdir)
116 $extmk = File.expand_path($0)[0, extdir.size+1] == extdir+"/"
117 if not $extmk and File.exist?(Config::CONFIG["archdir"] + "/ruby.h")
118   $hdrdir = $topdir = Config::CONFIG["archdir"]
119 elsif File.exist?(($top_srcdir ||= topdir)  + "/ruby.h") and
120     File.exist?(($topdir ||= Config::CONFIG["topdir"]) + "/config.h")
121   $hdrdir = $top_srcdir
122 elsif File.exist?((hdrdir = Config::CONFIG["rubyhdrdir"]) + "/ruby.h")
123   $topdir = $hdrdir = hdrdir
124 else
125   abort "can't find header files for ruby."
128 OUTFLAG = CONFIG['OUTFLAG']
129 CPPOUTFILE = CONFIG['CPPOUTFILE']
131 CONFTEST_C = "conftest.c"
133 class String
134   def quote
135     /\s/ =~ self ? "\"#{self}\"" : self
136   end
138 class Array
139   def quote
140     map {|s| s.quote}
141   end
144 def rm_f(*files)
145   FileUtils.rm_f(Dir[files.join("\0")])
148 def modified?(target, times)
149   (t = File.mtime(target)) rescue return nil
150   Array === times or times = [times]
151   t if times.all? {|n| n <= t}
154 def merge_libs(*libs)
155   libs.inject([]) do |x, y|
156     xy = x & y
157     xn = yn = 0
158     y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e}
159     y.each_with_index do |v, yi|
160       if xy.include?(v)
161         xi = [x.index(v), xn].max()
162         x[xi, 1] = y[yn..yi]
163         xn, yn = xi + (yi - yn + 1), yi + 1
164       end
165     end
166     x.concat(y[yn..-1] || [])
167   end
170 module Logging
171   @log = nil
172   @logfile = 'mkmf.log'
173   @orgerr = $stderr.dup
174   @orgout = $stdout.dup
175   @postpone = 0
177   def self::open
178     @log ||= File::open(@logfile, 'w')
179     @log.sync = true
180     $stderr.reopen(@log)
181     $stdout.reopen(@log)
182     yield
183   ensure
184     $stderr.reopen(@orgerr)
185     $stdout.reopen(@orgout)
186   end
188   def self::message(*s)
189     @log ||= File::open(@logfile, 'w')
190     @log.sync = true
191     @log.printf(*s)
192   end
194   def self::logfile file
195     @logfile = file
196     if @log and not @log.closed?
197       @log.flush
198       @log.close
199       @log = nil
200     end
201   end
202   
203   def self::postpone
204     tmplog = "mkmftmp#{@postpone += 1}.log"
205     open do
206       log, *save = @log, @logfile, @orgout, @orgerr
207       @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
208       begin
209         log.print(open {yield})
210         @log.close
211         File::open(tmplog) {|t| FileUtils.copy_stream(t, log)}
212       ensure
213         @log, @logfile, @orgout, @orgerr = log, *save
214         @postpone -= 1
215         rm_f tmplog
216       end
217     end
218   end
221 def xsystem command
222   Logging::open do
223     puts command.quote
224     system(command)
225   end
228 def xpopen command, *mode, &block
229   Logging::open do
230     case mode[0]
231     when nil, /^r/
232       puts "#{command} |"
233     else
234       puts "| #{command}"
235     end
236     IO.popen(command, *mode, &block)
237   end
240 def log_src(src)
241   src = src.split(/^/)
242   fmt = "%#{src.size.to_s.size}d: %s"
243   Logging::message <<"EOM"
244 checked program was:
245 /* begin */
247   src.each_with_index {|line, no| Logging::message fmt, no+1, line}
248   Logging::message <<"EOM"
249 /* end */
254 def create_tmpsrc(src)
255   src = yield(src) if block_given?
256   src = src.gsub(/[ \t]+$/, '').gsub(/\A\n+|^\n+$/, '').sub(/[^\n]\z/, "\\&\n")
257   open(CONFTEST_C, "wb") do |cfile|
258     cfile.print src
259   end
260   src
263 def try_do(src, command, &b)
264   src = create_tmpsrc(src, &b)
265   xsystem(command)
266 ensure
267   log_src(src)
270 def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
271   conf = Config::CONFIG.merge('hdrdir' => $hdrdir.quote,
272                               'src' => CONFTEST_C,
273                               'INCFLAGS' => $INCFLAGS,
274                               'CPPFLAGS' => $CPPFLAGS,
275                               'CFLAGS' => "#$CFLAGS",
276                               'ARCH_FLAG' => "#$ARCH_FLAG",
277                               'LDFLAGS' => "#$LDFLAGS #{ldflags}",
278                               'LIBPATH' => libpathflag(libpath),
279                               'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs",
280                               'LIBS' => "#$LIBRUBYARG_STATIC #{opt} #$LIBS")
281   Config::expand(TRY_LINK.dup, conf)
284 def cc_command(opt="")
285   conf = Config::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote)
286   Config::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}",
287                  conf)
290 def cpp_command(outfile, opt="")
291   conf = Config::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote)
292   Config::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
293                  conf)
296 def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
297   libpath.map{|x|
298     case x
299     when "$(topdir)", /\A\./
300       LIBPATHFLAG
301     else
302       LIBPATHFLAG+RPATHFLAG
303     end % x.quote
304   }.join
307 def try_link0(src, opt="", &b)
308   try_do(src, link_command("", opt), &b)
311 def try_link(src, opt="", &b)
312   try_link0(src, opt, &b)
313 ensure
314   rm_f "conftest*", "c0x32*"
317 def try_compile(src, opt="", &b)
318   try_do(src, cc_command(opt), &b)
319 ensure
320   rm_f "conftest*"
323 def try_cpp(src, opt="", &b)
324   try_do(src, cpp_command(CPPOUTFILE, opt), &b)
325 ensure
326   rm_f "conftest*"
329 def cpp_include(header)
330   if header
331     header = [header] unless header.kind_of? Array
332     header.map {|h| "#include <#{h}>\n"}.join
333   else
334     ""
335   end
338 def with_cppflags(flags)
339   cppflags = $CPPFLAGS
340   $CPPFLAGS = flags
341   ret = yield
342 ensure
343   $CPPFLAGS = cppflags unless ret
346 def with_cflags(flags)
347   cflags = $CFLAGS
348   $CFLAGS = flags
349   ret = yield
350 ensure
351   $CFLAGS = cflags unless ret
354 def with_ldflags(flags)
355   ldflags = $LDFLAGS
356   $LDFLAGS = flags
357   ret = yield
358 ensure
359   $LDFLAGS = ldflags unless ret
362 def try_static_assert(expr, headers = nil, opt = "", &b)
363   headers = cpp_include(headers)
364   try_compile(<<SRC, opt, &b)
365 #{COMMON_HEADERS}
366 #{headers}
367 /*top*/
368 int conftest_const[(#{expr}) ? 1 : -1];
372 def try_constant(const, headers = nil, opt = "", &b)
373   includes = cpp_include(headers)
374   if CROSS_COMPILING
375     if try_static_assert("#{const} > 0", headers, opt)
376       # positive constant
377     elsif try_static_assert("#{const} < 0", headers, opt)
378       neg = true
379       const = "-(#{const})"
380     elsif try_static_assert("#{const} == 0", headers, opt)
381       return 0
382     else
383       # not a constant
384       return nil
385     end
386     upper = 1
387     lower = 0
388     until try_static_assert("#{const} <= #{upper}", headers, opt)
389       lower = upper
390       upper <<= 1
391     end
392     return nil unless lower
393     while upper > lower + 1
394       mid = (upper + lower) / 2
395       if try_static_assert("#{const} > #{mid}", headers, opt)
396         lower = mid
397       else
398         upper = mid
399       end
400     end
401     upper = -upper if neg
402     return upper
403   else
404     src = %{#{COMMON_HEADERS}
405 #{includes}
406 #include <stdio.h>
407 /*top*/
408 int conftest_const = (int)(#{const});
409 int main() {printf("%d\\n", conftest_const); return 0;}
411     if try_link0(src, opt, &b)
412       xpopen("./conftest") do |f|
413         return Integer(f.gets)
414       end
415     end
416   end
417   nil
420 def try_func(func, libs, headers = nil, &b)
421   headers = cpp_include(headers)
422   try_link(<<"SRC", libs, &b) or try_link(<<"SRC", libs, &b)
423 #{COMMON_HEADERS}
424 #{headers}
425 /*top*/
426 int main() { return 0; }
427 int t() { void ((*volatile p)()); p = (void ((*)()))#{func}; return 0; }
429 #{headers}
430 /*top*/
431 int main() { return 0; }
432 int t() { #{func}(); return 0; }
436 def try_var(var, headers = nil, &b)
437   headers = cpp_include(headers)
438   try_compile(<<"SRC", &b)
439 #{COMMON_HEADERS}
440 #{headers}
441 /*top*/
442 int main() { return 0; }
443 int t() { const volatile void *volatile p; p = (void *)&#{var}; return 0; }
447 def egrep_cpp(pat, src, opt = "", &b)
448   src = create_tmpsrc(src, &b)
449   xpopen(cpp_command('', opt)) do |f|
450     if Regexp === pat
451       puts("    ruby -ne 'print if #{pat.inspect}'")
452       f.grep(pat) {|l|
453         puts "#{f.lineno}: #{l}"
454         return true
455       }
456       false
457     else
458       puts("    egrep '#{pat}'")
459       begin
460         stdin = $stdin.dup
461         $stdin.reopen(f)
462         system("egrep", pat)
463       ensure
464         $stdin.reopen(stdin)
465       end
466     end
467   end
468 ensure
469   rm_f "conftest*"
470   log_src(src)
473 def macro_defined?(macro, src, opt = "", &b)
474   src = src.sub(/[^\n]\z/, "\\&\n")
475   try_compile(src + <<"SRC", opt, &b)
476 /*top*/
477 #ifndef #{macro}
478 # error
479 >>>>>> #{macro} undefined <<<<<<
480 #endif
484 def try_run(src, opt = "", &b)
485   if try_link0(src, opt, &b)
486     xsystem("./conftest")
487   else
488     nil
489   end
490 ensure
491   rm_f "conftest*"
494 def install_files(mfile, ifiles, map = nil, srcprefix = nil)
495   ifiles or return
496   srcprefix ||= '$(srcdir)'
497   Config::expand(srcdir = srcprefix.dup)
498   dirs = []
499   path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]}
500   ifiles.each do |files, dir, prefix|
501     dir = map_dir(dir, map)
502     prefix = %r|\A#{Regexp.quote(prefix)}/?| if prefix
503     if /\A\.\// =~ files
504       # install files which are in current working directory.
505       files = files[2..-1]
506       len = nil
507     else
508       # install files which are under the $(srcdir).
509       files = File.join(srcdir, files)
510       len = srcdir.size
511     end
512     f = nil
513     Dir.glob(files) do |f|
514       f[0..len] = "" if len
515       d = File.dirname(f)
516       d.sub!(prefix, "") if prefix
517       d = (d.empty? || d == ".") ? dir : File.join(dir, d)
518       f = File.join(srcprefix, f) if len
519       path[d] << f
520     end
521     unless len or f
522       d = File.dirname(files)
523       d.sub!(prefix, "") if prefix
524       d = (d.empty? || d == ".") ? dir : File.join(dir, d)
525       path[d] << files
526     end
527   end
528   dirs
531 def install_rb(mfile, dest, srcdir = nil)
532   install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir)
535 def append_library(libs, lib)
536   format(LIBARG, lib) + " " + libs
539 def message(*s)
540   unless $extmk and not $VERBOSE
541     printf(*s)
542     $stdout.flush
543   end
546 def checking_for(m, fmt = nil)
547   f = caller[0][/in `(.*)'$/, 1] and f << ": " #` for vim
548   m = "checking #{/\Acheck/ =~ f ? '' : 'for '}#{m}... "
549   message "%s", m
550   a = r = nil
551   Logging::postpone do
552     r = yield
553     a = (fmt ? fmt % r : r ? "yes" : "no") << "\n"
554     "#{f}#{m}-------------------- #{a}\n"
555   end
556   message(a)
557   Logging::message "--------------------\n\n"
558   r
561 def checking_message(target, place = nil, opt = nil)
562   [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)|
563     if noun
564       [[:to_str], [:join, ","], [:to_s]].each do |meth, *args|
565         if noun.respond_to?(meth)
566           break noun = noun.send(meth, *args)
567         end
568       end
569       msg << " #{pre} #{noun}" unless noun.empty?
570     end
571     msg
572   end
575 # Returns whether or not +macro+ is defined either in the common header
576 # files or within any +headers+ you provide.
578 # Any options you pass to +opt+ are passed along to the compiler.
580 def have_macro(macro, headers = nil, opt = "", &b)
581   checking_for checking_message(macro, headers, opt) do
582     macro_defined?(macro, cpp_include(headers), opt, &b)
583   end
586 # Returns whether or not the given entry point +func+ can be found within
587 # +lib+.  If +func+ is nil, the 'main()' entry point is used by default.
588 # If found, it adds the library to list of libraries to be used when linking
589 # your extension.
591 # If +headers+ are provided, it will include those header files as the
592 # header files it looks in when searching for +func+.
594 # Real name of the library to be linked can be altered by
595 # '--with-FOOlib' configuration option.
597 def have_library(lib, func = nil, headers = nil, &b)
598   func = "main" if !func or func.empty?
599   lib = with_config(lib+'lib', lib)
600   checking_for checking_message("#{func}()", LIBARG%lib) do
601     if COMMON_LIBS.include?(lib)
602       true
603     else
604       libs = append_library($libs, lib)
605       if try_func(func, libs, headers, &b)
606         $libs = libs
607         true
608       else
609         false
610       end
611     end
612   end
615 # Returns whether or not the entry point +func+ can be found within the library
616 # +lib+ in one of the +paths+ specified, where +paths+ is an array of strings.
617 # If +func+ is nil , then the main() function is used as the entry point.
619 # If +lib+ is found, then the path it was found on is added to the list of
620 # library paths searched and linked against.
622 def find_library(lib, func, *paths, &b)
623   func = "main" if !func or func.empty?
624   lib = with_config(lib+'lib', lib)
625   paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
626   checking_for "#{func}() in #{LIBARG%lib}" do
627     libpath = $LIBPATH
628     libs = append_library($libs, lib)
629     begin
630       until r = try_func(func, libs, &b) or paths.empty?
631         $LIBPATH = libpath | [paths.shift]
632       end
633       if r
634         $libs = libs
635         libpath = nil
636       end
637     ensure
638       $LIBPATH = libpath if libpath
639     end
640     r
641   end
644 # Returns whether or not the function +func+ can be found in the common
645 # header files, or within any +headers+ that you provide.  If found, a
646 # macro is passed as a preprocessor constant to the compiler using the
647 # function name, in uppercase, prepended with 'HAVE_'.
649 # For example, if have_func('foo') returned true, then the HAVE_FOO
650 # preprocessor macro would be passed to the compiler.
652 def have_func(func, headers = nil, &b)
653   checking_for checking_message("#{func}()", headers) do
654     if try_func(func, $libs, headers, &b)
655       $defs.push(format("-DHAVE_%s", func.upcase))
656       true
657     else
658       false
659     end
660   end
663 # Returns whether or not the variable +var+ can be found in the common
664 # header files, or within any +headers+ that you provide.  If found, a
665 # macro is passed as a preprocessor constant to the compiler using the
666 # variable name, in uppercase, prepended with 'HAVE_'.
668 # For example, if have_var('foo') returned true, then the HAVE_FOO
669 # preprocessor macro would be passed to the compiler.
671 def have_var(var, headers = nil, &b)
672   checking_for checking_message(var, headers) do
673     if try_var(var, headers, &b)
674       $defs.push(format("-DHAVE_%s", var.upcase))
675       true
676     else
677       false
678     end
679   end
682 # Returns whether or not the given +header+ file can be found on your system.
683 # If found, a macro is passed as a preprocessor constant to the compiler using
684 # the header file name, in uppercase, prepended with 'HAVE_'.
686 # For example, if have_header('foo.h') returned true, then the HAVE_FOO_H
687 # preprocessor macro would be passed to the compiler.
689 def have_header(header, &b)
690   checking_for header do
691     if try_cpp(cpp_include(header), &b)
692       $defs.push(format("-DHAVE_%s", header.tr("a-z./\055", "A-Z___")))
693       true
694     else
695       false
696     end
697   end
700 # Instructs mkmf to search for the given +header+ in any of the +paths+
701 # provided, and returns whether or not it was found in those paths.
703 # If the header is found then the path it was found on is added to the list
704 # of included directories that are sent to the compiler (via the -I switch).
706 def find_header(header, *paths)
707   header = cpp_include(header)
708   checking_for header do
709     if try_cpp(header)
710       true
711     else
712       found = false
713       paths.each do |dir|
714         opt = "-I#{dir}".quote
715         if try_cpp(header, opt)
716           $INCFLAGS << " " << opt
717           found = true
718           break
719         end
720       end
721       found
722     end
723   end
726 # Returns whether or not the struct of type +type+ contains +member+.  If
727 # it does not, or the struct type can't be found, then false is returned.  You
728 # may optionally specify additional +headers+ in which to look for the struct
729 # (in addition to the common header files).
731 # If found, a macro is passed as a preprocessor constant to the compiler using
732 # the member name, in uppercase, prepended with 'HAVE_ST_'.
734 # For example, if have_struct_member('foo', 'bar') returned true, then the
735 # HAVE_ST_BAR preprocessor macro would be passed to the compiler.
737 def have_struct_member(type, member, headers = nil, &b)
738   checking_for checking_message("#{type}.#{member}", headers) do
739     if try_compile(<<"SRC", &b)
740 #{COMMON_HEADERS}
741 #{cpp_include(headers)}
742 /*top*/
743 int main() { return 0; }
744 int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
746       $defs.push(format("-DHAVE_ST_%s", member.upcase))
747       true
748     else
749       false
750     end
751   end
754 # Returns whether or not the static type +type+ is defined.  You may
755 # optionally pass additional +headers+ to check against in addition to the
756 # common header files.
758 # You may also pass additional flags to +opt+ which are then passed along to
759 # the compiler.
761 # If found, a macro is passed as a preprocessor constant to the compiler using
762 # the type name, in uppercase, prepended with 'HAVE_TYPE_'.
764 # For example, if have_type('foo') returned true, then the HAVE_TYPE_FOO
765 # preprocessor macro would be passed to the compiler.
767 def have_type(type, headers = nil, opt = "", &b)
768   checking_for checking_message(type, headers, opt) do
769     headers = cpp_include(headers)
770     if try_compile(<<"SRC", opt, &b)
771 #{COMMON_HEADERS}
772 #{headers}
773 /*top*/
774 typedef #{type} conftest_type;
775 static conftest_type conftestval[sizeof(conftest_type)?1:-1];
777       $defs.push(format("-DHAVE_TYPE_%s", type.strip.upcase.tr_s("^A-Z0-9_", "_")))
778       true
779     else
780       false
781     end
782   end
785 # Returns the size of the given +type+.  You may optionally specify additional
786 # +headers+ to search in for the +type+.
788 # If found, a macro is passed as a preprocessor constant to the compiler using
789 # the type name, in uppercase, prepended with 'SIZEOF_', followed by the type
790 # name, followed by '=X' where 'X' is the actual size.
792 # For example, if check_sizeof('mystruct') returned 12, then the
793 # SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to the compiler.
795 def check_sizeof(type, headers = nil, &b)
796   expr = "sizeof(#{type})"
797   fmt = "%d"
798   def fmt.%(x)
799     x ? super : "failed"
800   end
801   checking_for checking_message("size of #{type}", headers), fmt do
802     if size = try_constant(expr, headers, &b)
803       $defs.push(format("-DSIZEOF_%s=%d", type.upcase.tr_s("^A-Z0-9_", "_"), size))
804       size
805     end
806   end
809 def scalar_ptr_type?(type, member = nil, headers = nil, &b)
810   try_compile(<<"SRC", &b)   # pointer
811 #{COMMON_HEADERS}
812 #{cpp_include(headers)}
813 /*top*/
814 volatile #{type} conftestval;
815 int main() { return 0; }
816 int t() {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
820 def scalar_type?(type, member = nil, headers = nil, &b)
821   try_compile(<<"SRC", &b)   # pointer
822 #{COMMON_HEADERS}
823 #{cpp_include(headers)}
824 /*top*/
825 volatile #{type} conftestval;
826 int main() { return 0; }
827 int t() {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
831 def what_type?(type, member = nil, headers = nil, &b)
832   m = "#{type}"
833   name = type
834   if member
835     m << "." << member
836     name = "(((#{type} *)0)->#{member})"
837   end
838   fmt = "seems %s"
839   def fmt.%(x)
840     x ? super : "unknown"
841   end
842   checking_for checking_message(m, headers), fmt do
843     if scalar_ptr_type?(type, member, headers, &b)
844       if try_static_assert("sizeof(*#{name}) == 1", headers)
845         "string"
846       end
847     elsif scalar_type?(type, member, headers, &b)
848       if try_static_assert("sizeof(#{name}) > sizeof(long)", headers)
849         "long long"
850       elsif try_static_assert("sizeof(#{name}) > sizeof(int)", headers)
851         "long"
852       elsif try_static_assert("sizeof(#{name}) > sizeof(short)", headers)
853         "int"
854       elsif try_static_assert("sizeof(#{name}) > 1", headers)
855         "short"
856       else
857         "char"
858       end
859     end
860   end
863 def find_executable0(bin, path = nil)
864   ext = config_string('EXEEXT')
865   if File.expand_path(bin) == bin
866     return bin if File.executable?(bin)
867     ext and File.executable?(file = bin + ext) and return file
868     return nil
869   end
870   if path ||= ENV['PATH']
871     path = path.split(File::PATH_SEPARATOR)
872   else
873     path = %w[/usr/local/bin /usr/ucb /usr/bin /bin]
874   end
875   file = nil
876   path.each do |dir|
877     return file if File.executable?(file = File.join(dir, bin))
878     return file if ext and File.executable?(file << ext)
879   end
880   nil
883 def find_executable(bin, path = nil)
884   checking_for checking_message(bin, path) do
885     find_executable0(bin, path)
886   end
889 def arg_config(config, *defaults, &block)
890   $arg_config << [config, *defaults]
891   defaults << nil if !block and defaults.empty?
892   $configure_args.fetch(config.tr('_', '-'), *defaults, &block)
895 def with_config(config, *defaults)
896   config = config.sub(/^--with[-_]/, '')
897   val = arg_config("--with-"+config) do
898     if arg_config("--without-"+config)
899       false
900     elsif block_given?
901       yield(config, *defaults)
902     else
903       break *defaults
904     end
905   end
906   case val
907   when "yes"
908     true
909   when "no"
910     false
911   else
912     val
913   end
916 def enable_config(config, *defaults)
917   if arg_config("--enable-"+config)
918     true
919   elsif arg_config("--disable-"+config)
920     false
921   elsif block_given?
922     yield(config, *defaults)
923   else
924     return *defaults
925   end
928 def create_header(header = "extconf.h")
929   message "creating %s\n", header
930   sym = header.tr("a-z./\055", "A-Z___")
931   hdr = ["#ifndef #{sym}\n#define #{sym}\n"]
932   for line in $defs
933     case line
934     when /^-D([^=]+)(?:=(.*))?/
935       hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0] : 1}\n"
936     when /^-U(.*)/
937       hdr << "#undef #$1\n"
938     end
939   end
940   hdr << "#endif\n"
941   hdr = hdr.join
942   unless (IO.read(header) == hdr rescue false)
943     open(header, "w") do |hfile|
944       hfile.write(hdr)
945     end
946   end
947   $extconf_h = header
950 # Sets a +target+ name that the user can then use to configure various 'with'
951 # options with on the command line by using that name.  For example, if the
952 # target is set to "foo", then the user could use the --with-foo-dir command
953 # line option.
955 # You may pass along additional 'include' or 'lib' defaults via the +idefault+
956 # and +ldefault+ parameters, respectively.
958 # Note that dir_config only adds to the list of places to search for libraries
959 # and include files.  It does not link the libraries into your application.
961 def dir_config(target, idefault=nil, ldefault=nil)
962   if dir = with_config(target + "-dir", (idefault unless ldefault))
963     defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR)
964     idefault = ldefault = nil
965   end
967   idir = with_config(target + "-include", idefault)
968   $arg_config.last[1] ||= "${#{target}-dir}/include"
969   ldir = with_config(target + "-lib", ldefault)
970   $arg_config.last[1] ||= "${#{target}-dir}/lib"
972   idirs = idir ? Array === idir ? idir : idir.split(File::PATH_SEPARATOR) : []
973   if defaults
974     idirs.concat(defaults.collect {|dir| dir + "/include"})
975     idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR)
976   end
977   unless idirs.empty?
978     idirs.collect! {|dir| "-I" + dir}
979     idirs -= Shellwords.shellwords($CPPFLAGS)
980     unless idirs.empty?
981       $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ")
982     end
983   end
985   ldirs = ldir ? Array === ldir ? ldir : ldir.split(File::PATH_SEPARATOR) : []
986   if defaults
987     ldirs.concat(defaults.collect {|dir| dir + "/lib"})
988     ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR)
989   end
990   $LIBPATH = ldirs | $LIBPATH
992   [idir, ldir]
995 def pkg_config(pkg)
996   if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
997     # iff package specific config command is given
998     get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
999   elsif ($PKGCONFIG ||= 
1000          (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
1001          find_executable0(pkgconfig) && pkgconfig) and
1002       system("#{$PKGCONFIG} --exists #{pkg}")
1003     # default to pkg-config command
1004     get = proc {|opt| `#{$PKGCONFIG} --#{opt} #{pkg}`.chomp}
1005   elsif find_executable0(pkgconfig = "#{pkg}-config")
1006     # default to package specific config command, as a last resort.
1007     get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
1008   end
1009   if get
1010     cflags = get['cflags']
1011     ldflags = get['libs']
1012     libs = get['libs-only-l']
1013     ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ")
1014     $CFLAGS += " " << cflags
1015     $LDFLAGS += " " << ldflags
1016     $libs += " " << libs
1017     Logging::message "package configuration for %s\n", pkg
1018     Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n",
1019                      cflags, ldflags, libs
1020     [cflags, ldflags, libs]
1021   else
1022     Logging::message "package configuration for %s is not found\n", pkg
1023     nil
1024   end
1027 def with_destdir(dir)
1028   dir = dir.sub($dest_prefix_pattern, '')
1029   /\A\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir
1032 def winsep(s)
1033   s.tr('/', '\\')
1036 def configuration(srcdir)
1037   mk = []
1038   vpath = %w[$(srcdir) $(topdir) $(hdrdir)]
1039   if !CROSS_COMPILING
1040     case CONFIG['build_os']
1041     when 'cygwin'
1042       if CONFIG['target_os'] != 'cygwin'
1043         vpath.each {|p| p.sub!(/.*/, '$(shell cygpath -u \&)')}
1044       end
1045     when 'msdosdjgpp', 'mingw32'
1046       CONFIG['PATH_SEPARATOR'] = ';'
1047     end
1048   end
1049   mk << %{
1050 SHELL = /bin/sh
1052 #### Start of system configuration section. ####
1054 host = #{CONFIG["host"].quote}
1055 srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {CONFIG[$1||$2]}.quote}
1056 topdir = #{($extmk ? CONFIG["topdir"] : $topdir).quote}
1057 hdrdir = #{$extmk ? CONFIG["hdrdir"].quote : '$(topdir)'}
1058 VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
1060   if $extmk
1061     mk << "RUBYLIB = -\nRUBYOPT = -rpurelib.rb\n"
1062   end
1063   if destdir = CONFIG["prefix"][$dest_prefix_pattern, 1]
1064     mk << "\nDESTDIR = #{destdir}\n"
1065   end
1066   CONFIG.each do |key, var|
1067     next unless /prefix$/ =~ key
1068     mk << "#{key} = #{with_destdir(var)}\n"
1069   end
1070   CONFIG.each do |key, var|
1071     next if /^abs_/ =~ key
1072     next unless /^(?:src|top|hdr|(.*))dir$/ =~ key and $1
1073     mk << "#{key} = #{with_destdir(var)}\n"
1074   end
1075   if !$extmk and !$configure_args.has_key?('--ruby') and
1076       sep = config_string('BUILD_FILE_SEPARATOR')
1077     sep = ":/=#{sep}"
1078   else
1079     sep = ""
1080   end
1081   extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ")<<" "
1082   mk << %{
1083 CC = #{CONFIG['CC']}
1084 LIBRUBY = #{CONFIG['LIBRUBY']}
1085 LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
1086 LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
1087 LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC
1089 RUBY_EXTCONF_H = #{$extconf_h}
1090 CFLAGS   = #{$static ? '' : CONFIG['CCDLFLAGS']} #$CFLAGS #$ARCH_FLAG
1091 INCFLAGS = -I. -I$(rubyhdrdir) #$INCFLAGS
1092 CPPFLAGS = #{extconf_h}#{$CPPFLAGS}
1093 CXXFLAGS = $(CFLAGS) #{CONFIG['CXXFLAGS']}
1094 DLDFLAGS = #$LDFLAGS #$DLDFLAGS #$ARCH_FLAG
1095 LDSHARED = #{CONFIG['LDSHARED']}
1096 AR = #{CONFIG['AR']}
1097 EXEEXT = #{CONFIG['EXEEXT']}
1099 RUBY_INSTALL_NAME = #{CONFIG['RUBY_INSTALL_NAME']}
1100 RUBY_SO_NAME = #{CONFIG['RUBY_SO_NAME']}
1101 arch = #{CONFIG['arch']}
1102 sitearch = #{CONFIG['sitearch']}
1103 ruby_version = #{Config::CONFIG['ruby_version']}
1104 ruby = #{$ruby}
1105 RUBY = $(ruby#{sep})
1106 RM = #{config_string('RM') || '$(RUBY) -run -e rm -- -f'}
1107 MAKEDIRS = #{config_string('MAKEDIRS') || '@$(RUBY) -run -e mkdir -- -p'}
1108 INSTALL = #{config_string('INSTALL') || '@$(RUBY) -run -e install -- -vp'}
1109 INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'}
1110 INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'}
1111 COPY = #{config_string('CP') || '@$(RUBY) -run -e cp -- -v'}
1113 #### End of system configuration section. ####
1115 preload = #{$preload ? $preload.join(' ') : ''}
1117   if $nmake == ?b
1118     mk.each do |x|
1119       x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do
1120         "!ifndef " + $1 + "\n" +
1121         $& +
1122         "!endif\n"
1123       end
1124     end
1125   end
1126   mk
1129 def dummy_makefile(srcdir)
1130   configuration(srcdir) << <<RULES << CLEANINGS
1131 CLEANFILES = #{$cleanfiles.join(' ')}
1132 DISTCLEANFILES = #{$distcleanfiles.join(' ')}
1134 all install static install-so install-rb: Makefile
1136 RULES
1139 # Generates the Makefile for your extension, passing along any options and
1140 # preprocessor constants that you may have generated through other methods.
1142 # The +target+ name should correspond the name of the global function name
1143 # defined within your C extension, minus the 'Init_'.  For example, if your
1144 # C extension is defined as 'Init_foo', then your target would simply be 'foo'.
1146 # If any '/' characters are present in the target name, only the last name
1147 # is interpreted as the target name, and the rest are considered toplevel
1148 # directory names, and the generated Makefile will be altered accordingly to
1149 # follow that directory structure.
1151 # For example, if you pass 'test/foo' as a target name, your extension will
1152 # be installed under the 'test' directory.  This means that in order to
1153 # load the file within a Ruby program later, that directory structure will
1154 # have to be followed, e.g. "require 'test/foo'".
1156 def create_makefile(target, srcprefix = nil)
1157   $target = target
1158   libpath = $DEFLIBPATH|$LIBPATH
1159   message "creating Makefile\n"
1160   rm_f "conftest*"
1161   if CONFIG["DLEXT"] == $OBJEXT
1162     for lib in libs = $libs.split
1163       lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
1164     end
1165     $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
1166   end
1168   if target.include?('/')
1169     target_prefix, target = File.split(target)
1170     target_prefix[0,0] = '/'
1171   else
1172     target_prefix = ""
1173   end
1175   srcprefix ||= '$(srcdir)'
1176   Config::expand(srcdir = srcprefix.dup)
1178   if not $objs
1179     $objs = []
1180     srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
1181     for f in srcs
1182       obj = File.basename(f, ".*") << ".o"
1183       $objs.push(obj) unless $objs.index(obj)
1184     end
1185   elsif !(srcs = $srcs)
1186     srcs = $objs.collect {|obj| obj.sub(/\.o\z/, '.c')}
1187   end
1188   $srcs = srcs
1189   for i in $objs
1190     i.sub!(/\.o\z/, ".#{$OBJEXT}")
1191   end
1192   $objs = $objs.join(" ")
1194   target = nil if $objs == ""
1196   if target and EXPORT_PREFIX
1197     if File.exist?(File.join(srcdir, target + '.def'))
1198       deffile = "$(srcdir)/$(TARGET).def"
1199       unless EXPORT_PREFIX.empty?
1200         makedef = %{-pe "sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i"}
1201       end
1202     else
1203       makedef = %{-e "puts 'EXPORTS', '#{EXPORT_PREFIX}Init_$(TARGET)'"}
1204     end
1205     if makedef
1206       $distcleanfiles << '$(DEFFILE)'
1207       origdef = deffile
1208       deffile = "$(TARGET)-$(arch).def"
1209     end
1210   end
1211   origdef ||= ''
1213   libpath = libpathflag(libpath)
1215   dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
1216   staticlib = target ? "$(TARGET).#$LIBEXT" : ""
1217   mfile = open("Makefile", "wb")
1218   mfile.print configuration(srcprefix)
1219   mfile.print "
1220 libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")}
1221 LIBPATH = #{libpath}
1222 DEFFILE = #{deffile}
1224 CLEANFILES = #{$cleanfiles.join(' ')}
1225 DISTCLEANFILES = #{$distcleanfiles.join(' ')}
1227 extout = #{$extout}
1228 extout_prefix = #{$extout_prefix}
1229 target_prefix = #{target_prefix}
1230 LOCAL_LIBS = #{$LOCAL_LIBS}
1231 LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
1232 SRCS = #{srcs.collect(&File.method(:basename)).join(' ')}
1233 OBJS = #{$objs}
1234 TARGET = #{target}
1235 DLLIB = #{dllib}
1236 EXTSTATIC = #{$static || ""}
1237 STATIC_LIB = #{staticlib unless $static.nil?}
1238 #{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
1240   install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
1241   n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET).'
1242   mfile.print "
1243 TARGET_SO     = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
1244 CLEANLIBS     = #{n}#{CONFIG['DLEXT']} #{n}il? #{n}tds #{n}map
1245 CLEANOBJS     = *.#{$OBJEXT} *.#{$LIBEXT} *.s[ol] *.pdb *.exp *.bak
1247 all:            #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
1248 static:         $(STATIC_LIB)#{$extout ? " install-rb" : ""}
1250   mfile.print CLEANINGS
1251   dirs = []
1252   mfile.print "install: install-so install-rb\n\n"
1253   sodir = (dir = "$(RUBYARCHDIR)").dup
1254   mfile.print("install-so: #{dir}\n")
1255   if target
1256     f = "$(DLLIB)"
1257     dest = "#{dir}/#{f}"
1258     mfile.print "install-so: #{dest}\n"
1259     unless $extout
1260       mfile.print "#{dest}: #{f}\n"
1261       if (sep = config_string('BUILD_FILE_SEPARATOR'))
1262         f.gsub!("/", sep)
1263         dir.gsub!("/", sep)
1264         sep = ":/="+sep
1265         f.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2}
1266         f.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2}
1267         dir.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2}
1268         dir.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2}
1269       end
1270       mfile.print "\t$(INSTALL_PROG) #{f} #{dir}\n"
1271       if defined?($installed_list)
1272         mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
1273       end
1274     end
1275   end
1276   mfile.print("install-rb: pre-install-rb install-rb-default\n")
1277   mfile.print("install-rb-default: pre-install-rb-default\n")
1278   mfile.print("pre-install-rb: Makefile\n")
1279   mfile.print("pre-install-rb-default: Makefile\n")
1280   for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]]
1281     files = install_files(mfile, i, nil, srcprefix) or next
1282     for dir, *files in files
1283       unless dirs.include?(dir)
1284         dirs << dir
1285         mfile.print "pre-install-rb#{sfx}: #{dir}\n"
1286       end
1287       files.each do |f|
1288         dest = "#{dir}/#{File.basename(f)}"
1289         mfile.print("install-rb#{sfx}: #{dest}\n")
1290         mfile.print("#{dest}: #{f}\n\t$(#{$extout ? 'COPY' : 'INSTALL_DATA'}) ")
1291         sep = config_string('BUILD_FILE_SEPARATOR')
1292         if sep
1293           f = f.gsub("/", sep)
1294           sep = ":/="+sep
1295           f = f.gsub(/(\$\(\w+)(\))/) {$1+sep+$2}
1296           f = f.gsub(/(\$\{\w+)(\})/) {$1+sep+$2}
1297         else
1298           sep = ""
1299         end
1300         mfile.print("#{f} $(@D#{sep})\n")
1301         if defined?($installed_list) and !$extout
1302           mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
1303         end
1304       end
1305     end
1306   end
1307   dirs.unshift(sodir) if target and !dirs.include?(sodir)
1308   dirs.each {|dir| mfile.print "#{dir}:\n\t$(MAKEDIRS) $@\n"}
1310   mfile.print <<-SITEINSTALL
1312 site-install: site-install-so site-install-rb
1313 site-install-so: install-so
1314 site-install-rb: install-rb
1316   SITEINSTALL
1318   return unless target
1320   mfile.puts SRC_EXT.collect {|ext| ".path.#{ext} = $(VPATH)"} if $nmake == ?b
1321   mfile.print ".SUFFIXES: .#{SRC_EXT.join(' .')} .#{$OBJEXT}\n"
1322   mfile.print "\n"
1324   CXX_EXT.each do |ext|
1325     COMPILE_RULES.each do |rule|
1326       mfile.printf(rule, ext, $OBJEXT)
1327       mfile.printf("\n\t%s\n\n", COMPILE_CXX)
1328     end
1329   end
1330   %w[c].each do |ext|
1331     COMPILE_RULES.each do |rule|
1332       mfile.printf(rule, ext, $OBJEXT)
1333       mfile.printf("\n\t%s\n\n", COMPILE_C)
1334     end
1335   end
1337   mfile.print "$(RUBYARCHDIR)/" if $extout
1338   mfile.print "$(DLLIB): ", (makedef ? "$(DEFFILE) " : ""), "$(OBJS)\n"
1339   mfile.print "\t@-$(RM) $@\n"
1340   mfile.print "\t@-$(MAKEDIRS) $(@D)\n" if $extout
1341   link_so = LINK_SO.gsub(/^/, "\t")
1342   mfile.print link_so, "\n\n"
1343   unless $static.nil?
1344     mfile.print "$(STATIC_LIB): $(OBJS)\n\t"
1345     mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
1346     config_string('RANLIB') do |ranlib|
1347       mfile.print "\n\t@-#{ranlib} $(DLLIB) 2> /dev/null || true"
1348     end
1349   end
1350   mfile.print "\n\n"
1351   if makedef
1352     mfile.print "$(DEFFILE): #{origdef}\n"
1353     mfile.print "\t$(RUBY) #{makedef} #{origdef} > $@\n\n"
1354   end
1356   depend = File.join(srcdir, "depend")
1357   if File.exist?(depend)
1358     suffixes = []
1359     depout = []
1360     open(depend, "r") do |dfile|
1361       mfile.printf "###\n"
1362       cont = implicit = nil
1363       impconv = proc do
1364         COMPILE_RULES.each {|rule| depout << (rule % implicit[0]) << implicit[1]}
1365         implicit = nil
1366       end
1367       ruleconv = proc do |line|
1368         if implicit
1369           if /\A\t/ =~ line
1370             implicit[1] << line
1371             next
1372           else
1373             impconv[]
1374           end
1375         end
1376         if m = /\A\.(\w+)\.(\w+)(?:\s*:)/.match(line)
1377           suffixes << m[1] << m[2]
1378           implicit = [[m[1], m[2]], [m.post_match]]
1379           next
1380         elsif RULE_SUBST and /\A(?!\s*\w+\s*=)[$\w][^#]*:/ =~ line
1381           line.gsub!(%r"(\s)(?!\.)([^$(){}+=:\s\/\\,]+)(?=\s|\z)") {$1 + RULE_SUBST % $2}
1382         end
1383         depout << line
1384       end
1385       while line = dfile.gets()
1386         line.gsub!(/\.o\b/, ".#{$OBJEXT}")
1387         line.gsub!(/\$\(hdrdir\)\/config.h/, $config_h) if $config_h
1388         if /(?:^|[^\\])(?:\\\\)*\\$/ =~ line
1389           (cont ||= []) << line
1390           next
1391         elsif cont
1392           line = (cont << line).join
1393           cont = nil
1394         end
1395         ruleconv.call(line)
1396       end
1397       if cont
1398         ruleconv.call(cont.join)
1399       elsif implicit
1400         impconv.call
1401       end
1402     end
1403     unless suffixes.empty?
1404       mfile.print ".SUFFIXES: .", suffixes.uniq.join(" ."), "\n\n"
1405     end
1406     mfile.print "$(OBJS): $(RUBY_EXTCONF_H)\n\n" if $extconf_h
1407     mfile.print depout
1408   else
1409     headers = %w[ruby.h defines.h]
1410     if RULE_SUBST
1411       headers.each {|h| h.sub!(/.*/) {|*m| RULE_SUBST % m}}
1412     end
1413     headers << $config_h if $config_h
1414     headers << "$(RUBY_EXTCONF_H)" if $extconf_h
1415     mfile.print "$(OBJS): " # , headers.join(' '), "\n"
1416   end
1418   $makefile_created = true
1419 ensure
1420   mfile.close if mfile
1423 def init_mkmf(config = CONFIG)
1424   $makefile_created = false
1425   $arg_config = []
1426   $enable_shared = config['ENABLE_SHARED'] == 'yes'
1427   $defs = []
1428   $extconf_h = nil
1429   $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup
1430   $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup
1431   $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup
1432   $LDFLAGS = with_config("ldflags", arg_config("LDFLAGS", config["LDFLAGS"])).dup
1433   $INCFLAGS = "-I$(topdir) -I$(hdrdir) -I$(srcdir)"
1434   $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
1435   $LIBEXT = config['LIBEXT'].dup
1436   $OBJEXT = config["OBJEXT"].dup
1437   $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}"
1438   $LIBRUBYARG = ""
1439   $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC']
1440   $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED']
1441   $DEFLIBPATH = $extmk ? ["$(topdir)"] : CROSS_COMPILING ? [] : ["$(libdir)"]
1442   $DEFLIBPATH.unshift(".")
1443   $LIBPATH = []
1444   $INSTALLFILES = nil
1446   $objs = nil
1447   $srcs = nil
1448   $libs = ""
1449   if $enable_shared or Config.expand(config["LIBRUBY"].dup) != Config.expand(config["LIBRUBY_A"].dup)
1450     $LIBRUBYARG = config['LIBRUBYARG']
1451   end
1453   $LOCAL_LIBS = ""
1455   $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || []
1456   $cleanfiles << "mkmf.log"
1457   $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || []
1459   $extout ||= nil
1460   $extout_prefix ||= nil
1462   $arg_config.clear
1463   dir_config("opt")
1466 FailedMessage = <<MESSAGE
1467 Could not create Makefile due to some reason, probably lack of
1468 necessary libraries and/or headers.  Check the mkmf.log file for more
1469 details.  You may need configuration options.
1471 Provided configuration options:
1472 MESSAGE
1474 def mkmf_failed(path)
1475   unless $makefile_created or File.exist?("Makefile")
1476     opts = $arg_config.collect {|t, n| "\t#{t}#{n ? "=#{n}" : ""}\n"}
1477     abort "*** #{path} failed ***\n" + FailedMessage + opts.join
1478   end
1481 init_mkmf
1483 $make = with_config("make-prog", ENV["MAKE"] || "make")
1484 make, = Shellwords.shellwords($make)
1485 $nmake = nil
1486 case
1487 when $mswin
1488   $nmake = ?m if /nmake/i =~ make
1489 when $bccwin
1490   $nmake = ?b if /Borland/i =~ `#{make} -h`
1493 Config::CONFIG["srcdir"] = CONFIG["srcdir"] =
1494   $srcdir = arg_config("--srcdir", File.dirname($0))
1495 $configure_args["--topsrcdir"] ||= $srcdir
1496 if $curdir = arg_config("--curdir")
1497   Config.expand(curdir = $curdir.dup)
1498 else
1499   curdir = $curdir = "."
1501 unless File.expand_path(Config::CONFIG["topdir"]) == File.expand_path(curdir)
1502   CONFIG["topdir"] = $curdir
1503   Config::CONFIG["topdir"] = curdir
1505 $configure_args["--topdir"] ||= $curdir
1506 $ruby = arg_config("--ruby", RUBY_BIN_PATH)
1508 split = Shellwords.method(:shellwords).to_proc
1510 EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip}
1512 hdr = []
1513 config_string('COMMON_MACROS') do |s|
1514   Shellwords.shellwords(s).each do |w|
1515     hdr << "#define " + w.split(/=/, 2).join(" ")
1516   end
1518 config_string('COMMON_HEADERS') do |s|
1519   Shellwords.shellwords(s).each {|s| hdr << "#include <#{s}>"}
1521 COMMON_HEADERS = hdr.join("\n")
1522 COMMON_LIBS = config_string('COMMON_LIBS', &split) || []
1524 COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:]
1525 RULE_SUBST = config_string('RULE_SUBST')
1526 COMPILE_C = config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<'
1527 COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<'
1528 TRY_LINK = config_string('TRY_LINK') ||
1529   "$(CC) #{OUTFLAG}conftest $(INCFLAGS) $(CPPFLAGS) " \
1530   "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
1531 LINK_SO = config_string('LINK_SO') ||
1532   if CONFIG["DLEXT"] == $OBJEXT
1533     "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
1534   else
1535     "$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \
1536     "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)"
1537   end
1538 LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L"%s"'
1539 RPATHFLAG = config_string('RPATHFLAG') || ''
1540 LIBARG = config_string('LIBARG') || '-l%s'
1542 sep = config_string('BUILD_FILE_SEPARATOR') {|sep| ":/=#{sep}" if sep != "/"} || ""
1543 CLEANINGS = "
1544 clean:
1545                 @-$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep})
1547 distclean:      clean
1548                 @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
1549                 @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
1551 realclean:      distclean
1554 if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
1555   END {mkmf_failed($0)}