gem-compiler 0.8.0 → 0.9.0
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/CHANGELOG.md +20 -1
- data/README.md +95 -19
- data/Rakefile +2 -0
- data/lib/rubygems/commands/compile_command.rb +37 -4
- data/lib/rubygems/compiler.rb +76 -22
- data/lib/rubygems/compiler/version.rb +2 -1
- data/lib/rubygems_plugin.rb +2 -0
- data/test/rubygems/test_gem_commands_compile_command.rb +53 -0
- data/test/rubygems/test_gem_compiler.rb +159 -12
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f715fe84339746f8ec890e713c7e162bb73d53d5
|
4
|
+
data.tar.gz: 5898f0dfb960d964755662674c469c84d95e5db4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b879e33e40fa3ed600305f8c759caae5d3387af03577eb5fdf7bd5e8b3e61029edd7a5f5d3bdb33c6ca5a3fe5f6fa2beec001b48f70492f24042a74e51f9380d
|
7
|
+
data.tar.gz: 1212ed35d0ae616c54e1df0a857b40cfb83e03d6bcf52030e34e2d5ac160ca74097bee9ba360f0a4db4d19d22236b62524481700cfda2fbbbc553e6be247fc9c
|
data/CHANGELOG.md
CHANGED
@@ -10,6 +10,24 @@ upgrading.
|
|
10
10
|
|
11
11
|
## [Unreleased]
|
12
12
|
|
13
|
+
## [0.9.0] - 2020-04-05
|
14
|
+
|
15
|
+
### Added
|
16
|
+
- Allow symbol stripping from extensions (using `--strip`). (#40, #48, #50)
|
17
|
+
- Introduce more strict Ruby version locking (using `--abi-lock`). (#51, #52)
|
18
|
+
|
19
|
+
### Fixed
|
20
|
+
- Solve upcoming RubyGems deprecation warnings
|
21
|
+
|
22
|
+
### Changed
|
23
|
+
- Deal with RubyGems 3.x `new_spec` deprecation in tests.
|
24
|
+
- CI: Replace Travis/AppVeyor with GitHub Actions for Ubuntu, macOS and Windows.
|
25
|
+
- No longer raise exceptions when executed against non-compilable gems. (#38, #47)
|
26
|
+
|
27
|
+
### Removed
|
28
|
+
- Drop support for Ruby 2.3.x, as it reached EOL (End Of Life)
|
29
|
+
- Drop support for RubyGems older than 2.6.0 (Ruby 2.4 includes RubyGems 2.6.8)
|
30
|
+
|
13
31
|
## [0.8.0] - 2017-12-28
|
14
32
|
|
15
33
|
### Added
|
@@ -94,7 +112,8 @@ upgrading.
|
|
94
112
|
|
95
113
|
- Initial public release, extracted from internal project.
|
96
114
|
|
97
|
-
[Unreleased]: https://github.com/luislavena/gem-compiler/compare/v0.
|
115
|
+
[Unreleased]: https://github.com/luislavena/gem-compiler/compare/v0.9.0...HEAD
|
116
|
+
[0.8.0]: https://github.com/luislavena/gem-compiler/compare/v0.8.0...v0.9.0
|
98
117
|
[0.8.0]: https://github.com/luislavena/gem-compiler/compare/v0.7.0...v0.8.0
|
99
118
|
[0.7.0]: https://github.com/luislavena/gem-compiler/compare/v0.6.0...v0.7.0
|
100
119
|
[0.6.0]: https://github.com/luislavena/gem-compiler/compare/v0.5.0...v0.6.0
|
data/README.md
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
A RubyGems plugin that generates binary (pre-compiled) gems.
|
4
4
|
|
5
5
|
[](https://rubygems.org/gems/gem-compiler)
|
6
|
-
[](https://travis-ci.org/luislavena/gem-compiler)
|
7
|
-
[](https://ci.appveyor.com/project/luislavena/gem-compiler)
|
8
6
|
[](https://codeclimate.com/github/luislavena/gem-compiler)
|
9
7
|
|
10
8
|
- [home](https://github.com/luislavena/gem-compiler)
|
@@ -19,8 +17,49 @@ Ruby C extensions and bundles the result into a new gem.
|
|
19
17
|
It uses an *outside-in* approach and leverages on existing RubyGems code to
|
20
18
|
do it.
|
21
19
|
|
22
|
-
|
23
|
-
|
20
|
+
## Benefits
|
21
|
+
|
22
|
+
Using `gem-compiler` removes the need to install a compiler toolchain on the
|
23
|
+
platform used to run the extension. This means less dependencies are required
|
24
|
+
in those systems and can reduce associated update/maintenance cycles.
|
25
|
+
|
26
|
+
Additionally, by having only binaries, it reduces the time it takes to install
|
27
|
+
several gems that normally take minutes to compile themselves and the needed
|
28
|
+
dependencies.
|
29
|
+
|
30
|
+
Without `gem-compiler`, takes more than a minute to install Nokogiri on
|
31
|
+
Ubuntu 18.04:
|
32
|
+
|
33
|
+
```console
|
34
|
+
$ time gem install --local nokogiri-1.10.7.gem
|
35
|
+
Building native extensions. This could take a while...
|
36
|
+
Successfully installed nokogiri-1.10.7
|
37
|
+
1 gem installed
|
38
|
+
|
39
|
+
real 1m22.670s
|
40
|
+
user 1m5.856s
|
41
|
+
sys 0m18.637s
|
42
|
+
```
|
43
|
+
|
44
|
+
Compared to the installation of the pre-compiled version:
|
45
|
+
|
46
|
+
```console
|
47
|
+
$ gem compile nokogiri-1.10.7.gem --prune
|
48
|
+
Unpacking gem: 'nokogiri-1.10.7' in temporary directory...
|
49
|
+
Building native extensions. This could take a while...
|
50
|
+
Successfully built RubyGem
|
51
|
+
Name: nokogiri
|
52
|
+
Version: 1.10.7
|
53
|
+
File: nokogiri-1.10.7-x86_64-linux.gem
|
54
|
+
|
55
|
+
$ time gem install --local nokogiri-1.10.7-x86_64-linux.gem
|
56
|
+
Successfully installed nokogiri-1.10.7-x86_64-linux
|
57
|
+
1 gem installed
|
58
|
+
|
59
|
+
real 0m1.697s
|
60
|
+
user 0m1.281s
|
61
|
+
sys 0m0.509s
|
62
|
+
```
|
24
63
|
|
25
64
|
## Installation
|
26
65
|
|
@@ -91,22 +130,59 @@ process:
|
|
91
130
|
Successfully installed nokogiri-1.6.6.2-x86_64-darwin-12
|
92
131
|
1 gem installed
|
93
132
|
|
94
|
-
####
|
133
|
+
#### Restricting generated binary gems
|
134
|
+
|
135
|
+
Gems compiled with `gem-compiler` be lock to the version of Ruby used
|
136
|
+
to compile them, following Ruby's ABI compatibility (`MAJOR.MINOR`)
|
137
|
+
|
138
|
+
This means that a gem compiled with Ruby 2.6.1 could be installed in any
|
139
|
+
version of Ruby 2.6.x (Eg. 2.6.4).
|
140
|
+
|
141
|
+
You can tweak this behavior by using `--abi-lock` option during compilation.
|
142
|
+
There are 3 available modes:
|
95
143
|
|
96
|
-
|
97
|
-
|
144
|
+
* `ruby`: Follows Ruby's ABI. Gems compiled with Ruby 2.6.1 can be installed
|
145
|
+
in any Ruby 2.6.x (default behavior).
|
146
|
+
* `strict`: Uses Ruby's full version. Gems compiled with Ruby 2.6.1 can only
|
147
|
+
be installed in Ruby 2.6.1.
|
148
|
+
* `none`: Disables Ruby compatibility. Gems compiled with this option can be
|
149
|
+
installed on any version of Ruby (alias for `--no-abi-lock`).
|
98
150
|
|
99
|
-
|
100
|
-
Ruby
|
151
|
+
**Warning**: usage of `none` is not recommended since different versions of
|
152
|
+
Ruby might expose different APIs. The binary might be expecting specific
|
153
|
+
features not present in the version of Ruby you're installing the gem into.
|
101
154
|
|
102
|
-
|
155
|
+
#### Reducing extension's size (stripping)
|
103
156
|
|
104
|
-
|
157
|
+
By default, RubyGems do not strip symbols from compiled extensions, including
|
158
|
+
debugging information and can result in increased size of final package.
|
105
159
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
160
|
+
With `--strip`, you can reduce extensions by using same stripping options used
|
161
|
+
by Ruby itself (see `RbConfig::CONFIG["STRIP"]`):
|
162
|
+
|
163
|
+
```console
|
164
|
+
$ gem compile oj-3.10.0.gem --strip
|
165
|
+
Unpacking gem: 'oj-3.10.0' in temporary directory...
|
166
|
+
Building native extensions. This could take a while...
|
167
|
+
Stripping symbols from extensions (using 'strip -S -x')...
|
168
|
+
Successfully built RubyGem
|
169
|
+
Name: oj
|
170
|
+
Version: 3.10.0
|
171
|
+
File: oj-3.10.0-x86_64-linux.gem
|
172
|
+
```
|
173
|
+
|
174
|
+
Or you can provide your own stripping command instead:
|
175
|
+
|
176
|
+
```console
|
177
|
+
$ gem compile oj-3.10.0.gem --strip "strip --strip-unneeded"
|
178
|
+
Unpacking gem: 'oj-3.10.0' in temporary directory...
|
179
|
+
Building native extensions. This could take a while...
|
180
|
+
Stripping symbols from extensions (using 'strip --strip-unneeded')...
|
181
|
+
Successfully built RubyGem
|
182
|
+
Name: oj
|
183
|
+
Version: 3.10.0
|
184
|
+
File: oj-3.10.0-x86_64-linux.gem
|
185
|
+
```
|
110
186
|
|
111
187
|
### Compiling from Rake
|
112
188
|
|
@@ -129,9 +205,9 @@ required.
|
|
129
205
|
### Ruby and RubyGems
|
130
206
|
|
131
207
|
It's assumed you have Ruby and RubyGems installed. gem-compiler requires
|
132
|
-
RubyGems
|
208
|
+
RubyGems 2.6.x to work.
|
133
209
|
|
134
|
-
If you don't have RubyGems
|
210
|
+
If you don't have RubyGems 2.6.x, you can upgrade by running:
|
135
211
|
|
136
212
|
$ gem update --system
|
137
213
|
|
@@ -146,7 +222,7 @@ right one.
|
|
146
222
|
|
147
223
|
For those using RubyInstaller-based builds, you will need to download the
|
148
224
|
DevKit from their [downloads page](http://rubyinstaller.org/downloads)
|
149
|
-
and follow the
|
225
|
+
and follow the installation instructions.
|
150
226
|
|
151
227
|
To be sure your installation of Ruby is based on RubyInstaller, execute at
|
152
228
|
the command prompt:
|
@@ -155,7 +231,7 @@ the command prompt:
|
|
155
231
|
|
156
232
|
And from the output:
|
157
233
|
|
158
|
-
|
234
|
+
ruby 2.4.9p362 (2019-10-02 revision 67824) [x64-mingw32]
|
159
235
|
|
160
236
|
If you see `mingw32`, that means you're using a RubyInstaller build
|
161
237
|
(MinGW based).
|
data/Rakefile
CHANGED
@@ -1,9 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rbconfig"
|
1
4
|
require "rubygems/command"
|
2
5
|
|
3
6
|
class Gem::Commands::CompileCommand < Gem::Command
|
7
|
+
ABIs = {
|
8
|
+
"ruby" => :ruby,
|
9
|
+
"strict" => :strict,
|
10
|
+
"none" => :none
|
11
|
+
}.freeze
|
12
|
+
|
4
13
|
def initialize
|
5
|
-
|
6
|
-
|
14
|
+
defaults = {
|
15
|
+
output: Dir.pwd,
|
16
|
+
abi_lock: :ruby
|
17
|
+
}
|
18
|
+
|
19
|
+
super "compile", "Create binary pre-compiled gem", defaults
|
7
20
|
|
8
21
|
add_option "-O", "--output DIR", "Directory where binary will be stored" do |value, options|
|
9
22
|
options[:output] = File.expand_path(value, Dir.pwd)
|
@@ -17,8 +30,28 @@ class Gem::Commands::CompileCommand < Gem::Command
|
|
17
30
|
options[:prune] = true
|
18
31
|
end
|
19
32
|
|
20
|
-
add_option "
|
21
|
-
|
33
|
+
add_option "--abi-lock MODE",
|
34
|
+
"Lock to version of Ruby (ruby, strict, none)" do |value, options|
|
35
|
+
|
36
|
+
mode = ABIs[value]
|
37
|
+
unless mode
|
38
|
+
valid = ABIs.keys.sort
|
39
|
+
raise OptionParser::InvalidArgument, "#{value} (#{valid.join ', '} are valid)"
|
40
|
+
end
|
41
|
+
|
42
|
+
options[:abi_lock] = mode
|
43
|
+
end
|
44
|
+
|
45
|
+
add_option "-N", "--no-abi-lock", "Do not lock compiled Gem to Ruby's ABI (same as --abi-lock=none)" do |value, options|
|
46
|
+
options[:abi_lock] = :none
|
47
|
+
end
|
48
|
+
|
49
|
+
add_option "-S", "--strip [CMD]", "Strip symbols from generated binaries" do |value, options|
|
50
|
+
if value.nil? || value.empty?
|
51
|
+
options[:strip] = RbConfig::CONFIG["STRIP"]
|
52
|
+
else
|
53
|
+
options[:strip] = value
|
54
|
+
end
|
22
55
|
end
|
23
56
|
end
|
24
57
|
|
data/lib/rubygems/compiler.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "fileutils"
|
4
|
+
require "open3"
|
2
5
|
require "rbconfig"
|
3
6
|
require "tmpdir"
|
4
7
|
require "rubygems/installer"
|
@@ -25,6 +28,8 @@ class Gem::Compiler
|
|
25
28
|
|
26
29
|
artifacts = collect_artifacts
|
27
30
|
|
31
|
+
strip_artifacts artifacts
|
32
|
+
|
28
33
|
if shared_dir = options[:include_shared_dir]
|
29
34
|
shared_libs = collect_shared(shared_dir)
|
30
35
|
|
@@ -44,6 +49,19 @@ class Gem::Compiler
|
|
44
49
|
|
45
50
|
private
|
46
51
|
|
52
|
+
def adjust_abi_lock(gemspec)
|
53
|
+
abi_lock = @options[:abi_lock] || :ruby
|
54
|
+
case abi_lock
|
55
|
+
when :ruby
|
56
|
+
ruby_abi = RbConfig::CONFIG["ruby_version"]
|
57
|
+
gemspec.required_ruby_version = "~> #{ruby_abi}"
|
58
|
+
when :strict
|
59
|
+
cfg = RbConfig::CONFIG
|
60
|
+
ruby_abi = "#{cfg["MAJOR"]}.#{cfg["MINOR"]}.#{cfg["TEENY"]}.0"
|
61
|
+
gemspec.required_ruby_version = "~> #{ruby_abi}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
47
65
|
def adjust_gemspec_files(gemspec, artifacts)
|
48
66
|
# remove any non-existing files
|
49
67
|
if @options[:prune]
|
@@ -115,19 +133,9 @@ class Gem::Compiler
|
|
115
133
|
end
|
116
134
|
|
117
135
|
def prepare_installer
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
installer = Gem::Installer.at(@gemfile, unpack_options)
|
122
|
-
else
|
123
|
-
installer = Gem::Installer.new(@gemfile, options.dup.merge(unpack: true))
|
124
|
-
end
|
125
|
-
|
126
|
-
# RubyGems 2.2 specifics
|
127
|
-
if installer.spec.respond_to?(:full_gem_path=)
|
128
|
-
installer.spec.full_gem_path = @target_dir
|
129
|
-
installer.spec.extension_dir = File.join(@target_dir, "lib")
|
130
|
-
end
|
136
|
+
installer = Gem::Installer.at(@gemfile, options.dup.merge(unpack: true))
|
137
|
+
installer.spec.full_gem_path = @target_dir
|
138
|
+
installer.spec.extension_dir = File.join(@target_dir, "lib")
|
131
139
|
|
132
140
|
# Ensure Ruby version is met
|
133
141
|
if installer.respond_to?(:ensure_required_ruby_version_met)
|
@@ -141,14 +149,16 @@ class Gem::Compiler
|
|
141
149
|
|
142
150
|
# Hmm, gem already compiled?
|
143
151
|
if installer.spec.platform != Gem::Platform::RUBY
|
144
|
-
|
145
|
-
|
152
|
+
info "The gem file seems to be compiled already. Skipping."
|
153
|
+
cleanup
|
154
|
+
terminate_interaction
|
146
155
|
end
|
147
156
|
|
148
157
|
# Hmm, no extensions?
|
149
158
|
if installer.spec.extensions.empty?
|
150
|
-
|
151
|
-
|
159
|
+
info "There are no extensions to build on this gem file. Skipping."
|
160
|
+
cleanup
|
161
|
+
terminate_interaction
|
152
162
|
end
|
153
163
|
|
154
164
|
installer
|
@@ -162,10 +172,7 @@ class Gem::Compiler
|
|
162
172
|
gemspec.platform = Gem::Platform::CURRENT
|
163
173
|
|
164
174
|
# adjust version of Ruby
|
165
|
-
|
166
|
-
ruby_abi = RbConfig::CONFIG["ruby_version"]
|
167
|
-
gemspec.required_ruby_version = "~> #{ruby_abi}"
|
168
|
-
end
|
175
|
+
adjust_abi_lock(gemspec)
|
169
176
|
|
170
177
|
# build new gem
|
171
178
|
output_gem = nil
|
@@ -186,6 +193,45 @@ class Gem::Compiler
|
|
186
193
|
output_gem
|
187
194
|
end
|
188
195
|
|
196
|
+
def simple_run(command, command_name)
|
197
|
+
begin
|
198
|
+
output, status = Open3.capture2e(*command)
|
199
|
+
rescue => error
|
200
|
+
raise Gem::CompilerError, "#{command_name} failed#{error.message}"
|
201
|
+
end
|
202
|
+
|
203
|
+
yield(status, output) if block_given?
|
204
|
+
|
205
|
+
unless status.success?
|
206
|
+
exit_reason =
|
207
|
+
if status.exited?
|
208
|
+
", exit code #{status.exitstatus}"
|
209
|
+
elsif status.signaled?
|
210
|
+
", uncaught signal #{status.termsig}"
|
211
|
+
end
|
212
|
+
|
213
|
+
raise Gem::CompilerError, "#{command_name} failed#{exit_reason}"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def strip_artifacts(artifacts)
|
218
|
+
return unless options[:strip]
|
219
|
+
|
220
|
+
strip_cmd = options[:strip]
|
221
|
+
|
222
|
+
info "Stripping symbols from extensions (using '#{strip_cmd}')..."
|
223
|
+
|
224
|
+
artifacts.each do |artifact|
|
225
|
+
cmd = [strip_cmd, artifact].join(' ').rstrip
|
226
|
+
|
227
|
+
simple_run(cmd, "strip #{File.basename(artifact)}") do |status, output|
|
228
|
+
if status.success?
|
229
|
+
debug "Stripped #{File.basename(artifact)}"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
189
235
|
def tmp_dir
|
190
236
|
@tmp_dir ||= Dir.glob(Dir.mktmpdir).first
|
191
237
|
end
|
@@ -197,6 +243,14 @@ class Gem::Compiler
|
|
197
243
|
# unpack gem sources into target_dir
|
198
244
|
# We need the basename to keep the unpack happy
|
199
245
|
info "Unpacking gem: '#{basename}' in temporary directory..."
|
200
|
-
|
246
|
+
|
247
|
+
# RubyGems >= 3.1.x
|
248
|
+
if installer.respond_to?(:package)
|
249
|
+
package = installer.package
|
250
|
+
else
|
251
|
+
package = Gem::Package.new(@gemfile)
|
252
|
+
end
|
253
|
+
|
254
|
+
package.extract_files(@target_dir)
|
201
255
|
end
|
202
256
|
end
|
data/lib/rubygems_plugin.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rubygems/test_case"
|
2
4
|
require "rubygems/commands/compile_command"
|
3
5
|
require "rubygems/package"
|
@@ -20,4 +22,55 @@ class TestGemCommandsCompileCommand < Gem::TestCase
|
|
20
22
|
|
21
23
|
assert_match %r{Please specify a gem file on the command line}, e.message
|
22
24
|
end
|
25
|
+
|
26
|
+
def test_handle_abi_lock_ruby
|
27
|
+
@cmd.handle_options []
|
28
|
+
|
29
|
+
assert_equal :ruby, @cmd.options[:abi_lock]
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_handle_abi_lock_explicit_ruby
|
33
|
+
@cmd.handle_options ["--abi-lock=ruby"]
|
34
|
+
|
35
|
+
assert_equal :ruby, @cmd.options[:abi_lock]
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_handle_abi_lock_strict
|
39
|
+
@cmd.handle_options ["--abi-lock=strict"]
|
40
|
+
|
41
|
+
assert_equal :strict, @cmd.options[:abi_lock]
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_handle_abi_lock_none
|
45
|
+
@cmd.handle_options ["--abi-lock=none"]
|
46
|
+
|
47
|
+
assert_equal :none, @cmd.options[:abi_lock]
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_handle_no_abi_lock_none
|
51
|
+
@cmd.handle_options ["--no-abi-lock"]
|
52
|
+
|
53
|
+
assert_equal :none, @cmd.options[:abi_lock]
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_handle_abi_lock_unknown
|
57
|
+
e = assert_raises OptionParser::InvalidArgument do
|
58
|
+
@cmd.handle_options %w[--abi-lock unknown]
|
59
|
+
end
|
60
|
+
|
61
|
+
assert_equal "invalid argument: --abi-lock unknown (none, ruby, strict are valid)",
|
62
|
+
e.message
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_handle_strip_default
|
66
|
+
@cmd.handle_options %w[--strip]
|
67
|
+
|
68
|
+
assert_equal RbConfig::CONFIG["STRIP"], @cmd.options[:strip]
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_handle_strip_custom
|
72
|
+
@cmd.handle_options ["--strip", "strip --custom"]
|
73
|
+
|
74
|
+
assert_equal "strip --custom", @cmd.options[:strip]
|
75
|
+
end
|
23
76
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rubygems/test_case"
|
2
4
|
require "rubygems/compiler"
|
3
5
|
|
@@ -25,14 +27,16 @@ class TestGemCompiler < Gem::TestCase
|
|
25
27
|
|
26
28
|
compiler = Gem::Compiler.new(gem_file, :output => @output_dir)
|
27
29
|
|
28
|
-
|
30
|
+
assert_raises Gem::MockGemUi::SystemExitException do
|
29
31
|
use_ui @ui do
|
30
32
|
compiler.compile
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
+
out = @ui.output.split "\n"
|
37
|
+
|
38
|
+
assert_equal "There are no extensions to build on this gem file. Skipping.",
|
39
|
+
out.last
|
36
40
|
end
|
37
41
|
|
38
42
|
def test_compile_non_ruby
|
@@ -40,13 +44,15 @@ class TestGemCompiler < Gem::TestCase
|
|
40
44
|
|
41
45
|
compiler = Gem::Compiler.new(gem_file, :output => @output_dir)
|
42
46
|
|
43
|
-
|
47
|
+
assert_raises Gem::MockGemUi::SystemExitException do
|
44
48
|
use_ui @ui do
|
45
49
|
compiler.compile
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
49
|
-
|
53
|
+
out = @ui.output.split "\n"
|
54
|
+
|
55
|
+
assert_equal "The gem file seems to be compiled already. Skipping.", out.last
|
50
56
|
end
|
51
57
|
|
52
58
|
def test_compile_pre_install_hooks
|
@@ -307,7 +313,7 @@ class TestGemCompiler < Gem::TestCase
|
|
307
313
|
util_reset_arch
|
308
314
|
end
|
309
315
|
|
310
|
-
def
|
316
|
+
def test_compile_abi_lock_ruby
|
311
317
|
util_reset_arch
|
312
318
|
|
313
319
|
ruby_abi = RbConfig::CONFIG["ruby_version"]
|
@@ -317,7 +323,29 @@ class TestGemCompiler < Gem::TestCase
|
|
317
323
|
util_fake_extension s, "foo", util_custom_configure(artifact)
|
318
324
|
}
|
319
325
|
|
320
|
-
compiler = Gem::Compiler.new(gem_file, :output => @output_dir)
|
326
|
+
compiler = Gem::Compiler.new(gem_file, :output => @output_dir, :abi_lock => nil)
|
327
|
+
output_gem = nil
|
328
|
+
|
329
|
+
use_ui @ui do
|
330
|
+
output_gem = compiler.compile
|
331
|
+
end
|
332
|
+
|
333
|
+
spec = util_read_spec File.join(@output_dir, output_gem)
|
334
|
+
|
335
|
+
assert_equal Gem::Requirement.new("~> #{ruby_abi}"), spec.required_ruby_version
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_compile_abi_lock_explicit_ruby
|
339
|
+
util_reset_arch
|
340
|
+
|
341
|
+
ruby_abi = RbConfig::CONFIG["ruby_version"]
|
342
|
+
artifact = "foo.#{RbConfig::CONFIG["DLEXT"]}"
|
343
|
+
|
344
|
+
gem_file = util_bake_gem("foo") { |s|
|
345
|
+
util_fake_extension s, "foo", util_custom_configure(artifact)
|
346
|
+
}
|
347
|
+
|
348
|
+
compiler = Gem::Compiler.new(gem_file, :output => @output_dir, :abi_lock => :ruby)
|
321
349
|
output_gem = nil
|
322
350
|
|
323
351
|
use_ui @ui do
|
@@ -326,19 +354,65 @@ class TestGemCompiler < Gem::TestCase
|
|
326
354
|
|
327
355
|
spec = util_read_spec File.join(@output_dir, output_gem)
|
328
356
|
|
329
|
-
assert_equal
|
357
|
+
assert_equal Gem::Requirement.new("~> #{ruby_abi}"), spec.required_ruby_version
|
330
358
|
end
|
331
359
|
|
332
|
-
def
|
360
|
+
def test_compile_abi_lock_strict
|
333
361
|
util_reset_arch
|
334
362
|
|
363
|
+
ruby_abi = "%d.%d.%d.0" % RbConfig::CONFIG.values_at("MAJOR", "MINOR", "TEENY")
|
335
364
|
artifact = "foo.#{RbConfig::CONFIG["DLEXT"]}"
|
336
365
|
|
337
366
|
gem_file = util_bake_gem("foo") { |s|
|
338
367
|
util_fake_extension s, "foo", util_custom_configure(artifact)
|
339
368
|
}
|
340
369
|
|
341
|
-
compiler = Gem::Compiler.new(gem_file, :output => @output_dir, :
|
370
|
+
compiler = Gem::Compiler.new(gem_file, :output => @output_dir, :abi_lock => :strict)
|
371
|
+
output_gem = nil
|
372
|
+
|
373
|
+
use_ui @ui do
|
374
|
+
output_gem = compiler.compile
|
375
|
+
end
|
376
|
+
|
377
|
+
spec = util_read_spec File.join(@output_dir, output_gem)
|
378
|
+
|
379
|
+
assert_equal Gem::Requirement.new("~> #{ruby_abi}"), spec.required_ruby_version
|
380
|
+
end
|
381
|
+
|
382
|
+
def test_compile_abi_lock_none
|
383
|
+
util_reset_arch
|
384
|
+
|
385
|
+
artifact = "foo.#{RbConfig::CONFIG["DLEXT"]}"
|
386
|
+
|
387
|
+
gem_file = util_bake_gem("foo") { |s|
|
388
|
+
util_fake_extension s, "foo", util_custom_configure(artifact)
|
389
|
+
}
|
390
|
+
|
391
|
+
compiler = Gem::Compiler.new(gem_file, :output => @output_dir, :abi_lock => :none)
|
392
|
+
output_gem = nil
|
393
|
+
|
394
|
+
use_ui @ui do
|
395
|
+
output_gem = compiler.compile
|
396
|
+
end
|
397
|
+
|
398
|
+
spec = util_read_spec File.join(@output_dir, output_gem)
|
399
|
+
|
400
|
+
assert_equal Gem::Requirement.new(">= 0"), spec.required_ruby_version
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_compile_strip_cmd
|
404
|
+
util_reset_arch
|
405
|
+
hook_simple_run
|
406
|
+
|
407
|
+
old_rbconfig_strip = RbConfig::CONFIG["STRIP"]
|
408
|
+
RbConfig::CONFIG["STRIP"] = "rbconfig-strip-cmd"
|
409
|
+
|
410
|
+
gem_file = util_bake_gem("foo") do |spec|
|
411
|
+
util_dummy_extension spec, "bar"
|
412
|
+
end
|
413
|
+
|
414
|
+
compiler = Gem::Compiler.new(gem_file, :output => @output_dir,
|
415
|
+
:strip => "echo strip-custom")
|
342
416
|
output_gem = nil
|
343
417
|
|
344
418
|
use_ui @ui do
|
@@ -346,8 +420,38 @@ class TestGemCompiler < Gem::TestCase
|
|
346
420
|
end
|
347
421
|
|
348
422
|
spec = util_read_spec File.join(@output_dir, output_gem)
|
423
|
+
assert_includes spec.files, "lib/bar.#{RbConfig::CONFIG["DLEXT"]}"
|
424
|
+
|
425
|
+
assert_match %r|Stripping symbols from extensions|, @ui.output
|
426
|
+
refute_match %r|#{RbConfig::CONFIG["STRIP"]}|, @ui.output
|
427
|
+
assert_match %r|using 'echo strip-custom'|, @ui.output
|
428
|
+
ensure
|
429
|
+
RbConfig::CONFIG["STRIP"] = old_rbconfig_strip
|
430
|
+
restore_simple_run
|
431
|
+
end
|
432
|
+
|
433
|
+
##
|
434
|
+
# Replace `simple_run` to help testing command execution
|
435
|
+
|
436
|
+
def hook_simple_run
|
437
|
+
Gem::Compiler.class_eval do
|
438
|
+
alias_method :orig_simple_run, :simple_run
|
439
|
+
remove_method :simple_run
|
440
|
+
|
441
|
+
def simple_run(command, command_name)
|
442
|
+
say "#{command_name}: #{command}"
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
##
|
448
|
+
# Restore `simple_run` to its original version
|
349
449
|
|
350
|
-
|
450
|
+
def restore_simple_run
|
451
|
+
Gem::Compiler.class_eval do
|
452
|
+
remove_method :simple_run
|
453
|
+
alias_method :simple_run, :orig_simple_run
|
454
|
+
end
|
351
455
|
end
|
352
456
|
|
353
457
|
##
|
@@ -364,11 +468,54 @@ class TestGemCompiler < Gem::TestCase
|
|
364
468
|
def util_bake_gem(name = "a", *extra, &block)
|
365
469
|
files = ["lib/#{name}.rb"].concat(extra)
|
366
470
|
|
367
|
-
spec =
|
471
|
+
spec = if Gem::VERSION >= "3.0.0"
|
472
|
+
util_spec name, "1", nil, files, &block
|
473
|
+
else
|
474
|
+
new_spec name, "1", nil, files, &block
|
475
|
+
end
|
368
476
|
|
369
477
|
File.join @tempdir, "gems", "#{spec.full_name}.gem"
|
370
478
|
end
|
371
479
|
|
480
|
+
##
|
481
|
+
# Add a dummy, valid extension to provided spec
|
482
|
+
|
483
|
+
def util_dummy_extension(spec, name = "a")
|
484
|
+
extconf = File.join("ext", name, "extconf.rb")
|
485
|
+
dummy_c = File.join("ext", name, "dummy.c")
|
486
|
+
|
487
|
+
spec.extensions << extconf
|
488
|
+
spec.files << dummy_c
|
489
|
+
|
490
|
+
dir = spec.gem_dir
|
491
|
+
FileUtils.mkdir_p dir
|
492
|
+
|
493
|
+
Dir.chdir dir do
|
494
|
+
FileUtils.mkdir_p File.dirname(extconf)
|
495
|
+
|
496
|
+
# extconf.rb
|
497
|
+
File.open extconf, "w" do |f|
|
498
|
+
f.write <<~EOF
|
499
|
+
require "mkmf"
|
500
|
+
|
501
|
+
create_makefile("#{name}")
|
502
|
+
EOF
|
503
|
+
end
|
504
|
+
|
505
|
+
# dummy.c
|
506
|
+
File.open dummy_c, "w" do |f|
|
507
|
+
f.write <<~EOF
|
508
|
+
#include <ruby.h>
|
509
|
+
|
510
|
+
void Init_#{name}(void)
|
511
|
+
{
|
512
|
+
rb_p(ID2SYM(rb_intern("ok")));
|
513
|
+
}
|
514
|
+
EOF
|
515
|
+
end
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
372
519
|
##
|
373
520
|
# Add a fake extension to provided spec and accept an optional script.
|
374
521
|
# Default to no-op if none is provided.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gem-compiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luis Lavena
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -74,15 +74,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
74
|
requirements:
|
75
75
|
- - ">="
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 2.
|
77
|
+
version: 2.4.0
|
78
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 2.
|
82
|
+
version: 2.6.0
|
83
83
|
requirements: []
|
84
84
|
rubyforge_project:
|
85
|
-
rubygems_version: 2.
|
85
|
+
rubygems_version: 2.6.14.4
|
86
86
|
signing_key:
|
87
87
|
specification_version: 4
|
88
88
|
summary: A RubyGems plugin that generates binary gems.
|