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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0d72c341f9ccb50429bfd8a3542d3c9481f7e4d2
4
- data.tar.gz: 780d11e250a8e1637d287d8482c7eb319d170db8
2
+ SHA256:
3
+ metadata.gz: 6b5d2323276536d7b5525a84f71e6b740d93dbb7599bc593b07c6cbe4555d71a
4
+ data.tar.gz: 59c2d2f0e72494eb68b396f2c99b6c78229839b363abda938869134c205b1aab
5
5
  SHA512:
6
- metadata.gz: a4d9af481db298d53bba6d89b85f4f288043748ca736f84f751f1cb16ad829be4719fbf5faab58a14ebdbaa91a01d0cafbaa31104c1dbfaae6cd9093f371c1e5
7
- data.tar.gz: f7d499575077854ec5913209f0ec8fb83e01028a90b93ba86c8b221bc9b31f8c135a3df6370b47cc0a5f7a611167c1ae4f0971c6cec7032e40d435ff2123395e
6
+ metadata.gz: '074259969bc26ce9cf1c5ef33b6e64c16bdc6f6283248ed1b2d124268d8686eb103421a3208fbfd30d43518933c65f012d3394ebb5fc9c5566564aa50f04ff35'
7
+ data.tar.gz: 861960b3190b87b5b6ca902b2076e12abb6788a137bc7cf04d7fb6eb27fea7b9fb673e20b887c2a6e5285c6c4a4b3bf27f7d45362360d3149851e50c32cff25e
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
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 [yyyy] [name of copyright owner]
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 = '1.0.0'
5
+ s.version = FFI::Compiler::VERSION
4
6
  s.author = 'Wayne Meissner'
5
- s.email = 'wmeissner@gmail.com'
6
- s.homepage = 'http://wiki.github.com/ffi/ffi'
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 Rakefile LICENSE) + Dir.glob("{lib,spec}/**/*")
10
- s.has_rdoc = false
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.0.0'
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.join(' ')
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 << @functions.uniq.map { |f| "-DHAVE_#{f.upcase}=1" }
110
- @defines << @headers.uniq.map { |h| "-DHAVE_#{h.upcase.sub(/\./, '_')}=1" }
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).join(' ')
113
- cxxflags = (@cxxflags + @cflags + pic_flags + iflags + @defines).join(' ')
114
- ld_flags = (@library_paths.map { |path| "-L#{path}" } + @ldflags).join(' ')
115
- libs = (@libraries.map { |l| "-l#{l}" } + @libs).join(' ')
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
- unless @exclude.empty?
122
- files.delete_if { |f| f =~ Regexp.union(*@exclude) }
123
- end
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
- end
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
- file lib_name => obj_files do |t|
153
- sh "#{ld} #{so_flags} -o #{t.name} #{t.prerequisites.join(' ')} #{ld_flags} #{libs}"
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.join(' ')
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
@@ -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}/**/{#{FFI::Platform::ARCH}-#{FFI::Platform::OS}/#{library},#{library}}") do |f|
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
@@ -0,0 +1,7 @@
1
+
2
+ module FFI
3
+ module Compiler
4
+ VERSION = "1.3.1"
5
+ end
6
+ end
7
+
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.0.0
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: 2016-07-06 00:00:00.000000000 Z
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.0.0
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.0.0
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: wmeissner@gmail.com
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
- homepage: http://wiki.github.com/ffi/ffi
92
+ - lib/ffi-compiler/version.rb
93
+ homepage: https://github.com/ffi/ffi-compiler
88
94
  licenses:
89
- - Apache 2.0
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
- rubyforge_project:
107
- rubygems_version: 2.5.1
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