autoproj 2.11.0 → 2.12.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.
@@ -13,8 +13,13 @@ require 'autoproj/ops/install'
13
13
  ENV.delete('BUNDLE_GEMFILE')
14
14
  ENV.delete('RUBYLIB')
15
15
  ops = Autoproj::Ops::Install.new(Dir.pwd)
16
+
17
+ existing_config = File.join(Dir.pwd, '.autoproj', 'config.yml')
18
+ if File.file?(existing_config)
19
+ puts "Found existing configuration, using it as seed"
20
+ puts "use --no-seed-config to avoid this behavior"
21
+ ops.add_seed_config(existing_config)
22
+ end
16
23
  ops.parse_options(ARGV)
17
24
  ops.stage1
18
- if !ops.skip_stage2?
19
- ops.call_stage2
20
- end
25
+ ops.call_stage2 unless ops.skip_stage2?
@@ -44,6 +44,7 @@
44
44
  require 'autoproj/source_package_query'
45
45
  require 'autoproj/os_package_query'
46
46
 
47
+ require 'autoproj/ops/phase_reporting'
47
48
  require 'autoproj/ops/install'
48
49
  require 'autoproj/ops/tools'
49
50
  require 'autoproj/ops/loader'
@@ -149,11 +149,13 @@ def ignore(*paths)
149
149
 
150
150
  # Adds a new setup block to an existing package
151
151
  def setup_package(package_name, workspace: Autoproj.workspace, &block)
152
- raise ConfigError.new, "you must give a block to #setup_package" unless block
152
+ unless block
153
+ raise Autoproj::ConfigError.new, 'you must give a block to #setup_package'
154
+ end
153
155
 
154
156
  package_definition = workspace.manifest.find_package_definition(package_name)
155
157
  if !package_definition
156
- raise ConfigError.new, "#{package_name} is not a known package"
158
+ raise Autoproj::ConfigError.new, "#{package_name} is not a known package"
157
159
  elsif package_definition.autobuild.kind_of?(Autobuild::DummyPackage)
158
160
  # Nothing to do!
159
161
  else
@@ -56,4 +56,22 @@ def self.post_import(*packages, &block)
56
56
  end
57
57
  end
58
58
  end
59
+
60
+ # Shim for a smooth upgrade path to bundler 2.1+
61
+ def self.bundler_unbundled_system(*args, **options)
62
+ if Bundler.respond_to?(:unbundled_system)
63
+ Bundler.unbundled_system(*args, **options)
64
+ else
65
+ Bundler.clean_system(*args, **options)
66
+ end
67
+ end
68
+
69
+ # Shim for a smooth upgrade path to bundler 2.1+
70
+ def self.bundler_with_unbundled_env(&block)
71
+ if Bundler.respond_to?(:with_unbundled_env)
72
+ Bundler.with_unbundled_env(&block)
73
+ else
74
+ Bundler.with_clean_env(&block)
75
+ end
76
+ end
59
77
  end
@@ -10,21 +10,50 @@ def validate_options(argv, options = Hash.new)
10
10
  if argv.empty?
11
11
  default_cache_dirs = Autobuild::Importer.default_cache_dirs
12
12
  if !default_cache_dirs || default_cache_dirs.empty?
13
- raise CLIInvalidArguments, "no cache directory defined with e.g. the AUTOBUILD_CACHE_DIR environment variable, expected one cache directory as argument"
13
+ raise CLIInvalidArguments,
14
+ "no cache directory defined with e.g. the "\
15
+ "AUTOBUILD_CACHE_DIR environment variable, "\
16
+ "expected one cache directory as argument"
14
17
  end
15
- Autoproj.warn "using cache directory #{default_cache_dirs.first} from the autoproj configuration"
18
+ Autoproj.warn "using cache directory #{default_cache_dirs.first} "\
19
+ "from the autoproj configuration"
16
20
  argv << default_cache_dirs.first
17
21
  end
18
22
 
19
- return File.expand_path(argv.first, ws.root_dir), *argv[1..-1], options
23
+ if (compile = options[:gems_compile])
24
+ options[:gems_compile] = compile.map do |name|
25
+ name, *artifacts = name.split('+')
26
+ [name, artifacts: artifacts]
27
+ end
28
+ end
29
+
30
+ [File.expand_path(argv.first, ws.root_dir), *argv[1..-1], options]
20
31
  end
