MakeMakefile

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.

Constants

ASSEMBLE_C

Command which will translate C files to assembler sources in the generated Makefile

ASSEMBLE_CXX

Command which will translate C++ files to assembler sources in the generated Makefile

CLEANINGS

Makefile rules that will clean the extension build directory

COMMON_HEADERS

Common headers for Ruby C extensions

COMMON_LIBS

Common libraries for Ruby C extensions

COMPILE_C

Command which will compile C files in the generated Makefile

COMPILE_CXX

Command which will compile C++ files in the generated Makefile

COMPILE_RULES

make compile rules

CONFIG

The makefile configuration using the defaults from when Ruby was built.

CONFTEST_CXX
CXX_EXT

Extensions for files complied with a C++ compiler

C_EXT

Extensions for files compiled with a C compiler

EXPORT_PREFIX
HDR_EXT

Extensions for header files

LIBARG

Argument which will add a library to the linker

LIBPATHFLAG

Argument which will add a library path to the linker

LINK_SO

Command which will link a shared library

MAIN_DOES_NOTHING

A C main function which does no work

ORIG_LIBPATH
RPATHFLAG
RULE_SUBST
SRC_EXT

Extensions for source files

TRY_LINK

Command which will compile a program in order to test linking a library

TRY_LINK_CXX
UNIVERSAL_INTS

Public Instance Methods

check_signedness(type, headers = nil, opts = nil, &b) click to toggle source

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 preprocessor macro would be passed to the compiler. The SIGNEDNESS_OF_INT=-1 macro would be set for check_signedness('int')

 
 # File mkmf.rb, line 1387
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) click to toggle source

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 mkmf.rb, line 1358
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 checking_message("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) click to toggle source

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 an 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 the type name, followed by =X where "X" is the found convertible type name.

  • TYP2NUM and NUM2TYP, where TYP is the type name in uppercase with replacing an _t suffix with "T", followed by =X where "X" is the macro name to convert type to 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 mkmf.rb, line 1422
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") click to toggle source

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
#endif

Given 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 mkmf.rb, line 1714
def create_header(header = "extconf.h")
 message "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) click to toggle source

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.c

And 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.so

It 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 mkmf.rb, line 2218
 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.delete_prefix('./'))})
 $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" : ""
 conf = configuration(srcprefix)
 conf << "\
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(' ')}
LOCAL_HDRS = #{$headers.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 && $extmk ? '$(extout)/.timestamp' : '.'}
" #"
 # TODO: fixme
 install_dirs.each {|d| conf << ("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
 sodir = $extout ? '$(TARGET_SO_DIR)' : '$(RUBYARCHDIR)'
 n = '$(TARGET_SO_DIR)$(TARGET)'
 conf << "\
TARGET_SO_DIR =#{$extout ? " $(RUBYARCHDIR)/" : ''}
TARGET_SO = $(TARGET_SO_DIR)$(DLLIB)
CLEANLIBS = #{'$(TARGET_SO) ' if target}#{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
CLEANOBJS = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")} if target} *.bak
" #"
 conf = yield(conf) if block_given?
 mfile = open("Makefile", "wb")
 mfile.puts(conf)
 mfile.print "
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+)(\))/) {1ドル+sep+2ドル}
 s.gsub(/(\$\{\w+)(\})/) {1ドル+sep+2ドル}
 }
 rsep = ":#{fsep}=/"
 else
 fseprepl = proc {|s| s}
 sep = ""
 rsep = ""
 end
 dirs = []
 mfile.print "install: install-so install-rb\n\n"
 dir = sodir.dup
 mfile.print("install-so: ")
 if target
 f = "$(DLLIB)"
 dest = "$(TARGET_SO)"
 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 do-install-rb install-rb-default\n")
 mfile.print("install-rb-default: pre-install-rb-default do-install-rb-default\n")
 mfile.print("pre-install-rb: Makefile\n")
 mfile.print("pre-install-rb-default: Makefile\n")
 mfile.print("do-install-rb:\n")
 mfile.print("do-install-rb-default:\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("do-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
 q = "$(MAKE) -q do-install-rb#{sfx}"
 if $nmake
 mfile.print "!if \"$(Q)\" == \"@\"\n\t@#{q} || \\\n!endif\n\t"
 else
 mfile.print "\t$(Q1:0=@#{q} || )"
 end
 mfile.print "$(ECHO1:0=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.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 "$(TARGET_SO): "
 mfile.print "$(DEFFILE) " if makedef
 mfile.print "$(OBJS) Makefile"
 mfile.print " #{timestamp_file(sodir, 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) click to toggle source

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 mkmf.rb, line 2103
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)
 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
 if $extconf_h
 depout.unshift("$(OBJS): $(RUBY_EXTCONF_H)\n\n")
 depout.unshift("$(OBJS): $(hdrdir)/ruby/win32.h\n\n") if $mswin or $mingw
 end
 depout.flatten!
 depout
