ffi-compiler 0.0.1
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 +16 -0
- data/lib/ffi-compiler/mkrf.rb +168 -0
- metadata +95 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'ffi-compiler'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.author = 'Wayne Meissner'
|
5
|
+
s.email = 'wmeissner@gmail.com'
|
6
|
+
s.homepage = 'http://wiki.github.com/ffi/ffi'
|
7
|
+
s.summary = 'Ruby FFI Rakefile generator'
|
8
|
+
s.description = 'Ruby FFI library'
|
9
|
+
s.files = %w(ffi-compiler.gemspec) + Dir.glob("{lib,spec}/**/*")
|
10
|
+
s.has_rdoc = false
|
11
|
+
s.license = 'Apache 2.0'
|
12
|
+
s.required_ruby_version = '>= 1.9.3'
|
13
|
+
s.add_dependency 'rake'
|
14
|
+
s.add_dependency 'ffi', '>= 1.0.0'
|
15
|
+
s.add_development_dependency 'rspec'
|
16
|
+
end
|
@@ -0,0 +1,168 @@
|
|
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
|
+
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ffi-compiler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Wayne Meissner
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: ffi
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.0.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.0.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Ruby FFI library
|
63
|
+
email: wmeissner@gmail.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- ffi-compiler.gemspec
|
69
|
+
- lib/ffi-compiler/mkrf.rb
|
70
|
+
homepage: http://wiki.github.com/ffi/ffi
|
71
|
+
licenses:
|
72
|
+
- Apache 2.0
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.9.3
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.8.24
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Ruby FFI Rakefile generator
|
95
|
+
test_files: []
|