Parent

Class Index [+]

Quicksearch

Mkrf::Availability

The Availability class is concerned with libraries, headers, and functions. It can be easily wrapped (see Mkrf::Generator for an example) and should be able to be used as a basis for a variety of programs which need to determine functionality based on what libraries are available on the current system.

Constants

DEFAULT_INCLUDES
DEFAULT_INCLUDES
TEMP_SOURCE_FILE

These really shouldn’t be static like this..

TEMP_EXECUTABLE

Attributes

headers[R]
loaded_libs[R]
includes[R]
logger[R]
defines[R]

Public Class Methods

new(options = {}) click to toggle source

Create a new Availability instance.

Valid keys for the options hash include:

  • :loaded_libs — libraries to load by default

  • :library_paths — libraries paths to include by default

  • :headers — headers to load by default

  • :compiler — which compiler to use when determining availability

  • :includes — directories that should be searched for include files

    # File lib/mkrf/availability.rb, line 37
37:     def initialize(options = {})      
38:       @loaded_libs = [(options[:loaded_libs] || Config::CONFIG["LIBS"].gsub('-l', '').split)].flatten
39:       @library_paths = [(options[:library_paths] || [])].flatten
40:       # Not sure what COMMON_HEADERS looks like when populated
41:       @headers = options[:headers] || [] # Config::CONFIG["COMMON_HEADERS"]
42:       @compiler = options[:compiler] || Config::CONFIG["CC"]
43:       @includes = [(options[:includes] || DEFAULT_INCLUDES)].flatten
44:       @logger = Logger.new('mkrf.log')
45:       @defines = []
46:     end

Public Instance Methods

find_executable(bin, *paths) click to toggle source

Takes the name of an executable and an optional set of paths to search. If no paths are given, the environmental path is used by default. Returns the absolute path to an executable, or nil if not found.

     # File lib/mkrf/availability.rb, line 190
190:     def find_executable(bin, *paths)
191:       paths = ENV['PATH'].split(File::PATH_SEPARATOR) if paths.empty?
192:       paths.each do |path|
193:         file = File.join(path, bin)
194:         return file if File.executable?(file)
195:       end
196:       return nil
197:     end
has_function?(function) click to toggle source

Returns true if the function is able to be called based on libraries and headers currently loaded. Returns false otherwise.

Params:

  • function — the function to check for

     # File lib/mkrf/availability.rb, line 114
114:     def has_function?(function)
115:       if can_link?(simple_call(function)) or can_link?(simple_reference(function))
116:         logger.info "Function found: #{function}()"
117:         return true
118:       else
119:         logger.warn "Function not found: #{function}()"
120:         return false
121:       end
122:     end
has_header?(header, *paths) click to toggle source

Returns true if the header is found in the default search path or in optional paths passed as an argument, false otherwise. If the header is found, the preprocessor constant HAVE_BLAH is defined where BLAH is the name of the header in uppercase without the file extension.

Params:

  • header — the header to be searched for

  • paths — an optional list of search paths if the header is not found in the default paths

     # File lib/mkrf/availability.rb, line 98
 98:     def has_header?(header, *paths)
 99:       if header_already_loaded?(header) || header_can_link?(header) || 
100:                      header_found_in_paths?(header, paths)
101:         defines << format("HAVE_%s", header.tr("a-z./\0055", "A-Z___"))
102:         return true 
103:       end
104:       
105:       logger.warn "Header not found: #{header}"
106:       return false
107:     end
has_library?(library, function = "main", *paths) click to toggle source

Returns a boolean whether indicating whether the library can be found by attempting to reference the function passed (main by default).

Params:

  • library — the library to be included as a string

  • function — a method to base the inclusion of the library on. main by default.

  • paths — an optional list of search paths if the library is not found in the default paths

    # File lib/mkrf/availability.rb, line 81
81:     def has_library?(library, function = "main", *paths)
82:       logger.info "Checking for library: #{library}"
83:       return true if library_already_loaded?(library)
84:       return true if RUBY_PLATFORM =~ /mswin/ # TODO: find a way on windows
85:       # Should this be only found_library? or a specialized version with
86:       # path searching?
87:       found_library?(library, function)
88:     end
include_header(header, *paths) click to toggle source

Include a header in the list of availiable headers. Returns false if the header is not available. Returns non-false otherwise. If the header is found, the preprocessor constant HAVE_BLAH is defined where BLAH is the name of the header in uppercase without the file extension.

Params:

  • header — the name of the header to be included as a string.

  • paths — an optional list of search paths if the header is not found in the default paths.

    # File lib/mkrf/availability.rb, line 70
70:     def include_header(header, *paths)
71:       @headers << header if has_header?(header, *paths)
72:     end
include_library(library, function = "main", *paths) click to toggle source

Include a library in the list of available libs. Returns false if the library is not available. Returns non-false otherwise.

Params:

  • library — the library to be included as a string.

  • function — a method to base the inclusion of the library on. main by default.

  • paths — an optional list of search paths if the library is not found in the default paths.

    # File lib/mkrf/availability.rb, line 55
55:     def include_library(library, function = "main", *paths)
56:       paths.each do |library_dir|
57:         @library_paths << library_dir
58:       end
59:       @loaded_libs << library if has_library?(library, function)
60:     end
includes_compile_string() click to toggle source

Returns a string of include directories formatted for compilation

     # File lib/mkrf/availability.rb, line 183
183:     def includes_compile_string
184:       @includes.collect {|i| "-I#{i}"}.join(' ')
185:     end
ldshared_string() click to toggle source
     # File lib/mkrf/availability.rb, line 166