end
 
dir_config(target) click to toggle source
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 mkmf.rb, line 1764
def dir_config(target, idefault=nil, ldefault=nil)
 if conf = $config_dirs[target]
 return conf
 end
 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
 $config_dirs[target] = [idir, ldir]
end
 
dummy_makefile(srcdir) click to toggle source

creates a stub Makefile.

 
 # File mkmf.rb, line 2072
 def dummy_makefile(srcdir)
 configuration(srcdir) << <<RULES << CLEANINGS
CLEANFILES = #{$cleanfiles.join(' ')}
DISTCLEANFILES = #{$distcleanfiles.join(' ')}
all install static install-so install-rb: Makefile
 @$(NULLCMD)
.PHONY: all install static install-so install-rb
.PHONY: clean clean-so clean-static clean-rb
RULES
 end
 
enable_config(config, default=nil) click to toggle source

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 mkmf.rb, line 1676
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) click to toggle source

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 mkmf.rb, line 1606
def find_executable(bin, path = nil)
 checking_for checking_message(bin, path) do
 find_executable0(bin, path)
 end
end
 
find_header(header, *paths) click to toggle source

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 mkmf.rb, line 1172
def find_header(header, *paths)
 message = checking_message(header, paths)
 header = cpp_include(header)
 checking_for message 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) click to toggle source

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 mkmf.rb, line 1046
def find_library(lib, func, *paths, &b)
 dir_config(lib)
 lib = with_config(lib+'lib', lib)
 paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
 checking_for checking_message(func && 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) click to toggle source

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 mkmf.rb, line 1269
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 checking_message(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) click to toggle source

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 mkmf.rb, line 1317
def have_const(const, headers = nil, opt = "", &b)
 checking_for checking_message([*const].compact.join(' '), headers, opt) do
 try_const(const, headers, opt, &b)
 end
end
 
have_framework(fw, &b) click to toggle source

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 mkmf.rb, line 1143
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) click to toggle source

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 mkmf.rb, line 1080
def have_func(func, headers = nil, opt = "", &b)
 checking_for checking_message(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) click to toggle source

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 mkmf.rb, line 1120
def have_header(header, preheaders = nil, opt = "", &b)
 dir_config(header[/.*?(?=\/)|.*?(?=\.)/])
 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) click to toggle source

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 mkmf.rb, line 1020
def have_library(lib, func = nil, headers = nil, opt = "", &b)
 dir_config(lib)
 lib = with_config(lib+'lib', lib)
 checking_for checking_message(func && 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) click to toggle source

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 mkmf.rb, line 1003
def have_macro(macro, headers = nil, opt = "", &b)
 checking_for checking_message(macro, headers, opt) do
 macro_defined?(macro, cpp_include(headers), opt, &b)
 end
end
 
have_struct_member(type, member, headers = nil, opt = "", &b) click to toggle source

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 mkmf.rb, line 1208
 def have_struct_member(type, member, headers = nil, opt = "", &b)
 checking_for checking_message("#{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) click to toggle source

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 mkmf.rb, line 1256
def have_type(type, headers = nil, opt = "", &b)
 checking_for checking_message(type, headers, opt) do
 try_type(type, headers, opt, &b)
 end
end
 
have_var(var, headers = nil, opt = "", &b) click to toggle source

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 mkmf.rb, line 1102
def have_var(var, headers = nil, opt = "", &b)
 checking_for checking_message(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) click to toggle source

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:

  1. If --with-{pkg}-config={command} is given via command line option: {command} {option}

  2. {pkg}-config {option}

  3. pkg-config {option} {pkg}

Where {option} is, for instance, --cflags.

The values obtained are appended to +$INCFLAGS+, +$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 mkmf.rb, line 1821
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::message "package configuration for %s\n", pkg
 Logging::message "incflags: %s\ncflags: %s\nldflags: %s\nlibs: %s\n\n",
 incflags, cflags, ldflags, libs
 [[incflags, cflags].join(' '), ldflags, libs]
 else
 Logging::message "package configuration for %s is not found\n", pkg
 nil
 end
end
 
try_const(const, headers = nil, opt = "", &b) click to toggle source

Returns whether or not the constant const is defined.

See also have_const

 
 # File mkmf.rb, line 1286
 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) click to toggle source

Returns whether or not the static type type is defined.

See also have_type

 
 # File mkmf.rb, line 1229
 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) click to toggle source

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 mkmf.rb, line 1641
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
 

AltStyle によって変換されたページ (->オリジナル) /