Rake::ExtensionTask

Attributes

config_script[RW]
cross_compile[RW]
cross_platform[RW]
cross_config_options[RW]
no_native[RW]

Public Instance Methods

binary(platform = nil) click to toggle source
    # File lib/rake/extensiontask.rb, line 35
35:     def binary(platform = nil)
36:       if platform == "java"
37:         warn_once Compiling a native C extension on JRuby. This is discouraged and a Java extension should be preferred.
38:         "#{name}.#{RbConfig::MAKEFILE_CONFIG['DLEXT']}"
39:       else
40:         super
41:       end
42:     end
cross_compiling(&block) click to toggle source
    # File lib/rake/extensiontask.rb, line 31
31:     def cross_compiling(&block)
32:       @cross_compiling = block if block_given?
33:     end
cross_platform() click to toggle source
    # File lib/rake/extensiontask.rb, line 27
27:     def cross_platform
28:       @cross_platform ||= 'i386-mingw32'
29:     end
define() click to toggle source
    # File lib/rake/extensiontask.rb, line 47
47:     def define
48:       if (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ironruby')
49:         warn_once WARNING: You're attempting to (cross-)compile C extensions from a platform(#{RUBY_ENGINE}) that does not support native extensions or mkmf.rb.Rerun `rake` under MRI Ruby 1.8.x/1.9.x to cross/native compile.
50:         return
51:       end
52: 
53:       super
54: 
55:       # only gems with 'ruby' platforms are allowed to define native tasks
56:       define_native_tasks if !@no_native && (@gem_spec && @gem_spec.platform == 'ruby')
57: 
58:       # only define cross platform functionality when enabled
59:       return unless @cross_compile
60: 
61:       if cross_platform.is_a?(Array) then
62:         cross_platform.each { |platf| define_cross_platform_tasks(platf) }
63:       else
64:         define_cross_platform_tasks(cross_platform)
65:       end
66:     end
init(name = nil, gem_spec = nil) click to toggle source
    # File lib/rake/extensiontask.rb, line 17
17:     def init(name = nil, gem_spec = nil)
18:       super
19:       @config_script = 'extconf.rb'
20:       @source_pattern = "*.c"
21:       @cross_compile = false
22:       @cross_config_options = []
23:       @cross_compiling = nil
24:       @no_native = false
25:     end

Private Instance Methods

compiles_cross_platform() click to toggle source
     # File lib/rake/extensiontask.rb, line 368
368:     def compiles_cross_platform
369:       [*@cross_platform].map { |p| "compile:#{p}" }
370:     end
define_compile_tasks(for_platform = nil, ruby_ver = RUBY_VERSION) click to toggle source
     # File lib/rake/extensiontask.rb, line 73
 73:     def define_compile_tasks(for_platform = nil, ruby_ver = RUBY_VERSION)
 74:       # platform usage
 75:       platf = for_platform || platform
 76: 
 77:       # lib_path
 78:       lib_path = lib_dir
 79: 
 80:       # tmp_path
 81:       tmp_path = "#{@tmp_dir}/#{platf}/#{@name}/#{ruby_ver}"
 82: 
 83:       # cleanup and clobbering
 84:       CLEAN.include(tmp_path)
 85:       CLOBBER.include("#{lib_path}/#{binary(platf)}")
 86:       CLOBBER.include("#{@tmp_dir}")
 87: 
 88:       # directories we need
 89:       directory tmp_path
 90:       directory lib_dir
 91: 
 92:       # copy binary from temporary location to final lib
 93:       # tmp/extension_name/extension_name.{so,bundle} => lib/
 94:       task "copy:#{@name}:#{platf}:#{ruby_ver}" => [lib_path, "#{tmp_path}/#{binary(platf)}"] do
 95:         cp "#{tmp_path}/#{binary(platf)}", "#{lib_path}/#{binary(platf)}"
 96:       end
 97: 
 98:       # binary in temporary folder depends on makefile and source files
 99:       # tmp/extension_name/extension_name.{so,bundle}
100:       file "#{tmp_path}/#{binary(platf)}" => ["#{tmp_path}/Makefile"] + source_files do
101:         chdir tmp_path do
102:           sh make
103:         end
104:       end
105: 
106:       # makefile depends of tmp_dir and config_script
107:       # tmp/extension_name/Makefile
108:       file "#{tmp_path}/Makefile" => [tmp_path, extconf] do |t|
109:         options = @config_options.dup
110: 
111:         # include current directory
112:         cmd = ['-I.']
113: 
114:         # if fake.rb is present, add to the command line
115:         if t.prerequisites.include?("#{tmp_path}/fake.rb") then
116:           cmd << '-rfake'
117:         end
118: 
119:         # build a relative path to extconf script
120:         abs_tmp_path = Pathname.new(Dir.pwd) + tmp_path
121:         abs_extconf = Pathname.new(Dir.pwd) + extconf
122: 
123:         # now add the extconf script
124:         cmd << abs_extconf.relative_path_from(abs_tmp_path)
125: 
126:         # rbconfig.rb will be present if we are cross compiling
127:         if t.prerequisites.include?("#{tmp_path}/rbconfig.rb") then
128:           options.push(*@cross_config_options)
129:         end
130: 
131:         # add options to command
132:         cmd.push(*options)
133: 
134:         chdir tmp_path do
135:           # FIXME: Rake is broken for multiple arguments system() calls.
136:           # Add current directory to the search path of Ruby
137:           # Also, include additional parameters supplied.
138:           ruby cmd.join(' ')
139:         end
140:       end
141: 
142:       # compile tasks
143:       unless Rake::Task.task_defined?('compile') then
144:         desc "Compile all the extensions"
145:         task "compile"
146:       end
147: 
148:       # compile:name
149:       unless Rake::Task.task_defined?("compile:#{@name}") then
150:         desc "Compile #{@name}"
151:         task "compile:#{@name}"
152:       end
153: 
154:       # Allow segmented compilation by platform (open door for 'cross compile')
155:       task "compile:#{@name}:#{platf}" => ["copy:#{@name}:#{platf}:#{ruby_ver}"]
156:       task "compile:#{platf}" => ["compile:#{@name}:#{platf}"]
157: 
158:       # Only add this extension to the compile chain if current
159:       # platform matches the indicated one.
160:       if platf == RUBY_PLATFORM then
161:         # ensure file is always copied
162:         file "#{lib_path}/#{binary(platf)}" => ["copy:#{name}:#{platf}:#{ruby_ver}"]
163: 
164:         task "compile:#{@name}" => ["compile:#{@name}:#{platf}"]
165:         task "compile" => ["compile:#{platf}"]
166:       end
167:     end
define_cross_platform_tasks(for_platform) click to toggle source
     # File lib/rake/extensiontask.rb, line 234
234:     def define_cross_platform_tasks(for_platform)
235:       if ruby_vers = ENV['RUBY_CC_VERSION']
236:         ruby_vers = ENV['RUBY_CC_VERSION'].split(':')
237:       else
238:         ruby_vers = [RUBY_VERSION]
239:       end
240: 
241:       multi = (ruby_vers.size > 1) ? true : false
242: 
243:       ruby_vers.each do |version|
244:         # save original lib_dir
245:         orig_lib_dir = @lib_dir
246: 
247:         # tweak lib directory only when targeting multiple versions
248:         if multi then
249:           version =~ /(\d+.\d+)/
250:           @lib_dir = "#{@lib_dir}/#{$1}"
251:         end
252: 
253:         define_cross_platform_tasks_with_version(for_platform, version)
254: 
255:         # restore lib_dir
256:         @lib_dir = orig_lib_dir
257:       end
258:     end
define_cross_platform_tasks_with_version(for_platform, ruby_ver) click to toggle source
     # File lib/rake/extensiontask.rb, line 260
260:     def define_cross_platform_tasks_with_version(for_platform, ruby_ver)
261:       config_path = File.expand_path("~/.rake-compiler/config.yml")
262: 
263:       # warn the user about the need of configuration to use cross compilation.
264:       unless File.exist?(config_path)
265:         warn "rake-compiler must be configured first to enable cross-compilation"
266:         return
267:       end
268: 
269:       config_file = YAML.load_file(config_path)
270: 
271:       # tmp_path
272:       tmp_path = "#{@tmp_dir}/#{for_platform}/#{@name}/#{ruby_ver}"
273: 
274:       # lib_path
275:       lib_path = lib_dir
276: 
277:       unless rbconfig_file = config_file["rbconfig-#{ruby_ver}"] then
278:         warn "no configuration section for specified version of Ruby (rbconfig-#{ruby_ver})"
279:         return
280:       end
281: 
282:       # mkmf
283:       mkmf_file = File.expand_path(File.join(File.dirname(rbconfig_file), '..', 'mkmf.rb'))
284: 
285:       # define compilation tasks for cross platform!
286:       define_compile_tasks(for_platform, ruby_ver)
287: 
288:       # chain fake.rb, rbconfig.rb and mkmf.rb to Makefile generation
289:       file "#{tmp_path}/Makefile" => ["#{tmp_path}/fake.rb",
290:                                       "#{tmp_path}/rbconfig.rb",
291:                                       "#{tmp_path}/mkmf.rb"]
292: 
293:       # copy the file from the cross-ruby location
294:       file "#{tmp_path}/rbconfig.rb" => [rbconfig_file] do |t|
295:         cp t.prerequisites.first, t.name
296:       end
297: 
298:       # copy mkmf from cross-ruby location
299:       file "#{tmp_path}/mkmf.rb" => [mkmf_file] do |t|
300:         cp t.prerequisites.first, t.name
301:       end
302: 
303:       # genearte fake.rb for different ruby versions
304:       file "#{tmp_path}/fake.rb" do |t|
305:         File.open(t.name, 'w') do |f|
306:           f.write fake_rb(ruby_ver)
307:         end
308:       end
309: 
310:       # now define native tasks for cross compiled files
311:       if @gem_spec && @gem_spec.platform == 'ruby' then
312:         define_native_tasks(for_platform, ruby_ver, @cross_compiling)
313:       end
314: 
315:       # create cross task
316:       task 'cross' do
317:         # clear compile dependencies
318:         Rake::Task['compile'].prerequisites.reject! { |t| !compiles_cross_platform.include?(t) }
319: 
320:         # chain the cross platform ones
321:         task 'compile' => ["compile:#{for_platform}"]
322: 
323:         # clear lib/binary dependencies and trigger cross platform ones
324:         # check if lib/binary is defined (damn bundle versus so versus dll)
325:         if Rake::Task.task_defined?("#{lib_path}/#{binary(for_platform)}") then
326:           Rake::Task["#{lib_path}/#{binary(for_platform)}"].prerequisites.clear
327:         end
328: 
329:         # FIXME: targeting multiple platforms copies the file twice
330:         file "#{lib_path}/#{binary(for_platform)}" => ["copy:#{@name}:#{for_platform}:#{ruby_ver}"]
331: 
332:         # if everything for native task is in place
333:         if @gem_spec && @gem_spec.platform == 'ruby' then
334:           # double check: only cross platform native tasks should be here
335:           # FIXME: Sooo brittle
336:           Rake::Task['native'].prerequisites.reject! { |t| !natives_cross_platform.include?(t) }
337:           task 'native' => ["native:#{for_platform}"]
338:         end
339:       end
340:     end
define_native_tasks(for_platform = nil, ruby_ver = RUBY_VERSION, callback = nil) click to toggle source
     # File lib/rake/extensiontask.rb, line 169
169:     def define_native_tasks(for_platform = nil, ruby_ver = RUBY_VERSION, callback = nil)
170:       platf = for_platform || platform
171: 
172:       # tmp_path
173:       tmp_path = "#{@tmp_dir}/#{platf}/#{@name}/#{ruby_ver}"
174: 
175:       # lib_path
176:       lib_path = lib_dir
177: 
178:       # create 'native:gem_name' and chain it to 'native' task
179:       unless Rake::Task.task_defined?("native:#{@gem_spec.name}:#{platf}")
180:         task "native:#{@gem_spec.name}:#{platf}" do |t|
181:           # FIXME: truly duplicate the Gem::Specification
182:           # workaround the lack of #dup for Gem::Specification
183:           spec = gem_spec.dup
184: 
185:           # adjust to specified platform
186:           spec.platform = Gem::Platform.new(platf)
187: 
188:           # clear the extensions defined in the specs
189:           spec.extensions.clear
190: 
191:           # add the binaries that this task depends on
192:           ext_files = []
193: 
194:           # go through native prerequisites and grab the real extension files from there
195:           t.prerequisites.each do |ext|
196:             ext_files << ext
197:           end
198: 
199:           # include the files in the gem specification
200:           spec.files += ext_files
201: 
202:           # expose gem specification for customization
203:           if callback
204:             callback.call(spec)
205:           end
206: 
207:           # Generate a package for this gem
208:           gem_package = Rake::GemPackageTask.new(spec) do |pkg|
209:             pkg.need_zip = false
210:             pkg.need_tar = false
211:           end
212:         end
213:       end
214: 
215:       # add binaries to the dependency chain
216:       task "native:#{@gem_spec.name}:#{platf}" => ["#{lib_path}/#{binary(platf)}"]
217: 
218:       # ensure the extension get copied
219:       unless Rake::Task.task_defined?("#{lib_path}/#{binary(platf)}") then
220:         file "#{lib_path}/#{binary(platf)}" => ["copy:#{@name}:#{platf}:#{ruby_ver}"]
221:       end
222: 
223:       # Allow segmented packaging by platform (open door for 'cross compile')
224:       task "native:#{platf}" => ["native:#{@gem_spec.name}:#{platf}"]
225: 
226:       # Only add this extension to the compile chain if current
227:       # platform matches the indicated one.
228:       if platf == RUBY_PLATFORM then
229:         task "native:#{@gem_spec.name}" => ["native:#{@gem_spec.name}:#{platf}"]
230:         task "native" => ["native:#{platf}"]
231:       end
232:     end
dev_null() click to toggle source
     # File lib/rake/extensiontask.rb, line 360
360:     def dev_null
361:       windows? ? 'NUL' : '/dev/null'
362:     end
extconf() click to toggle source
     # File lib/rake/extensiontask.rb, line 342
342:     def extconf
343:       "#{@ext_dir}/#{@config_script}"
344:     end
fake_rb(version) click to toggle source
     # File lib/rake/extensiontask.rb, line 376
376:     def fake_rb(version)
377:               class Object          remove_const :RUBY_PLATFORM          remove_const :RUBY_VERSION          RUBY_PLATFORM = "i386-mingw32"          RUBY_VERSION = "#{version}"        end
378:     end
make() click to toggle source
     # File lib/rake/extensiontask.rb, line 346
346:     def make
347:       unless @make
348:         @make =
349:           if RUBY_PLATFORM =~ /mswin/ then
350:             'nmake'
351:           else
352:             ENV['MAKE'] || ]gmake make].find { |c|
353:               system("#{c} -v >> #{dev_null} 2>&1")
354:             }
355:           end
356:       end
357:       @make
358:     end
natives_cross_platform() click to toggle source
     # File lib/rake/extensiontask.rb, line 372
372:     def natives_cross_platform
373:       [*@cross_platform].map { |p| "native:#{p}" }
374:     end
source_files() click to toggle source
     # File lib/rake/extensiontask.rb, line 364
364:     def source_files
365:      @source_files ||= FileList["#{@ext_dir}/#{@source_pattern}"]
366:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.