166:     def ldshared_string
167:       if RUBY_PLATFORM =~ /mswin/
168:         "link -nologo -incremental:no -debug -opt:ref -opt:icf -dll"
169:       else
170:         Config::CONFIG['LDSHARED']
171:       end
172:     end
library_compile_string() click to toggle source

Returns a string of libraries formatted for compilation

     # File lib/mkrf/availability.rb, line 149
149:     def library_compile_string
150:       if RUBY_PLATFORM =~ /mswin/
151:         @loaded_libs.join(' ')
152:       else
153:         @loaded_libs.collect {|l| "-l#{l}"}.join(' ')
154:       end
155:     end
library_paths_compile_string() click to toggle source

Returns a string of libraries directories formatted for compilation

     # File lib/mkrf/availability.rb, line 158
158:     def library_paths_compile_string
159:       if RUBY_PLATFORM =~ /mswin/
160:         @library_paths.collect {|l| "/libpath:#{l}"}.join(' ')
161:       else
162:         @library_paths.collect {|l| "-L#{l}"}.join(' ')
163:       end
164:     end
with_headers(*args, &b) click to toggle source
     # File lib/mkrf/availability.rb, line 136
136:     def with_headers(*args, &b)
137:       with_stackable_attribute('headers', *args, &b)
138:     end
with_includes(*args, &b) click to toggle source
     # File lib/mkrf/availability.rb, line 144
144:     def with_includes(*args, &b)
145:       with_stackable_attribute('includes', *args, &b)
146:     end
with_loaded_libs(*args, &b) click to toggle source
     # File lib/mkrf/availability.rb, line 140
140:     def with_loaded_libs(*args, &b)
141:       with_stackable_attribute('loaded_libs', *args, &b)
142:     end

Private Instance Methods

create_source(src) click to toggle source

Creates a temporary source file with the string passed

     # File lib/mkrf/availability.rb, line 288
288:     def create_source(src)
289:       File.open(TEMP_SOURCE_FILE, "w+") do |f|
290:         f.write(src)
291:       end
292:     end
found_library?(library, function) click to toggle source
     # File lib/mkrf/availability.rb, line 201
201:     def found_library?(library, function)
202:       library_found = with_loaded_libs(library) {
203:         has_function? function
204:       }
205:       
206:       library_found ? logger.info("Library found: #{library}") : 
207:                         logger.warn("Library not found: #{library}")
208:       
209:       library_found
210:     end
header_already_loaded?(header) click to toggle source
     # File lib/mkrf/availability.rb, line 232
232:     def header_already_loaded?(header)
233:       if @headers.include? header
234:         logger.info("Header already loaded: #{header}")
235:         return true
236:       end 
237:       
238:       return false
239:     end
header_found_in_paths?(header, paths) click to toggle source

def library_found_in_paths?(library, paths)

  paths.each do |include_path|

    if with_libs(include_path) { library_can_link?(header) }
      @libspath << include_path
      return true
    end
  end
  
  return false

end

     # File lib/mkrf/availability.rb, line 254
254:     def header_found_in_paths?(header, paths)
255:       paths.each do |include_path|
256:         if with_includes(include_path) { header_can_link?(header) }
257:           @includes << include_path
258:           return true
259:         end
260:       end
261:       
262:       return false
263:     end
header_include_string() click to toggle source
     # File lib/mkrf/availability.rb, line 275
275:     def header_include_string
276:       @headers.collect {|header| "#include <#{header}>"}.join('\n')
277:     end
library_already_loaded?(library) click to toggle source
     # File lib/mkrf/availability.rb, line 223
223:     def library_already_loaded?(library)
224:       if @loaded_libs.include? library
225:         logger.info "Library already loaded: #{library}" 
226:         return true
227:       end
228:       
229:       return false
230:     end
silence_command_line() click to toggle source
     # File lib/mkrf/availability.rb, line 321
321:     def silence_command_line
322:       yield and return if $debug
323:       silence_stream(STDERR) do
324:         silence_stream(STDOUT) do
325:           yield
326:         end
327:       end
328:     end
silence_stream(stream) click to toggle source

Silences any stream for the duration of the block.

  silence_stream(STDOUT) do
    puts 'This will never be seen'
  end

  puts 'But this will'
     # File lib/mkrf/availability.rb, line 339
339:     def silence_stream(stream)
340:       old_stream = stream.dup
341:       stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
342:       stream.sync = true
343:       yield
344:     ensure
345:       stream.reopen(old_stream)
346:     end
simple_call(func) click to toggle source

Basic skeleton for calling a function

     # File lib/mkrf/availability.rb, line 295
295:     def simple_call(func)
296:       src =         #{header_include_string}        int main() { return 0; }        int t() { #{func}(); return 0; }
297:     end
simple_include(header) click to toggle source

skeleton for testing includes

     # File lib/mkrf/availability.rb, line 313
313:     def simple_include(header)
314:       src =         #{header_include_string}        #include <#{header}>        int main() { return 0; }
315:     end
simple_reference(func) click to toggle source

Basic skeleton for referencing a function

     # File lib/mkrf/availability.rb, line 304
304:     def simple_reference(func)
305:       src =         #{header_include_string}        int main() { return 0; }        int t() { void ((*volatile p)()); p = (void ((*)()))#{func}; return 0; }
306:     end
with_stackable_attribute(attribute, *args) click to toggle source
     # File lib/mkrf/availability.rb, line 265
265:     def with_stackable_attribute(attribute, *args)
266:       args = args.to_a
267:       instance_variable_set("@#{attribute}", 
268:                             instance_variable_get("@#{attribute}") + args)
269:       value = yield
270:       instance_variable_set("@#{attribute}", 
271:                             instance_variable_get("@#{attribute}") - args)
272:       return value
273:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.