ffi-compiler 1.0.0 → 1.3.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.
- checksums.yaml +5 -5
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/ffi-compiler.gemspec +9 -7
- data/lib/ffi-compiler/compile_task.rb +49 -21
- data/lib/ffi-compiler/loader.rb +5 -1
- data/lib/ffi-compiler/multi_file_task.rb +41 -0
- data/lib/ffi-compiler/shell.rb +24 -0
- data/lib/ffi-compiler/version.rb +7 -0
- metadata +17 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6b5d2323276536d7b5525a84f71e6b740d93dbb7599bc593b07c6cbe4555d71a
|
4
|
+
data.tar.gz: 59c2d2f0e72494eb68b396f2c99b6c78229839b363abda938869134c205b1aab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '074259969bc26ce9cf1c5ef33b6e64c16bdc6f6283248ed1b2d124268d8686eb103421a3208fbfd30d43518933c65f012d3394ebb5fc9c5566564aa50f04ff35'
|
7
|
+
data.tar.gz: 861960b3190b87b5b6ca902b2076e12abb6788a137bc7cf04d7fb6eb27fea7b9fb673e20b887c2a6e5285c6c4a4b3bf27f7d45362360d3149851e50c32cff25e
|
data/Gemfile
ADDED
data/LICENSE
CHANGED
@@ -187,7 +187,7 @@
|
|
187
187
|
same "printed page" as the copyright notice for easier
|
188
188
|
identification within third-party archives.
|
189
189
|
|
190
|
-
Copyright
|
190
|
+
Copyright 2020 FFI
|
191
191
|
|
192
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
193
193
|
you may not use this file except in compliance with the License.
|
data/ffi-compiler.gemspec
CHANGED
@@ -1,17 +1,19 @@
|
|
1
|
+
require_relative 'lib/ffi-compiler/version'
|
2
|
+
|
1
3
|
Gem::Specification.new do |s|
|
2
4
|
s.name = 'ffi-compiler'
|
3
|
-
s.version =
|
5
|
+
s.version = FFI::Compiler::VERSION
|
4
6
|
s.author = 'Wayne Meissner'
|
5
|
-
s.email = 'wmeissner@gmail.com'
|
6
|
-
s.homepage = '
|
7
|
+
s.email = ['wmeissner@gmail.com', 'steve@advancedcontrol.com.au']
|
8
|
+
s.homepage = 'https://github.com/ffi/ffi-compiler'
|
7
9
|
s.summary = 'Ruby FFI Rakefile generator'
|
8
10
|
s.description = 'Ruby FFI library'
|
9
|
-
s.files = %w(ffi-compiler.gemspec README.md
|
10
|
-
s.
|
11
|
-
s.license = 'Apache 2.0'
|
11
|
+
s.files = %w(ffi-compiler.gemspec Gemfile Rakefile README.md LICENSE) + Dir.glob("{lib,spec}/**/*")
|
12
|
+
s.license = 'Apache-2.0'
|
12
13
|
s.required_ruby_version = '>= 1.9'
|
13
14
|
s.add_dependency 'rake'
|
14
|
-
s.add_dependency 'ffi', '>= 1.
|
15
|
+
s.add_dependency 'ffi', '>= 1.15.5'
|
15
16
|
s.add_development_dependency 'rspec'
|
16
17
|
s.add_development_dependency 'rubygems-tasks'
|
17
18
|
end
|
19
|
+
|
@@ -5,12 +5,39 @@ require 'ffi'
|
|
5
5
|
require 'tmpdir'
|
6
6
|
require 'rbconfig'
|
7
7
|
require_relative 'platform'
|
8
|
+
require_relative 'shell'
|
9
|
+
require_relative 'multi_file_task'
|
8
10
|
|
9
11
|
module FFI
|
10
12
|
module Compiler
|
11
13
|
DEFAULT_CFLAGS = %w(-fexceptions -O -fno-omit-frame-pointer -fno-strict-aliasing)
|
12
14
|
DEFAULT_LDFLAGS = %w(-fexceptions)
|
13
15
|
|
16
|
+
class Flags
|
17
|
+
attr_accessor :raw
|
18
|
+
|
19
|
+
def initialize(flags)
|
20
|
+
@flags = flags
|
21
|
+
@raw = true # For backward compatibility
|
22
|
+
end
|
23
|
+
|
24
|
+
def <<(flag)
|
25
|
+
if @raw
|
26
|
+
@flags += shellsplit(flag.to_s)
|
27
|
+
else
|
28
|
+
@flags << flag
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_a
|
33
|
+
@flags
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
shelljoin(@flags)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
14
41
|
class CompileTask < Rake::TaskLib
|
15
42
|
attr_reader :cflags, :cxxflags, :ldflags, :libs, :platform
|
16
43
|
attr_accessor :name, :ext_dir, :source_dirs, :exclude
|
@@ -26,9 +53,9 @@ module FFI
|
|
26
53
|
@libraries = []
|
27
54
|
@headers = []
|
28
55
|
@functions = []
|
29
|
-
@cflags = DEFAULT_CFLAGS.dup
|
30
|
-
@cxxflags = DEFAULT_CFLAGS.dup
|
31
|
-
@ldflags = DEFAULT_LDFLAGS.dup
|
56
|
+
@cflags = Flags.new(shellsplit(ENV['CFLAGS']) || DEFAULT_CFLAGS.dup)
|
57
|
+
@cxxflags = Flags.new(shellsplit(ENV['CXXFLAGS']) || DEFAULT_CFLAGS.dup)
|
58
|
+
@ldflags = Flags.new(shellsplit(ENV['LDFLAGS']) || DEFAULT_LDFLAGS.dup)
|
32
59
|
@libs = []
|
33
60
|
@platform = Platform.system
|
34
61
|
@exports = []
|
@@ -93,7 +120,7 @@ module FFI
|
|
93
120
|
else
|
94
121
|
so_flags << '-shared'
|
95
122
|
end
|
96
|
-
so_flags = so_flags
|
123
|
+
so_flags = shelljoin(so_flags)
|
97
124
|
|
98
125
|
out_dir = "#{@platform.arch}-#{@platform.os}"
|
99
126
|
if @ext_dir != '.'
|
@@ -106,36 +133,36 @@ module FFI
|
|
106
133
|
lib_name = File.join(out_dir, Platform.system.map_library_name(@name))
|
107
134
|
|
108
135
|
iflags = @include_paths.uniq.map { |p| "-I#{p}" }
|
109
|
-
@defines
|
110
|
-
@defines
|
136
|
+
@defines += @functions.uniq.map { |f| "-DHAVE_#{f.upcase}=1" }
|
137
|
+
@defines += @headers.uniq.map { |h| "-DHAVE_#{h.upcase.sub(/\./, '_')}=1" }
|
111
138
|
|
112
|
-
cflags = (@cflags + pic_flags + iflags + @defines)
|
113
|
-
cxxflags = (@cxxflags + @cflags + pic_flags + iflags + @defines)
|
114
|
-
ld_flags = (@library_paths.map { |path| "-L#{path}" } + @ldflags
|
115
|
-
libs = (@libraries.map { |l| "-l#{l}" } + @libs)
|
139
|
+
cflags = shelljoin(@cflags.to_a + pic_flags + iflags + @defines)
|
140
|
+
cxxflags = shelljoin(@cxxflags.to_a + @cflags.to_a + pic_flags + iflags + @defines)
|
141
|
+
ld_flags = shelljoin(@library_paths.map { |path| "-L#{path}" } + @ldflags.to_a)
|
142
|
+
libs = shelljoin(@libraries.map { |l| "-l#{l}" } + @libs)
|
116
143
|
|
117
144
|
src_files = []
|
118
145
|
obj_files = []
|
119
146
|
@source_dirs.each do |dir|
|
120
147
|
files = FileList["#{dir}/**/*.{c,cpp}"]
|
121
|
-
|
122
|
-
|
123
|
-
|
148
|
+
unless @exclude.empty?
|
149
|
+
files.delete_if { |f| f =~ Regexp.union(*@exclude) }
|
150
|
+
end
|
124
151
|
src_files += files
|
125
152
|
obj_files += files.ext('.o').map { |f| File.join(out_dir, f.sub(/^#{dir}\//, '')) }
|
126
|
-
|
153
|
+
end
|
127
154
|
|
128
155
|
index = 0
|
129
156
|
src_files.each do |src|
|
130
157
|
obj_file = obj_files[index]
|
131
158
|
if src =~ /\.c$/
|
132
159
|
file obj_file => [ src, File.dirname(obj_file) ] do |t|
|
133
|
-
sh "#{cc} #{cflags} -o #{t.name} -c #{t.prerequisites[0]}"
|
160
|
+
sh "#{cc} #{cflags} -o #{shellescape(t.name)} -c #{shellescape(t.prerequisites[0])}"
|
134
161
|
end
|
135
162
|
|
136
163
|
else
|
137
164
|
file obj_file => [ src, File.dirname(obj_file) ] do |t|
|
138
|
-
sh "#{cxx} #{cxxflags} -o #{t.name} -c #{t.prerequisites[0]}"
|
165
|
+
sh "#{cxx} #{cxxflags} -o #{shellescape(t.name)} -c #{shellescape(t.prerequisites[0])}"
|
139
166
|
end
|
140
167
|
end
|
141
168
|
|
@@ -149,15 +176,16 @@ module FFI
|
|
149
176
|
obj_files.map { |f| File.dirname(f) }.sort.uniq.map { |d| directory d }
|
150
177
|
|
151
178
|
desc "Build dynamic library"
|
152
|
-
|
153
|
-
|
179
|
+
MultiFileTask.define_task(lib_name => src_files + obj_files) do |t|
|
180
|
+
objs = t.prerequisites.select { |file| file.end_with?('.o') }
|
181
|
+
sh "#{ld} #{so_flags} -o #{shellescape(t.name)} #{shelljoin(objs)} #{ld_flags} #{libs}"
|
154
182
|
end
|
155
183
|
CLEAN.include(lib_name)
|
156
184
|
|
157
185
|
@exports.each do |e|
|
158
186
|
desc "Export #{e[:rb_file]}"
|
159
187
|
file e[:header] => [ e[:rb_file] ] do |t|
|
160
|
-
ruby "-I#{File.join(File.dirname(__FILE__), 'fake_ffi')} -I#{File.dirname(t.prerequisites[0])} #{File.join(File.dirname(__FILE__), 'exporter.rb')} #{t.prerequisites[0]} #{t.name}"
|
188
|
+
ruby "-I#{File.join(File.dirname(__FILE__), 'fake_ffi')} -I#{File.dirname(t.prerequisites[0])} #{File.join(File.dirname(__FILE__), 'exporter.rb')} #{shellescape(t.prerequisites[0])} #{shellescape(t.name)}"
|
161
189
|
end
|
162
190
|
|
163
191
|
obj_files.each { |o| file o => [ e[:header] ] }
|
@@ -221,10 +249,10 @@ module FFI
|
|
221
249
|
File.open(path, 'w') do |f|
|
222
250
|
f << src
|
223
251
|
end
|
224
|
-
cflags = opts
|
252
|
+
cflags = shelljoin(opts)
|
225
253
|
output = File.join(dir, 'ffi-test')
|
226
254
|
begin
|
227
|
-
return system "#{cc} #{cflags} -o #{output} -c #{path} > #{path}.log 2>&1"
|
255
|
+
return system "#{cc} #{cflags} -o #{shellescape(output)} -c #{shellescape(path)} > #{shellescape(path)}.log 2>&1"
|
228
256
|
rescue
|
229
257
|
return false
|
230
258
|
end
|
data/lib/ffi-compiler/loader.rb
CHANGED
@@ -9,7 +9,11 @@ module FFI
|
|
9
9
|
library = Platform.system.map_library_name(name)
|
10
10
|
root = false
|
11
11
|
Pathname.new(start_path || caller_path(caller[0])).ascend do |path|
|
12
|
-
Dir.glob("#{path}
|
12
|
+
Dir.glob("#{path}/**/#{FFI::Platform::ARCH}-#{FFI::Platform::OS}/#{library}") do |f|
|
13
|
+
return f
|
14
|
+
end
|
15
|
+
|
16
|
+
Dir.glob("#{path}/**/#{library}") do |f|
|
13
17
|
return f
|
14
18
|
end
|
15
19
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
module FFI
|
4
|
+
module Compiler
|
5
|
+
class MultiFileTask < Rake::MultiTask
|
6
|
+
def needed?
|
7
|
+
begin
|
8
|
+
@application.options.build_all || out_of_date?(File.mtime(name))
|
9
|
+
rescue Errno::ENOENT
|
10
|
+
true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def timestamp
|
15
|
+
begin
|
16
|
+
File.mtime(name)
|
17
|
+
rescue Errno::ENOENT
|
18
|
+
Rake::LATE
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def invoke_with_call_chain(task_args, invocation_chain)
|
23
|
+
return unless needed?
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def out_of_date?(timestamp)
|
30
|
+
all_prerequisite_tasks.any? do |prereq|
|
31
|
+
prereq_task = application[prereq, @scope]
|
32
|
+
if prereq_task.instance_of?(Rake::FileTask)
|
33
|
+
File.exist?(prereq_task.name) && prereq_task.timestamp > timestamp
|
34
|
+
else
|
35
|
+
prereq_task.needed?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
require 'rbconfig'
|
3
|
+
|
4
|
+
def shellescape(str)
|
5
|
+
return str unless str
|
6
|
+
if FFI::Platform::OS == 'windows'
|
7
|
+
'"' + str.gsub('"', '""') + '"'
|
8
|
+
else
|
9
|
+
str.shellescape
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def shelljoin(args)
|
14
|
+
if FFI::Platform::OS == 'windows'
|
15
|
+
args.reduce { |cmd, arg| cmd + ' ' + shellescape(arg) }
|
16
|
+
else
|
17
|
+
args.shelljoin
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def shellsplit(str)
|
22
|
+
return str unless str
|
23
|
+
str.shellsplit
|
24
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffi-compiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wayne Meissner
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
33
|
+
version: 1.15.5
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.
|
40
|
+
version: 1.15.5
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,11 +67,14 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
description: Ruby FFI library
|
70
|
-
email:
|
70
|
+
email:
|
71
|
+
- wmeissner@gmail.com
|
72
|
+
- steve@advancedcontrol.com.au
|
71
73
|
executables: []
|
72
74
|
extensions: []
|
73
75
|
extra_rdoc_files: []
|
74
76
|
files:
|
77
|
+
- Gemfile
|
75
78
|
- LICENSE
|
76
79
|
- README.md
|
77
80
|
- Rakefile
|
@@ -82,13 +85,16 @@ files:
|
|
82
85
|
- lib/ffi-compiler/fake_ffi/ffi-compiler/loader.rb
|
83
86
|
- lib/ffi-compiler/fake_ffi/ffi.rb
|
84
87
|
- lib/ffi-compiler/loader.rb
|
88
|
+
- lib/ffi-compiler/multi_file_task.rb
|
85
89
|
- lib/ffi-compiler/platform.rb
|
90
|
+
- lib/ffi-compiler/shell.rb
|
86
91
|
- lib/ffi-compiler/task.rb
|
87
|
-
|
92
|
+
- lib/ffi-compiler/version.rb
|
93
|
+
homepage: https://github.com/ffi/ffi-compiler
|
88
94
|
licenses:
|
89
|
-
- Apache
|
95
|
+
- Apache-2.0
|
90
96
|
metadata: {}
|
91
|
-
post_install_message:
|
97
|
+
post_install_message:
|
92
98
|
rdoc_options: []
|
93
99
|
require_paths:
|
94
100
|
- lib
|
@@ -103,10 +109,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
109
|
- !ruby/object:Gem::Version
|
104
110
|
version: '0'
|
105
111
|
requirements: []
|
106
|
-
|
107
|
-
|
108
|
-
signing_key:
|
112
|
+
rubygems_version: 3.5.6
|
113
|
+
signing_key:
|
109
114
|
specification_version: 4
|
110
115
|
summary: Ruby FFI Rakefile generator
|
111
116
|
test_files: []
|
112
|
-
has_rdoc: false
|