ext/extmk.rb


DEFINITIONS

This source file includes following functions.


   1  #! /usr/local/bin/ruby
   2  # -*- ruby -*-
   3  
   4  $force_static = nil
   5  $install = nil
   6  $destdir = nil
   7  $clean = nil
   8  $nodynamic = nil
   9  $extinit = nil
  10  $extobjs = nil
  11  
  12  if ARGV[0] == 'static'
  13    $force_static = true
  14    ARGV.shift
  15  elsif ARGV[0] == 'install'
  16    $install = true
  17    $destdir = ARGV[1] || ''
  18    ARGV.shift
  19  elsif ARGV[0] == 'clean'
  20    $clean = "clean"
  21    ARGV.shift
  22  elsif ARGV[0] == 'distclean'
  23    $clean = "distclean"
  24    ARGV.shift
  25  elsif ARGV[0] == 'realclean'
  26    $clean = "realclean"
  27    ARGV.shift
  28  end
  29  
  30  $extlist = []
  31  
  32  $:.replace ["."]
  33  require 'rbconfig'
  34  
  35  srcdir = Config::CONFIG["srcdir"]
  36  
  37  $:.replace [srcdir, srcdir+"/lib", "."]
  38  
  39  require 'mkmf'
  40  require 'find'
  41  require 'ftools'
  42  require 'shellwords'
  43  
  44  $topdir = File.expand_path(".")
  45  $top_srcdir = srcdir
  46  
  47  Object.class_eval do remove_method :create_makefile end
  48  
  49  def create_makefile(target)
  50    $target = target
  51    if target.include?('/')
  52      target_prefix, target = File.split(target)
  53      target_prefix[0,0] = '/'
  54    else
  55      target_prefix = ""
  56    end
  57    rm_f "conftest*"
  58    if CONFIG["DLEXT"] == $OBJEXT
  59      libs = $libs.split
  60      for lib in libs
  61        lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
  62      end
  63      $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
  64    end
  65  
  66    $DLDFLAGS = CONFIG["DLDFLAGS"].dup
  67  
  68    if $configure_args['--enable-shared'] or CONFIG["LIBRUBY"] != CONFIG["LIBRUBY_A"]
  69      $libs = CONFIG["LIBRUBYARG"] + " " + $libs
  70      $LIBPATH.unshift $topdir
  71    end
  72  
  73    defflag = ''
  74    if RUBY_PLATFORM =~ /cygwin|mingw/ and not $static
  75      if not File.exist? target + '.def'
  76        open(target + '.def', 'wb') do |f|
  77          f.print "EXPORTS\n", "Init_", target, "\n"
  78        end
  79      end
  80      defflag = target + ".def"
  81    elsif RUBY_PLATFORM =~ /bccwin32/
  82      deffile = target + '.def'
  83      if not File.exist? target + '.def'
  84        open(deffile, 'wb') do |f|
  85          f.print "EXPORTS\n", "_Init_", target, "\n"
  86        end
  87      end
  88    end
  89  
  90    if RUBY_PLATFORM =~ /mswin32|bccwin32/
  91      libpath = $LIBPATH.join(';')
  92    else
  93      $LIBPATH.each {|d| $DLDFLAGS << " -L" << d}
  94      if /netbsdelf/ =~ RUBY_PLATFORM
  95        $LIBPATH.each {|d| $DLDFLAGS << " -Wl,-R" + d unless d == $topdir}
  96      end
  97    end
  98  
  99    $srcdir = File.join($top_srcdir,"ext",$mdir)
 100    mfile = open("Makefile", "w")
 101    mfile.binmode if /mingw/ =~ RUBY_PLATFORM
 102    mfile.printf <<EOL, if $static then "" else CONFIG["CCDLFLAGS"] end, $defs.join(" ")
 103  SHELL = /bin/sh
 104  
 105  #### Start of system configuration section. ####
 106  
 107  srcdir = #{$srcdir}
 108  VPATH = #{$srcdir}
 109  
 110  topdir = #{$topdir}
 111  hdrdir = #{$top_srcdir}
 112  
 113  CC = #{CONFIG['CC']}
 114  
 115  CFLAGS   = %s #{CFLAGS} #$CFLAGS
 116  CPPFLAGS = -I$(topdir) -I$(hdrdir) %s #$CPPFLAGS
 117  #{
 118  if /bccwin32/ =~ RUBY_PLATFORM
 119    "DLDFLAGS = #$LDFLAGS -L" + '"$(libdir:/=\\);$(topdir:/=\\)"' + "\n" +
 120    "LDSHARED = #{CONFIG['LDSHARED']}\n"
 121  else
 122    "DLDFLAGS = #$DLDFLAGS #$LDFLAGS\n" +
 123    "LDSHARED = #{CONFIG['LDSHARED']} #{defflag}\n"
 124  end
 125  }
 126  EOL
 127    mfile.puts "LIBPATH = #{libpath}" if libpath
 128  
 129    mfile.puts ".SUFFIXES: .#{CONFIG['OBJEXT']}" unless #{CONFIG['OBJEXT']} == "o"
 130  
 131    mfile.printf "\
 132  
 133  RUBY_INSTALL_NAME = #{CONFIG['RUBY_INSTALL_NAME']}
 134  RUBY_SO_NAME = #{CONFIG['RUBY_SO_NAME']}
 135  ruby_version = #{Config::CONFIG["ruby_version"]}
 136  
 137  prefix = #{CONFIG['prefix']}
 138  exec_prefix = #{CONFIG['exec_prefix']}
 139  libdir = #{CONFIG['libdir']}
 140  rubylibdir = $(libdir)/ruby/$(ruby_version)
 141  #pkglibdir = $(libdir)/$(RUBY_INSTALL_NAME)/#{CONFIG['MAJOR']}.#{CONFIG['MINOR']}
 142  pkglibdir = $(libdir)/ruby/#{CONFIG['MAJOR']}.#{CONFIG['MINOR']}
 143  archdir = $(pkglibdir)/#{CONFIG['arch']}
 144  target_prefix = #{target_prefix}
 145  #{CONFIG['SET_MAKE']}
 146  
 147  #### End of system configuration section. ####
 148  
 149  "
 150    mfile.printf "LOCAL_LIBS = %s %s\n", $LOCAL_LIBS, $local_flags
 151    if /bccwin32/ =~ RUBY_PLATFORM
 152      mfile.printf "LIBS = $(topdir:/=\\)\\%s\n", $libs
 153    else
 154      mfile.printf "LIBS = %s\n", $libs
 155    end
 156    mfile.printf "OBJS = "
 157    if !$objs or (/bccwin32/ =~ RUBY_PLATFORM) then
 158      $objs = []
 159      for f in Dir["#{$top_srcdir}/ext/#{$mdir}/*.{#{SRC_EXT.join(%q{,})}}"]
 160        f = File.basename(f)
 161        f.sub!(/(#{SRC_EXT.join(%q{|})})$/, $OBJEXT)
 162        $objs.push f
 163      end
 164    else
 165      for i in $objs
 166        i.sub!(/\.o\z/, ".#{$OBJEXT}")
 167      end
 168    end
 169    mfile.printf $objs.join(" ")
 170    mfile.printf "\n"
 171  
 172    if /bccwin32/ =~ RUBY_PLATFORM
 173      ruby_interpreter = '$(topdir:/=\)/miniruby' + CONFIG['EXEEXT']
 174    else
 175      ruby_interpreter = "$(topdir)/miniruby" + CONFIG['EXEEXT']
 176      if /nmake/i =~ $make
 177        ruby_interpreter = '$(topdir:/=\)\miniruby' + CONFIG['EXEEXT']
 178      end
 179    end
 180    if defined? CROSS_COMPILING
 181      ruby_interpreter = CONFIG['MINIRUBY']
 182    end
 183  
 184    mfile.printf <<EOS
 185  TARGET = #{target}
 186  DLLIB = $(TARGET).#{$static ? $LIBEXT : CONFIG['DLEXT']}
 187  
 188  RUBY = #{ruby_interpreter} -I$(topdir) -I$(hdrdir)/lib
 189  RM = $(RUBY) -rftools -e "File::rm_f(*ARGV.map do|x|Dir[x]end.flatten.uniq)"
 190  MAKEDIRS = $(RUBY) -r ftools -e 'File::makedirs(*ARGV)'
 191  INSTALL_PROG = $(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0555, true)'
 192  INSTALL_DATA = $(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)'
 193  
 194  EXEEXT = CONFIG['EXEEXT']
 195  
 196  all:            $(DLLIB)
 197  
 198  clean:
 199                  @$(RM) *.#{$OBJEXT} *.so *.sl *.#{$LIBEXT} $(DLLIB)
 200  #{
 201  if /bccwin32/ =~ RUBY_PLATFORM
 202    "             @$(RM) *.def *.ilc *.ild *.ilf *.ils *.map *.tds *.bak $(CLEANFILES)\n" +
 203    "             @if exist $(target).def.org ren $(target).def.org $(target).def"
 204  else
 205    "             @$(RM) *.ilk *.exp *.pdb *.bak $(CLEANFILES)"
 206  end
 207  }
 208  
 209  distclean:      clean
 210                  @$(RM) Makefile extconf.h conftest.*
 211                  @$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
 212  
 213  realclean:      distclean
 214  EOS
 215  
 216    mfile.printf <<EOS
 217  
 218  install:
 219          @$(MAKEDIRS) $(DESTDIR)$(libdir) $(DESTDIR)$(pkglibdir) $(DESTDIR)$(archdir)$(target_prefix)
 220  EOS
 221    unless $static
 222      mfile.printf "\
 223          @$(INSTALL_PROG) $(DLLIB) $(DESTDIR)$(archdir)$(target_prefix)/$(DLLIB)
 224  "
 225    end
 226    save_srcdir = Config::CONFIG['srcdir']
 227    Config::CONFIG['srcdir'] = $srcdir
 228    install_rb(mfile, '$(DESTDIR)$(rubylibdir)$(target_prefix)', '$(srcdir)')
 229    Config::CONFIG['srcdir'] = save_srcdir
 230    mfile.printf "\n"
 231  
 232    unless /mswin32/ =~ RUBY_PLATFORM
 233      if /bccwin32/ =~ RUBY_PLATFORM
 234        src = '$(<:\\=/)'
 235      else
 236        src = '$<'
 237      end
 238      copt = cxxopt = ''
 239    else
 240      if /nmake/i =~ $make
 241        src = '$(<:\\=/)'
 242      else
 243        src = '$(subst /,\\\\,$<)'
 244      end
 245      copt = '-Tc'
 246      cxxopt = '-Tp'
 247    end
 248    unless /nmake/i =~ $make
 249      if /bccwin32/ =~ RUBY_PLATFORM
 250      mfile.print "
 251  {$(srcdir)}.cc{}.#{CONFIG['OBJEXT']}:
 252          $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 253  {$(srcdir)}.cpp{}.#{CONFIG['OBJEXT']}:
 254          $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 255  {$(srcdir)}.cxx{}.#{CONFIG['OBJEXT']}:
 256          $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 257  {$(srcdir)}.c{}.#{CONFIG['OBJEXT']}:
 258          $(CC) $(CFLAGS) $(CPPFLAGS) -c #{copt}#{src}
 259  "
 260      end
 261      mfile.puts "
 262  .cc.#{CONFIG['OBJEXT']}:
 263          $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 264  .cpp.#{CONFIG['OBJEXT']}:
 265          $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 266  .cxx.#{CONFIG['OBJEXT']}:
 267          $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 268  .C.#{CONFIG['OBJEXT']}:
 269          $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 270  .c.#{CONFIG['OBJEXT']}:
 271          $(CC) $(CFLAGS) $(CPPFLAGS) -c #{copt}#{src}
 272  "
 273    else
 274      mfile.print "
 275  {$(srcdir)}.c{}.#{CONFIG['OBJEXT']}:
 276          $(CC) -I. -I$(<D) $(CFLAGS) $(CPPFLAGS) -c #{copt}#{src}
 277  .c.#{CONFIG['OBJEXT']}:
 278          $(CC) $(CFLAGS) $(CPPFLAGS) -c #{copt}#{src}
 279  {$(srcdir)}.cc{}.#{CONFIG['OBJEXT']}:
 280          $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 281  .cc.#{CONFIG['OBJEXT']}:
 282          $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 283  {$(srcdir)}.cpp{}.#{CONFIG['OBJEXT']}:
 284          $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 285  .cpp.#{CONFIG['OBJEXT']}:
 286          $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 287  {$(srcdir)}.cxx{}.#{CONFIG['OBJEXT']}:
 288          $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 289  .cxx.#{CONFIG['OBJEXT']}:
 290          $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c #{cxxopt}#{src}
 291  "
 292    end
 293  
 294    if $static
 295      if CONFIG['AR'] =~ /^lib\b/i
 296        mfile.printf "\
 297  $(DLLIB): $(OBJS)
 298          #{CONFIG['AR']} /OUT:$(DLLIB) $(OBJS)
 299  "
 300      else
 301        mfile.printf "\
 302  $(DLLIB): $(OBJS)
 303          #{CONFIG['AR']} cru $(DLLIB) $(OBJS)
 304          @-#{CONFIG['RANLIB']} $(DLLIB) 2> /dev/null || true
 305  "
 306      end
 307    elsif CONFIG['DLEXT'] != $OBJEXT
 308      mfile.print "$(DLLIB): $(OBJS)\n"
 309      if /bccwin32/ =~ RUBY_PLATFORM 
 310        mfile.print "\t$(LDSHARED) $(DLDFLAGS) C0D32.OBJ $(OBJS), $@,, CW32.LIB IMPORT32.LIB WS2_32.LIB $(LIBS), #{deffile}\n"
 311      else
 312        if /mswin32/ =~ RUBY_PLATFORM
 313          if /nmake/i =~ $make
 314            mfile.print "\tset LIB=$(LIBPATH:/=\\);$(LIB)\n"
 315          else
 316            mfile.print "\tenv LIB='$(subst /,\\\\,$(LIBPATH));$(LIB)' \\\n"
 317          end
 318        end
 319        mfile.print "\t$(LDSHARED) $(DLDFLAGS) #{OUTFLAG}$(DLLIB) $(OBJS) $(LIBS) $(LOCAL_LIBS)\n"
 320      end
 321    elsif RUBY_PLATFORM == "m68k-human"
 322      mfile.printf "\
 323  $(DLLIB): $(OBJS)
 324          ar cru $(DLLIB) $(OBJS)
 325  "
 326    else
 327      mfile.printf "\
 328  $(DLLIB): $(OBJS)
 329          ld $(DLDFLAGS) -r -o $(DLLIB) $(OBJS)
 330  "
 331    end
 332  
 333    if File.exist?("#{$srcdir}/depend")
 334      dfile = open("#{$srcdir}/depend", "r")
 335      mfile.printf "###\n"
 336      while line = dfile.gets()
 337        line.gsub!(/\.o\b/, ".#{$OBJEXT}")
 338        if /bccwin32/ =~ RUBY_PLATFORM
 339          line.gsub!(/(\s)([^\s\/]+\.[ch])/, '\1{$(srcdir)}\2')
 340        else
 341          line.gsub!(/(\s)([^\s\/]+\.[ch])/, '\1{$(srcdir)}\2') if /nmake/i =~ $make
 342        end
 343        mfile.printf "%s", line.gsub(/\$\(hdrdir\)\/config.h/, '$(topdir)/config.h')
 344      end
 345      dfile.close
 346    end
 347    mfile.close
 348  end
 349  
 350  def extmake(target)
 351    if $force_static or $static_ext[target]
 352      $static = target
 353    else
 354      $static = false
 355    end
 356  
 357    unless $install or $clean
 358      return if $nodynamic and not $static
 359    end
 360  
 361    $OBJEXT = CONFIG['OBJEXT']
 362    $LIBEXT = "a"
 363    $objs = nil
 364    $libs = CONFIG['DLDLIBS'].dup
 365    $local_flags = ""
 366    if /mswin32/ =~ RUBY_PLATFORM
 367      $LIBEXT = "lib"
 368      $local_flags = "-link /INCREMENTAL:no /EXPORT:Init_$(TARGET)"
 369    elsif /bccwin32/ =~ RUBY_PLATFORM
 370      $LIBEXT = "lib"
 371    end
 372    $LOCAL_LIBS = ""              # to be assigned in extconf.rb
 373    $CFLAGS = ""
 374    $CPPFLAGS = CONFIG['CPPFLAGS']
 375    $LDFLAGS = ""
 376    $LIBPATH = [$libdir]
 377    $INCFLAGS = "-I#{$topdir}"
 378  
 379    dir_config("opt")
 380  
 381    begin
 382      dir = Dir.pwd
 383      File.mkpath target unless File.directory?(target)
 384      Dir.chdir target
 385      $target = target
 386      $mdir = target
 387      unless $install or $clean
 388        if $static_ext.size > 0 ||
 389          !File.exist?("./Makefile") ||
 390          older("./Makefile", $setup) ||
 391          older("./Makefile", "#{$top_srcdir}/ext/extmk.rb") ||
 392          older("./Makefile", "#{$top_srcdir}/ext/#{target}/makefile.rb") ||
 393          older("./Makefile", "#{$top_srcdir}/ext/#{target}/extconf.rb")
 394        then
 395          $defs = []
 396          Logging::logfile 'mkmf.log'
 397          if File.exist?("#{$top_srcdir}/ext/#{target}/makefile.rb")
 398            load "#{$top_srcdir}/ext/#{target}/makefile.rb"
 399          elsif File.exist?("#{$top_srcdir}/ext/#{target}/extconf.rb")
 400            load "#{$top_srcdir}/ext/#{target}/extconf.rb"
 401          else
 402            create_makefile(target)
 403          end
 404        end
 405      end
 406      if File.exist?("./Makefile")
 407        if $static
 408          $extlist.push [$static, $target, File.basename($target)]
 409        end
 410        if $install
 411          if /bccwin32/ =~ RUBY_PLATFORM
 412            system "#{$make} -DDESTDIR=#{$destdir} install"
 413          else
 414            system "#{$make} install DESTDIR=#{$destdir}"
 415          end
 416        elsif $clean
 417          system "#{$make} #{$clean}"
 418        else
 419          unless system "#{$make} all"
 420            if ENV["MAKEFLAGS"] != "k" and ENV["MFLAGS"] != "-k"
 421              exit
 422            end
 423          end
 424        end
 425      end
 426      if $static
 427        $extlibs ||= ""
 428        $extlibs += " " + $DLDFLAGS if $DLDFLAGS
 429        $extlibs += " " + $LDFLAGS unless $LDFLAGS == ""
 430        $extlibs += " " + $libs unless $libs == ""
 431        $extlibs += " " + $LOCAL_LIBS unless $LOCAL_LIBS == ""
 432      end
 433    ensure
 434      rm_f "conftest*"
 435      Dir.chdir dir
 436    end
 437  end
 438  
 439  $make = ENV["MAKE"]
 440  $make ||= with_config("make-prog", "make")
 441  
 442  File::makedirs('ext')
 443  Dir::chdir('ext')
 444  
 445  # get static-link modules
 446  $static_ext = {}
 447  for setup in [CONFIG['setup'], File::join($top_srcdir, "ext", CONFIG['setup'])]
 448    if File.file? setup
 449      f = open(setup) 
 450      while line = f.gets()
 451        line.chomp!
 452        line.sub!(/#.*$/, '')
 453        next if /^\s*$/ =~ line
 454        if /^option +nodynamic/ =~ line
 455          $nodynamic = true
 456          next
 457        end
 458        target = line.split[0]
 459        target = target.downcase if /mswin32|bccwin32/ =~ RUBY_PLATFORM
 460        $static_ext[target] = true
 461      end
 462      $setup = setup
 463      f.close
 464      break
 465    end
 466  end
 467  
 468  ext_prefix = "#{$top_srcdir}/ext"
 469  for d in Dir["#{ext_prefix}/**/*"]
 470    File.directory?(d) || next
 471    File.file?(d + "/MANIFEST") || next
 472    
 473    d.slice!(0, ext_prefix.length + 1)
 474    if $install
 475      print "installing ", d, "\n"
 476    elsif $clean
 477      print "cleaning ", d, "\n"
 478    else
 479      print "compiling ", d, "\n"
 480      if RUBY_PLATFORM =~ /-aix/ and older("../ruby.imp", "../miniruby")
 481        load "#{$top_srcdir}/ext/aix_mksym.rb"
 482      end
 483    end
 484    $stdout.flush
 485    extmake(d)
 486  end
 487  
 488  if $install or $clean
 489    Dir.chdir ".."
 490    exit
 491  end
 492  $extinit = "" unless $extinit
 493  
 494  ruby = CONFIG["RUBY_INSTALL_NAME"] + CONFIG["EXEEXT"]
 495  miniruby = "miniruby" + CONFIG["EXEEXT"]
 496  
 497  $extobjs = "" unless $extobjs
 498  if $extlist.size > 0
 499    for s,t,i in $extlist
 500      f = format("%s/%s.%s", s, i, $LIBEXT)
 501      if File.exist?(f)
 502        $extinit += format("\
 503  \tInit_%s();\n\
 504  \trb_provide(\"%s.so\");\n\
 505  ", i, t)
 506        $extobjs += "ext/"
 507        $extobjs += f
 508        $extobjs += " "
 509      else
 510        false
 511      end
 512    end
 513  
 514    if older("extinit.c", $setup) || older("extinit.c", "#{$top_srcdir}/ext/extmk.rb")
 515      f = open("extinit.c", "w")
 516      f.printf "void Init_ext() {\n"
 517      f.printf $extinit
 518      f.printf "}\n"
 519      f.close
 520    end
 521    if older("extinit.#{$OBJEXT}", "extinit.c")
 522      cmd = CONFIG["CC"] + " " + CFLAGS + " -c extinit.c"
 523      print cmd, "\n"
 524      system cmd or exit 1
 525    end
 526  
 527    Dir.chdir ".."
 528  
 529    if older(ruby, $setup) or older(ruby, miniruby)
 530      rm_f ruby
 531    end
 532  
 533    $extobjs = "ext/extinit.#{$OBJEXT} " + $extobjs
 534    if RUBY_PLATFORM =~ /m68k-human|beos/
 535      $extlibs.gsub!("-L/usr/local/lib", "") if $extlibs
 536    end
 537    system format(%[#{$make} #{ruby} EXTOBJS='%s' EXTLIBS='%s'], $extobjs, $extlibs)
 538  else
 539    Dir.chdir ".."
 540    if older(ruby, miniruby)
 541      rm_f ruby
 542      system("#{$make} #{ruby}")
 543    end
 544  end
 545  
 546  #Local variables:
 547  # mode: ruby
 548  #end: