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