Module: MakeMakefile
| Relationships & Source Files | |
| Defined in: | lib/mkmf.rb | 
Overview
mkmf.rb is used by Ruby C extensions to generate a Makefile which will correctly compile and link the C extension to Ruby and a third-party library.
Constant Summary
- 
    ASSEMBLE_C =
    # File 'lib/mkmf.rb', line 2652Command which will translate C files to assembler sources in the generated Makefile config_string('ASSEMBLE_C') || COMPILE_C.sub(/(?<=\s)-c(?=\s)/, '-S') 
- 
    ASSEMBLE_CXX =
    # File 'lib/mkmf.rb', line 2657Command which will translate C++ files to assembler sources in the generated Makefile config_string('ASSEMBLE_CXX') || COMPILE_CXX.sub(/(?<=\s)-c(?=\s)/, '-S') 
- 
    CLEANINGS =
    # File 'lib/mkmf.rb', line 2701Makefile rules that will clean the extension build directory " clean-static:: clean-rb-default:: clean-rb:: clean-so:: clean: clean-so clean-static clean-rb-default clean-rb \t\t-$(Q)$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep}) .*.time distclean-rb-default:: distclean-rb:: distclean-so:: distclean-static:: distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb \t\t-$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) #{CONFTEST}.* mkmf.log \t\t-$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep}) \t\t-$(Q)$(RMDIRS) $(DISTCLEANDIRS#{sep})#{$ignore_error} realclean: distclean "
- 
    COMMON_HEADERS =
    # File 'lib/mkmf.rb', line 2626Common headers for Ruby C extensions hdr.join("\n") 
- 
    COMMON_LIBS =
    # File 'lib/mkmf.rb', line 2631Common libraries for Ruby C extensions config_string('COMMON_LIBS', &split) || [] 
- 
    COMPILE_C =
    # File 'lib/mkmf.rb', line 2642Command which will compile C files in the generated Makefile config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<' 
- 
    COMPILE_CXX =
    # File 'lib/mkmf.rb', line 2647Command which will compile C++ files in the generated Makefile config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<' 
- 
    COMPILE_RULES =
    # File 'lib/mkmf.rb', line 2636make compile rules config_string('COMPILE_RULES', &split) || %w[.%s.%s:] 
- 
    CONFIG =
    # File 'lib/mkmf.rb', line 63The makefile configuration using the defaults from when Ruby was built. RbConfig::MAKEFILE_CONFIG 
- 
    CXX_EXT =
    # File 'lib/mkmf.rb', line 74Extensions for files complied with a C++ compiler %w[cc mm cxx cpp]
- 
    C_EXT =
    # File 'lib/mkmf.rb', line 69Extensions for files compiled with a C compiler %w[c m]
- 
    EXPORT_PREFIX =
    
 # File 'lib/mkmf.rb', line 2608config_string('EXPORT_PREFIX') {|s| s.strip} 
- 
    HDR_EXT =
    # File 'lib/mkmf.rb', line 87Extensions for header files %w[h hpp]
- 
    LIBARG =
    # File 'lib/mkmf.rb', line 2687Argument which will add a library to the linker config_string('LIBARG') || '-l%s' 
- 
    LIBPATHFLAG =
    # File 'lib/mkmf.rb', line 2681Argument which will add a library path to the linker config_string('LIBPATHFLAG') || ' -L%s' 
- 
    LINK_SO =
    # File 'lib/mkmf.rb', line 2669Command which will link a shared library (config_string('LINK_SO') || "").sub(/^$/) do if CONFIG["DLEXT"] == $OBJEXT "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n" else "$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \ "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)" end end 
- 
    MAIN_DOES_NOTHING =
    # File 'lib/mkmf.rb', line 2692A C main function which does no work config_string('MAIN_DOES_NOTHING') || "int main(int argc, char **argv)\n{\n return 0;\n}" 
- 
    ORIG_LIBPATH =
    
 # File 'lib/mkmf.rb', line 64ENV['LIB'] 
- 
    RPATHFLAG =
    
 # File 'lib/mkmf.rb', line 2682config_string('RPATHFLAG') || '' 
- 
    RULE_SUBST =
    
 # File 'lib/mkmf.rb', line 2637config_string('RULE_SUBST') 
- 
    SRC_EXT =
    # File 'lib/mkmf.rb', line 82Extensions for source files C_EXT + CXX_EXT 
- 
    TRY_LINK =
    # File 'lib/mkmf.rb', line 2662Command which will compile a program in order to test linking a library config_string('TRY_LINK') || "$(CC) #{OUTFLAG}#{CONFTEST}#{$EXEEXT} $(INCFLAGS) $(CPPFLAGS) " \ "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)" 
- 
    UNIVERSAL_INTS =
    
 # File 'lib/mkmf.rb', line 2693config_string('UNIVERSAL_INTS') {|s| Shellwords.shellwords(s)} || %w[int short long long\ long] 
Instance Method Summary
- 
    
      #check_signedness(type, headers = nil, opts = nil, &b)  
    
    Returns the signedness of the given type.
- 
    
      #check_sizeof(type, headers = nil, opts = "", &b)  
    
    Returns the size of the given type.
- 
    
      #convertible_int(type, headers = nil, opts = nil, &b)  
    
    Returns the convertible integer type of the given type.
- 
    
      #create_header(header = "extconf.h")  
    
    Generates a header file consisting of the various macro definitions generated by other methods such as have_func and have_header. 
- 
    
      #create_makefile(target, srcprefix = nil)  
    
    Generates the Makefile for your extension, passing along any options and preprocessor constants that you may have generated through other methods. 
- 
    
      #depend_rules(depend)  
    
    Processes the data contents of the “depend” file. 
