Class: Mkrf::Generator

Inherits:
Object
  • Object
show all
Includes:
Rake
Defined in:
lib/mkrf/generator.rb

Overview

Generator is concerned with taking configuration for an extension and writing a Rakefile to the local filesystem which will later be used to build the extension.

You will typically only create one Generator per extconf.rb file, which in turn will generate a Rakefile for building one extension module.

Usage

In the most basic usage, Generator simply takes the name of the library to compile:

require 'mkrf'
Mkrf::Generator.new('libtrivial')

Configuration of the build can be passed to the Generator constructor as a block:

Mkrf::Generator.new('libxml') do |g|
  g.include_library('socket','socket')
  g.include_header('libxml/xmlversion.h',
                   '/opt/include/libxml2',
                   '/usr/local/include/libxml2',
                   '/usr/include/libxml2')
end

It is also possible to specify the library paths in include_library

Mkrf::Generator.new('libxml') do |g|
  g.include_library('socket','socket', '/usr/local/lib/libxml')
end

Constant Summary collapse

CONFIG =
Config::CONFIG

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(extension_name, source_patterns = ["*.c"], availability_options = {}) {|_self| ... } ⇒ Generator

Create a Generator object which writes a Rakefile to the current directory of the local filesystem.

Params:

  • extension_name – the name of the extension

  • source_patterns – an array of patterns describing source files to be compiled. [“*.c”] is the default.

Yields:

  • (_self)

Yield Parameters:



73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/mkrf/generator.rb', line 73

def initialize(extension_name, source_patterns = ["*.c"], availability_options = {})
  @sources = source_patterns
  @extension_name = extension_name + ".#{CONFIG['DLEXT']}"
  @available = Mkrf::Availability.new(availability_options)
  @defines = []
  @cc = CONFIG['CC']
  
  @objects  = ''
  @ldshared = ''
  @cflags   = "#{CONFIG['CCDLFLAGS']} #{CONFIG['CFLAGS']} #{CONFIG['ARCH_FLAG']}"
  
  yield self if block_given?
  write_rakefile
end

Instance Attribute Details

#additional_codeObject

Any extra code, given as a string, to be appended to the Rakefile.



47
48
49
# File 'lib/mkrf/generator.rb', line 47

def additional_code
  @additional_code
end

#cflagsObject

You may append to these attributes directly in your Generator.new block, for example: g.objects << ' ../common/foo.o ../common/bar.so -lmystuff' or g.cflags << ' -ansi -Wall'

Note the extra space at the beginning of those strings.



54
55
56
# File 'lib/mkrf/generator.rb', line 54

def cflags
  @cflags
end

#ldsharedObject

Any additional options you’d like appended to your system-specific linker command (which is used to build the shared library).



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

def ldshared
  @ldshared
end

#objectsObject

objects is for adding additional object files to the link-edit command – outside of the ones that correspond to the source files.



58
59
60
# File 'lib/mkrf/generator.rb', line 58

def objects
  @objects
end

Instance Method Details

#abort!(str, code = 1) ⇒ Object

Logs a fatal error and exits with a non-zero code (defaults to 1)



141
142
143
144
# File 'lib/mkrf/generator.rb', line 141

def abort!(str, code = 1)
  logger.fatal str
  exit code
end

#add_define(defn) ⇒ Object

Add a define to the compile string. Example:

Mkrf::Generator.new('my_library') do |g|    
  g.add_define('HAVE_PTHREADS')
end

Params:

  • defn – string to add to compile time defines



101
102
103
# File 'lib/mkrf/generator.rb', line 101

def add_define(defn)
  @available.defines << defn
end

#defines_compile_stringObject

:nodoc:



153
154
155
# File 'lib/mkrf/generator.rb', line 153

def defines_compile_string # :nodoc:
  @available.defines.collect {|define| "-D#{define}"}.join(' ')
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)


126
127
128
# File 'lib/mkrf/generator.rb', line 126

def has_function?(function)
  @available.has_function? function
end

#include_header(*args) ⇒ Object

Include a header in the compile. Returns false if the header is not available, returns non-false otherwise. As a side effect, a compile time define occurs as HAVE_ appended with the name of the header in upper and scored case. Parameters are the same as Mkrf::Availability#include_header



117
118
119
# File 'lib/mkrf/generator.rb', line 117

def include_header(*args)
  @available.include_header(*args)
end

#include_library(*args) ⇒ Object

Include a library in the compile. Returns false if the library is not available. Returns non-false otherwise. Parameters are the same as Mkrf::Availability#include_library



108
109
110
# File 'lib/mkrf/generator.rb', line 108

def include_library(*args)
  @available.include_library(*args)
end

#loggerObject

Returns mkrf’s logger instance. You can use this to set logging levels.

Mkrf::Generator.new('libsomethin') do |g|
  g.logger.level = Logger::WARN
end


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

def logger
  @available.logger
end

#rakefile_contentsObject

:nodoc:



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/mkrf/generator.rb', line 157

def rakefile_contents # :nodoc:
  <<-END_RAKEFILE
# Generated by mkrf
require 'rake/clean'

CLEAN.include('*.o')
CLOBBER.include('#{@extension_name}', 'mkrf.log')

SRC = FileList[#{sources.join(',')}]
OBJ = SRC.ext('o')
CC = '#{@cc}'

ADDITIONAL_OBJECTS = '#{objects}'

LDSHARED = "#{CONFIG['LDSHARED']} #{ldshared}"

LIBPATH =  "-L#{CONFIG['rubylibdir']} #{@available.library_paths_compile_string}"

INCLUDES = "#{@available.includes_compile_string}"

LIBS = "#{@available.library_compile_string}"

CFLAGS = "#{cflags} #{defines_compile_string}"

RUBYARCHDIR = "\#{ENV["RUBYARCHDIR"]}"

task :default => ['#{@extension_name}']

rule '.o' => '.c' do |t|
  sh "\#{CC} \#{CFLAGS} \#{INCLUDES} -c -o \#{t.name} \#{t.source}"
end

desc "Build this extension"
file '#{@extension_name}' => OBJ do
  sh "\#{LDSHARED} \#{LIBPATH} -o #{@extension_name} \#{OBJ} \#{ADDITIONAL_OBJECTS} \#{LIBS}"
end

desc "Install this extension"
task :install => '#{@extension_name}' do
  makedirs "\#{RUBYARCHDIR}"
  install "#{@extension_name}", "\#{RUBYARCHDIR}"
end

#{additional_code}
  END_RAKEFILE
end

#sourcesObject

An array of the source patterns as single quoted strings



89
90
91
# File 'lib/mkrf/generator.rb', line 89

def sources
  @sources.collect {|s| "'#{s}'"}
end

#write_rakefile(filename = "Rakefile") ⇒ Object

:nodoc:



146
147
148
149
150
151
# File 'lib/mkrf/generator.rb', line 146

def write_rakefile(filename = "Rakefile") # :nodoc:
  File.open(filename, "w+") do |f|
    f.puts rakefile_contents
  end
  logger.info "Rakefile written"
end