* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / lib / mkmf.rb
blob318394054745bf0ef5b1cb205a5ca44c93e41e61
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 = RbConfig::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"]
54 $vendordir = CONFIG["vendordir"]
55 $vendorlibdir = CONFIG["vendorlibdir"]
56 $vendorarchdir = CONFIG["vendorarchdir"]
58 $mswin = /mswin/ =~ RUBY_PLATFORM
59 $bccwin = /bccwin/ =~ RUBY_PLATFORM
60 $mingw = /mingw/ =~ RUBY_PLATFORM
61 $cygwin = /cygwin/ =~ RUBY_PLATFORM
62 $human = /human/ =~ RUBY_PLATFORM
63 $netbsd = /netbsd/ =~ RUBY_PLATFORM
64 $os2 = /os2/ =~ RUBY_PLATFORM
65 $beos = /beos/ =~ RUBY_PLATFORM
66 $haiku = /haiku/ =~ RUBY_PLATFORM
67 $solaris = /solaris/ =~ RUBY_PLATFORM
68 $dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
70 # :stopdoc:
72 def config_string(key, config = CONFIG)
73   s = config[key] and !s.empty? and block_given? ? yield(s) : s
74 end
76 def dir_re(dir)
77   Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$(?:\(target_prefix\)|\{target_prefix\}))?')
78 end
80 def relative_from(path, base)
81   dir = File.join(path, "")
82   if File.expand_path(dir) == File.expand_path(dir, base)
83     path
84   else
85     File.join(base, path)
86   end
87 end
89 INSTALL_DIRS = [
90   [dir_re('commondir'), "$(RUBYCOMMONDIR)"],
91   [dir_re('sitedir'), "$(RUBYCOMMONDIR)"],
92   [dir_re('vendordir'), "$(RUBYCOMMONDIR)"],
93   [dir_re('rubylibdir'), "$(RUBYLIBDIR)"],
94   [dir_re('archdir'), "$(RUBYARCHDIR)"],
95   [dir_re('sitelibdir'), "$(RUBYLIBDIR)"],
96   [dir_re('vendorlibdir'), "$(RUBYLIBDIR)"],
97   [dir_re('sitearchdir'), "$(RUBYARCHDIR)"],
98   [dir_re('vendorarchdir'), "$(RUBYARCHDIR)"],
99   [dir_re('rubyhdrdir'), "$(RUBYHDRDIR)"],
100   [dir_re('sitehdrdir'), "$(SITEHDRDIR)"],
101   [dir_re('vendorhdrdir'), "$(VENDORHDRDIR)"],
102   [dir_re('bindir'), "$(BINDIR)"],
105 def install_dirs(target_prefix = nil)
106   if $extout
107     dirs = [
108       ['BINDIR',        '$(extout)/bin'],
109       ['RUBYCOMMONDIR', '$(extout)/common'],
110       ['RUBYLIBDIR',    '$(RUBYCOMMONDIR)$(target_prefix)'],
111       ['RUBYARCHDIR',   '$(extout)/$(arch)$(target_prefix)'],
112       ['HDRDIR',        '$(extout)/include/ruby$(target_prefix)'],
113       ['ARCHHDRDIR',    '$(extout)/include/$(arch)/ruby$(target_prefix)'],
114       ['extout',        "#$extout"],
115       ['extout_prefix', "#$extout_prefix"],
116     ]
117   elsif $extmk
118     dirs = [
119       ['BINDIR',        '$(bindir)'],
120       ['RUBYCOMMONDIR', '$(rubylibdir)'],
121       ['RUBYLIBDIR',    '$(rubylibdir)$(target_prefix)'],
122       ['RUBYARCHDIR',   '$(archdir)$(target_prefix)'],
123       ['HDRDIR',        '$(rubyhdrdir)/ruby$(target_prefix)'],
124       ['ARCHHDRDIR',    '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
125     ]
126   elsif $configure_args.has_key?('--vendor')
127     dirs = [
128       ['BINDIR',        '$(bindir)'],
129       ['RUBYCOMMONDIR', '$(vendordir)$(target_prefix)'],
130       ['RUBYLIBDIR',    '$(vendorlibdir)$(target_prefix)'],
131       ['RUBYARCHDIR',   '$(vendorarchdir)$(target_prefix)'],
132       ['HDRDIR',        '$(rubyhdrdir)/ruby$(target_prefix)'],
133       ['ARCHHDRDIR',    '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
134     ]
135   else
136     dirs = [
137       ['BINDIR',        '$(bindir)'],
138       ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'],
139       ['RUBYLIBDIR',    '$(sitelibdir)$(target_prefix)'],
140       ['RUBYARCHDIR',   '$(sitearchdir)$(target_prefix)'],
141       ['HDRDIR',        '$(rubyhdrdir)/ruby$(target_prefix)'],
142       ['ARCHHDRDIR',    '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
143     ]
144   end
145   dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")]
146   dirs
149 def map_dir(dir, map = nil)
150   map ||= INSTALL_DIRS
151   map.inject(dir) {|d, (orig, new)| d.gsub(orig, new)}
154 topdir = File.dirname(libdir = File.dirname(__FILE__))
155 extdir = File.expand_path("ext", topdir)
156 path = File.expand_path($0)
157 $extmk = path[0, topdir.size+1] == topdir+"/" && %r"\A(ext|enc|tool)\z" =~ File.dirname(path[topdir.size+1..-1])
158 if not $extmk and File.exist?(($hdrdir = RbConfig::CONFIG["rubyhdrdir"]) + "/ruby/ruby.h")
159   $topdir = $hdrdir
160   $top_srcdir = $hdrdir
161   $arch_hdrdir = $hdrdir + "/$(arch)"
162 elsif File.exist?(($hdrdir = ($top_srcdir ||= topdir) + "/include")  + "/ruby.h")
163   $topdir ||= RbConfig::CONFIG["topdir"]
164   $arch_hdrdir = "$(extout)/include/$(arch)"
165 else
166   abort "mkmf.rb can't find header files for ruby at #{$hdrdir}/ruby.h"
169 OUTFLAG = CONFIG['OUTFLAG']
170 COUTFLAG = CONFIG['COUTFLAG']
171 CPPOUTFILE = CONFIG['CPPOUTFILE']
173 CONFTEST_C = "conftest.c".freeze
175 class String
176   # Wraps a string in escaped quotes if it contains whitespace.
177   def quote
178     /\s/ =~ self ? "\"#{self}\"" : "#{self}"
179   end
181   # Generates a string used as cpp macro name.
182   def tr_cpp
183     strip.upcase.tr_s("^A-Z0-9_", "_")
184   end
186 class Array
187   # Wraps all strings in escaped quotes if they contain whitespace.
188   def quote
189     map {|s| s.quote}
190   end
193 def rm_f(*files)
194   FileUtils.rm_f(Dir[*files])
197 # Returns time stamp of the +target+ file if it exists and is newer
198 # than or equal to all of +times+.
199 def modified?(target, times)
200   (t = File.mtime(target)) rescue return nil
201   Array === times or times = [times]
202   t if times.all? {|n| n <= t}
205 def merge_libs(*libs)
206   libs.inject([]) do |x, y|
207     xy = x & y
208     xn = yn = 0
209     y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e}
210     y.each_with_index do |v, yi|
211       if xy.include?(v)
212         xi = [x.index(v), xn].max()
213         x[xi, 1] = y[yn..yi]
214         xn, yn = xi + (yi - yn + 1), yi + 1
215       end
216     end
217     x.concat(y[yn..-1] || [])
218   end
221 # This is a custom logging module. It generates an mkmf.log file when you
222 # run your extconf.rb script. This can be useful for debugging unexpected
223 # failures.
225 # This module and its associated methods are meant for internal use only.
227 module Logging
228   @log = nil
229   @logfile = 'mkmf.log'
230   @orgerr = $stderr.dup
231   @orgout = $stdout.dup
232   @postpone = 0
233   @quiet = $extmk
235   def self::open
236     @log ||= File::open(@logfile, 'w')
237     @log.sync = true
238     $stderr.reopen(@log)
239     $stdout.reopen(@log)
240     yield
241   ensure
242     $stderr.reopen(@orgerr)
243     $stdout.reopen(@orgout)
244   end
246   def self::message(*s)
247     @log ||= File::open(@logfile, 'w')
248     @log.sync = true
249     @log.printf(*s)
250   end
252   def self::logfile file
253     @logfile = file
254     if @log and not @log.closed?
255       @log.flush
256       @log.close
257       @log = nil
258     end
259   end
260   
261   def self::postpone
262     tmplog = "mkmftmp#{@postpone += 1}.log"
263     open do
264       log, *save = @log, @logfile, @orgout, @orgerr
265       @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
266       begin
267         log.print(open {yield})
268         @log.close
269         File::open(tmplog) {|t| FileUtils.copy_stream(t, log)}
270       ensure
271         @log, @logfile, @orgout, @orgerr = log, *save
272         @postpone -= 1
273         rm_f tmplog
274       end
275     end
276   end
278   class << self
279     attr_accessor :quiet
280   end
283 def xsystem command
284   varpat = /\$\((\w+)\)|\$\{(\w+)\}/
285   if varpat =~ command
286     vars = Hash.new {|h, k| h[k] = ''; ENV[k]}
287     command = command.dup
288     nil while command.gsub!(varpat) {vars[$1||$2]}
289   end
290   Logging::open do
291     puts command.quote
292     system(command)
293   end
296 def xpopen command, *mode, &block
297   Logging::open do
298     case mode[0]
299     when nil, /^r/
300       puts "#{command} |"
301     else
302       puts "| #{command}"
303     end
304     IO.popen(command, *mode, &block)
305   end
308 def log_src(src)
309   src = src.split(/^/)
310   fmt = "%#{src.size.to_s.size}d: %s"
311   Logging::message <<"EOM"
312 checked program was:
313 /* begin */
315   src.each_with_index {|line, no| Logging::message fmt, no+1, line}
316   Logging::message <<"EOM"
317 /* end */
322 def create_tmpsrc(src)
323   src = yield(src) if block_given?
324   src[0, 0] = COMMON_HEADERS + "\n"
325   src = src.gsub(/[ \t]+$/, '').gsub(/\A\n+|^\n+$/, '').sub(/[^\n]\z/, "\\&\n")
326   count = 0
327   begin
328     open(CONFTEST_C, "wb") do |cfile|
329       cfile.print src
330     end
331   rescue Errno::EACCES
332     if (count += 1) < 5
333       sleep 0.2
334       retry
335     end
336   end
337   src
340 def try_do(src, command, &b)
341   src = create_tmpsrc(src, &b)
342   xsystem(command)
343 ensure
344   log_src(src)
347 def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
348   conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote,
349                                 'src' => CONFTEST_C,
350                                 'arch_hdrdir' => "#$arch_hdrdir",
351                                 'top_srcdir' => $top_srcdir.quote,
352                                 'INCFLAGS' => "#$INCFLAGS",
353                                 'CPPFLAGS' => "#$CPPFLAGS",
354                                 'CFLAGS' => "#$CFLAGS",
355                                 'ARCH_FLAG' => "#$ARCH_FLAG",
356                                 'LDFLAGS' => "#$LDFLAGS #{ldflags}",
357                                 'LIBPATH' => libpathflag(libpath),
358                                 'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs",
359                                 'LIBS' => "#$LIBRUBYARG_STATIC #{opt} #$LIBS")
360   RbConfig::expand(TRY_LINK.dup, conf)
363 def cc_command(opt="")
364   conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
365                                 'arch_hdrdir' => "#$arch_hdrdir",
366                                 'top_srcdir' => $top_srcdir.quote)
367   RbConfig::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}",
368                    conf)
371 def cpp_command(outfile, opt="")
372   conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
373                                 'arch_hdrdir' => "#$arch_hdrdir",
374                                 'top_srcdir' => $top_srcdir.quote)
375   RbConfig::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
376                    conf)
379 def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
380   libpath.map{|x|
381     case x
382     when "$(topdir)", /\A\./
383       LIBPATHFLAG
384     else
385       LIBPATHFLAG+RPATHFLAG
386     end % x.quote
387   }.join
390 def try_link0(src, opt="", &b)
391   try_do(src, link_command("", opt), &b)
394 def try_link(src, opt="", &b)
395   try_link0(src, opt, &b)
396 ensure
397   rm_f "conftest*", "c0x32*"
400 def try_compile(src, opt="", &b)
401   try_do(src, cc_command(opt), &b)
402 ensure
403   rm_f "conftest*"
406 def try_cpp(src, opt="", &b)
407   try_do(src, cpp_command(CPPOUTFILE, opt), &b)
408 ensure
409   rm_f "conftest*"
412 def cpp_include(header)
413   if header
414     header = [header] unless header.kind_of? Array
415     header.map {|h| "#include <#{h}>\n"}.join
416   else
417     ""
418   end
421 def with_cppflags(flags)
422   cppflags = $CPPFLAGS
423   $CPPFLAGS = flags
424   ret = yield
425 ensure
426   $CPPFLAGS = cppflags unless ret
429 def with_cflags(flags)
430   cflags = $CFLAGS
431   $CFLAGS = flags
432   ret = yield
433 ensure
434   $CFLAGS = cflags unless ret
437 def with_ldflags(flags)
438   ldflags = $LDFLAGS
439   $LDFLAGS = flags
440   ret = yield
441 ensure
442   $LDFLAGS = ldflags unless ret
445 def try_static_assert(expr, headers = nil, opt = "", &b)
446   headers = cpp_include(headers)
447   try_compile(<<SRC, opt, &b)
448 #{COMMON_HEADERS}
449 #{headers}
450 /*top*/
451 int conftest_const[(#{expr}) ? 1 : -1];
455 def try_constant(const, headers = nil, opt = "", &b)
456   includes = cpp_include(headers)
457   if CROSS_COMPILING
458     if try_static_assert("#{const} > 0", headers, opt)
459       # positive constant
460     elsif try_static_assert("#{const} < 0", headers, opt)
461       neg = true
462       const = "-(#{const})"
463     elsif try_static_assert("#{const} == 0", headers, opt)
464       return 0
465     else
466       # not a constant
467       return nil
468     end
469     upper = 1
470     lower = 0
471     until try_static_assert("#{const} <= #{upper}", headers, opt)
472       lower = upper
473       upper <<= 1
474     end
475     return nil unless lower
476     while upper > lower + 1
477       mid = (upper + lower) / 2
478       if try_static_assert("#{const} > #{mid}", headers, opt)
479         lower = mid
480       else
481         upper = mid
482       end
483     end
484     upper = -upper if neg
485     return upper
486   else
487     src = %{#{COMMON_HEADERS}
488 #{includes}
489 #include <stdio.h>
490 /*top*/
491 int conftest_const = (int)(#{const});
492 int main() {printf("%d\\n", conftest_const); return 0;}
494     if try_link0(src, opt, &b)
495       xpopen("./conftest") do |f|
496         return Integer(f.gets)
497       end
498     end
499   end
500   nil
503 def try_func(func, libs, headers = nil, &b)
504   headers = cpp_include(headers)
505   try_link(<<"SRC", libs, &b) or try_link(<<"SRC", libs, &b)
506 #{COMMON_HEADERS}
507 #{headers}
508 /*top*/
509 int main() { return 0; }
510 int t() { void ((*volatile p)()); p = (void ((*)()))#{func}; return 0; }
512 #{headers}
513 /*top*/
514 int main() { return 0; }
515 int t() { #{func}(); return 0; }
519 def try_var(var, headers = nil, &b)
520   headers = cpp_include(headers)
521   try_compile(<<"SRC", &b)
522 #{COMMON_HEADERS}
523 #{headers}
524 /*top*/
525 int main() { return 0; }
526 int t() { const volatile void *volatile p; p = &(&#{var})[0]; return 0; }
530 def egrep_cpp(pat, src, opt = "", &b)
531   src = create_tmpsrc(src, &b)
532   xpopen(cpp_command('', opt)) do |f|
533     if Regexp === pat
534       puts("    ruby -ne 'print if #{pat.inspect}'")
535       f.grep(pat) {|l|
536         puts "#{f.lineno}: #{l}"
537         return true
538       }
539       false
540     else
541       puts("    egrep '#{pat}'")
542       begin
543         stdin = $stdin.dup
544         $stdin.reopen(f)
545         system("egrep", pat)
546       ensure
547         $stdin.reopen(stdin)
548       end
549     end
550   end
551 ensure
552   rm_f "conftest*"
553   log_src(src)
556 # This is used internally by the have_macro? method.
557 def macro_defined?(macro, src, opt = "", &b)
558   src = src.sub(/[^\n]\z/, "\\&\n")
559   try_compile(src + <<"SRC", opt, &b)
560 /*top*/
561 #ifndef #{macro}
562 # error
563 >>>>>> #{macro} undefined <<<<<<
564 #endif
568 def try_run(src, opt = "", &b)
569   if try_link0(src, opt, &b)
570     xsystem("./conftest")
571   else
572     nil
573   end
574 ensure
575   rm_f "conftest*"
578 def install_files(mfile, ifiles, map = nil, srcprefix = nil)
579   ifiles or return
580   ifiles.empty? and return
581   srcprefix ||= '$(srcdir)'
582   RbConfig::expand(srcdir = srcprefix.dup)
583   dirs = []
584   path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]}
585   ifiles.each do |files, dir, prefix|
586     dir = map_dir(dir, map)
587     prefix &&= %r|\A#{Regexp.quote(prefix)}/?|
588     if /\A\.\// =~ files
589       # install files which are in current working directory.
590       files = files[2..-1]
591       len = nil
592     else
593       # install files which are under the $(srcdir).
594       files = File.join(srcdir, files)
595       len = srcdir.size
596     end
597     f = nil
598     Dir.glob(files) do |fx|
599       f = fx
600       f[0..len] = "" if len
601       case File.basename(f)
602       when *$NONINSTALLFILES
603         next
604       end
605       d = File.dirname(f)
606       d.sub!(prefix, "") if prefix
607       d = (d.empty? || d == ".") ? dir : File.join(dir, d)
608       f = File.join(srcprefix, f) if len
609       path[d] << f
610     end
611     unless len or f
612       d = File.dirname(files)
613       d.sub!(prefix, "") if prefix
614       d = (d.empty? || d == ".") ? dir : File.join(dir, d)
615       path[d] << files
616     end
617   end
618   dirs
621 def install_rb(mfile, dest, srcdir = nil)
622   install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir)
625 def append_library(libs, lib) # :no-doc:
626   format(LIBARG, lib) + " " + libs
629 def message(*s)
630   unless Logging.quiet and not $VERBOSE
631     printf(*s)
632     $stdout.flush
633   end
636 # This emits a string to stdout that allows users to see the results of the
637 # various have* and find* methods as they are tested.
639 # Internal use only.
641 def checking_for(m, fmt = nil)
642   f = caller[0][/in `(.*)'$/, 1] and f << ": " #` for vim #'
643   m = "checking #{/\Acheck/ =~ f ? '' : 'for '}#{m}... "
644   message "%s", m
645   a = r = nil
646   Logging::postpone do
647     r = yield
648     a = (fmt ? fmt % r : r ? "yes" : "no") << "\n"
649     "#{f}#{m}-------------------- #{a}\n"
650   end
651   message(a)
652   Logging::message "--------------------\n\n"
653   r
656 def checking_message(target, place = nil, opt = nil)
657   [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)|
658     if noun
659       [[:to_str], [:join, ","], [:to_s]].each do |meth, *args|
660         if noun.respond_to?(meth)
661           break noun = noun.send(meth, *args)
662         end
663       end
664       msg << " #{pre} #{noun}" unless noun.empty?
665     end
666     msg
667   end
670 # :startdoc:
672 # Returns whether or not +macro+ is defined either in the common header
673 # files or within any +headers+ you provide.
675 # Any options you pass to +opt+ are passed along to the compiler.
677 def have_macro(macro, headers = nil, opt = "", &b)
678   checking_for checking_message(macro, headers, opt) do
679     macro_defined?(macro, cpp_include(headers), opt, &b)
680   end
683 # Returns whether or not the given entry point +func+ can be found within
684 # +lib+.  If +func+ is nil, the 'main()' entry point is used by default.
685 # If found, it adds the library to list of libraries to be used when linking
686 # your extension.
688 # If +headers+ are provided, it will include those header files as the
689 # header files it looks in when searching for +func+.
691 # The real name of the library to be linked can be altered by
692 # '--with-FOOlib' configuration option.
694 def have_library(lib, func = nil, headers = nil, &b)
695   func = "main" if !func or func.empty?
696   lib = with_config(lib+'lib', lib)
697   checking_for checking_message("#{func}()", LIBARG%lib) do
698     if COMMON_LIBS.include?(lib)
699       true
700     else
701       libs = append_library($libs, lib)
702       if try_func(func, libs, headers, &b)
703         $libs = libs
704         true
705       else
706         false
707       end
708     end
709   end
712 # Returns whether or not the entry point +func+ can be found within the library
713 # +lib+ in one of the +paths+ specified, where +paths+ is an array of strings.
714 # If +func+ is nil , then the main() function is used as the entry point.
716 # If +lib+ is found, then the path it was found on is added to the list of
717 # library paths searched and linked against.
719 def find_library(lib, func, *paths, &b)
720   func = "main" if !func or func.empty?
721   lib = with_config(lib+'lib', lib)
722   paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
723   checking_for "#{func}() in #{LIBARG%lib}" do
724     libpath = $LIBPATH
725     libs = append_library($libs, lib)
726     begin
727       until r = try_func(func, libs, &b) or paths.empty?
728         $LIBPATH = libpath | [paths.shift]
729       end
730       if r
731         $libs = libs
732         libpath = nil
733       end
734     ensure
735       $LIBPATH = libpath if libpath
736     end
737     r
738   end
741 # Returns whether or not the function +func+ can be found in the common
742 # header files, or within any +headers+ that you provide.  If found, a
743 # macro is passed as a preprocessor constant to the compiler using the
744 # function name, in uppercase, prepended with 'HAVE_'.
746 # For example, if have_func('foo') returned true, then the HAVE_FOO
747 # preprocessor macro would be passed to the compiler.
749 def have_func(func, headers = nil, &b)
750   checking_for checking_message("#{func}()", headers) do
751     if try_func(func, $libs, headers, &b)
752       $defs.push(format("-DHAVE_%s", func.tr_cpp))
753       true
754     else
755       false
756     end
757   end
760 # Returns whether or not the variable +var+ can be found in the common
761 # header files, or within any +headers+ that you provide.  If found, a
762 # macro is passed as a preprocessor constant to the compiler using the
763 # variable name, in uppercase, prepended with 'HAVE_'.
765 # For example, if have_var('foo') returned true, then the HAVE_FOO
766 # preprocessor macro would be passed to the compiler.
768 def have_var(var, headers = nil, &b)
769   checking_for checking_message(var, headers) do
770     if try_var(var, headers, &b)
771       $defs.push(format("-DHAVE_%s", var.tr_cpp))
772       true
773     else
774       false
775     end
776   end
779 # Returns whether or not the given +header+ file can be found on your system.
780 # If found, a macro is passed as a preprocessor constant to the compiler using
781 # the header file name, in uppercase, prepended with 'HAVE_'.
783 # For example, if have_header('foo.h') returned true, then the HAVE_FOO_H
784 # preprocessor macro would be passed to the compiler.
786 def have_header(header, &b)
787   checking_for header do
788     if try_cpp(cpp_include(header), &b)
789       $defs.push(format("-DHAVE_%s", header.tr("a-z./\055", "A-Z___")))
790       true
791     else
792       false
793     end
794   end
797 # Instructs mkmf to search for the given +header+ in any of the +paths+
798 # provided, and returns whether or not it was found in those paths.
800 # If the header is found then the path it was found on is added to the list
801 # of included directories that are sent to the compiler (via the -I switch).
803 def find_header(header, *paths)
804   message = checking_message(header, paths)
805   header = cpp_include(header)
806   checking_for message do
807     if try_cpp(header)
808       true
809     else
810       found = false
811       paths.each do |dir|
812         opt = "-I#{dir}".quote
813         if try_cpp(header, opt)
814           $INCFLAGS << " " << opt
815           found = true
816           break
817         end
818       end
819       found
820     end
821   end
824 # Returns whether or not the struct of type +type+ contains +member+.  If
825 # it does not, or the struct type can't be found, then false is returned.  You
826 # may optionally specify additional +headers+ in which to look for the struct
827 # (in addition to the common header files).
829 # If found, a macro is passed as a preprocessor constant to the compiler using
830 # the type name and the member name, in uppercase, prepended with 'HAVE_'.
832 # For example, if have_struct_member('struct foo', 'bar') returned true, then the
833 # HAVE_STRUCT_FOO_BAR preprocessor macro would be passed to the compiler.
835 # HAVE_ST_BAR is also defined for backward compatibility.
837 def have_struct_member(type, member, headers = nil, &b)
838   checking_for checking_message("#{type}.#{member}", headers) do
839     if try_compile(<<"SRC", &b)
840 #{COMMON_HEADERS}
841 #{cpp_include(headers)}
842 /*top*/
843 int main() { return 0; }
844 int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
846       $defs.push(format("-DHAVE_%s_%s", type.tr_cpp, member.tr_cpp))
847       $defs.push(format("-DHAVE_ST_%s", member.tr_cpp)) # backward compatibility
848       true
849     else
850       false
851     end
852   end
855 def try_type(type, headers = nil, opt = "", &b)
856   if try_compile(<<"SRC", opt, &b)
857 #{COMMON_HEADERS}
858 #{cpp_include(headers)}
859 /*top*/
860 typedef #{type} conftest_type;
861 int conftestval[sizeof(conftest_type)?1:-1];
863     $defs.push(format("-DHAVE_TYPE_%s", type.tr_cpp))
864     true
865   else
866     false
867   end
870 # Returns whether or not the static type +type+ is defined.  You may
871 # optionally pass additional +headers+ to check against in addition to the
872 # common header files.
874 # You may also pass additional flags to +opt+ which are then passed along to
875 # the compiler.
877 # If found, a macro is passed as a preprocessor constant to the compiler using
878 # the type name, in uppercase, prepended with 'HAVE_TYPE_'.
880 # For example, if have_type('foo') returned true, then the HAVE_TYPE_FOO
881 # preprocessor macro would be passed to the compiler.
883 def have_type(type, headers = nil, opt = "", &b)
884   checking_for checking_message(type, headers, opt) do
885     try_type(type, headers, opt, &b)
886   end
889 # Returns where the static type +type+ is defined.
891 # You may also pass additional flags to +opt+ which are then passed along to
892 # the compiler.
894 # See also +have_type+.
896 def find_type(type, opt, *headers, &b)
897   opt ||= ""
898   fmt = "not found"
899   def fmt.%(x)
900     x ? x.respond_to?(:join) ? x.join(",") : x : self
901   end
902   checking_for checking_message(type, nil, opt), fmt do
903     headers.find do |h|
904       try_type(type, h, opt, &b)
905     end
906   end
909 def try_const(const, headers = nil, opt = "", &b)
910   const, type = *const
911   if try_compile(<<"SRC", opt, &b)
912 #{COMMON_HEADERS}
913 #{cpp_include(headers)}
914 /*top*/
915 typedef #{type || 'int'} conftest_type;
916 conftest_type conftestval = #{type ? '' : '(int)'}#{const};
918     $defs.push(format("-DHAVE_CONST_%s", const.tr_cpp))
919     true
920   else
921     false
922   end
925 # Returns whether or not the constant +const+ is defined.  You may
926 # optionally pass the +type+ of +const+ as <code>[const, type]</code>,
927 # like as:
929 #   have_const(%w[PTHREAD_MUTEX_INITIALIZER pthread_mutex_t], "pthread.h")
931 # You may also pass additional +headers+ to check against in addition
932 # to the common header files, and additional flags to +opt+ which are
933 # then passed along to the compiler.
935 # If found, a macro is passed as a preprocessor constant to the compiler using
936 # the type name, in uppercase, prepended with 'HAVE_CONST_'.
938 # For example, if have_const('foo') returned true, then the HAVE_CONST_FOO
939 # preprocessor macro would be passed to the compiler.
941 def have_const(const, headers = nil, opt = "", &b)
942   checking_for checking_message([*const].compact.join(' '), headers, opt) do
943     try_const(const, headers, opt, &b)
944   end
947 # Returns the size of the given +type+.  You may optionally specify additional
948 # +headers+ to search in for the +type+.
950 # If found, a macro is passed as a preprocessor constant to the compiler using
951 # the type name, in uppercase, prepended with 'SIZEOF_', followed by the type
952 # name, followed by '=X' where 'X' is the actual size.
954 # For example, if check_sizeof('mystruct') returned 12, then the
955 # SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to the compiler.
957 def check_sizeof(type, headers = nil, &b)
958   expr = "sizeof(#{type})"
959   fmt = "%d"
960   def fmt.%(x)
961     x ? super : "failed"
962   end
963   checking_for checking_message("size of #{type}", headers), fmt do
964     if size = try_constant(expr, headers, &b)
965       $defs.push(format("-DSIZEOF_%s=%d", type.tr_cpp, size))
966       size
967     end
968   end
971 # :stopdoc:
973 # Used internally by the what_type? method to determine if +type+ is a scalar
974 # pointer.
975 def scalar_ptr_type?(type, member = nil, headers = nil, &b)
976   try_compile(<<"SRC", &b)   # pointer
977 #{COMMON_HEADERS}
978 #{cpp_include(headers)}
979 /*top*/
980 volatile #{type} conftestval;
981 int main() { return 0; }
982 int t() {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
986 # Used internally by the what_type? method to determine if +type+ is a scalar
987 # pointer.
988 def scalar_type?(type, member = nil, headers = nil, &b)
989   try_compile(<<"SRC", &b)   # pointer
990 #{COMMON_HEADERS}
991 #{cpp_include(headers)}
992 /*top*/
993 volatile #{type} conftestval;
994 int main() { return 0; }
995 int t() {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
999 def what_type?(type, member = nil, headers = nil, &b)
1000   m = "#{type}"
1001   name = type
1002   if member
1003     m << "." << member
1004     name = "(((#{type} *)0)->#{member})"
1005   end
1006   fmt = "seems %s"
1007   def fmt.%(x)
1008     x ? super : "unknown"
1009   end
1010   checking_for checking_message(m, headers), fmt do
1011     if scalar_ptr_type?(type, member, headers, &b)
1012       if try_static_assert("sizeof(*#{name}) == 1", headers)
1013         "string"
1014       end
1015     elsif scalar_type?(type, member, headers, &b)
1016       if try_static_assert("sizeof(#{name}) > sizeof(long)", headers)
1017         "long long"
1018       elsif try_static_assert("sizeof(#{name}) > sizeof(int)", headers)
1019         "long"
1020       elsif try_static_assert("sizeof(#{name}) > sizeof(short)", headers)
1021         "int"
1022       elsif try_static_assert("sizeof(#{name}) > 1", headers)
1023         "short"
1024       else
1025         "char"
1026       end
1027     end
1028   end
1031 # This method is used internally by the find_executable method.
1033 # Internal use only.
1035 def find_executable0(bin, path = nil)
1036   ext = config_string('EXEEXT')
1037   if File.expand_path(bin) == bin
1038     return bin if File.executable?(bin)
1039     ext and File.executable?(file = bin + ext) and return file
1040     return nil
1041   end
1042   if path ||= ENV['PATH']
1043     path = path.split(File::PATH_SEPARATOR)
1044   else
1045     path = %w[/usr/local/bin /usr/ucb /usr/bin /bin]
1046   end
1047   file = nil
1048   path.each do |dir|
1049     return file if File.executable?(file = File.join(dir, bin))
1050     return file if ext and File.executable?(file << ext)
1051   end
1052   nil
1055 # :startdoc:
1057 # Searches for the executable +bin+ on +path+. The default path is your
1058 # PATH environment variable. If that isn't defined, it will resort to
1059 # searching /usr/local/bin, /usr/ucb, /usr/bin and /bin.
1061 # If found, it will return the full path, including the executable name,
1062 # of where it was found.
1064 # Note that this method does not actually affect the generated Makefile.
1066 def find_executable(bin, path = nil)
1067   checking_for checking_message(bin, path) do
1068     find_executable0(bin, path)
1069   end
1072 # :stopdoc:
1074 def arg_config(config, default=nil, &block)
1075   $arg_config << [config, default]
1076   defaults = []
1077   if default
1078     defaults << default
1079   elsif !block
1080     defaults << nil
1081   end
1082   $configure_args.fetch(config.tr('_', '-'), *defaults, &block)
1085 # :startdoc:
1087 # Tests for the presence of a --with-<tt>config</tt> or --without-<tt>config</tt>
1088 # option. Returns true if the with option is given, false if the without
1089 # option is given, and the default value otherwise.
1091 # This can be useful for adding custom definitions, such as debug information.
1093 # Example:
1095 #    if with_config("debug")
1096 #       $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1097 #    end
1099 def with_config(config, default=nil)
1100   config = config.sub(/^--with[-_]/, '')
1101   val = arg_config("--with-"+config) do
1102     if arg_config("--without-"+config)
1103       false
1104     elsif block_given?
1105       yield(config, default)
1106     else
1107       break default
1108     end
1109   end
1110   case val
1111   when "yes"
1112     true
1113   when "no"
1114     false
1115   else
1116     val
1117   end
1120 # Tests for the presence of an --enable-<tt>config</tt> or
1121 # --disable-<tt>config</tt> option. Returns true if the enable option is given,
1122 # false if the disable option is given, and the default value otherwise.
1124 # This can be useful for adding custom definitions, such as debug information.
1126 # Example:
1128 #    if enable_config("debug")
1129 #       $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1130 #    end
1132 def enable_config(config, default=nil)
1133   if arg_config("--enable-"+config)
1134     true
1135   elsif arg_config("--disable-"+config)
1136     false
1137   elsif block_given?
1138     yield(config, default)
1139   else
1140     return default
1141   end
1144 # Generates a header file consisting of the various macro definitions generated
1145 # by other methods such as have_func and have_header. These are then wrapped in
1146 # a custom #ifndef based on the +header+ file name, which defaults to
1147 # 'extconf.h'.
1149 # For example:
1151 #    # extconf.rb
1152 #    require 'mkmf'
1153 #    have_func('realpath')
1154 #    have_header('sys/utime.h')
1155 #    create_header
1156 #    create_makefile('foo')
1158 # The above script would generate the following extconf.h file:
1160 #    #ifndef EXTCONF_H
1161 #    #define EXTCONF_H
1162 #    #define HAVE_REALPATH 1
1163 #    #define HAVE_SYS_UTIME_H 1
1164 #    #endif
1166 # Given that the create_header method generates a file based on definitions
1167 # set earlier in your extconf.rb file, you will probably want to make this
1168 # one of the last methods you call in your script.
1170 def create_header(header = "extconf.h")
1171   message "creating %s\n", header
1172     sym = header.tr("a-z./\055", "A-Z___")
1173   hdr = ["#ifndef #{sym}\n#define #{sym}\n"]
1174       for line in $defs
1175         case line
1176         when /^-D([^=]+)(?:=(.*))?/
1177       hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0] : 1}\n"
1178         when /^-U(.*)/
1179       hdr << "#undef #$1\n"
1180         end
1181       end
1182   hdr << "#endif\n"
1183   hdr = hdr.join
1184   unless (IO.read(header) == hdr rescue false)
1185     open(header, "w") do |hfile|
1186       hfile.write(hdr)
1187     end
1188   end
1189   $extconf_h = header
1192 # Sets a +target+ name that the user can then use to configure various 'with'
1193 # options with on the command line by using that name.  For example, if the
1194 # target is set to "foo", then the user could use the --with-foo-dir command
1195 # line option.
1197 # You may pass along additional 'include' or 'lib' defaults via the +idefault+
1198 # and +ldefault+ parameters, respectively.
1200 # Note that dir_config only adds to the list of places to search for libraries
1201 # and include files.  It does not link the libraries into your application.
1203 def dir_config(target, idefault=nil, ldefault=nil)
1204   if dir = with_config(target + "-dir", (idefault unless ldefault))
1205     defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR)
1206     idefault = ldefault = nil
1207   end
1209   idir = with_config(target + "-include", idefault)
1210   $arg_config.last[1] ||= "${#{target}-dir}/include"
1211   ldir = with_config(target + "-lib", ldefault)
1212   $arg_config.last[1] ||= "${#{target}-dir}/lib"
1214   idirs = idir ? Array === idir ? idir : idir.split(File::PATH_SEPARATOR) : []
1215   if defaults
1216     idirs.concat(defaults.collect {|d| d + "/include"})
1217     idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR)
1218   end
1219   unless idirs.empty?
1220     idirs.collect! {|d| "-I" + d}
1221     idirs -= Shellwords.shellwords($CPPFLAGS)
1222     unless idirs.empty?
1223       $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ")
1224     end
1225   end
1227   ldirs = ldir ? Array === ldir ? ldir : ldir.split(File::PATH_SEPARATOR) : []
1228   if defaults
1229     ldirs.concat(defaults.collect {|d| d + "/lib"})
1230     ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR)
1231   end
1232   $LIBPATH = ldirs | $LIBPATH
1234   [idir, ldir]
1237 # :stopdoc:
1239 # Handles meta information about installed libraries. Uses your platform's
1240 # pkg-config program if it has one.
1241 def pkg_config(pkg)
1242   if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
1243     # iff package specific config command is given
1244     get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
1245   elsif ($PKGCONFIG ||= 
1246          (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
1247          find_executable0(pkgconfig) && pkgconfig) and
1248       system("#{$PKGCONFIG} --exists #{pkg}")
1249     # default to pkg-config command
1250     get = proc {|opt| `#{$PKGCONFIG} --#{opt} #{pkg}`.chomp}
1251   elsif find_executable0(pkgconfig = "#{pkg}-config")
1252     # default to package specific config command, as a last resort.
1253     get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
1254   end
1255   if get
1256     cflags = get['cflags']
1257     ldflags = get['libs']
1258     libs = get['libs-only-l']
1259     ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ")
1260     $CFLAGS += " " << cflags
1261     $LDFLAGS += " " << ldflags
1262     $libs += " " << libs
1263     Logging::message "package configuration for %s\n", pkg
1264     Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n",
1265                      cflags, ldflags, libs
1266     [cflags, ldflags, libs]
1267   else
1268     Logging::message "package configuration for %s is not found\n", pkg
1269     nil
1270   end
1273 def with_destdir(dir)
1274   dir = dir.sub($dest_prefix_pattern, '')
1275   /\A\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir
1278 # Converts forward slashes to backslashes. Aimed at MS Windows.
1280 # Internal use only.
1282 def winsep(s)
1283   s.tr('/', '\\')
1286 def configuration(srcdir)
1287   mk = []
1288   vpath = $VPATH.dup
1289   if !CROSS_COMPILING
1290     case CONFIG['build_os']
1291     when 'cygwin'
1292       if CONFIG['target_os'] != 'cygwin'
1293         vpath = vpath.map {|p| p.sub(/.*/, '$(shell cygpath -u \&)')}
1294       end
1295     when 'msdosdjgpp', 'mingw32'
1296       CONFIG['PATH_SEPARATOR'] = ';'
1297     end
1298   end
1299   CONFIG["hdrdir"] ||= $hdrdir
1300   mk << %{
1301 SHELL = /bin/sh
1303 #### Start of system configuration section. ####
1305 if $extmk
1306   "top_srcdir = " + $top_srcdir.sub(%r"\A#{Regexp.quote($topdir)}/", "$(topdir)/")
1309 srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {CONFIG[$1||$2]}.quote}
1310 topdir = #{($extmk ? CONFIG["topdir"] : $topdir).quote}
1311 hdrdir = #{CONFIG["hdrdir"].quote}
1312 arch_hdrdir = #{$arch_hdrdir}
1313 VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
1315   if $extmk
1316     mk << "RUBYLIB = -\nRUBYOPT = -r$(top_srcdir)/ext/purelib.rb\n"
1317   end
1318   if destdir = CONFIG["prefix"][$dest_prefix_pattern, 1]
1319     mk << "\nDESTDIR = #{destdir}\n"
1320   end
1321   CONFIG.each do |key, var|
1322     next unless /prefix$/ =~ key
1323     mk << "#{key} = #{with_destdir(var)}\n"
1324   end
1325   CONFIG.each do |key, var|
1326     next if /^abs_/ =~ key
1327     next if /^(?:src|top|hdr)dir$/ =~ key
1328     next unless /dir$/ =~ key
1329     mk << "#{key} = #{with_destdir(var)}\n"
1330   end
1331   if !$extmk and !$configure_args.has_key?('--ruby') and
1332       sep = config_string('BUILD_FILE_SEPARATOR')
1333     sep = ":/=#{sep}"
1334   else
1335     sep = ""
1336   end
1337   extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ")<<" "
1338   mk << %{
1339 CC = #{CONFIG['CC']}
1340 CXX = #{CONFIG['CXX']}
1341 LIBRUBY = #{CONFIG['LIBRUBY']}
1342 LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
1343 LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
1344 LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC
1345 OUTFLAG = #{OUTFLAG}
1346 COUTFLAG = #{COUTFLAG}
1348 RUBY_EXTCONF_H = #{$extconf_h}
1349 cflags   = #{CONFIG['cflags']}
1350 optflags = #{CONFIG['optflags']}
1351 debugflags = #{CONFIG['debugflags']}
1352 warnflags = #{CONFIG['warnflags']}
1353 CFLAGS   = #{$static ? '' : CONFIG['CCDLFLAGS']} #$CFLAGS #$ARCH_FLAG
1354 INCFLAGS = -I. #$INCFLAGS
1355 DEFS     = #{CONFIG['DEFS']}
1356 CPPFLAGS = #{extconf_h}#{$CPPFLAGS}
1357 CXXFLAGS = $(CFLAGS) #{CONFIG['CXXFLAGS']}
1358 ldflags  = #{$LDFLAGS}
1359 dldflags = #{$DLDFLAGS}
1360 archflag = #{$ARCH_FLAG}
1361 DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
1362 LDSHARED = #{CONFIG['LDSHARED']}
1363 LDSHAREDXX = #{config_string('LDSHAREDXX') || '$(LDSHARED)'}
1364 AR = #{CONFIG['AR']}
1365 EXEEXT = #{CONFIG['EXEEXT']}
1367 RUBY_INSTALL_NAME = #{CONFIG['RUBY_INSTALL_NAME']}
1368 RUBY_SO_NAME = #{CONFIG['RUBY_SO_NAME']}
1369 arch = #{CONFIG['arch']}
1370 sitearch = #{CONFIG['sitearch']}
1371 ruby_version = #{RbConfig::CONFIG['ruby_version']}
1372 ruby = #{$ruby}
1373 RUBY = $(ruby#{sep})
1374 RM = #{config_string('RM') || '$(RUBY) -run -e rm -- -f'}
1375 MAKEDIRS = #{config_string('MAKEDIRS') || '@$(RUBY) -run -e mkdir -- -p'}
1376 INSTALL = #{config_string('INSTALL') || '@$(RUBY) -run -e install -- -vp'}
1377 INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'}
1378 INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'}
1379 COPY = #{config_string('CP') || '@$(RUBY) -run -e cp -- -v'}
1381 #### End of system configuration section. ####
1383 preload = #{defined?($preload) && $preload ? $preload.join(' ') : ''}
1385   if $nmake == ?b
1386     mk.each do |x|
1387       x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do
1388         "!ifndef " + $1 + "\n" +
1389         $& +
1390         "!endif\n"
1391       end
1392     end
1393   end
1394   mk
1396 # :startdoc:
1398 def dummy_makefile(srcdir)
1399   configuration(srcdir) << <<RULES << CLEANINGS
1400 CLEANFILES = #{$cleanfiles.join(' ')}
1401 DISTCLEANFILES = #{$distcleanfiles.join(' ')}
1403 all install static install-so install-rb: Makefile
1405 RULES
1408 def depend_rules(depend)
1409   suffixes = []
1410   depout = []
1411   cont = implicit = nil
1412   impconv = proc do
1413     COMPILE_RULES.each {|rule| depout << (rule % implicit[0]) << implicit[1]}
1414     implicit = nil
1415   end
1416   ruleconv = proc do |line|
1417     if implicit
1418       if /\A\t/ =~ line
1419         implicit[1] << line
1420         next
1421       else
1422         impconv[]
1423       end
1424     end
1425     if m = /\A\.(\w+)\.(\w+)(?:\s*:)/.match(line)
1426       suffixes << m[1] << m[2]
1427       implicit = [[m[1], m[2]], [m.post_match]]
1428       next
1429     elsif RULE_SUBST and /\A(?!\s*\w+\s*=)[$\w][^#]*:/ =~ line
1430       line.gsub!(%r"(\s)(?!\.)([^$(){}+=:\s\/\\,]+)(?=\s|\z)") {$1 + RULE_SUBST % $2}
1431     end
1432     depout << line
1433   end
1434   depend.each_line do |line|
1435     line.gsub!(/\.o\b/, ".#{$OBJEXT}")
1436     line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h) if $config_h
1437     line.gsub!(%r"\$\(hdrdir\)/(?!ruby(?![^:;/\s]))(?=[-\w]+\.h)", '\&ruby/')
1438     if $nmake && /\A\s*\$\(RM|COPY\)/ =~ line
1439       line.gsub!(%r"[-\w\./]{2,}"){$&.tr("/", "\\")}
1440       line.gsub!(/(\$\((?!RM|COPY)[^:)]+)(?=\))/, '\1:/=\\')
1441     end
1442     if /(?:^|[^\\])(?:\\\\)*\\$/ =~ line
1443       (cont ||= []) << line
1444       next
1445     elsif cont
1446       line = (cont << line).join
1447       cont = nil
1448     end
1449     ruleconv.call(line)
1450   end
1451   if cont
1452     ruleconv.call(cont.join)
1453   elsif implicit
1454     impconv.call
1455   end
1456   unless suffixes.empty?
1457     depout.unshift(".SUFFIXES: ." + suffixes.uniq.join(" .") + "\n\n")
1458   end
1459   depout.unshift("$(OBJS): $(RUBY_EXTCONF_H)\n\n") if $extconf_h
1460   depout.flatten!
1461   depout
1464 # Generates the Makefile for your extension, passing along any options and
1465 # preprocessor constants that you may have generated through other methods.
1467 # The +target+ name should correspond the name of the global function name
1468 # defined within your C extension, minus the 'Init_'.  For example, if your
1469 # C extension is defined as 'Init_foo', then your target would simply be 'foo'.
1471 # If any '/' characters are present in the target name, only the last name
1472 # is interpreted as the target name, and the rest are considered toplevel
1473 # directory names, and the generated Makefile will be altered accordingly to
1474 # follow that directory structure.
1476 # For example, if you pass 'test/foo' as a target name, your extension will
1477 # be installed under the 'test' directory.  This means that in order to
1478 # load the file within a Ruby program later, that directory structure will
1479 # have to be followed, e.g. "require 'test/foo'".
1481 # The +srcprefix+ should be used when your source files are not in the same
1482 # directory as your build script. This will not only eliminate the need for
1483 # you to manually copy the source files into the same directory as your build
1484 # script, but it also sets the proper +target_prefix+ in the generated
1485 # Makefile.
1487 # Setting the +target_prefix+ will, in turn, install the generated binary in
1488 # a directory under your Config::CONFIG['sitearchdir'] that mimics your local
1489 # filesystem when you run 'make install'.
1491 # For example, given the following file tree:
1493 #    ext/
1494 #       extconf.rb
1495 #       test/
1496 #          foo.c
1498 # And given the following code:
1500 #    create_makefile('test/foo', 'test')
1502 # That will set the +target_prefix+ in the generated Makefile to 'test'. That,
1503 # in turn, will create the following file tree when installed via the
1504 # 'make install' command:
1506 #    /path/to/ruby/sitearchdir/test/foo.so
1508 # It is recommended that you use this approach to generate your makefiles,
1509 # instead of copying files around manually, because some third party
1510 # libraries may depend on the +target_prefix+ being set properly.
1512 # The +srcprefix+ argument can be used to override the default source
1513 # directory, i.e. the current directory . It is included as part of the VPATH
1514 # and added to the list of INCFLAGS.
1516 def create_makefile(target, srcprefix = nil)
1517   $target = target
1518   libpath = $DEFLIBPATH|$LIBPATH
1519   message "creating Makefile\n"
1520   rm_f "conftest*"
1521   if CONFIG["DLEXT"] == $OBJEXT
1522     for lib in libs = $libs.split
1523       lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
1524     end
1525     $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
1526   end
1528   if target.include?('/')
1529     target_prefix, target = File.split(target)
1530     target_prefix[0,0] = '/'
1531   else
1532     target_prefix = ""
1533   end
1535   srcprefix ||= '$(srcdir)'
1536   RbConfig::expand(srcdir = srcprefix.dup)
1538   if not $objs
1539     $objs = []
1540     srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
1541     for f in srcs
1542       obj = File.basename(f, ".*") << ".o"
1543       $objs.push(obj) unless $objs.index(obj)
1544     end
1545   elsif !(srcs = $srcs)
1546     srcs = $objs.collect {|o| o.sub(/\.o\z/, '.c')}
1547   end
1548   $srcs = srcs
1549   for i in $objs
1550     i.sub!(/\.o\z/, ".#{$OBJEXT}")
1551   end
1552   $objs = $objs.join(" ")
1554   target = nil if $objs == ""
1556   if target and EXPORT_PREFIX
1557     if File.exist?(File.join(srcdir, target + '.def'))
1558       deffile = "$(srcdir)/$(TARGET).def"
1559       unless EXPORT_PREFIX.empty?
1560         makedef = %{-pe "$_.sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i"}
1561       end
1562     else
1563       makedef = %{-e "puts 'EXPORTS', '#{EXPORT_PREFIX}Init_$(TARGET)'"}
1564     end
1565     if makedef
1566       $distcleanfiles << '$(DEFFILE)'
1567       origdef = deffile
1568       deffile = "$(TARGET)-$(arch).def"
1569     end
1570   end
1571   origdef ||= ''
1573   if $extmk and not $extconf_h
1574     create_header
1575   end
1577   libpath = libpathflag(libpath)
1579   dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
1580   staticlib = target ? "$(TARGET).#$LIBEXT" : ""
1581   mfile = open("Makefile", "wb")
1582   mfile.print(*configuration(srcprefix))
1583   mfile.print "
1584 libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")}
1585 LIBPATH = #{libpath}
1586 DEFFILE = #{deffile}
1588 CLEANFILES = #{$cleanfiles.join(' ')}
1589 DISTCLEANFILES = #{$distcleanfiles.join(' ')}
1591 extout = #{$extout}
1592 extout_prefix = #{$extout_prefix}
1593 target_prefix = #{target_prefix}
1594 LOCAL_LIBS = #{$LOCAL_LIBS}
1595 LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
1596 SRCS = #{srcs.collect(&File.method(:basename)).join(' ')}
1597 OBJS = #{$objs}
1598 TARGET = #{target}
1599 DLLIB = #{dllib}
1600 EXTSTATIC = #{$static || ""}
1601 STATIC_LIB = #{staticlib unless $static.nil?}
1602 #{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
1603 " #"
1604   # TODO: fixme
1605   install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
1606   n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET)'
1607   mfile.print "
1608 TARGET_SO     = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
1609 CLEANLIBS     = #{n}.#{CONFIG['DLEXT']} #{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
1610 CLEANOBJS     = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, '$(TARGET)')}} *.bak
1612 all:            #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
1613 static:         $(STATIC_LIB)#{$extout ? " install-rb" : ""}
1615   mfile.print CLEANINGS
1616   dirs = []
1617   mfile.print "install: install-so install-rb\n\n"
1618   sodir = (dir = "$(RUBYARCHDIR)").dup
1619   mfile.print("install-so: ")
1620   if target
1621     f = "$(DLLIB)"
1622     dest = "#{dir}/#{f}"
1623     mfile.puts dir, "install-so: #{dest}"
1624     unless $extout
1625       mfile.print "#{dest}: #{f}\n"
1626       if (sep = config_string('BUILD_FILE_SEPARATOR'))
1627         f.gsub!("/", sep)
1628         dir.gsub!("/", sep)
1629         sep = ":/="+sep
1630         f.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2}
1631         f.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2}
1632         dir.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2}
1633         dir.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2}
1634       end
1635       mfile.print "\t$(INSTALL_PROG) #{f} #{dir}\n"
1636       if defined?($installed_list)
1637         mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
1638       end
1639     end
1640   else
1641     mfile.puts "Makefile"
1642   end
1643   mfile.print("install-rb: pre-install-rb install-rb-default\n")
1644   mfile.print("install-rb-default: pre-install-rb-default\n")
1645   mfile.print("pre-install-rb: Makefile\n")
1646   mfile.print("pre-install-rb-default: Makefile\n")
1647   for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]]
1648     files = install_files(mfile, i, nil, srcprefix) or next
1649     for dir, *files in files
1650       unless dirs.include?(dir)
1651         dirs << dir
1652         mfile.print "pre-install-rb#{sfx}: #{dir}\n"
1653       end if $nmake
1654       for f in files
1655         dest = "#{dir}/#{File.basename(f)}"
1656         mfile.print("install-rb#{sfx}: #{dest}\n")
1657         mfile.print("#{dest}: #{f}\n")
1658         mfile.print("\t$(MAKEDIRS) $(@D)\n") unless $nmake
1659         mfile.print("\t$(#{$extout ? 'COPY' : 'INSTALL_DATA'}) ")
1660         sep = config_string('BUILD_FILE_SEPARATOR')
1661         if sep
1662           f = f.gsub("/", sep)
1663           sep = ":/="+sep
1664           f = f.gsub(/(\$\(\w+)(\))/) {$1+sep+$2}
1665           f = f.gsub(/(\$\{\w+)(\})/) {$1+sep+$2}
1666         else
1667           sep = ""
1668         end
1669         mfile.print("#{f} $(@D#{sep})\n")
1670         if defined?($installed_list) and !$extout
1671           mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
1672         end
1673       end
1674     end
1675   end
1676   dirs.unshift(sodir) if target and !dirs.include?(sodir)
1677   dirs.each {|d| mfile.print "#{d}:\n\t$(MAKEDIRS) $@\n" if $nmake || d == sodir}
1679   mfile.print <<-SITEINSTALL
1681 site-install: site-install-so site-install-rb
1682 site-install-so: install-so
1683 site-install-rb: install-rb
1685   SITEINSTALL
1687   return unless target
1689   mfile.puts SRC_EXT.collect {|ext| ".path.#{ext} = $(VPATH)"} if $nmake == ?b
1690   mfile.print ".SUFFIXES: .#{SRC_EXT.join(' .')} .#{$OBJEXT}\n"
1691   mfile.print "\n"
1693   CXX_EXT.each do |ext|
1694     COMPILE_RULES.each do |rule|
1695       mfile.printf(rule, ext, $OBJEXT)
1696       mfile.printf("\n\t%s\n\n", COMPILE_CXX)
1697     end
1698   end
1699   %w[c].each do |ext|
1700     COMPILE_RULES.each do |rule|
1701       mfile.printf(rule, ext, $OBJEXT)
1702       mfile.printf("\n\t%s\n\n", COMPILE_C)
1703     end
1704   end
1706   sep = config_string('BUILD_FILE_SEPARATOR') {|s| ":/=#{s}" if s != "/"} || ""
1707   mfile.print "$(RUBYARCHDIR)/" if $extout
1708   mfile.print "$(DLLIB): ", (makedef ? "$(DEFFILE) " : ""), "$(OBJS)\n"
1709   mfile.print "\t@-$(RM) $(@#{sep})\n"
1710   mfile.print "\t@-$(MAKEDIRS) $(@D)\n" if $extout
1711   link_so = LINK_SO.gsub(/^/, "\t")
1712   if srcs.any?(&%r"\.(?:#{CXX_EXT.join('|')})\z".method(:===))
1713     link_so = link_so.sub(/\bLDSHARED\b/, '\&XX')
1714   end
1715   mfile.print link_so, "\n\n"
1716   unless $static.nil?
1717     mfile.print "$(STATIC_LIB): $(OBJS)\n\t@-$(RM) $(@#{sep})\n\t"
1718     mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
1719     config_string('RANLIB') do |ranlib|
1720       mfile.print "\n\t@-#{ranlib} $(DLLIB) 2> /dev/null || true"
1721     end
1722   end
1723   mfile.print "\n\n"
1724   if makedef
1725     mfile.print "$(DEFFILE): #{origdef}\n"
1726     mfile.print "\t$(RUBY) #{makedef} #{origdef} > $@\n\n"
1727   end
1729   depend = File.join(srcdir, "depend")
1730   if File.exist?(depend)
1731     mfile.print("###\n", *depend_rules(File.read(depend)))
1732   else
1733     headers = %w[ruby.h defines.h]
1734     if RULE_SUBST
1735       headers.each {|h| h.sub!(/.*/, &RULE_SUBST.method(:%))}
1736     end
1737     headers << $config_h if $config_h
1738     headers << '$(RUBY_EXTCONF_H)' if $extconf_h
1739     mfile.print "$(OBJS): ", headers.join(' '), "\n"
1740   end
1742   $makefile_created = true
1743 ensure
1744   mfile.close if mfile
1747 # :stopdoc:
1749 def init_mkmf(config = CONFIG)
1750   $makefile_created = false
1751   $arg_config = []
1752   $enable_shared = config['ENABLE_SHARED'] == 'yes'
1753   $defs = []
1754   $extconf_h = nil
1755   $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup
1756   $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup
1757   $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup
1758   $LDFLAGS = with_config("ldflags", arg_config("LDFLAGS", config["LDFLAGS"])).dup
1759   $INCFLAGS = "-I$(arch_hdrdir)"
1760   $INCFLAGS << " -I$(hdrdir)/ruby/backward" unless $extmk
1761   $INCFLAGS << " -I$(hdrdir) -I$(srcdir)"
1762   $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
1763   $LIBEXT = config['LIBEXT'].dup
1764   $OBJEXT = config["OBJEXT"].dup
1765   $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}"
1766   $LIBRUBYARG = ""
1767   $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC']
1768   $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED']
1769   $DEFLIBPATH = $extmk ? ["$(topdir)"] : CROSS_COMPILING ? [] : ["$(libdir)"]
1770   $DEFLIBPATH.unshift(".")
1771   $LIBPATH = []
1772   $INSTALLFILES = []
1773   $NONINSTALLFILES = [/~\z/, /\A#.*#\z/, /\A\.#/, /\.bak\z/i, /\.orig\z/, /\.rej\z/, /\.l[ao]\z/, /\.o\z/]
1774   $VPATH = %w[$(srcdir) $(arch_hdrdir)/ruby $(hdrdir)/ruby]
1776   $objs = nil
1777   $srcs = nil
1778   $libs = ""
1779   if $enable_shared or RbConfig.expand(config["LIBRUBY"].dup) != RbConfig.expand(config["LIBRUBY_A"].dup)
1780     $LIBRUBYARG = config['LIBRUBYARG']
1781   end
1783   $LOCAL_LIBS = ""
1785   $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || []
1786   $cleanfiles << "mkmf.log"
1787   $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || []
1789   $extout ||= nil
1790   $extout_prefix ||= nil
1792   $arg_config.clear
1793   dir_config("opt")
1796 FailedMessage = <<MESSAGE
1797 Could not create Makefile due to some reason, probably lack of
1798 necessary libraries and/or headers.  Check the mkmf.log file for more
1799 details.  You may need configuration options.
1801 Provided configuration options:
1802 MESSAGE
1804 # Returns whether or not the Makefile was successfully generated. If not,
1805 # the script will abort with an error message.
1807 # Internal use only.
1809 def mkmf_failed(path)
1810   unless $makefile_created or File.exist?("Makefile")
1811     opts = $arg_config.collect {|t, n| "\t#{t}#{n ? "=#{n}" : ""}\n"}
1812     abort "*** #{path} failed ***\n" + FailedMessage + opts.join
1813   end
1816 # :startdoc:
1818 init_mkmf
1820 $make = with_config("make-prog", ENV["MAKE"] || "make")
1821 make, = Shellwords.shellwords($make)
1822 $nmake = nil
1823 case
1824 when $mswin
1825   $nmake = ?m if /nmake/i =~ make
1826 when $bccwin
1827   $nmake = ?b if /Borland/i =~ `#{make} -h`
1830 RbConfig::CONFIG["srcdir"] = CONFIG["srcdir"] =
1831   $srcdir = arg_config("--srcdir", File.dirname($0))
1832 $configure_args["--topsrcdir"] ||= $srcdir
1833 if $curdir = arg_config("--curdir")
1834   RbConfig.expand(curdir = $curdir.dup)
1835 else
1836   curdir = $curdir = "."
1838 unless File.expand_path(RbConfig::CONFIG["topdir"]) == File.expand_path(curdir)
1839   CONFIG["topdir"] = $curdir
1840   RbConfig::CONFIG["topdir"] = curdir
1842 $configure_args["--topdir"] ||= $curdir
1843 $ruby = arg_config("--ruby", File.join(RbConfig::CONFIG["bindir"], CONFIG["ruby_install_name"]))
1845 split = Shellwords.method(:shellwords).to_proc
1847 EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip}
1849 hdr = ['#include "ruby.h"' "\n"]
1850 config_string('COMMON_MACROS') do |s|
1851   Shellwords.shellwords(s).each do |w|
1852     hdr << "#define " + w.split(/=/, 2).join(" ")
1853   end
1855 config_string('COMMON_HEADERS') do |s|
1856   Shellwords.shellwords(s).each {|w| hdr << "#include <#{w}>"}
1858 COMMON_HEADERS = hdr.join("\n")
1859 COMMON_LIBS = config_string('COMMON_LIBS', &split) || []
1861 COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:]
1862 RULE_SUBST = config_string('RULE_SUBST')
1863 COMPILE_C = config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<'
1864 COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<'
1865 TRY_LINK = config_string('TRY_LINK') ||
1866   "$(CC) #{OUTFLAG}conftest $(INCFLAGS) $(CPPFLAGS) " \
1867   "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
1868 LINK_SO = config_string('LINK_SO') ||
1869   if CONFIG["DLEXT"] == $OBJEXT
1870     "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
1871   else
1872     "$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \
1873     "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)"
1874   end
1875 LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L"%s"'
1876 RPATHFLAG = config_string('RPATHFLAG') || ''
1877 LIBARG = config_string('LIBARG') || '-l%s'
1879 sep = config_string('BUILD_FILE_SEPARATOR') {|s| ":/=#{s}" if sep != "/"} || ""
1880 CLEANINGS = "
1881 clean:
1882                 @-$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep})
1884 distclean:      clean
1885                 @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
1886                 @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
1888 realclean:      distclean
1891 if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
1892   END {mkmf_failed($0)}