- 
    
      #dir_config(target)  
    
    Sets a targetname that the user can then use to configure various “with” options with on the command line by using that name.
- 
    
      #dummy_makefile(srcdir)  
    
    creates a stub Makefile. 
- 
    
      #enable_config(config, default = nil)  
    
    Tests for the presence of an --enable-config or--disable-config option.
- 
    
      #find_executable(bin, path = nil)  
    
    Searches for the executable binonpath.
- 
    
      #find_header(header, *paths)  
    
    Instructs mkmf to search for the given headerin any of thepathsprovided, and returns whether or not it was found in those paths.
- 
    
      #find_library(lib, func, *paths, &b)  
    
    Returns whether or not the entry point funccan be found within the librarylibin one of thepathsspecified, wherepathsis an array of strings.
- 
    
      #find_type(type, opt, *headers, &b)  
    
    Returns where the static type typeis defined.
- 
    
      #have_const(const, headers = nil, opt = "", &b)  
    
    Returns whether or not the constant constis defined.
- 
    
      #have_framework(fw, &b)  
    
    Returns whether or not the given frameworkcan be found on your system.
- 
    
      #have_func(func, headers = nil, opt = "", &b)  
    
    Returns whether or not the function funccan be found in the common header files, or within anyheadersthat you provide.
- 
    
      #have_header(header, preheaders = nil, opt = "", &b)  
    
    Returns whether or not the given headerfile can be found on your system.
- 
    
      #have_library(lib, func = nil, headers = nil, opt = "", &b)  
    
    Returns whether or not the given entry point funccan be found withinlib.
- 
    
      #have_macro(macro, headers = nil, opt = "", &b)  
    
    Returns whether or not macrois defined either in the common header files or within anyheadersyou provide.
- 
    
      #have_struct_member(type, member, headers = nil, opt = "", &b)  
    
    Returns whether or not the struct of type typecontainsmember.
- 
    
      #have_type(type, headers = nil, opt = "", &b)  
    
    Returns whether or not the static type typeis defined.
- 
    
      #have_var(var, headers = nil, opt = "", &b)  
    
    Returns whether or not the variable varcan be found in the common header files, or within anyheadersthat you provide.
- 
    
      #pkg_config(pkg, option = nil)  
    
    Returns compile/link information about an installed library in a tuple of [cflags, ldflags, libs], by using the command found first in the following commands:
- 
    
      #try_const(const, headers = nil, opt = "", &b)  
    
    Returns whether or not the constant constis defined.
- 
    
      #try_type(type, headers = nil, opt = "", &b)  
    
    Returns whether or not the static type typeis defined.
- 
    
      #with_config(config, default = nil)  
    
    Tests for the presence of a --with-config or--without-config option.