21
32
 
22
- def run(cache_dir, *package_names, all: true, keep_going: false, checkout_only: false)
33
+ def run(cache_dir, *package_names,
34
+ keep_going: false,
35
+ packages: true, all: true, checkout_only: false,
36
+ gems: false, gems_compile: [], gems_compile_force: false)
23
37
  initialize_and_load
24
38
  finalize_setup
25
39
 
26
- cache_op = Autoproj::Ops::Cache.new(cache_dir, ws.manifest)
27
- cache_op.create_or_update(*package_names, all: all, keep_going: keep_going, checkout_only: checkout_only)
40
+ cache_op = Autoproj::Ops::Cache.new(cache_dir, ws)
41
+ if packages
42
+ cache_op.create_or_update(
43
+ *package_names,
44
+ all: all, keep_going: keep_going,
45
+ checkout_only: checkout_only
46
+ )
47
+ end
48
+
49
+ if gems
50
+ Autoproj.message "caching gems in #{cache_op.gems_cache_dir}"
51
+ cache_op.create_or_update_gems(
52
+ keep_going: keep_going,
53
+ compile: gems_compile,
54
+ compile_force: gems_compile_force
55
+ )
56
+ end
28
57
  end
29
58
  end
30
59
  end
@@ -300,13 +300,34 @@ def build(*packages)
300
300
  end
301
301
  end
302
302
 
303
- desc 'cache CACHE_DIR', 'create or update a cache directory that can be given to AUTOBUILD_CACHE_DIR'
304
- option :keep_going, aliases: :k,
305
- desc: 'do not stop on errors'
306
- option :checkout_only, aliases: :c, type: :boolean, default: false,
307
- desc: "only checkout packages, do not update already-cached ones"
308
- option :all, type: :boolean, default: true,
309
- desc: "cache all defined packages (the default) or only the selected ones"
303
+ desc 'cache CACHE_DIR', 'create or update a cache directory that '\
304
+ 'can be given to AUTOBUILD_CACHE_DIR'
305
+ option :keep_going,
306
+ aliases: :k,
307
+ desc: 'do not stop on errors'
308
+ option :checkout_only,
309
+ aliases: :c, type: :boolean, default: false,
310
+ desc: 'only checkout packages, do not update already-cached ones'
311
+ option :all,
312
+ type: :boolean, default: true,
313
+ desc: 'cache all defined packages (the default), '\
314
+ ' or only the selected ones'
315
+ option :packages,
316
+ type: :boolean, default: true,
317
+ desc: 'update the package cache'
318
+ option :gems,
319
+ type: :boolean, default: false,
320
+ desc: 'update the gems cache'
321
+ option :gems_compile_force,
322
+ type: :boolean, default: false,
323
+ desc: 'with --gems-compile, recompile existing gems as well'
324
+ option :gems_compile,
325
+ type: :array,
326
+ desc: 'pre-compile the following gems. This requires gem-compiler '\
327
+ 'to be available in the workspace. Use GEM_NAME+ARTIFACT'\
328
+ '[+ARTIFACT] to add files or directories to the precompiled '\
329
+ 'gems beyond what gem-compiler auto-adds (which is mostly '\
330
+ 'dynamic libraries)'
310
331
  def cache(*args)
311
332
  run_autoproj_cli(:cache, :Cache, Hash[], *args)
312
333
  end
@@ -10,7 +10,7 @@ def initialize(ws = Workspace.default,
10
10
  end
11
11
 
12
12
  def package_metadata(package)
13
- u = package.autobuild.test_utility
13
+ u = package.test_utility
14
14
  super.merge(
15
15
  'coverage_available' => !!u.coverage_available?,
16
16
  'coverage_enabled' => !!u.coverage_enabled?,
@@ -89,24 +89,37 @@ def run(user_selection, options = {})
89
89
  raise CLIInvalidArguments, "autoproj: the provided package "\
90
90
  "is not selected for build"
91
91
  end
92
+ return if package_names.empty?
92
93
 
93
94
  packages = package_names.map do |pkg_name|
94
95
  ws.manifest.find_package_definition(pkg_name)
95
96
  end
96
97
 
98
+ apply_to_packages(packages, parallel: options[:parallel])
99
+ end
100
+
101
+ def apply_to_packages(packages, parallel: ws.config.parallel_build_level)
102
+ if @report_path
103
+ reporting = Ops::PhaseReporting.new(
104
+ @utility_name, @report_path,
105
+ method(:package_metadata)
106
+ )
107
+ end
108
+
109
+ reporting&.initialize_incremental_report
97
110
  Autobuild.apply(
98
- package_names,
99
- "autoproj-#{utility_name}",
100
- [utility_name],
101
- parallel: options[:parallel]
102
- )
111
+ packages.map(&:name), "autoproj-#{@utility_name}",
112
+ [@utility_name], parallel: parallel
113
+ ) do |pkg, phase|
114
+ reporting&.report_incremental(pkg) if phase == utility_name
115
+ end
103
116
 
104
117
  ensure
105
- create_report(packages) if packages && @report_path
118
+ reporting&.create_report(packages.map(&:autobuild))
106
119
  end
107
120
 
108
- def package_metadata(package)
109
- u = package.autobuild.utility(@utility_name)
121
+ def package_metadata(autobuild_package)
122
+ u = autobuild_package.utility(@utility_name)
110
123
  {
111
124
  'source_dir' => u.source_dir,
112
125
  'target_dir' => u.target_dir,
@@ -117,23 +130,6 @@ def package_metadata(package)
117
130
  'installed' => !!u.installed?,
118
131
  }
119
132
  end
120
-
121
- def create_report(packages)
122
- info = packages.each_with_object({}) do |p, map|
123
- map[p.name] = package_metadata(p)
124
- end
125
-
126
- FileUtils.mkdir_p File.dirname(@report_path)
127
- File.open(@report_path, 'w') do |io|
128
- dump = JSON.dump(
129
- "#{@utility_name}_report" => {
130
- 'timestamp' => Time.now,
131
- 'packages' => info
132
- }
133
- )
134
- io.write dump
135
- end
136
- end
137
133
  end
138
134
  end
139
135
  end
@@ -196,7 +196,9 @@ def configure(option_name)
196
196
  Autoproj.info " using: #{value} (noninteractive mode)"
197
197
  end
198
198
  @modified = true
199
- if !is_default
199
+ if is_default
200
+ value = opt.validate(value)
201
+ else
200
202
  config[option_name] = [value, true]
201
203
  displayed_options[option_name] = value
202
204
  end
@@ -353,6 +355,10 @@ def shell_helpers=(flag)
353
355
  set 'shell_helpers', flag, true
354
356
  end
355
357
 
358
+ def bundler_version
359
+ get 'bundler_version', nil
360
+ end
361
+
356
362
  def apply_autobuild_configuration
357
363
  if has_value_for?('autobuild')
358
364
  params = get('autobuild')
@@ -369,6 +375,11 @@ def importer_cache_dir
369
375
  get('importer_cache_dir', nil)
370
376
  end
371
377
 
378
+ # Set import and gem cache directory
379
+ def importer_cache_dir=(path)
380
+ set('importer_cache_dir', path, true)
381
+ end
382
+
372
383
  # Sets the directory in which packages will be installed
373
384
  def prefix_dir=(path)
374
385
  set('prefix', path, true)
@@ -1,7 +1,8 @@
1
1
  module Autoproj
2
2
  # Manifest of installed packages imported from another autoproj installation
3
3
  class InstallationManifest
4
- Package = Struct.new :name, :type, :vcs, :srcdir, :prefix, :builddir, :logdir, :dependencies
4
+ Package = Struct.new :name, :type, :vcs, :srcdir, :importdir,
5
+ :prefix, :builddir, :logdir, :dependencies
5
6
  PackageSet = Struct.new :name, :vcs, :raw_local_dir, :user_local_dir
6
7
 
7
8
  attr_reader :path
@@ -28,11 +29,11 @@ def add_package_set(pkg_set)
28
29
  def each_package_set(&block)
29
30
  package_sets.each_value(&block)
30
31
  end
31
-
32
+
32
33
  def each_package(&block)
33
34
  packages.each_value(&block)
34
35
  end
35
-
36
+
36
37
  def load
37
38
  @packages = Hash.new
38
39
  raw = YAML.load(File.open(path))
@@ -51,8 +52,8 @@ def load
51
52
  package_sets[pkg_set.name] = pkg_set
52
53
  else
53
54
  pkg = Package.new(
54
- entry['name'], entry['type'], entry['vcs'], entry['srcdir'], entry['prefix'],
55
- entry['builddir'], entry['logdir'], entry['dependencies'])
55
+ entry['name'], entry['type'], entry['vcs'], entry['srcdir'], entry['importdir'],
56
+ entry['prefix'], entry['builddir'], entry['logdir'], entry['dependencies'])
56
57
  packages[pkg.name] = pkg
