ffi-compiler 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/ffi-compiler.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'ffi-compiler'
3
- s.version = '0.0.2'
3
+ s.version = '0.0.3'
4
4
  s.author = 'Wayne Meissner'
5
5
  s.email = 'wmeissner@gmail.com'
6
6
  s.homepage = 'http://wiki.github.com/ffi/ffi'
@@ -2,18 +2,28 @@ require 'rake/tasklib'
2
2
  require 'rake/clean'
3
3
  require 'ffi'
4
4
  require 'tmpdir'
5
+ require 'rbconfig'
5
6
 
6
7
  module FFI
7
8
  class Compiler
9
+ DEFAULT_CFLAGS = %w(-fexceptions -O -fno-omit-frame-pointer -fno-strict-aliasing)
10
+ DEFAULT_LDFLAGS = %w(-fexceptions)
11
+
8
12
  class Task < Rake::TaskLib
13
+ attr_reader :cflags, :cxxflags, :ldflags, :libs
14
+
9
15
  def initialize(name)
10
- @name = name
16
+ @name = File.basename(name)
11
17
  @defines = []
12
18
  @include_paths = []
13
19
  @library_paths = []
14
20
  @libraries = []
15
21
  @headers = []
16
22
  @functions = []
23
+ @cflags = DEFAULT_CFLAGS.dup
24
+ @cxxflags = DEFAULT_CFLAGS.dup
25
+ @ldflags = DEFAULT_LDFLAGS.dup
26
+ @libs = []
17
27
 
18
28
  yield self if block_given?
19
29
  define_task!
@@ -40,55 +50,51 @@ module FFI
40
50
  try_library(libname, @library_paths) || try_library(libname, paths)
41
51
  end
42
52
 
43
- def create_rakefile!
44
- create_rakefile(@name)
45
- end
46
-
47
53
  private
48
54
  def define_task!
49
- lib_name = FFI.map_library_name(@name)
50
- pic_flags = '-fPIC'
51
- so_flags = ''
52
- ld_flags = ''
53
- cc = 'cc'
54
- cxx = 'c++'
55
- iflags = @include_paths.uniq.map { |p| "-I#{p}" }.join(' ')
56
- defines = @functions.uniq.map { |f| "-DHAVE_#{f.upcase}=1" }.join(' ')
57
- defines << " " + @headers.uniq.map { |h| "-DHAVE_#{h.upcase.sub(/\./, '_')}=1" }.join(' ')
58
-
55
+ pic_flags = %w(-fPIC)
56
+ so_flags = []
57
+
59
58
  if FFI::Platform.mac?
60
- pic_flags = ''
61
- ld_flags += ' -dynamiclib '
59
+ pic_flags = []
60
+ so_flags << '-dynamiclib'
62
61
 
63
62
  elsif FFI::Platform.name =~ /linux/
64
- so_flags += " -shared -Wl,-soname,#{lib_name} "
63
+ so_flags << "-shared -Wl,-soname,#{lib_name}"
64
+
65
+ else
66
+ so_flags << '-shared'
65
67
  end
68
+ so_flags = so_flags.join(' ')
69
+
70
+ lib_name = FFI.map_library_name(@name)
66
71
 
67
- cflags = "#{pic_flags} #{iflags} #{defines}".strip
68
- ld_flags += so_flags
69
- ld_flags += @library_paths.map { |path| "-L#{path}" }.join(' ')
70
- ld_flags.strip!
71
- ld = FileList['*.cpp'].empty? ? cc : cxx
72
- cxxflags = cflags
73
- libs = @libraries.map { |l| "-l#{l}" }.join(" ")
72
+ iflags = @include_paths.uniq.map { |p| "-I#{p}" }
73
+ defines = @functions.uniq.map { |f| "-DHAVE_#{f.upcase}=1" }
74
+ defines << @headers.uniq.map { |h| "-DHAVE_#{h.upcase.sub(/\./, '_')}=1" }
74
75
 