Instance Method Details
#check_signedness(type, headers = nil, opts = nil, &b)
Returns the signedness of the given type.  You may optionally specify additional headers to search in for the type.
If the type is found and is a numeric type, a macro is passed as a preprocessor constant to the compiler using the type name, in uppercase, prepended with SIGNEDNESS_OF_, followed by the type name, followed by =X where “X” is positive integer if the type is unsigned and a negative integer if the type is signed.
For example, if size_t is defined as unsigned, then check_signedness('size_t') would return +1 and the SIGNEDNESS_OF_SIZE_T=1</code> preprocessor macro would be passed to the compiler.  The SIGNEDNESS_OF_INT=-1 macro would be set for check_signedness('int')
# File 'lib/mkmf.rb', line 1355
def check_signedness(type, headers = nil, opts = nil, &b) typedef, member, prelude = typedef_expr(type, headers) signed = nil checking_for("signedness of #{type}", STRING_OR_FAILED_FORMAT) do signed = try_signedness(typedef, member, [prelude], opts, &b) or next nil $defs.push("-DSIGNEDNESS_OF_%s=%+d" % [type.tr_cpp, signed]) signed < 0 ? "signed" : "unsigned" end signed end
#check_sizeof(type, headers = nil, opts = "", &b)
Returns the size of the given type.  You may optionally specify additional headers to search in for the type.
If found, a macro is passed as a preprocessor constant to the compiler using the type name, in uppercase, prepended with SIZEOF_, followed by the type name, followed by =X where “X” is the actual size.
For example, if check_sizeof('mystruct') returned 12, then the SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to the compiler.
# File 'lib/mkmf.rb', line 1326
def check_sizeof(type, headers = nil, opts = "", &b) typedef, member, prelude = typedef_expr(type, headers) prelude << "#{typedef} *rbcv_ptr_;\n" prelude = [prelude] expr = "sizeof((*rbcv_ptr_)#{"." << member if member})" fmt = STRING_OR_FAILED_FORMAT checking_for ("size of #{type}", headers), fmt do if size = try_constant(expr, prelude, opts, &b) $defs.push(format("-DSIZEOF_%s=%s", type.tr_cpp, size)) size end end end
#convertible_int(type, headers = nil, opts = nil, &b)
Returns the convertible integer type of the given type.  You may optionally specify additional headers to search in for the type. convertible means actually the same type, or typedef'd from the same type.
If the type is a integer type and the convertible type is found, the following macros are passed as preprocessor constants to the compiler using the type name, in uppercase.
- 
TYPEOF_, followed by thetypename, followed by=Xwhere “X” is the found convertible type name.
- 
TYP2NUMandNUM2TYP, whereTYPis thetypename in uppercase with replacing an_tsuffix with “T”, followed by=Xwhere “X” is the macro name to converttypeto an Integer object, and vice versa.
For example, if foobar_t is defined as unsigned long, then convertible_int("foobar_t") would return “unsigned long”, and define these macros:
#define TYPEOF_FOOBAR_T unsigned long
#define FOOBART2NUM ULONG2NUM
#define NUM2FOOBART NUM2ULONG# File 'lib/mkmf.rb', line 1390
def convertible_int(type, headers = nil, opts = nil, &b) type, macname = *type checking_for("convertible type of #{type}", STRING_OR_FAILED_FORMAT) do if UNIVERSAL_INTS.include?(type) type else typedef, member, prelude = typedef_expr(type, headers, &b) if member prelude << "static rbcv_typedef_ rbcv_var;" compat = UNIVERSAL_INTS.find {|t| try_static_assert("sizeof(rbcv_var.#{member}) == sizeof(#{t})", [prelude], opts, &b) } else next unless signed = try_signedness(typedef, member, [prelude]) u = "unsigned " if signed > 0 prelude << "extern rbcv_typedef_ foo();" compat = UNIVERSAL_INTS.find {|t| try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, :werror=>true, &b) } end if compat macname ||= type.sub(/_(?=t\z)/, '').tr_cpp conv = (compat == "long long" ? "LL" : compat.upcase) compat = "#{u}#{compat}" typename = type.tr_cpp $defs.push(format("-DSIZEOF_%s=SIZEOF_%s", typename, compat.tr_cpp)) $defs.push(format("-DTYPEOF_%s=%s", typename, compat.quote)) $defs.push(format("-DPRI_%s_PREFIX=PRI_%s_PREFIX", macname, conv)) conv = (u ? "U" : "") + conv $defs.push(format("-D%s2NUM=%s2NUM", macname, conv)) $defs.push(format("-DNUM2%s=NUM2%s", macname, conv)) compat end end end end
#create_header(header = "extconf.h")
Generates a header file consisting of the various macro definitions generated by other methods such as have_func and have_header. These are then wrapped in a custom #ifndef based on the header file name, which defaults to “extconf.h”.
For example:
# extconf.rb
require 'mkmf'
have_func('realpath')
have_header('sys/utime.h')
create_header
create_makefile('foo')The above script would generate the following extconf.h file:
#ifndef EXTCONF_H
#define EXTCONF_H
#define HAVE_REALPATH 1
#define HAVE_SYS_UTIME_H 1
#endifGiven that the create_header method generates a file based on definitions set earlier in your extconf.rb file, you will probably want to make this one of the last methods you call in your script.
# File 'lib/mkmf.rb', line 1681
def create_header(header = "extconf.h") "creating %s\n", header sym = header.tr_cpp hdr = ["#ifndef #{sym}\n#define #{sym}\n"] for line in $defs case line when /^-D([^=]+)(?:=(.*))?/ hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0].gsub(/(?=\t+)/, "\\\n") : 1}\n" when /^-U(.*)/ hdr << "#undef #$1\n" end end hdr << "#endif\n" hdr = hdr.join("") log_src(hdr, "#{header} is") unless (IO.read(header) == hdr rescue false) open(header, "wb") do |hfile| hfile.write(hdr) end end $extconf_h = header end
#create_makefile(target, srcprefix = nil)
Generates the Makefile for your extension, passing along any options and preprocessor constants that you may have generated through other methods.
The target name should correspond the name of the global function name defined within your C extension, minus the Init_.  For example, if your C extension is defined as Init_foo, then your target would simply be “foo”.
If any “/” characters are present in the target name, only the last name is interpreted as the target name, and the rest are considered toplevel directory names, and the generated Makefile will be altered accordingly to follow that directory structure.
For example, if you pass “test/foo” as a target name, your extension will be installed under the “test” directory.  This means that in order to load the file within a Ruby program later, that directory structure will have to be followed, e.g. require 'test/foo'.
The srcprefix should be used when your source files are not in the same directory as your build script. This will not only eliminate the need for you to manually copy the source files into the same directory as your build script, but it also sets the proper target_prefix in the generated Makefile.
Setting the target_prefix will, in turn, install the generated binary in a directory under your RbConfig::CONFIG['sitearchdir'] that mimics your local filesystem when you run make install.
For example, given the following file tree:
ext/
  extconf.rb
  test/
    foo.cAnd given the following code:
