Class: Mkrf::Availability

Inherits:
Object
  • Object
show all
Defined in:
lib/mkrf/availability.rb

Overview

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.

Constant Summary collapse

DEFAULT_INCLUDES =
[Config::CONFIG['includedir'], Config::CONFIG["archdir"],
Config::CONFIG['sitelibdir'], "."]
TEMP_SOURCE_FILE =

These really shouldn’t be static like this..

"temp_source.c"
TEMP_EXECUTABLE =
"temp_executable"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Availability

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



29
30
31
32
33
34
35
36
37
38
# File 'lib/mkrf/availability.rb', line 29

def initialize(options = {})      
  @loaded_libs = (options[:loaded_libs] || Config::CONFIG["LIBS"].gsub('-l', '').split).to_a
  @library_paths = (options[:library_paths] || "").to_a
  # Not sure what COMMON_HEADERS looks like when populated
  @headers = options[:headers] || [] # Config::CONFIG["COMMON_HEADERS"]
  @compiler = options[:compiler] || Config::CONFIG["CC"]
  @includes = (options[:includes] || DEFAULT_INCLUDES).to_a
  @logger = Logger.new('mkrf.log')
  @defines = []
end

Instance Attribute Details

#definesObject (readonly)

Returns the value of attribute defines.



19
20
21
# File 'lib/mkrf/availability.rb', line 19

def defines
  @defines
end

#headersObject (readonly)

Returns the value of attribute headers.



19
20
21
# File 'lib/mkrf/availability.rb', line 19

def headers
  @headers
end

#includesObject (readonly)

Returns the value of attribute includes.



19
20
21
# File 'lib/mkrf/availability.rb', line 19

def includes
  @includes
end

#loaded_libsObject (readonly)

Returns the value of attribute loaded_libs.



19
20
21
# File 'lib/mkrf/availability.rb', line 19

def loaded_libs
  @loaded_libs
end

#loggerObject (readonly)

Returns the value of attribute logger.



19
20
21
# File 'lib/mkrf/availability.rb', line 19

def logger
  @logger
end

Instance Method Details

#can_link?(function_body) ⇒ Boolean

Returns the result of an attempt to compile and link the function body passed in

Returns:

  • (Boolean)


118
119
120
121
122
123
124
125
126
# File 'lib/mkrf/availability.rb', line 118

def can_link?(function_body)
  silence_command_line do
    create_source(function_body)
    system(link_command)
  end
ensure
  FileUtils.rm_f TEMP_SOURCE_FILE
  FileUtils.rm_f TEMP_EXECUTABLE
end

#find_executable(bin, *paths) ⇒ Object

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.



182
183
184
185
186
187
188
189
# File 'lib/mkrf/availability.rb', line 182

def find_executable(bin, *paths)
  paths = ENV['PATH'].split(File::PATH_SEPARATOR) if paths.empty?
  paths.each do |path|
    file = File.join(path, bin)
    return file if File.executable?(file)
  end
  return nil
end

#has_function?(function) ⇒ Boolean

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

Returns:

  • (Boolean)


106
107
108
109
110
111
112
113
114
# File 'lib/mkrf/availability.rb', line 106

def has_function?(function)
  if can_link?(simple_call(function)) or can_link?(simple_reference(function))
    logger.info "Function found: #{function}()"
    return true
  else
    logger.warn "Function not found: #{function}()"
    return false
  end
end

#has_header?(header, *paths) ⇒ Boolean

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

Returns:

  • (Boolean)


90
91
92
93
94
95
96
97
98
99
# File 'lib/mkrf/availability.rb', line 90

def has_header?(header, *paths)
  if header_already_loaded?(header) || header_can_link?(header) || 
                 header_found_in_paths?(header, paths)
    defines << format("HAVE_%s", header.tr("a-z./\055", "A-Z___"))
    return true 
  end
  
  logger.warn "Header not found: #{header}"
  return false
end

#has_library?(library, function = "main", *paths) ⇒ Boolean

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

Returns:

  • (Boolean)


73
74
75
76
77
78
79
80
# File 'lib/mkrf/availability.rb', line 73

def has_library?(library, function = "main", *paths)
  logger.info "Checking for library: #{library}"
  return true if library_already_loaded?(library)
  return true if RUBY_PLATFORM =~ /mswin/ # TODO: find a way on windows
  # Should this be only found_library? or a specialized version with
  # path searching?
  found_library?(library, function)
end

#include_header(header, *paths) ⇒ Object

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.



62
63
64
# File 'lib/mkrf/availability.rb', line 62

def include_header(header, *paths)
  @headers << header if has_header?(header, *paths)
end

#include_library(library, function = "main", *paths) ⇒ Object

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.



47
48
49
50
51
52
# File 'lib/mkrf/availability.rb', line 47

def include_library(library, function = "main", *paths)
  paths.each do |library_dir|
    @library_paths << library_dir
  end
  @loaded_libs << library if has_library?(library, function)
end

#includes_compile_stringObject

Returns a string of include directories formatted for compilation



175
176
177
# File 'lib/mkrf/availability.rb', line 175

def includes_compile_string
  @includes.collect {|i| "-I#{i}"}.join(' ')
end

#ld_outfile(filename) ⇒ Object

:nodoc:



166
167
168
169
170
171
172
# File 'lib/mkrf/availability.rb', line 166

def ld_outfile(filename) # :nodoc:
  if RUBY_PLATFORM =~ /mswin/
    "-out:#{filename}"
  else
    "-o #{filename}"
  end
end

#ldshared_stringObject



158
159
160
161
162
163
164
# File 'lib/mkrf/availability.rb', line 158

def ldshared_string
  if RUBY_PLATFORM =~ /mswin/
    "link -nologo -incremental:no -debug -opt:ref -opt:icf -dll"
  else
    Config::CONFIG['LDSHARED']
  end
end

#library_compile_stringObject

Returns a string of libraries formatted for compilation



141
142
143
144
145
146
147
# File 'lib/mkrf/availability.rb', line 141

def library_compile_string
  if RUBY_PLATFORM =~ /mswin/
    @loaded_libs.join(' ')
  else
    @loaded_libs.collect {|l| "-l#{l}"}.join(' ')
  end
end

#library_paths_compile_stringObject

Returns a string of libraries directories formatted for compilation



150
151
152
153
154
155
156
# File 'lib/mkrf/availability.rb', line 150

def library_paths_compile_string
  if RUBY_PLATFORM =~ /mswin/
    @library_paths.collect {|l| "/libpath:#{l}"}.join(' ')
  else
    @library_paths.collect {|l| "-L#{l}"}.join(' ')
  end
end

#with_headers(*args, &b) ⇒ Object



128
129
130
# File 'lib/mkrf/availability.rb', line 128

def with_headers(*args, &b)
  with_stackable_attribute('headers', *args, &b)
end

#with_includes(*args, &b) ⇒ Object



136
137
138
# File 'lib/mkrf/availability.rb', line 136

def with_includes(*args, &b)
  with_stackable_attribute('includes', *args, &b)
end

#with_loaded_libs(*args, &b) ⇒ Object



132
133
134
# File 'lib/mkrf/availability.rb', line 132

def with_loaded_libs(*args, &b)
  with_stackable_attribute('loaded_libs', *args, &b)
end