| Path: | mkmf.rb |
| Last Update: | Mon Oct 01 13:18:32 -0500 2007 |
module to create Makefile for extension modules invoke like: ruby -r mkmf extconf.rb
| CONFIG | = | Config::MAKEFILE_CONFIG |
| ORIG_LIBPATH | = | ENV['LIB'] |
| CXX_EXT | = | %w[cc cxx cpp] |
| SRC_EXT | = | %w[c m] << CXX_EXT |
| INSTALL_DIRS | = | [ [dir_re('commondir'), "$(RUBYCOMMONDIR)"], [dir_re("sitedir"), "$(RUBYCOMMONDIR)"], [dir_re('rubylibdir'), "$(RUBYLIBDIR)"], [dir_re('archdir'), "$(RUBYARCHDIR)"], [dir_re('sitelibdir'), "$(RUBYLIBDIR)"], [dir_re('sitearchdir'), "$(RUBYARCHDIR)"] |
| OUTFLAG | = | CONFIG['OUTFLAG'] |
| CPPOUTFILE | = | CONFIG['CPPOUTFILE'] |
| CONFTEST_C | = | "conftest.c" |
| FailedMessage | = | <<MESSAGE Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options. Provided configuration options: MESSAGE |
| EXPORT_PREFIX | = | config_string('EXPORT_PREFIX') {|s| s.strip} |
| COMMON_HEADERS | = | hdr.join("\n") |
| COMMON_LIBS | = | config_string('COMMON_LIBS', &split) || [] |
| COMPILE_RULES | = | config_string('COMPILE_RULES', &split) || %w[.%s.%s:] |
| RULE_SUBST | = | config_string('RULE_SUBST') |
| COMPILE_C | = | config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<' |
| COMPILE_CXX | = | config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<' |
| TRY_LINK | = | config_string('TRY_LINK') || "$(CC) #{OUTFLAG}conftest $(INCFLAGS) $(CPPFLAGS) " \ "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)" |
| LINK_SO | = | config_string('LINK_SO') || if CONFIG["DLEXT"] == $OBJEXT |
# File mkmf.rb, line 898 def arg_config(config, *defaults, &block) $arg_config << [config, *defaults] defaults << nil if !block and defaults.empty? $configure_args.fetch(config.tr('_', '-'), *defaults, &block) end
# File mkmf.rb, line 284 def cc_command(opt="") conf = Config::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote) Config::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}", conf) end
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 802 def check_sizeof(type, headers = nil, &b) expr = "sizeof(#{type})" fmt = "%d" def fmt.%(x) x ? super : "failed" end checking_for checking_message("size of #{type}", headers), fmt do if size = try_constant(expr, headers, &b) $defs.push(format("-DSIZEOF_%s=%d", type.upcase.tr_s("^A-Z0-9_", "_"), size)) size end end end
# File mkmf.rb, line 551 def checking_for(m, fmt = nil) f = caller[0][/in `(.*)'$/, 1] and f << ": " #` for vim m = "checking #{/\Acheck/ =~ f ? '' : 'for '}#{m}... " message "%s", m a = r = nil Logging::postpone do r = yield a = (fmt ? fmt % r : r ? "yes" : "no") << "\n" "#{f}#{m}-------------------- #{a}\n" end message(a) Logging::message "--------------------\n\n" r end
# File mkmf.rb, line 566 def checking_message(target, place = nil, opt = nil) [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)| if noun [[:to_str], [:join, ","], [:to_s]].each do |meth, *args| if noun.respond_to?(meth) break noun = noun.send(meth, *args) end end msg << " #{pre} #{noun}" unless noun.empty? end msg end end
# File mkmf.rb, line 66 def config_string(key, config = CONFIG) s = config[key] and !s.empty? and block_given? ? yield(s) : s end
# File mkmf.rb, line 1045 def configuration(srcdir) mk = [] vpath = %w[$(srcdir) $(topdir) $(hdrdir)] if !CROSS_COMPILING case CONFIG['build_os'] when 'cygwin' if CONFIG['target_os'] != 'cygwin' vpath.each {|p| p.sub!(/.*/, '$(shell cygpath -u \&)')} end when 'msdosdjgpp', 'mingw32' CONFIG['PATH_SEPARATOR'] = ';' end end mk << %{ SHELL = /bin/sh #### Start of system configuration section. #### srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {CONFIG[$1||$2]}.quote} topdir = #{($extmk ? CONFIG["topdir"] : $topdir).quote} hdrdir = #{$extmk ? CONFIG["hdrdir"].quote : '$(topdir)'} VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])} } if $extmk mk << "RUBYLIB = -\nRUBYOPT = -rpurelib.rb\n" end if destdir = CONFIG["prefix"][$dest_prefix_pattern, 1] mk << "\nDESTDIR = #{destdir}\n" end CONFIG.each do |key, var| next unless /prefix$/ =~ key mk << "#{key} = #{with_destdir(var)}\n" end CONFIG.each do |key, var| next if /^abs_/ =~ key next unless /^(?:src|top|hdr|(.*))dir$/ =~ key and $1 mk << "#{key} = #{with_destdir(var)}\n" end if !$extmk and !$configure_args.has_key?('--ruby') and sep = config_string('BUILD_FILE_SEPARATOR') sep = ":/=#{sep}" else sep = "" end extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ")<<" " mk << %{ CC = #{CONFIG['CC']} LIBRUBY = #{CONFIG['LIBRUBY']} LIBRUBY_A = #{CONFIG['LIBRUBY_A']} LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC RUBY_EXTCONF_H = #{$extconf_h} CFLAGS = #{$static ? '' : CONFIG['CCDLFLAGS']} #$CFLAGS #$ARCH_FLAG INCFLAGS = -I. #$INCFLAGS CPPFLAGS = #{extconf_h}#{$CPPFLAGS} CXXFLAGS = $(CFLAGS) #{CONFIG['CXXFLAGS']} DLDFLAGS = #$LDFLAGS #$DLDFLAGS #$ARCH_FLAG LDSHARED = #{CONFIG['LDSHARED']} AR = #{CONFIG['AR']} EXEEXT = #{CONFIG['EXEEXT']} RUBY_INSTALL_NAME = #{CONFIG['RUBY_INSTALL_NAME']} RUBY_SO_NAME = #{CONFIG['RUBY_SO_NAME']} arch = #{CONFIG['arch']} sitearch = #{CONFIG['sitearch']} ruby_version = #{Config::CONFIG['ruby_version']} ruby = #{$ruby} RUBY = $(ruby#{sep}) RM = #{config_string('RM') || '$(RUBY) -run -e rm -- -f'} MAKEDIRS = #{config_string('MAKEDIRS') || '@$(RUBY) -run -e mkdir -- -p'} INSTALL = #{config_string('INSTALL') || '@$(RUBY) -run -e install -- -vp'} INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'} INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'} COPY = #{config_string('CP') || '@$(RUBY) -run -e cp -- -v'} #### End of system configuration section. #### preload = #{$preload ? $preload.join(' ') : ''} } if $nmake == ?b mk.each do |x| x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do "!ifndef " + $1 + "\n" + $& + "!endif\n" end end end mk end
# File mkmf.rb, line 290 def cpp_command(outfile, opt="") conf = Config::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote) Config::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}", conf) end
# File mkmf.rb, line 329 def cpp_include(header) if header header = [header] unless header.kind_of? Array header.map {|h| "#include <#{h}>\n"}.join else "" end end
# File mkmf.rb, line 937 def create_header(header = "extconf.h") message "creating %s\n", header sym = header.tr("a-z./\055", "A-Z___") hdr = ["#ifndef #{sym}\n#define #{sym}\n"] for line in $defs case line when /^-D([^=]+)(?:=(.*))?/ hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0] : 1}\n" when /^-U(.*)/ hdr << "#undef #$1\n" end end hdr << "#endif\n" hdr = hdr.join unless (IO.read(header) == hdr rescue false) open(header, "w") do |hfile| hfile.write(hdr) end end $extconf_h = header end
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’".
# File mkmf.rb, line 1165 def create_makefile(target, srcprefix = nil) $target = target libpath = $DEFLIBPATH|$LIBPATH message "creating Makefile\n" 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)' Config::expand(srcdir = srcprefix.dup) if not $objs $objs = [] srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")] for f in srcs obj = File.basename(f, ".*") << ".o" $objs.push(obj) unless $objs.index(obj) end elsif !(srcs = $srcs) srcs = $objs.collect {|obj| obj.sub(/\.o\z/, '.c')} end $srcs = srcs for i in $objs i.sub!(/\.o\z/, ".#{$OBJEXT}") end $objs = $objs.join(" ") target = nil if $objs == "" if target and EXPORT_PREFIX if File.exist?(File.join(srcdir, target + '.def')) deffile = "$(srcdir)/$(TARGET).def" unless EXPORT_PREFIX.empty? makedef = %{-pe "sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i"} end else makedef = %{-e "puts 'EXPORTS', '#{EXPORT_PREFIX}Init_$(TARGET)'"} end if makedef $distcleanfiles << '$(DEFFILE)' origdef = deffile deffile = "$(TARGET)-$(arch).def" end end origdef ||= '' libpath = libpathflag(libpath) dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : "" staticlib = target ? "$(TARGET).#$LIBEXT" : "" mfile = open("Makefile", "wb") mfile.print configuration(srcprefix) mfile.print " libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")} LIBPATH = #{libpath} DEFFILE = #{deffile} CLEANFILES = #{$cleanfiles.join(' ')} DISTCLEANFILES = #{$distcleanfiles.join(' ')} extout = #{$extout} extout_prefix = #{$extout_prefix} target_prefix = #{target_prefix} LOCAL_LIBS = #{$LOCAL_LIBS} LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS} SRCS = #{srcs.collect(&File.method(:basename)).join(' ')} OBJS = #{$objs} TARGET = #{target} DLLIB = #{dllib} EXTSTATIC = #{$static || ""} STATIC_LIB = #{staticlib unless $static.nil?} #{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""} " 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']} #{n}il? #{n}tds #{n}map CLEANOBJS = *.#{$OBJEXT} *.#{$LIBEXT} *.s[ol] *.pdb *.exp *.bak all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"} static: $(STATIC_LIB)#{$extout ? " install-rb" : ""} " mfile.print CLEANINGS dirs = [] mfile.print "install: install-so install-rb\n\n" sodir = (dir = "$(RUBYARCHDIR)").dup mfile.print("install-so: #{dir}\n") if target f = "$(DLLIB)" dest = "#{dir}/#{f}" mfile.print "install-so: #{dest}\n" unless $extout mfile.print "#{dest}: #{f}\n" if (sep = config_string('BUILD_FILE_SEPARATOR')) f.gsub!("/", sep) dir.gsub!("/", sep) sep = ":/="+sep f.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2} f.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2} dir.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2} dir.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2} end mfile.print "\t$(INSTALL_PROG) #{f} #{dir}\n" if defined?($installed_list) mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n" end end 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}: #{dir}\n" end files.each do |f| dest = "#{dir}/#{File.basename(f)}" mfile.print("install-rb#{sfx}: #{dest}\n") mfile.print("#{dest}: #{f}\n\t$(#{$extout ? 'COPY' : 'INSTALL_DATA'}) ") sep = config_string('BUILD_FILE_SEPARATOR') if sep f = f.gsub("/", sep) sep = ":/="+sep f = f.gsub(/(\$\(\w+)(\))/) {$1+sep+$2} f = f.gsub(/(\$\{\w+)(\})/) {$1+sep+$2} else sep = "" end mfile.print("#{f} $(@D#{sep})\n") if defined?($installed_list) and !$extout mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n") end end end end dirs.unshift(sodir) if target and !dirs.include?(sodir) dirs.each {|dir| mfile.print "#{dir}:\n\t$(MAKEDIRS) $@\n"} mfile.print "\nsite-install: site-install-so site-install-rb\nsite-install-so: install-so\nsite-install-rb: install-rb\n\n" return unless target mfile.puts SRC_EXT.collect {|ext| ".path.#{ext} = $(VPATH)"} if $nmake == ?b mfile.print ".SUFFIXES: .#{SRC_EXT.join(' .')} .#{$OBJEXT}\n" mfile.print "\n" CXX_EXT.each do |ext| COMPILE_RULES.each do |rule| mfile.printf(rule, ext, $OBJEXT) mfile.printf("\n\t%s\n\n", COMPILE_CXX) end end %w[c].each do |ext| COMPILE_RULES.each do |rule| mfile.printf(rule, ext, $OBJEXT) mfile.printf("\n\t%s\n\n", COMPILE_C) end end mfile.print "$(RUBYARCHDIR)/" if $extout mfile.print "$(DLLIB): ", (makedef ? "$(DEFFILE) " : ""), "$(OBJS)\n" mfile.print "\t@-$(RM) $@\n" mfile.print "\t@-$(MAKEDIRS) $(@D)\n" if $extout link_so = LINK_SO.gsub(/^/, "\t") mfile.print link_so, "\n\n" unless $static.nil? mfile.print "$(STATIC_LIB): $(OBJS)\n\t" mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)" config_string('RANLIB') do |ranlib| mfile.print "\n\t@-#{ranlib} $(DLLIB) 2> /dev/null || true" end end mfile.print "\n\n" if makedef mfile.print "$(DEFFILE): #{origdef}\n" mfile.print "\t$(RUBY) #{makedef} #{origdef} > $@\n\n" end depend = File.join(srcdir, "depend") if File.exist?(depend) suffixes = [] depout = [] open(depend, "r") do |dfile| mfile.printf "###\n" cont = implicit = nil impconv = proc do COMPILE_RULES.each {|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.gsub!(%r"(\s)(?!\.)([^$(){}+=:\s\/\\,]+)(?=\s|\z)") {$1 + RULE_SUBST % $2} end depout << line end while line = dfile.gets() line.gsub!(/\.o\b/, ".#{$OBJEXT}") line.gsub!(/\$\(hdrdir\)\/config.h/, $config_h) if $config_h 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 end unless suffixes.empty? mfile.print ".SUFFIXES: .", suffixes.uniq.join(" ."), "\n\n" end mfile.print "$(OBJS): $(RUBY_EXTCONF_H)\n\n" if $extconf_h mfile.print depout else headers = %w[ruby.h defines.h] if RULE_SUBST headers.each {|h| h.sub!(/.*/) {|*m| RULE_SUBST % m}} end headers << $config_h if $config_h headers << "$(RUBY_EXTCONF_H)" if $extconf_h mfile.print "$(OBJS): ", headers.join(' '), "\n" end $makefile_created = true ensure mfile.close if mfile end
# File mkmf.rb, line 254 def create_tmpsrc(src) src = yield(src) if block_given? src = src.gsub(/[ \t]+$/, '').gsub(/\A\n+|^\n+$/, '').sub(/[^\n]\z/, "\\&\n") open(CONFTEST_C, "wb") do |cfile| cfile.print src end src end
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 command line option.
You may pass along additional ‘include’ or ‘lib’ defaults via the idefault and ldefault parameters, respectively.
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 970 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}/lib" idirs = idir ? Array === idir ? idir : idir.split(File::PATH_SEPARATOR) : [] if defaults idirs.concat(defaults.collect {|dir| dir + "/include"}) idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR) end unless idirs.empty? idirs.collect! {|dir| "-I" + dir} idirs -= Shellwords.shellwords($CPPFLAGS) unless idirs.empty? $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ") end end ldirs = ldir ? Array === ldir ? ldir : ldir.split(File::PATH_SEPARATOR) : [] if defaults ldirs.concat(defaults.collect {|dir| dir + "/lib"}) ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR) end $LIBPATH = ldirs | $LIBPATH [idir, ldir] end
# File mkmf.rb, line 70 def dir_re(dir) Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$(?:\(target_prefix\)|\{target_prefix\}))?') end
# File mkmf.rb, line 1137 def dummy_makefile(srcdir) configuration(srcdir) << "CLEANFILES = \#{$cleanfiles.join(' ')}\nDISTCLEANFILES = \#{$distcleanfiles.join(' ')}\n\nall install static install-so install-rb: Makefile\n\n" << CLEANINGS end
# File mkmf.rb, line 451 def egrep_cpp(pat, src, opt = "", &b) src = create_tmpsrc(src, &b) xpopen(cpp_command('', opt)) do |f| if Regexp === pat puts(" ruby -ne 'print if #{pat.inspect}'") f.grep(pat) {|l| puts "#{f.lineno}: #{l}" return true } false else puts(" egrep '#{pat}'") begin stdin = $stdin.dup $stdin.reopen(f) system("egrep", pat) ensure $stdin.reopen(stdin) end end end ensure rm_f "conftest*" log_src(src) end
# File mkmf.rb, line 925 def enable_config(config, *defaults) if arg_config("--enable-"+config) true elsif arg_config("--disable-"+config) false elsif block_given? yield(config, *defaults) else return *defaults end end
# File mkmf.rb, line 892 def find_executable(bin, path = nil) checking_for checking_message(bin, path) do find_executable0(bin, path) end end
# File mkmf.rb, line 872 def find_executable0find_executable0(bin, path = nil) ext = config_string('EXEEXT') if File.expand_path(bin) == bin return bin if File.executable?(bin) ext and File.executable?(file = bin + ext) and return file return nil end if path ||= ENV['PATH'] path = path.split(File::PATH_SEPARATOR) else path = %w[/usr/local/bin /usr/ucb /usr/bin /bin] end file = nil path.each do |dir| return file if File.executable?(file = File.join(dir, bin)) return file if ext and File.executable?(file << ext) end nil end
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 711 def find_header(header, *paths) header = cpp_include(header) checking_for header do if try_cpp(header) true else found = false paths.each do |dir| opt = "-I#{dir}".quote if try_cpp(header, opt) $INCFLAGS << " " << opt found = true break end end found end end end
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 627 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}() in #{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
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_’.
For example, if have_func(‘foo’) returned true, then the HAVE_FOO preprocessor macro would be passed to the compiler.
# File mkmf.rb, line 657 def have_func(func, headers = nil, &b) checking_for checking_message("#{func}()", headers) do if try_func(func, $libs, headers, &b) $defs.push(format("-DHAVE_%s", func.upcase)) true else false end end end
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 694 def have_header(header, &b) checking_for header do if try_cpp(cpp_include(header), &b) $defs.push(format("-DHAVE_%s", header.tr("a-z./\055", "A-Z___"))) true else false end end end
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.
Real name of the library to be linked can be altered by ’—with-FOOlib’ configuration option.
# File mkmf.rb, line 602 def have_library(lib, func = nil, headers = nil, &b) func = "main" if !func or func.empty? lib = with_config(lib+'lib', lib) checking_for checking_message("#{func}()", LIBARG%lib) do if COMMON_LIBS.include?(lib) true else libs = append_library($libs, lib) if try_func(func, libs, headers, &b) $libs = libs true else false end end end end
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 585 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
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 member name, in uppercase, prepended with ‘HAVE_ST_’.
For example, if have_struct_member(‘foo’, ‘bar’) returned true, then the HAVE_ST_BAR preprocessor macro would be passed to the compiler.
# File mkmf.rb, line 742 def have_struct_member(type, member, headers = nil, &b) checking_for checking_message("#{type}.#{member}", headers) do if try_compile("\#{COMMON_HEADERS}\n\#{cpp_include(headers)}\n/*top*/\nint main() { return 0; }\nint s = (char *)&((\#{type}*)0)->\#{member} - (char *)0;\n", &b) $defs.push(format("-DHAVE_ST_%s", member.upcase)) true else false end end end
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 773 def have_type(type, headers = nil, opt = "", &b) checking_for checking_message(type, headers, opt) do headers = cpp_include(headers) if try_compile("\#{COMMON_HEADERS}\n\#{headers}\n/*top*/\ntypedef \#{type} conftest_type;\nstatic conftest_type conftestval[sizeof(conftest_type)?1:-1];\n", opt, &b) $defs.push(format("-DHAVE_TYPE_%s", type.strip.upcase.tr_s("^A-Z0-9_", "_"))) true else false end end end
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_’.
For example, if have_var(‘foo’) returned true, then the HAVE_FOO preprocessor macro would be passed to the compiler.
# File mkmf.rb, line 676 def have_var(var, headers = nil, &b) checking_for checking_message(var, headers) do if try_var(var, headers, &b) $defs.push(format("-DHAVE_%s", var.upcase)) true else false end end end
# File mkmf.rb, line 1433 def init_mkmf(config = CONFIG) $makefile_created = false $arg_config = [] $enable_shared = config['ENABLE_SHARED'] == 'yes' $defs = [] $extconf_h = nil $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup $LDFLAGS = with_config("ldflags", arg_config("LDFLAGS", config["LDFLAGS"])).dup $INCFLAGS = "-I$(topdir) -I$(hdrdir) -I$(srcdir)" $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup $LIBEXT = config['LIBEXT'].dup $OBJEXT = config["OBJEXT"].dup $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}" $LIBRUBYARG = "" $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC'] $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED'] $DEFLIBPATH = $extmk ? ["$(topdir)"] : CROSS_COMPILING ? [] : ["$(libdir)"] $DEFLIBPATH.unshift(".") $LIBPATH = [] $INSTALLFILES = nil $objs = nil $srcs = nil $libs = "" if $enable_shared or Config.expand(config["LIBRUBY"].dup) != Config.expand(config["LIBRUBY_A"].dup) $LIBRUBYARG = config['LIBRUBYARG'] end $LOCAL_LIBS = "" $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || [] $cleanfiles << "mkmf.log" $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || [] $extout ||= nil $extout_prefix ||= nil $arg_config.clear dir_config("opt") end
# File mkmf.rb, line 83 def install_dirs(target_prefix = nil) if $extout dirs = [ ['RUBYCOMMONDIR', '$(extout)/common'], ['RUBYLIBDIR', '$(RUBYCOMMONDIR)$(target_prefix)'], ['RUBYARCHDIR', '$(extout)/$(arch)$(target_prefix)'], ['extout', "#$extout"], ['extout_prefix', "#$extout_prefix"], ] elsif $extmk dirs = [ ['RUBYCOMMONDIR', '$(rubylibdir)'], ['RUBYLIBDIR', '$(rubylibdir)$(target_prefix)'], ['RUBYARCHDIR', '$(archdir)$(target_prefix)'], ] else dirs = [ ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'], ['RUBYLIBDIR', '$(sitelibdir)$(target_prefix)'], ['RUBYARCHDIR', '$(sitearchdir)$(target_prefix)'], ] end dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")] dirs end
# File mkmf.rb, line 499 def install_files(mfile, ifiles, map = nil, srcprefix = nil) ifiles or return srcprefix ||= '$(srcdir)' Config::expand(srcdir = srcprefix.dup) dirs = [] path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]} ifiles.each do |files, dir, prefix| dir = map_dir(dir, map) prefix = %r|\A#{Regexp.quote(prefix)}/?| if prefix if /\A\.\// =~ files # install files which are in current working directory. files = files[2..-1] len = nil else # install files which are under the $(srcdir). files = File.join(srcdir, files) len = srcdir.size end f = nil Dir.glob(files) do |f| f[0..len] = "" if len d = File.dirname(f) d.sub!(prefix, "") if prefix d = (d.empty? || d == ".") ? dir : File.join(dir, d) f = File.join(srcprefix, f) if len path[d] << f end unless len or f d = File.dirname(files) d.sub!(prefix, "") if prefix d = (d.empty? || d == ".") ? dir : File.join(dir, d) path[d] << files end end dirs end
# File mkmf.rb, line 536 def install_rb(mfile, dest, srcdir = nil) install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir) end
# File mkmf.rb, line 296 def libpathflag(libpath=$DEFLIBPATH|$LIBPATH) libpath.map{|x| case x when "$(topdir)", /\A\./ LIBPATHFLAG else LIBPATHFLAG+RPATHFLAG end % x.quote }.join end
# File mkmf.rb, line 270 def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH) conf = Config::CONFIG.merge('hdrdir' => $hdrdir.quote, 'src' => CONFTEST_C, 'INCFLAGS' => $INCFLAGS, 'CPPFLAGS' => $CPPFLAGS, 'CFLAGS' => "#$CFLAGS", 'ARCH_FLAG' => "#$ARCH_FLAG", 'LDFLAGS' => "#$LDFLAGS #{ldflags}", 'LIBPATH' => libpathflag(libpath), 'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs", 'LIBS' => "#$LIBRUBYARG_STATIC #{opt} #$LIBS") Config::expand(TRY_LINK.dup, conf) end
# File mkmf.rb, line 238 def log_src(src) src = src.split(/^/) fmt = "%#{src.size.to_s.size}d: %s" Logging::message "checked program was:\n/* begin */\n" src.each_with_index {|line, no| Logging::message fmt, no+1, line} Logging::message "/* end */\n\n" end
# File mkmf.rb, line 477 def macro_defined?(macro, src, opt = "", &b) src = src.sub(/[^\n]\z/, "\\&\n") try_compile(src + "/*top*/\n#ifndef \#{macro}\n# error\n>>>>>> \#{macro} undefined <<<<<<\n#endif\n", opt, &b) end
# File mkmf.rb, line 109 def map_dir(dir, map = nil) map ||= INSTALL_DIRS map.inject(dir) {|dir, (orig, new)| dir.gsub(orig, new)} end
# File mkmf.rb, line 152 def merge_libs(*libs) libs.inject([]) do |x, y| xy = x & y xn = yn = 0 y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e} y.each_with_index do |v, yi| if xy.include?(v) xi = [x.index(v), xn].max() x[xi, 1] = y[yn..yi] xn, yn = xi + (yi - yn + 1), yi + 1 end end x.concat(y[yn..-1] || []) end end
# File mkmf.rb, line 544 def message(*s) unless $extmk and not $VERBOSE printf(*s) $stdout.flush end end
# File mkmf.rb, line 1485 def mkmf_failed(path) unless $makefile_created or File.exist?("Makefile") opts = $arg_config.collect {|t, n| "\t#{t}#{n ? "=#{n}" : ""}\n"} abort "*** #{path} failed ***\n" + FailedMessage + opts.join end end
# File mkmf.rb, line 146 def modified?(target, times) (t = File.mtime(target)) rescue return nil Array === times or times = [times] t if times.all? {|n| n <= t} end
# File mkmf.rb, line 1004 def pkg_config(pkg) if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig) # iff package specific config command is given get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp} elsif ($PKGCONFIG ||= (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) && find_executable0(pkgconfig) && pkgconfig) and system("#{$PKGCONFIG} --exists #{pkg}") # default to pkg-config command get = proc {|opt| `#{$PKGCONFIG} --#{opt} #{pkg}`.chomp} elsif find_executable0(pkgconfig = "#{pkg}-config") # default to package specific config command, as a last resort. get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp} end if get cflags = get['cflags'] ldflags = get['libs'] libs = get['libs-only-l'] ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ") $CFLAGS += " " << cflags $LDFLAGS += " " << ldflags $libs += " " << libs Logging::message "package configuration for %s\n", pkg Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n", cflags, ldflags, libs [cflags, ldflags, libs] else Logging::message "package configuration for %s is not found\n", pkg nil end end
# File mkmf.rb, line 816 def scalar_ptr_type?scalar_ptr_type?(type, member = nil, headers = nil, &b) try_compile("\#{COMMON_HEADERS}\n\#{cpp_include(headers)}\n/*top*/\nvolatile \#{type} conftestval;\nint main() { return 0; }\nint t() {return (int)(1-*(conftestval\#{member ? \".\#{member}\" : \"\"}));}\n", &b) # pointer end
# File mkmf.rb, line 828 def scalar_type?(type, member = nil, headers = nil, &b) try_compile("\#{COMMON_HEADERS}\n\#{cpp_include(headers)}\n/*top*/\nvolatile \#{type} conftestval;\nint main() { return 0; }\nint t() {return (int)(1-(conftestval\#{member ? \".\#{member}\" : \"\"}));}\n", &b) # pointer end
# File mkmf.rb, line 317 def try_compile(src, opt="", &b) try_do(src, cc_command(opt), &b) ensure rm_f "conftest*" end
# File mkmf.rb, line 373 def try_constant(const, headers = nil, opt = "", &b) includes = cpp_include(headers) if CROSS_COMPILING if try_static_assert("#{const} > 0", headers, opt) # positive constant elsif try_static_assert("#{const} < 0", headers, opt) neg = true const = "-(#{const})" elsif try_static_assert("#{const} == 0", headers, opt) return 0 else # not a constant return nil end upper = 1 lower = 0 until try_static_assert("#{const} <= #{upper}", headers, opt) lower = upper upper <<= 1 end return nil unless lower while upper > lower + 1 mid = (upper + lower) / 2 if try_static_assert("#{const} > #{mid}", headers, opt) lower = mid else upper = mid end end upper = -upper if neg return upper else src = %{#{COMMON_HEADERS} #{includes} #include <stdio.h> /*top*/ int conftest_const = (int)(#{const}); int main() {printf("%d\\n", conftest_const); return 0;} } if try_link0(src, opt, &b) xpopen("./conftest") do |f| return Integer(f.gets) end end end nil end
# File mkmf.rb, line 323 def try_cpp(src, opt="", &b) try_do(src, cpp_command(CPPOUTFILE, opt), &b) ensure rm_f "conftest*" end
# File mkmf.rb, line 263 def try_do(src, command, &b) src = create_tmpsrc(src, &b) xsystem(command) ensure log_src(src) end
# File mkmf.rb, line 421 def try_func(func, libs, headers = nil, &b) headers = cpp_include(headers) try_link("\#{COMMON_HEADERS}\n\#{headers}\n/*top*/\nint main() { return 0; }\nint t() { void ((*volatile p)()); p = (void ((*)()))\#{func}; return 0; }\n", libs, &b) or try_link("\#{headers}\n/*top*/\nint main() { return 0; }\nint t() { \#{func}(); return 0; }\n", libs, &b) end
# File mkmf.rb, line 311 def try_link(src, opt="", &b) try_link0(src, opt, &b) ensure rm_f "conftest*", "c0x32*" end
# File mkmf.rb, line 489 def try_run(src, opt = "", &b) if try_link0(src, opt, &b) xsystem("./conftest") else nil end ensure rm_f "conftest*" end
# File mkmf.rb, line 362 def try_static_assert(expr, headers = nil, opt = "", &b) headers = cpp_include(headers) try_compile("\#{COMMON_HEADERS}\n\#{headers}\n/*top*/\nint conftest_const[(\#{expr}) ? 1 : -1];\n", opt, &b) end
# File mkmf.rb, line 439 def try_var(var, headers = nil, &b) headers = cpp_include(headers) try_compile("\#{COMMON_HEADERS}\n\#{headers}\n/*top*/\nint main() { return 0; }\nint t() { const volatile void *volatile p; p = (void *)&\#{var}; return 0; }\n", &b) end
# File mkmf.rb, line 840 def what_type?(type, member = nil, headers = nil, &b) m = "#{type}" name = type if member m << "." << member name = "(((#{type} *)0)->#{member})" end fmt = "seems %s" def fmt.%(x) x ? super : "unknown" end checking_for checking_message(m, headers), fmt do if scalar_ptr_type?(type, member, headers, &b) if try_static_assert("sizeof(*#{name}) == 1", headers) "string" end elsif scalar_type?(type, member, headers, &b) if try_static_assert("sizeof(#{name}) > sizeof(long)", headers) "long long" elsif try_static_assert("sizeof(#{name}) > sizeof(int)", headers) "long" elsif try_static_assert("sizeof(#{name}) > sizeof(short)", headers) "int" elsif try_static_assert("sizeof(#{name}) > 1", headers) "short" else "char" end end end end
# File mkmf.rb, line 346 def with_cflags(flags) cflags = $CFLAGS $CFLAGS = flags ret = yield ensure $CFLAGS = cflags unless ret end
# File mkmf.rb, line 904 def with_config(config, *defaults) config = config.sub(/^--with[-_]/, '') val = arg_config("--with-"+config) do if arg_config("--without-"+config) false elsif block_given? yield(config, *defaults) else break *defaults end end case val when "yes" true when "no" false else val end end
# File mkmf.rb, line 338 def with_cppflags(flags) cppflags = $CPPFLAGS $CPPFLAGS = flags ret = yield ensure $CPPFLAGS = cppflags unless ret end
# File mkmf.rb, line 1036 def with_destdir(dir) dir = dir.sub($dest_prefix_pattern, '') /\A\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir end
# File mkmf.rb, line 354 def with_ldflags(flags) ldflags = $LDFLAGS $LDFLAGS = flags ret = yield ensure $LDFLAGS = ldflags unless ret end
# File mkmf.rb, line 226 def xpopen command, *mode, &block Logging::open do case mode[0] when nil, /^r/ puts "#{command} |" else puts "| #{command}" end IO.popen(command, *mode, &block) end end
ruby-doc.org is a service of James Britt and Happy Camper Studios, a Ruby application development company in Phoenix, AZ.
Documentation content on ruby-doc.org is provided by remarkable members of the Ruby community.
For more information on the Ruby programming language, visit ruby-lang.org.
Want to help improve Ruby's API docs? See Ruby Documentation Guidelines.