create_makefile('test/foo', 'test')That will set the target_prefix in the generated Makefile to “test”. That, in turn, will create the following file tree when installed via the make install command:
/path/to/ruby/sitearchdir/test/foo.soIt is recommended that you use this approach to generate your makefiles, instead of copying files around manually, because some third party libraries may depend on the target_prefix being set properly.
The srcprefix argument can be used to override the default source directory, i.e. the current directory.  It is included as part of the VPATH and added to the list of INCFLAGS.
# File 'lib/mkmf.rb', line 2180
def create_makefile(target, srcprefix = nil)
  $target = target
  libpath = $DEFLIBPATH|$LIBPATH
  message "creating Makefile\n"
  MakeMakefile.rm_f "#{CONFTEST}*"
  if CONFIG["DLEXT"] == $OBJEXT
    for lib in libs = $libs.split
      lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
    end
    $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
  end
  if target.include?('/')
    target_prefix, target = File.split(target)
    target_prefix[0,0] = '/'
  else
    target_prefix = ""
  end
  srcprefix ||= "$(srcdir)/#{srcprefix}".chomp('/')
  RbConfig.expand(srcdir = srcprefix.dup)
  ext = ".#{$OBJEXT}"
  orig_srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")].sort
  if not $objs
    srcs = $srcs || orig_srcs
    $objs = []
    objs = srcs.inject(Hash.new {[]}) {|h, f|
      h.key?(o = File.basename(f, ".*") << ext) or $objs << o
      h[o] <<= f
      h
    }
    unless objs.delete_if {|b, f| f.size == 1}.empty?
      dups = objs.sort.map {|b, f|
        "#{b[/.*\./]}{#{f.collect {|n| n[/([^.]+)\z/]}.join(',')}}"
      }
      abort "source files duplication - #{dups.join(", ")}"
    end
  else
    $objs.collect! {|o| File.basename(o, ".*") << ext} unless $OBJEXT == "o"
    srcs = $srcs || $objs.collect {|o| o.chomp(ext) << ".c"}
  end
  $srcs = srcs
  hdrs = Dir[File.join(srcdir, "*.{#{HDR_EXT.join(%q{,})}}")]
  target = nil if $objs.empty?
  if target and EXPORT_PREFIX
    if File.exist?(File.join(srcdir, target + '.def'))
      deffile = "$(srcdir)/$(TARGET).def"
      unless EXPORT_PREFIX.empty?
        makedef = %{$(RUBY) -pe "$$_.sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i" #{deffile}}
      end
    else
      makedef = %{(echo EXPORTS && echo $(TARGET_ENTRY))}
    end
    if makedef
      $cleanfiles << '$(DEFFILE)'
      origdef = deffile
      deffile = "$(TARGET)-$(arch).def"
    end
  end
  origdef ||= ''
  if $extout and $INSTALLFILES
    $cleanfiles.concat($INSTALLFILES.collect {|files, dir|File.join(dir, files.sub(/\A\.\//, ''))})
    $distcleandirs.concat($INSTALLFILES.collect {|files, dir| dir})
  end
  if $extmk and $static
    $defs << "-DRUBY_EXPORT=1"
  end
  if $extmk and not $extconf_h
    create_header
  end
  libpath = libpathflag(libpath)
  dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
  staticlib = target ? "$(TARGET).#$LIBEXT" : ""
  mfile = open("Makefile", "wb")
  conf = configuration(srcprefix)
  conf = yield(conf) if block_given?
  mfile.puts(conf)
  mfile.print "
libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")}
LIBPATH = #{libpath}
DEFFILE = #{deffile}
CLEANFILES = #{$cleanfiles.join(' ')}
DISTCLEANFILES = #{$distcleanfiles.join(' ')}
DISTCLEANDIRS = #{$distcleandirs.join(' ')}
extout = #{$extout && $extout.quote}
extout_prefix = #{$extout_prefix}
target_prefix = #{target_prefix}
LOCAL_LIBS = #{$LOCAL_LIBS}
LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
ORIG_SRCS = #{orig_srcs.collect(&File.method(:basename)).join(' ')}
SRCS = $(ORIG_SRCS) #{(srcs - orig_srcs).collect(&File.method(:basename)).join(' ')}
OBJS = #{$objs.join(" ")}
HDRS = #{hdrs.map{|h| '$(srcdir)/' + File.basename(h)}.join(' ')}
TARGET = #{target}
TARGET_NAME = #{target && target[/\A\w+/]}
TARGET_ENTRY = #{EXPORT_PREFIX || ''}Init_$(TARGET_NAME)
DLLIB = #{dllib}
EXTSTATIC = #{$static || ""}
STATIC_LIB = #{staticlib unless $static.nil?}
#{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
TIMESTAMP_DIR = #{$extout ? '$(extout)/.timestamp' : '.'}
" #"
  # TODO: fixme
  install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
  n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET)'
  mfile.print "
TARGET_SO     = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
CLEANLIBS     = #{n}.#{CONFIG['DLEXT']} #{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
CLEANOBJS     = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")} if target} *.bak
all:    #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
static: #{$extmk && !$static ? "all" : "$(STATIC_LIB)#{$extout ? " install-rb" : ""}"}
.PHONY: all install static install-so install-rb
.PHONY: clean clean-so clean-static clean-rb
"
  mfile.print CLEANINGS
  fsep = config_string('BUILD_FILE_SEPARATOR') {|s| s unless s == "/"}
  if fsep
    sep = ":/=#{fsep}"
    fseprepl = proc {|s|
      s = s.gsub("/", fsep)
      s = s.gsub(/(\$\(\w+)(\))/) {$1sep$2}
      s.gsub(/(\$\{\w+)(\})/) {$1sep$2}
    }
    rsep = ":#{fsep}=/"
  else
    fseprepl = proc {|s| s}
    sep = ""
    rsep = ""
  end
  dirs = []
  mfile.print "install: install-so install-rb\n\n"
  sodir = (dir = "$(RUBYARCHDIR)").dup
  mfile.print("install-so: ")
  if target
    f = "$(DLLIB)"
    dest = "#{dir}/#{f}"
    stamp = timestamp_file(dir, target_prefix)
    if $extout
      mfile.puts dest
      mfile.print "clean-so::\n"
      mfile.print "\t-$(Q)$(RM) #{fseprepl[dest]} #{fseprepl[stamp]}\n"
      mfile.print "\t-$(Q)$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n"
    else
      mfile.print "#{f} #{stamp}\n"
      mfile.print "\t$(INSTALL_PROG) #{fseprepl[f]} #{dir}\n"
      if defined?($installed_list)
        mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
      end
    end
    mfile.print "clean-static::\n"
    mfile.print "\t-$(Q)$(RM) $(STATIC_LIB)\n"
  else
    mfile.puts "Makefile"
  end
  mfile.print("install-rb: pre-install-rb install-rb-default\n")
  mfile.print("install-rb-default: pre-install-rb-default\n")
  mfile.print("pre-install-rb: Makefile\n")
  mfile.print("pre-install-rb-default: Makefile\n")
  for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]]
    files = install_files(mfile, i, nil, srcprefix) or next
    for dir, *files in files
      unless dirs.include?(dir)
        dirs << dir
        mfile.print "pre-install-rb#{sfx}: #{timestamp_file(dir, target_prefix)}\n"
      end
      for f in files
        dest = "#{dir}/#{File.basename(f)}"
        mfile.print("install-rb#{sfx}: #{dest}\n")
        mfile.print("#{dest}: #{f} #{timestamp_file(dir, target_prefix)}\n")
        mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D)\n")
        if defined?($installed_list) and !$extout
          mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
        end
        if $extout
          mfile.print("clean-rb#{sfx}::\n")
          mfile.print("\t-$(Q)$(RM) #{fseprepl[dest]}\n")
        end
      end
    end
    mfile.print "pre-install-rb#{sfx}:\n"
    if files.empty?
      mfile.print("\t@$(NULLCMD)\n")
    else
      mfile.print("\t$(ECHO) installing#{sfx.sub(/^-/, " ")} #{target} libraries\n")
    end
    if $extout
      dirs.uniq!
      unless dirs.empty?
        mfile.print("clean-rb#{sfx}::\n")
        for dir in dirs.sort_by {|d| -d.count('/')}
          stamp = timestamp_file(dir, target_prefix)
          mfile.print("\t-$(Q)$(RM) #{fseprepl[stamp]}\n")
          mfile.print("\t-$(Q)$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n")
        end
      end
    end
  end
  dirs.unshift(sodir) if target and !dirs.include?(sodir)
  dirs.each do |d|
    t = timestamp_file(d, target_prefix)
    mfile.print "#{t}:\n\t$(Q) $(MAKEDIRS) $(@D) #{d}\n\t$(Q) $(TOUCH) $@\n"
  end
  mfile.print <<-SITEINSTALL
site-install: site-install-so site-install-rb
site-install-so: install-so
site-install-rb: install-rb
  SITEINSTALL
  return unless target
  mfile.puts SRC_EXT.collect {|e| ".path.#{e} = $(VPATH)"} if $nmake == ?b
  mfile.print ".SUFFIXES: .#{(SRC_EXT + [$OBJEXT, $ASMEXT]).compact.join(' .')}\n"
  mfile.print "\n"
  compile_command = "\n\t$(ECHO) compiling $(<#{rsep})\n\t$(Q) %s\n\n"
  command = compile_command % COMPILE_CXX
  asm_command = compile_command.sub(/compiling/, 'translating') % ASSEMBLE_CXX
  CXX_EXT.each do |e|
    each_compile_rules do |rule|
      mfile.printf(rule, e, $OBJEXT)
      mfile.print(command)
      mfile.printf(rule, e, $ASMEXT)
      mfile.print(asm_command)
    end
  end
  command = compile_command % COMPILE_C
  asm_command = compile_command.sub(/compiling/, 'translating') % ASSEMBLE_C
  C_EXT.each do |e|
    each_compile_rules do |rule|
      mfile.printf(rule, e, $OBJEXT)
      mfile.print(command)
      mfile.printf(rule, e, $ASMEXT)
      mfile.print(asm_command)
    end
  end
  mfile.print "$(RUBYARCHDIR)/" if $extout
  mfile.print "$(DLLIB): "
  mfile.print "$(DEFFILE) " if makedef
  mfile.print "$(OBJS) Makefile"
  mfile.print " #{timestamp_file('$(RUBYARCHDIR)', target_prefix)}" if $extout
  mfile.print "\n"
  mfile.print "\t$(ECHO) linking shared-object #{target_prefix.sub(/\A\/(.*)/, '\1/')}$(DLLIB)\n"
  mfile.print "\t-$(Q)$(RM) $(@#{sep})\n"
  link_so = LINK_SO.gsub(/^/, "\t$(Q) ")
  if srcs.any?(&%r"\.(?:#{CXX_EXT.join('|')})\z".method(:===))
    link_so = link_so.sub(/\bLDSHARED\b/, '\&XX')
  end
  mfile.print link_so, "\n\n"
  unless $static.nil?
    mfile.print "$(STATIC_LIB): $(OBJS)\n\t-$(Q)$(RM) $(@#{sep})\n\t"
    mfile.print "$(ECHO) linking static-library $(@#{rsep})\n\t$(Q) "
    mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
    config_string('RANLIB') do |ranlib|
      mfile.print "\n\t-$(Q)#{ranlib} $(@) 2> /dev/null || true"
    end
  end
  mfile.print "\n\n"
  if makedef
    mfile.print "$(DEFFILE): #{origdef}\n"
    mfile.print "\t$(ECHO) generating $(@#{rsep})\n"
    mfile.print "\t$(Q) #{makedef} > $@\n\n"
  end
  depend = File.join(srcdir, "depend")
  if File.exist?(depend)
    mfile.print("###\n", *depend_rules(File.read(depend)))
  else
    mfile.print "$(OBJS): $(HDRS) $(ruby_headers)\n"
  end
  $makefile_created = true
ensure
  mfile.close if mfile
end
  #depend_rules(depend)
Processes the data contents of the “depend” file. Each line of this file is expected to be a file name.
Returns the output of findings, in Makefile format.
# File 'lib/mkmf.rb', line 2067
def depend_rules(depend) suffixes = [] depout = [] cont = implicit = nil impconv = proc do each_compile_rules {|rule| depout << (rule % implicit[0]) << implicit[1]} implicit = nil end ruleconv = proc do |line| if implicit if /\A\t/ =~ line implicit[1] << line next else impconv[] end end if m = /\A\.(\w)\.(\w)(?:\s*:)/.match(line) suffixes << m[1] << m[2] implicit = [[m[1], m[2]], [m.post_match]] next elsif RULE_SUBST and /\A(?!\s*\w+\s*=)[$\w][^#]*:/ =~ line line.sub!(/\s*\#.*$/, '') comment = $& line.gsub!(%r"(\s)(?!\.)([^$(){}=:\s\\,])(?=\s|\z)") {$1 + RULE_SUBST % $2} line = line.chomp + comment + "\n" if comment end depout << line end depend.each_line do |line| line.gsub!(/\.o\b/, ".#{$OBJEXT}") line.gsub!(/\{\$\(VPATH\)\}/, "") unless $nmake line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h) line.gsub!(%r"\$\(hdrdir\)/(?!ruby(?![^:;/\s]))(?=[-\w]+\.h)", '\&ruby/') if $nmake && /\A\s*\$\(RM|COPY\)/ =~ line line.gsub!(%r"[-\w\./]{2,}"){$&.tr("/", "\\")} line.gsub!(/(\$\((?!RM|COPY)[^:)]+)(?=\))/, '\1:/=\\') end if /(?:^|[^\\])(?:\\\\)*\\$/ =~ line (cont ||= []) << line next elsif cont line = (cont << line).join cont = nil end ruleconv.call(line) end if cont ruleconv.call(cont.join) elsif implicit impconv.call end unless suffixes.empty? depout.unshift(".SUFFIXES: ." + suffixes.uniq.join(" .") + "\n\n") end depout.unshift("$(OBJS): $(RUBY_EXTCONF_H)\n\n") if $extconf_h depout.flatten! depout end
    
      #dir_config(target)  
      #dir_config(target, prefix)  
      #dir_config(target, idefault, ldefault)  
    
  
Sets a target name that the user can then use to configure various “with” options with on the command line by using that name.  For example, if the target is set to “foo”, then the user could use the --with-foo-dir=prefix, --with-foo-include=dir and --with-foo-lib=dir command line options to tell where to search for header/library files.
You may pass along additional parameters to specify default values.  If one is given it is taken as default prefix, and if two are given they are taken as “include” and “lib” defaults in that order.
In any case, the return value will be an array of determined “include” and “lib” directories, either of which can be nil if no corresponding command line option is given when no default value is specified.
Note that dir_config only adds to the list of places to search for libraries and include files. It does not link the libraries into your application.
# File 'lib/mkmf.rb', line 1731
def dir_config(target, idefault=nil, ldefault=nil) if dir = with_config(target + "-dir", (idefault unless ldefault)) defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR) idefault = ldefault = nil end idir = with_config(target + "-include", idefault) $arg_config.last[1] ||= "${#{target}-dir}/include" ldir = with_config(target + "-lib", ldefault) $arg_config.last[1] ||= "${#{target}-dir}/#{_libdir_basename}" idirs = idir ? Array === idir ? idir.dup : idir.split(File::PATH_SEPARATOR) : [] if defaults idirs.concat(defaults.collect {|d| d + "/include"}) idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR) end unless idirs.empty? idirs.collect! {|d| "-I" + d} idirs -= Shellwords.shellwords($CPPFLAGS) unless idirs.empty? $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ") end end ldirs = ldir ? Array === ldir ? ldir.dup : ldir.split(File::PATH_SEPARATOR) : [] if defaults ldirs.concat(defaults.collect {|d| "#{d}/#{_libdir_basename}"}) ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR) end $LIBPATH = ldirs | $LIBPATH [idir, ldir] end
#dummy_makefile(srcdir)
creates a stub Makefile.
# File 'lib/mkmf.rb', line 2037
def dummy_makefile(srcdir) configuration(srcdir) << <<RULES << CLEANINGS CLEANFILES = #{$cleanfiles.join(' ')} DISTCLEANFILES = #{$distcleanfiles.join(' ')} all install static install-so install-rb: Makefile .PHONY: all install static install-so install-rb .PHONY: clean clean-so clean-static clean-rb RULES end
#enable_config(config, default = nil)
Tests for the presence of an --enable-config or --disable-config option. Returns true if the enable option is given, false if the disable option is given, and the default value otherwise.
This can be useful for adding custom definitions, such as debug information.
Example:
if enable_config("debug")
   $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