57
58
  end
58
59
  end
@@ -74,6 +75,7 @@ def save(path = self.path)
74
75
  'type' => v.class.name,
75
76
  'vcs' => package_def.vcs.to_hash,
76
77
  'srcdir' => v.srcdir,
78
+ 'importdir' => (v.importdir if v.respond_to?(:importdir)),
77
79
  'builddir' => (v.builddir if v.respond_to?(:builddir)),
78
80
  'logdir' => v.logdir,
79
81
  'prefix' => v.prefix,
@@ -87,34 +87,36 @@ def force_build_packages(selected_packages, all_enabled_packages)
87
87
  # names of the packages that should be rebuilt
88
88
  # @return [void]
89
89
  def build_packages(all_enabled_packages, options = Hash.new)
90
+ if @report_path
91
+ reporting = Ops::PhaseReporting.new(
92
+ 'build', @report_path, method(:package_metadata)
93
+ )
94
+ end
95
+
90
96
  Autobuild.do_rebuild = false
91
97
  Autobuild.do_forced_build = false
98
+ reporting&.initialize_incremental_report
92
99
  begin
93
- Autobuild.apply(all_enabled_packages, "autoproj-build", ['build'], options)
100
+ Autobuild.apply(
101
+ all_enabled_packages,
102
+ "autoproj-build", ['build'], options
103
+ ) do |pkg, phase|
104
+ reporting&.report_incremental(pkg) if phase == 'build'
105
+ end
106
+
94
107
  ensure
95
- create_report(all_enabled_packages) if @report_path
108
+ packages = all_enabled_packages.map do |name|
109
+ @manifest.find_autobuild_package(name)
110
+ end
111
+ reporting&.create_report(packages)
96
112
  end
97
113
  end
98
114
 
99
- def create_report(package_list)
100
- FileUtils.mkdir_p File.dirname(@report_path)
101
-
102
- packages = package_list.each_with_object({}) do |pkg_name, h|
103
- pkg = manifest.find_autobuild_package(pkg_name)
104
-
105
- h[pkg.name] = {
106
- invoked: !!pkg.install_invoked?,
107
- success: !!pkg.installed?
108
- }
109
- end
110
-
111
- report = JSON.pretty_generate({
112
- build_report: {
113
- timestamp: Time.now,
114
- packages: packages
115
- }
116
- })
117
- IO.write(@report_path, report)
115
+ def package_metadata(autobuild_package)
116
+ {
117
+ invoked: !!autobuild_package.install_invoked?,
118
+ success: !!autobuild_package.installed?
119
+ }
118
120
  end
119
121
  end
120
122
  end
@@ -4,9 +4,10 @@ class Cache
4
4
  attr_reader :cache_dir
5
5
  attr_reader :manifest
6
6
 
7
- def initialize(cache_dir, manifest)
7
+ def initialize(cache_dir, ws)
8
8
  @cache_dir = cache_dir
9
- @manifest = manifest
9
+ @ws = ws
10
+ @manifest = ws.manifest
10
11
  end
11
12
 
12
13
  def with_retry(count)
@@ -27,29 +28,39 @@ def git_cache_dir
27
28
  File.join(cache_dir, 'git')
28
29
  end
29
30
 
30
- def cache_git(pkg, options = Hash.new)
31
+ def cache_git(pkg, checkout_only: false)
31
32
  pkg.importdir = File.join(git_cache_dir, pkg.name)
32
- if options[:checkout_only] && File.directory?(pkg.importdir)
33
- return
34
- end
33
+ return if checkout_only && File.directory?(pkg.importdir)
35
34
 
36
35
  pkg.importer.local_branch = nil
37
36
  pkg.importer.remote_branch = nil
38
37
  pkg.importer.remote_name = 'autobuild'
39
38
 
40
- if !File.directory?(pkg.importdir)
39
+ unless File.directory?(pkg.importdir)
41
40
  FileUtils.mkdir_p File.dirname(pkg.importdir)
