lib/ffi-compiler/task.rb in ffi-compiler-0.0.2 vs lib/ffi-compiler/task.rb in ffi-compiler-0.0.3
- old
+ new
@@ -1,21 +1,31 @@
require 'rake/tasklib'
require 'rake/clean'
require 'ffi'
require 'tmpdir'
+require 'rbconfig'
module FFI
class Compiler
+ DEFAULT_CFLAGS = %w(-fexceptions -O -fno-omit-frame-pointer -fno-strict-aliasing)
+ DEFAULT_LDFLAGS = %w(-fexceptions)
+
class Task < Rake::TaskLib
+ attr_reader :cflags, :cxxflags, :ldflags, :libs
+
def initialize(name)
- @name = name
+ @name = File.basename(name)
@defines = []
@include_paths = []
@library_paths = []
@libraries = []
@headers = []
@functions = []
+ @cflags = DEFAULT_CFLAGS.dup
+ @cxxflags = DEFAULT_CFLAGS.dup
+ @ldflags = DEFAULT_LDFLAGS.dup
+ @libs = []
yield self if block_given?
define_task!
end
@@ -38,59 +48,55 @@
def have_library?(libname, *paths)
try_library(libname, @library_paths) || try_library(libname, paths)
end
- def create_rakefile!
- create_rakefile(@name)
- end
-
private
def define_task!
- lib_name = FFI.map_library_name(@name)
- pic_flags = '-fPIC'
- so_flags = ''
- ld_flags = ''
- cc = 'cc'
- cxx = 'c++'
- iflags = @include_paths.uniq.map { |p| "-I#{p}" }.join(' ')
- defines = @functions.uniq.map { |f| "-DHAVE_#{f.upcase}=1" }.join(' ')
- defines << " " + @headers.uniq.map { |h| "-DHAVE_#{h.upcase.sub(/\./, '_')}=1" }.join(' ')
-
+ pic_flags = %w(-fPIC)
+ so_flags = []
+
if FFI::Platform.mac?
- pic_flags = ''
- ld_flags += ' -dynamiclib '
+ pic_flags = []
+ so_flags << '-dynamiclib'
elsif FFI::Platform.name =~ /linux/
- so_flags += " -shared -Wl,-soname,#{lib_name} "
+ so_flags << "-shared -Wl,-soname,#{lib_name}"
+
+ else
+ so_flags << '-shared'
end
+ so_flags = so_flags.join(' ')
- cflags = "#{pic_flags} #{iflags} #{defines}".strip
- ld_flags += so_flags
- ld_flags += @library_paths.map { |path| "-L#{path}" }.join(' ')
- ld_flags.strip!
- ld = FileList['*.cpp'].empty? ? cc : cxx
- cxxflags = cflags
- libs = @libraries.map { |l| "-l#{l}" }.join(" ")
+ lib_name = FFI.map_library_name(@name)
- obj_files = FileList['*.c', '*.cpp'].map { |f| f.gsub(/\.(c|cpp)$/, '.o') }
+ iflags = @include_paths.uniq.map { |p| "-I#{p}" }
+ defines = @functions.uniq.map { |f| "-DHAVE_#{f.upcase}=1" }
+ defines << @headers.uniq.map { |h| "-DHAVE_#{h.upcase.sub(/\./, '_')}=1" }
+ cflags = (@cflags + pic_flags + iflags + defines).join(' ')
+ cxxflags = (@cxxflags + @cflags + pic_flags + iflags + defines).join(' ')
+ ld_flags = (@library_paths.map { |path| "-L#{path}" } + @ldflags).join(' ')
+ libs = (@libraries.map { |l| "-l#{l}" } + @libs).join(' ')
+
+ src_files = FileList['*.{c,cpp}']
+ obj_files = src_files.ext '.o'
+ ld = src_files.detect { |f| f =~ /\.cpp$/ } ? cxx : cc
+
CLEAN.include(obj_files)
- desc "Compile C file to object file"
- rule '.o' => ['.c'] do |t|
+ rule '.o' => '.c' do |t|
sh "#{cc} #{cflags} -o #{t.name} -c #{t.source}"
end
- desc "Compile C++ file to object file"
- rule '.o' => ['.cpp'] do |t|
+ rule '.o' => '.cpp' do |t|
sh "#{cxx} #{cxxflags} -o #{t.name} -c #{t.source}"
end
- desc "Compile to dynamic library"
+ desc "Build dynamic library"
file lib_name => obj_files do |t|
- sh "#{ld} #{ld_flags} -o #{t.name} #{t.prerequisites.join(' ')} #{libs}"
+ sh "#{ld} #{so_flags} -o #{t.name} #{t.prerequisites.join(' ')} #{ld_flags} #{libs}"
end
CLEAN.include(lib_name)
task :default => [ lib_name ]
end
@@ -136,18 +142,26 @@
end
def try_compile(src, *opts)
Dir.mktmpdir do |dir|
path = File.join(dir, 'ffi-test.c')
- File.open(path, "w") do |f|
+ File.open(path, 'w') do |f|
f << src
end
begin
- return system "cc #{opts.join(' ')} -o #{File.join(dir, 'ffi-test')} #{path} >& /dev/null"
+ return system "#{cc} #{opts.join(' ')} -o #{File.join(dir, 'ffi-test')} #{path} >& /dev/null"
rescue
return false
end
end
end
+
+ def cc
+ @cc ||= (ENV['CC'] || RbConfig::CONFIG['CC'] || 'cc')
+ end
+
+ def cxx
+ @cxx ||= (ENV['CXX'] || RbConfig::CONFIG['CXX'] || 'c++')
+ end
end
end
-end
\ No newline at end of file
+end