end# File 'lib/mkmf.rb', line 1643
def enable_config(config, default=nil) if arg_config("--enable-"+config) true elsif arg_config("--disable-"+config) false elsif block_given? yield(config, default) else return default end end
#find_executable(bin, path = nil)
Searches for the executable bin on path.  The default path is your PATH environment variable. If that isn't defined, it will resort to searching /usr/local/bin, /usr/ucb, /usr/bin and /bin.
If found, it will return the full path, including the executable name, of where it was found.
Note that this method does not actually affect the generated Makefile.
# File 'lib/mkmf.rb', line 1573
def find_executable(bin, path = nil) checking_for (bin, path) do find_executable0(bin, path) end end
#find_header(header, *paths)
Instructs mkmf to search for the given header in any of the paths provided, and returns whether or not it was found in those paths.
If the header is found then the path it was found on is added to the list of included directories that are sent to the compiler (via the -I switch).
# File 'lib/mkmf.rb', line 1140
def find_header(header, *paths) = (header, paths) header = cpp_include(header) checking_for do if try_header(header) true else found = false paths.each do |dir| opt = "-I#{dir}".quote if try_header(header, opt) $INCFLAGS << " " << opt found = true break end end found end end end
#find_library(lib, func, *paths, &b)
Returns whether or not the entry point func can be found within the library lib in one of the paths specified, where paths is an array of strings.  If func is nil , then the main() function is used as the entry point.
If lib is found, then the path it was found on is added to the list of library paths searched and linked against.
# File 'lib/mkmf.rb', line 1015
def find_library(lib, func, *paths, &b) func = "main" if !func or func.empty? lib = with_config(lib+'lib', lib) paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten checking_for (func.funcall_style, LIBARG%lib) do libpath = $LIBPATH libs = append_library($libs, lib) begin until r = try_func(func, libs, &b) or paths.empty? $LIBPATH = libpath | [paths.shift] end if r $libs = libs libpath = nil end ensure $LIBPATH = libpath if libpath end r end end
#find_type(type, opt, *headers, &b)
Returns where the static type type is defined.
You may also pass additional flags to opt which are then passed along to the compiler.
See also #have_type.
# File 'lib/mkmf.rb', line 1237
def find_type(type, opt, *headers, &b) opt ||= "" fmt = "not found" def fmt.%(x) x ? x.respond_to?(:join) ? x.join(",") : x : self end checking_for (type, nil, opt), fmt do headers.find do |h| try_type(type, h, opt, &b) end end end
#have_const(const, headers = nil, opt = "", &b)
Returns whether or not the constant const is defined.  You may optionally pass the type of const as [const, type], such as:
have_const(%w[PTHREAD_MUTEX_INITIALIZER pthread_mutex_t], "pthread.h")You may also pass additional headers to check against in addition to the common header files, and additional flags to opt which are then passed along to the compiler.
If found, a macro is passed as a preprocessor constant to the compiler using the type name, in uppercase, prepended with HAVE_CONST_.
For example, if have_const('foo') returned true, then the HAVE_CONST_FOO preprocessor macro would be passed to the compiler.
# File 'lib/mkmf.rb', line 1285
def have_const(const, headers = nil, opt = "", &b) checking_for ([*const].compact.join(' '), headers, opt) do try_const(const, headers, opt, &b) end end
#have_framework(fw, &b)
Returns whether or not the given framework can be found on your system. If found, a macro is passed as a preprocessor constant to the compiler using the framework name, in uppercase, prepended with HAVE_FRAMEWORK_.
For example, if have_framework('Ruby') returned true, then the HAVE_FRAMEWORK_RUBY preprocessor macro would be passed to the compiler.
If fw is a pair of the framework name and its header file name that header file is checked, instead of the normally used header file which is named same as the framework.
# File 'lib/mkmf.rb', line 1111
def have_framework(fw, &b) if Array === fw fw, header = *fw else header = "#{fw}.h" end checking_for fw do src = cpp_include("#{fw}/#{header}") << "\n" "int main(void){return 0;}" opt = " -framework #{fw}" if try_link(src, opt, &b) or (objc = try_link(src, "-ObjC#{opt}", &b)) $defs.push(format("-DHAVE_FRAMEWORK_%s", fw.tr_cpp)) # TODO: non-worse way than this hack, to get rid of separating # option and its argument. $LDFLAGS << " -ObjC" if objc and /(\A|\s)-ObjC(\s|\z)/ !~ $LDFLAGS $LIBS << opt true else false end end end
#have_func(func, headers = nil, opt = "", &b)
Returns whether or not the function func can be found in the common header files, or within any headers that you provide.  If found, a macro is passed as a preprocessor constant to the compiler using the function name, in uppercase, prepended with HAVE_.
To check functions in an additional library, you need to check that library first using have_library().  The func shall be either mere function name or function name with arguments.
For example, if have_func('foo') returned true, then the HAVE_FOO preprocessor macro would be passed to the compiler.
# File 'lib/mkmf.rb', line 1049
def have_func(func, headers = nil, opt = "", &b) checking_for (func.funcall_style, headers, opt) do if try_func(func, $libs, headers, opt, &b) $defs << "-DHAVE_#{func.sans_arguments.tr_cpp}" true else false end end end
#have_header(header, preheaders = nil, opt = "", &b)
Returns whether or not the given header file can be found on your system. If found, a macro is passed as a preprocessor constant to the compiler using the header file name, in uppercase, prepended with HAVE_.
For example, if have_header('foo.h') returned true, then the HAVE_FOO_H preprocessor macro would be passed to the compiler.
# File 'lib/mkmf.rb', line 1089
def have_header(header, preheaders = nil, opt = "", &b) checking_for header do if try_header(cpp_include(preheaders)+cpp_include(header), opt, &b) $defs.push(format("-DHAVE_%s", header.tr_cpp)) true else false end end end
#have_library(lib, func = nil, headers = nil, opt = "", &b)
Returns whether or not the given entry point func can be found within lib.  If func is nil, the main() entry point is used by default.  If found, it adds the library to list of libraries to be used when linking your extension.
If headers are provided, it will include those header files as the header files it looks in when searching for func.
The real name of the library to be linked can be altered by --with-FOOlib configuration option.
# File 'lib/mkmf.rb', line 989
def have_library(lib, func = nil, headers = nil, opt = "", &b) func = "main" if !func or func.empty? lib = with_config(lib+'lib', lib) checking_for (func.funcall_style, LIBARG%lib, opt) do if COMMON_LIBS.include?(lib) true else libs = append_library($libs, lib) if try_func(func, libs, headers, opt, &b) $libs = libs true else false end end end end
#have_macro(macro, headers = nil, opt = "", &b)
Returns whether or not macro is defined either in the common header files or within any headers you provide.
Any options you pass to opt are passed along to the compiler.
# File 'lib/mkmf.rb', line 972
def have_macro(macro, headers = nil, opt = "", &b) checking_for (macro, headers, opt) do macro_defined?(macro, cpp_include(headers), opt, &b) end end
#have_struct_member(type, member, headers = nil, opt = "", &b)
Returns whether or not the struct of type type contains member.  If it does not, or the struct type can't be found, then false is returned. You may optionally specify additional headers in which to look for the struct (in addition to the common header files).
If found, a macro is passed as a preprocessor constant to the compiler using the type name and the member name, in uppercase, prepended with HAVE_.
For example, if have_struct_member('struct foo', 'bar') returned true, then the HAVE_STRUCT_FOO_BAR preprocessor macro would be passed to the compiler.
HAVE_ST_BAR is also defined for backward compatibility.
# File 'lib/mkmf.rb', line 1176
def have_struct_member(type, member, headers = nil, opt = "", &b) checking_for ("#{type}.#{member}", headers) do if try_compile(<<"SRC", opt, &b) #{cpp_include(headers)} /*top*/ int s = (char *)&((#{type}*)0)->#{member} - (char *)0; #{MAIN_DOES_NOTHING} SRC $defs.push(format("-DHAVE_%s_%s", type.tr_cpp, member.tr_cpp)) $defs.push(format("-DHAVE_ST_%s", member.tr_cpp)) # backward compatibility true else false end end end
#have_type(type, headers = nil, opt = "", &b)
Returns whether or not the static type type is defined.  You may optionally pass additional headers to check against in addition to the common header files.
You may also pass additional flags to opt which are then passed along to the compiler.
If found, a macro is passed as a preprocessor constant to the compiler using the type name, in uppercase, prepended with HAVE_TYPE_.
For example, if have_type('foo') returned true, then the HAVE_TYPE_FOO preprocessor macro would be passed to the compiler.
# File 'lib/mkmf.rb', line 1224
def have_type(type, headers = nil, opt = "", &b) checking_for (type, headers, opt) do try_type(type, headers, opt, &b) end end
#have_var(var, headers = nil, opt = "", &b)
Returns whether or not the variable var can be found in the common header files, or within any headers that you provide.  If found, a macro is passed as a preprocessor constant to the compiler using the variable name, in uppercase, prepended with HAVE_.
To check variables in an additional library, you need to check that library first using have_library().
For example, if have_var('foo') returned true, then the HAVE_FOO preprocessor macro would be passed to the compiler.
# File 'lib/mkmf.rb', line 1071
def have_var(var, headers = nil, opt = "", &b) checking_for (var, headers, opt) do if try_var(var, headers, opt, &b) $defs.push(format("-DHAVE_%s", var.tr_cpp)) true else false end end end
#pkg_config(pkg, option = nil)
Returns compile/link information about an installed library in a tuple of [cflags, ldflags, libs], by using the command found first in the following commands:
- 
If --with-{pkg}-config={command}is given via command line option:{command} {option}
- 
{pkg}-config {option}
- 
pkg-config {option} {pkg}
Where option is, for instance, --cflags.
The values obtained are appended to $CFLAGS, $LDFLAGS and $libs.
If an option argument is given, the config command is invoked with the option and a stripped output string is returned without modifying any of the global values mentioned above.
# File 'lib/mkmf.rb', line 1784
def pkg_config(pkg, option=nil) if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig) # iff package specific config command is given elsif ($PKGCONFIG ||= (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) && find_executable0(pkgconfig) && pkgconfig) and xsystem("#{$PKGCONFIG} --exists #{pkg}") # default to pkg-config command pkgconfig = $PKGCONFIG get = proc {|opt| opt = xpopen("#{$PKGCONFIG} --#{opt} #{pkg}", err:[:child, :out], &:read) Logging.open {puts opt.each_line.map{|s|"=> #{s.inspect}"}} opt.strip if $?.success? } elsif find_executable0(pkgconfig = "#{pkg}-config") # default to package specific config command, as a last resort. else pkgconfig = nil end if pkgconfig get ||= proc {|opt| opt = xpopen("#{pkgconfig} --#{opt}", err:[:child, :out], &:read) Logging.open {puts opt.each_line.map{|s|"=> #{s.inspect}"}} opt.strip if $?.success? } end orig_ldflags = $LDFLAGS if get and option get[option] elsif get and try_ldflags(ldflags = get['libs']) if incflags = get['cflags-only-I'] $INCFLAGS << " " << incflags cflags = get['cflags-only-other'] else cflags = get['cflags'] end libs = get['libs-only-l'] if cflags $CFLAGS += " " << cflags $CXXFLAGS += " " << cflags end if libs ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ") else libs, ldflags = Shellwords.shellwords(ldflags).partition {|s| s =~ /-l([^ ]+)/ }.map {|l|l.quote.join(" ")} end $libs += " " << libs $LDFLAGS = [orig_ldflags, ldflags].join(' ') Logging:: "package configuration for %s\n", pkg Logging:: "cflags: %s\nldflags: %s\nlibs: %s\n\n", cflags, ldflags, libs [cflags, ldflags, libs] else Logging:: "package configuration for %s is not found\n", pkg nil end end
#try_const(const, headers = nil, opt = "", &b)
Returns whether or not the constant const is defined.
See also #have_const
# File 'lib/mkmf.rb', line 1254
def try_const(const, headers = nil, opt = "", &b) const, type = *const if try_compile(<<"SRC", opt, &b) #{cpp_include(headers)} /*top*/ typedef #{type || 'int'} conftest_type; conftest_type conftestval = #{type ? '' : '(int)'}#{const}; SRC $defs.push(format("-DHAVE_CONST_%s", const.tr_cpp)) true else false end end
#try_type(type, headers = nil, opt = "", &b)
Returns whether or not the static type type is defined.
See also #have_type
# File 'lib/mkmf.rb', line 1197
def try_type(type, headers = nil, opt = "", &b) if try_compile(<<"SRC", opt, &b) #{cpp_include(headers)} /*top*/ typedef #{type} conftest_type; int conftestval[sizeof(conftest_type)?1:-1]; SRC $defs.push(format("-DHAVE_TYPE_%s", type.tr_cpp)) true else false end end
#with_config(config, default = nil)
Tests for the presence of a --with-config or --without-config option.  Returns true if the with option is given, false if the without option is given, and the default value otherwise.
This can be useful for adding custom definitions, such as debug information.
Example:
if with_config("debug")
   $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
end# File 'lib/mkmf.rb', line 1608
def with_config(config, default=nil) config = config.sub(/^--with[-_]/, '') val = arg_config("--with-"+config) do if arg_config("--without-"+config) false elsif block_given? yield(config, default) else break default end end case val when "yes" true when "no" false else val end end