42
- Autobuild::Subprocess.run("autoproj-cache", "import", Autobuild.tool(:git), "--git-dir", pkg.importdir, 'init', "--bare")
41
+ Autobuild::Subprocess.run(
42
+ "autoproj-cache", "import", Autobuild.tool(:git),
43
+ "--git-dir", pkg.importdir, 'init', "--bare"
44
+ )
43
45
  end
44
46
  pkg.importer.update_remotes_configuration(pkg)
45
47
 
46
48
  with_retry(10) do
47
- Autobuild::Subprocess.run('autoproj-cache', :import, Autobuild.tool('git'), '--git-dir', pkg.importdir, 'remote', 'update', 'autobuild')
49
+ Autobuild::Subprocess.run(
50
+ 'autoproj-cache', :import, Autobuild.tool('git'),
51
+ '--git-dir', pkg.importdir, 'remote', 'update', 'autobuild'
52
+ )
48
53
  end
49
54
  with_retry(10) do
50
- Autobuild::Subprocess.run('autoproj-cache', :import, Autobuild.tool('git'), '--git-dir', pkg.importdir, 'fetch', 'autobuild', '--tags')
55
+ Autobuild::Subprocess.run(
56
+ 'autoproj-cache', :import, Autobuild.tool('git'),
57
+ '--git-dir', pkg.importdir, 'fetch', 'autobuild', '--tags'
58
+ )
51
59
  end
52
- Autobuild::Subprocess.run('autoproj-cache', :import, Autobuild.tool('git'), '--git-dir', pkg.importdir, 'gc', '--prune=all')
60
+ Autobuild::Subprocess.run(
61
+ 'autoproj-cache', :import, Autobuild.tool('git'),
62
+ '--git-dir', pkg.importdir, 'gc', '--prune=all'
63
+ )
53
64
  end
54
65
 
55
66
  def archive_cache_dir
@@ -63,7 +74,8 @@ def cache_archive(pkg)
63
74
  end
64
75
  end
65
76
 
66
- def create_or_update(*package_names, all: true, keep_going: false, checkout_only: false)
77
+ def create_or_update(*package_names, all: true, keep_going: false,
78
+ checkout_only: false)
67
79
  FileUtils.mkdir_p cache_dir
68
80
 
69
81
  if package_names.empty?
