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