75
- obj_files = FileList['*.c', '*.cpp'].map { |f| f.gsub(/\.(c|cpp)$/, '.o') }
76
+ cflags = (@cflags + pic_flags + iflags + defines).join(' ')
77
+ cxxflags = (@cxxflags + @cflags + pic_flags + iflags + defines).join(' ')
78
+ ld_flags = (@library_paths.map { |path| "-L#{path}" } + @ldflags).join(' ')
79
+ libs = (@libraries.map { |l| "-l#{l}" } + @libs).join(' ')
80
+
81
+ src_files = FileList['*.{c,cpp}']
82
+ obj_files = src_files.ext '.o'
83
+ ld = src_files.detect { |f| f =~ /\.cpp$/ } ? cxx : cc
76
84
 
77
85
  CLEAN.include(obj_files)
78
86
 
79
- desc "Compile C file to object file"
80
- rule '.o' => ['.c'] do |t|
87
+ rule '.o' => '.c' do |t|
81
88
  sh "#{cc} #{cflags} -o #{t.name} -c #{t.source}"
82
89
  end
83
90
 
84
- desc "Compile C++ file to object file"
85
- rule '.o' => ['.cpp'] do |t|
91
+ rule '.o' => '.cpp' do |t|
86
92
  sh "#{cxx} #{cxxflags} -o #{t.name} -c #{t.source}"
87
93
  end
88
94
 
89
- desc "Compile to dynamic library"
95
+ desc "Build dynamic library"
90
96
  file lib_name => obj_files do |t|
91
- sh "#{ld} #{ld_flags} -o #{t.name} #{t.prerequisites.join(' ')} #{libs}"
97
+ sh "#{ld} #{so_flags} -o #{t.name} #{t.prerequisites.join(' ')} #{ld_flags} #{libs}"
92
98
  end
93
99
  CLEAN.include(lib_name)
94
100
 
@@ -138,16 +144,24 @@ module FFI
138
144
  def try_compile(src, *opts)
139
145
  Dir.mktmpdir do |dir|
140
146
  path = File.join(dir, 'ffi-test.c')
141
- File.open(path, "w") do |f|
147
+ File.open(path, 'w') do |f|
142
148
  f << src
143
149
  end
144
150
  begin
145
- return system "cc #{opts.join(' ')} -o #{File.join(dir, 'ffi-test')} #{path} >& /dev/null"
151
+ return system "#{cc} #{opts.join(' ')} -o #{File.join(dir, 'ffi-test')} #{path} >& /dev/null"
146
152
  rescue
147
153
  return false
148
154
  end
149
155
  end
150
156
  end
157
+
158
+ def cc
159
+ @cc ||= (ENV['CC'] || RbConfig::CONFIG['CC'] || 'cc')
160
+ end
161
+
162
+ def cxx
163
+ @cxx ||= (ENV['CXX'] || RbConfig::CONFIG['CXX'] || 'c++')
164
+ end
151
165
  end
152
166
  end
153
- end
167
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-compiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-16 00:00:00.000000000 Z
12
+ date: 2013-01-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -70,7 +70,6 @@ files:
70
70
  - Rakefile
71
71
  - LICENSE
72
72
  - lib/ffi-compiler/loader.rb
73
- - lib/ffi-compiler/mkrf.rb
74
73
  - lib/ffi-compiler/task.rb
75
74
  homepage: http://wiki.github.com/ffi/ffi
76
75
  licenses:
@@ -1,168 +0,0 @@
1
- require 'ffi'
2
- require 'tmpdir'
3
-
4
- module FFI
5
- class Compiler
6
- def initialize(name, &block)
7
- @name = name
8
- @defines = []
9
- @include_paths = []
10
- @library_paths = []
11
- @libraries = []
12
- @headers = []
13
- @functions = []
14
-
15
- if block_given?
16
- yield self
17
- create_rakefile!
18
- end
19
- end
20
-
21
- def have_func?(func)
22
- main = <<-C_FILE
23
- extern void #{func}();
24
- int main(int argc, char **argv) { #{func}(); return 0; }
25
- C_FILE
26
-
27
- if try_compile(main)
28
- @functions << func
29
- return true
30
- end
31
- false
32
- end
33
-
34
- def have_header?(header, *paths)
35
- try_header(header, @include_paths) || try_header(header, paths)
36
- end
37
-
38
- def have_library?(libname, *paths)
39
- try_library(libname, @library_paths) || try_library(libname, paths)
40
- end
41
-
42
- def create_rakefile!
43
- create_rakefile(@name)
44
- end
45
-
46
- private
47
-
48
- def try_header(header, paths)
49
- main = <<-C_FILE
50
- #include <#{header}>
51
- int main(int argc, char **argv) { return 0; }
52
- C_FILE
53
-
54
- if paths.empty? && try_compile(main)
55
- @headers << header
56
- return true
57
- end
58
-
59
- paths.each do |path|
60
- if try_compile(main, "-I#{path}")
61
- @include_paths << path
62
- @headers << header
63
- return true
64
- end
65
- end
66
- false
67
- end
68
-
69
-
70
- def try_library(libname, paths)
71
- main = <<-C_FILE
72
- int main(int argc, char **argv) { return 0; }
73
- C_FILE
74
-
75
- if paths.empty? && try_compile(main)
76
- @libraries << libname
77
- return true
78
- end
79
-
80
- paths.each do |path|
81
- if try_compile(main, "-L#{path}", "-l#{libname}")
82
- @library_paths << path
83
- @libraries << libname
84
- end
85
- end
86
- end
87
-
88
- def try_compile(src, *opts)
89
- Dir.mktmpdir do |dir|
90
- path = File.join(dir, 'ffi-test.c')
91
- File.open(path, "w") do |f|
92
- f << src
93
- end
94
- begin
95
- return system "cc #{opts.join(' ')} -o #{File.join(dir, 'ffi-test')} #{path} >& /dev/null"
96
- rescue
97
- return false
98
- end
99
- end
100
- end
101
-
102
- def create_rakefile(name)
103
- lib_name = FFI.map_library_name(name)
104
- pic_flags = '-fPIC'
105
- so_flags = ''
106
- ld_flags = ''
107
- cc = 'cc'
108
- cxx = 'c++'
109
- iflags = @include_paths.uniq.map{ |p| "-I#{p}" }.join(' ')
110
- defines = @functions.uniq.map { |f| "-DHAVE_#{f.upcase}=1" }.join(' ')
111
- defines << " " + @headers.uniq.map { |h| "-DHAVE_#{h.upcase.sub(/\./, '_')}=1" }.join(' ')
112
-
113
- if FFI::Platform.mac?
114
- pic_flags = ''
115
- ld_flags += ' -dynamiclib '
116
-
117
- elsif FFI::Platform.name =~ /linux/
118
- so_flags += " -shared -Wl,-soname,#{lib_name} "
119
- end
120
-
121
- cflags = "#{pic_flags} #{iflags} #{defines}".strip
122
- ld_flags += so_flags
123
- ld_flags += @library_paths.map { |path| "-L#{path}" }.join(' ')
124
- ld_flags.strip!
125
-
126
- File.open('Rakefile', 'w') do |f|
127
- f.puts <<-RAKEFILE
128
-
129
- require 'rake/clean'
130
-
131
- CC = '#{cc}'
132
- CXX = '#{cxx}'
133
- LD = FileList['*.cpp'].empty? ? CC : CXX
134
- CFLAGS = '#{cflags}'
135
- CXXFLAGS = '#{cflags}'
136
- LDFLAGS = '#{ld_flags}'
137
- LIBS = '#{@libraries.map {|l| "-l#{l}" }.join(" ")}'
138
-
139
- OBJ_FILES = FileList['*.c', '*.cpp'].map { |f| f.gsub(/\.(c|cpp)$/, '.o') }
140
-
141
- CLEAN.include(OBJ_FILES)
142
-
143
- desc "Compile C file to object file"
144
- rule '.o' => [ '.c' ] do |t|
145
- sh "\#{CC} \#{CFLAGS} -o \#{t.name} -c \#{t.source}"
146
- end
147
-
148
- desc "Compile C++ file to object file"
149
- rule '.o' => [ '.cpp' ] do |t|
150
- sh "\#{CXX} \#{CXXFLAGS} -o \#{t.name} -c \#{t.source} "
151
- end
152
-
153
- desc "Compile to dynamic library"
154
- task :compile => "#{lib_name}"
155
-
156
- file "#{lib_name}" => OBJ_FILES do |t|
157
- sh "\#{LD} \#{LDFLAGS} -o \#{t.name} \#{t.prerequisites.join(' ')} \#{LIBS}"
158
- end
159
-
160
- task :default => :compile
161
-
162
- RAKEFILE
163
- end
164
- end
165
-
166
- end
167
- end
168
-