@@ -75,7 +87,7 @@ def create_or_update(*package_names, all: true, keep_going: false, checkout_only
75
87
  end
76
88
  else
77
89
  packages = package_names.map do |name|
78
- if pkg = manifest.find_autobuild_package(name)
90
+ if (pkg = manifest.find_autobuild_package(name))
79
91
  pkg
80
92
  else
81
93
  raise PackageNotFound, "no package named #{name}"
@@ -88,7 +100,10 @@ def create_or_update(*package_names, all: true, keep_going: false, checkout_only
88
100
  total = packages.size
89
101
  Autoproj.message "Handling #{total} packages"
90
102
  packages.each_with_index do |pkg, i|
91
- next if pkg.srcdir != pkg.importdir # No need to process this one, it is uses another package's import
103
+ # No need to process this one, it is uses another package's
104
+ # import
105
+ next if pkg.srcdir != pkg.importdir
106
+
92
107
  begin
93
108
  case pkg.importer
94
109
  when Autobuild::Git
@@ -103,27 +118,117 @@ def create_or_update(*package_names, all: true, keep_going: false, checkout_only
103
118
  rescue Interrupt
104
119
  raise
105
120
  rescue ::Exception => e
106
- if keep_going
107
- pkg.error " failed to cache #{pkg.name}, but going on as requested"
108
- lines = e.to_s.split("\n")
109
- if lines.empty?
110
- lines = e.message.split("\n")
111
- end
112
- if lines.empty?
113
- lines = ["unknown error"]
114
- end
115
- pkg.message(lines.shift, :red, :bold)
116
- lines.each do |line|
117
- pkg.message(line)
121
+ raise unless keep_going
122
+
123
+ pkg.error " failed to cache #{pkg.name}, "\
124
+ 'but going on as requested'
125
+ lines = e.to_s.split('\n')
126
+ lines = e.message.split('\n') if lines.empty?
127
+ lines = ['unknown error'] if lines.empty?
128
+ pkg.message(lines.shift, :red, :bold)
129
+ lines.each do |line|
130
+ pkg.message(line)
131
+ end
132
+ nil
133
+ end
134
+ end
135
+ end
136
+
137
+ def gems_cache_dir
138
+ File.join(cache_dir, 'package_managers', 'gem')
139
+ end
140
+
141
+ def create_or_update_gems(keep_going: true, compile_force: false, compile: [])
142
+ # Note: this might directly copy into the cache directoy, and
143
+ # we support it later
144
+ cache_dir = File.join(@ws.prefix_dir, 'gems', 'vendor', 'cache')
145
+ PackageManagers::BundlerManager.run_bundler(
146
+ @ws, 'cache'
147
+ )
148
+
149
+ FileUtils.mkdir_p(gems_cache_dir) unless File.exist?(gems_cache_dir)
150
+
151
+ needs_copy =
152
+ if File.exist?(cache_dir)
153
+ real_cache_dir = File.realpath(cache_dir)
154
+ real_target_dir = File.realpath(gems_cache_dir)
155
+ (real_cache_dir != real_target_dir)
156
+ end
157
+
158
+ synchronize_gems_cache_dirs(real_cache_dir, real_target_dir) if needs_copy
159
+
160
+ platform_suffix = "-#{Gem::Platform.local}.gem"
161
+ failed = []
162
+ compile.each do |gem_name, artifacts: []|
163
+ Dir.glob(File.join(cache_dir, "#{gem_name}*.gem")) do |gem|
164
+ next if gem.end_with?(platform_suffix)
165
+
166
+ gem_basename = File.basename(gem, ".gem")
167
+ expected_platform_gem = File.join(
168
+ real_target_dir, "#{gem_basename}#{platform_suffix}"
169
+ )
170
+ next if !compile_force && File.file?(expected_platform_gem)
171
+
172
+ begin
173
+ compile_gem(gem, artifacts: artifacts, output: real_target_dir)
174
+ rescue CompilationFailed
175
+ unless keep_going
176
+ raise CompilationFailed, "#{gem} failed to compile"
118
177
  end
119
- nil
120
- else
121
- raise
178
+
179
+ failed << gem
122
180
  end
123
181
  end
124
182
  end
183
+
184
+ unless failed.empty?
185
+ raise CompilationFailed, "#{failed.sort.join(', ')} failed to compile"
186
+ end
187
+ end
188
+
189
+ class CompilationFailed < RuntimeError; end
190
+
191
+ def synchronize_gems_cache_dirs(source, target)
192
+ Dir.glob(File.join(source, "*.gem")) do |source_file|
193
+ basename = File.basename(source_file)
194
+ target_file = File.join(target, basename)
195
+ next if File.file?(target_file)
196
+
197
+ Autoproj.message "gems: caching #{basename}"
198
+ FileUtils.cp source_file, target_file
199
+ end
200
+ end
201
+
202
+ def guess_gem_program
203
+ if Autobuild.programs['gem']
204
+ return Autobuild.programs['gem']
205
+ end
206
+
207
+ ruby_bin = RbConfig::CONFIG['RUBY_INSTALL_NAME']
208
+ ruby_bindir = RbConfig::CONFIG['bindir']
209
+
210
+ candidates = ['gem']
211
+ if ruby_bin =~ /^ruby(.+)$/
212
+ candidates << "gem#{$1}"
213
+ end
214
+
215
+ candidates.each do |gem_name|
216
+ if File.file?(gem_full_path = File.join(ruby_bindir, gem_name))
217
+ Autobuild.programs['gem'] = gem_full_path
218
+ return Autobuild.programs['gem']
219
+ end
220
+ end
221
+
222
+ raise ArgumentError, "cannot find a gem program (tried #{candidates.sort.join(", ")} in #{ruby_bindir})"
223
+ end
224
+
225
+ private def compile_gem(gem_path, output:, artifacts: [])
226
+ artifacts = artifacts.flat_map { |n| ["--artifact", n] }
227
+ unless system(Autobuild.tool('ruby'), '-S', guess_gem_program,
228
+ 'compile', '--output', output, *artifacts, gem_path)
229
+ raise CompilationFailed, "#{gem_path} failed to compile"
230
+ end
125
231
  end
126
232
  end
127
233
  end
128
234
  end
129
-