ffi-compiler 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ffi-compiler.gemspec +1 -1
- data/lib/ffi-compiler/task.rb +49 -35
- metadata +2 -3
- data/lib/ffi-compiler/mkrf.rb +0 -168
data/ffi-compiler.gemspec
CHANGED
data/lib/ffi-compiler/task.rb
CHANGED
@@ -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
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
59
|
+
pic_flags = []
|
60
|
+
so_flags << '-dynamiclib'
|
62
61
|
|
63
62
|
elsif FFI::Platform.name =~ /linux/
|
64
|
-
so_flags
|
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
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 "
|
95
|
+
desc "Build dynamic library"
|
90
96
|
file lib_name => obj_files do |t|
|
91
|
-
sh "#{ld} #{
|
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,
|
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.
|
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-
|
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:
|
data/lib/ffi-compiler/mkrf.rb
DELETED
@@ -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
|
-
|