autobuild 1.17.0 → 1.18.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 +4 -4
- data/.rubocop.yml +107 -0
- data/Gemfile +2 -1
- data/Rakefile +1 -4
- data/autobuild.gemspec +14 -11
- data/bin/autobuild +4 -3
- data/lib/autobuild.rb +4 -5
- data/lib/autobuild/build_logfile.rb +6 -4
- data/lib/autobuild/config.rb +90 -40
- data/lib/autobuild/configurable.rb +30 -18
- data/lib/autobuild/environment.rb +126 -120
- data/lib/autobuild/exceptions.rb +48 -31
- data/lib/autobuild/import/archive.rb +134 -82
- data/lib/autobuild/import/cvs.rb +28 -24
- data/lib/autobuild/import/darcs.rb +13 -16
- data/lib/autobuild/import/git-lfs.rb +37 -30
- data/lib/autobuild/import/git.rb +231 -179
- data/lib/autobuild/import/hg.rb +23 -18
- data/lib/autobuild/import/svn.rb +48 -29
- data/lib/autobuild/importer.rb +530 -499
- data/lib/autobuild/mail_reporter.rb +77 -77
- data/lib/autobuild/package.rb +171 -101
- data/lib/autobuild/packages/autotools.rb +47 -42
- data/lib/autobuild/packages/cmake.rb +71 -65
- data/lib/autobuild/packages/dummy.rb +9 -8
- data/lib/autobuild/packages/genom.rb +1 -1
- data/lib/autobuild/packages/gnumake.rb +19 -13
- data/lib/autobuild/packages/import.rb +2 -6
- data/lib/autobuild/packages/orogen.rb +32 -31
- data/lib/autobuild/packages/pkgconfig.rb +2 -2
- data/lib/autobuild/packages/python.rb +7 -2
- data/lib/autobuild/packages/ruby.rb +22 -17
- data/lib/autobuild/parallel.rb +35 -39
- data/lib/autobuild/pkgconfig.rb +25 -13
- data/lib/autobuild/progress_display.rb +23 -23
- data/lib/autobuild/rake_task_extension.rb +6 -6
- data/lib/autobuild/reporting.rb +38 -26
- data/lib/autobuild/subcommand.rb +72 -65
- data/lib/autobuild/test.rb +8 -7
- data/lib/autobuild/test_utility.rb +10 -9
- data/lib/autobuild/timestamps.rb +28 -23
- data/lib/autobuild/tools.rb +17 -16
- data/lib/autobuild/utility.rb +16 -18
- data/lib/autobuild/version.rb +1 -1
- metadata +39 -38
@@ -7,27 +7,28 @@ class DummyPackage < Package
|
|
7
7
|
def installstamp
|
8
8
|
"#{srcdir}/#{STAMPFILE}"
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def initialize(*args)
|
12
12
|
super
|
13
13
|
end
|
14
14
|
|
15
|
-
def import(options = Hash.new)
|
16
|
-
end
|
15
|
+
def import(options = Hash.new); end
|
17
16
|
|
18
17
|
def prepare
|
19
|
-
%w
|
18
|
+
%w[import prepare build doc].each do |phase|
|
20
19
|
task "#{name}-#{phase}"
|
21
20
|
t = Rake::Task["#{name}-#{phase}"]
|
22
|
-
def t.needed
|
21
|
+
def t.needed?
|
22
|
+
false
|
23
|
+
end
|
23
24
|
end
|
24
25
|
task(installstamp)
|
25
26
|
t = Rake::Task[installstamp]
|
26
|
-
def t.needed
|
27
|
+
def t.needed?
|
28
|
+
false
|
29
|
+
end
|
27
30
|
|
28
31
|
super
|
29
32
|
end
|
30
33
|
end
|
31
34
|
end
|
32
|
-
|
33
|
-
|
@@ -74,7 +74,7 @@ def get_requires
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
# Alias this package to the ones defined in the EXTRA_PKGCONFIG
|
77
|
+
# Alias this package to the ones defined in the EXTRA_PKGCONFIG
|
78
78
|
# flag in configure.ac.user
|
79
79
|
def get_provides
|
80
80
|
configure_ac_user = File.join(srcdir, 'configure.ac.user')
|
@@ -4,13 +4,13 @@ module Autobuild
|
|
4
4
|
def self.make_is_gnumake?(pkg, path = Autobuild.tool(:make))
|
5
5
|
@make_is_gnumake ||= Hash.new
|
6
6
|
@gnumake_version ||= Hash.new
|
7
|
-
if @make_is_gnumake.
|
7
|
+
if @make_is_gnumake.key?(path)
|
8
8
|
@make_is_gnumake[path]
|
9
9
|
else
|
10
10
|
begin
|
11
11
|
result = pkg.run('prepare', path, '--version')
|
12
12
|
@make_is_gnumake[path] = (result.first =~ /GNU Make/)
|
13
|
-
@gnumake_version[path] = result.first.scan(/[\d.]+/)[0]
|
13
|
+
@gnumake_version[path] = Gem::Version.new(result.first.scan(/[\d.]+/)[0])
|
14
14
|
rescue Autobuild::SubcommandFailed
|
15
15
|
@make_is_gnumake[path] = false
|
16
16
|
end
|
@@ -28,31 +28,37 @@ def self.make_has_gnumake_jobserver?(pkg, path = Autobuild.tool(:make))
|
|
28
28
|
def self.invoke_make_parallel(pkg, cmd_path = Autobuild.tool(:make))
|
29
29
|
reserved = nil
|
30
30
|
if make_has_j_option?(pkg, cmd_path) && pkg.parallel_build_level != 1
|
31
|
-
if manager = Autobuild.parallel_task_manager
|
31
|
+
if (manager = Autobuild.parallel_task_manager)
|
32
32
|
job_server = manager.job_server
|
33
|
-
|
33
|
+
|
34
|
+
specific_parallel_level = (pkg.parallel_build_level !=
|
35
|
+
Autobuild.parallel_build_level)
|
36
|
+
if !make_has_gnumake_jobserver?(pkg, cmd_path) || specific_parallel_level
|
34
37
|
reserved = pkg.parallel_build_level
|
35
|
-
|
38
|
+
# Account for the one token autobuild uses
|
39
|
+
job_server.get(reserved - 1)
|
36
40
|
yield("-j#{pkg.parallel_build_level}")
|
37
41
|
end
|
38
|
-
|
39
|
-
|
42
|
+
|
43
|
+
jobserver_fds_arg = "#{job_server.rio.fileno},#{job_server.wio.fileno}"
|
44
|
+
|
45
|
+
if @gnumake_version[cmd_path] >= Gem::Version.new("4.2.0")
|
46
|
+
yield("--jobserver-auth=#{jobserver_fds_arg}", "-j")
|
40
47
|
else
|
41
|
-
yield("--jobserver-fds=#{
|
48
|
+
yield("--jobserver-fds=#{jobserver_fds_arg}", "-j")
|
42
49
|
end
|
43
50
|
end
|
44
51
|
yield("-j#{pkg.parallel_build_level}")
|
45
52
|
else yield
|
46
53
|
end
|
47
54
|
ensure
|
48
|
-
if reserved
|
49
|
-
job_server.put(reserved)
|
50
|
-
end
|
55
|
+
job_server.put(reserved) if reserved
|
51
56
|
end
|
52
|
-
|
57
|
+
|
53
58
|
def self.make_subcommand(pkg, phase, *options, &block)
|
54
59
|
invoke_make_parallel(pkg, Autobuild.tool(:make)) do |*make_parallel_options|
|
55
|
-
pkg.run(phase, Autobuild.tool(:make),
|
60
|
+
pkg.run(phase, Autobuild.tool(:make),
|
61
|
+
*make_parallel_options, *options, &block)
|
56
62
|
end
|
57
63
|
end
|
58
64
|
end
|
@@ -5,7 +5,7 @@ module Autobuild
|
|
5
5
|
def self.import(spec, &proc)
|
6
6
|
ImporterPackage.new(spec, &proc)
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
class ImporterPackage < Package
|
10
10
|
attr_reader :exclude
|
11
11
|
|
@@ -19,9 +19,7 @@ def prepare
|
|
19
19
|
|
20
20
|
exclude = self.exclude.dup
|
21
21
|
exclude << Regexp.new("^#{Regexp.quote(installstamp)}")
|
22
|
-
if doc_dir
|
23
|
-
exclude << Regexp.new("^#{Regexp.quote(doc_dir)}")
|
24
|
-
end
|
22
|
+
exclude << Regexp.new("^#{Regexp.quote(doc_dir)}") if doc_dir
|
25
23
|
|
26
24
|
source_tree(srcdir) do |pkg|
|
27
25
|
pkg.exclude.concat exclude
|
@@ -32,5 +30,3 @@ def prepare
|
|
32
30
|
end
|
33
31
|
end
|
34
32
|
end
|
35
|
-
|
36
|
-
|
@@ -41,7 +41,7 @@ class << self
|
|
41
41
|
# This is still considered experimental. Use
|
42
42
|
# Orogen.always_regenerate= to set it
|
43
43
|
def always_regenerate?
|
44
|
-
|
44
|
+
@always_regenerate
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -63,14 +63,15 @@ def self.orocos_target
|
|
63
63
|
|
64
64
|
class << self
|
65
65
|
attr_accessor :default_type_export_policy
|
66
|
-
# The list of enabled transports as an array of strings (default:
|
66
|
+
# The list of enabled transports as an array of strings (default:
|
67
|
+
# typelib, corba)
|
67
68
|
attr_reader :transports
|
68
69
|
|
69
70
|
attr_reader :orogen_options
|
70
71
|
end
|
71
72
|
@orogen_options = []
|
72
73
|
@default_type_export_policy = :used
|
73
|
-
@transports = %w
|
74
|
+
@transports = %w[corba typelib mqueue]
|
74
75
|
@rtt_scripting = true
|
75
76
|
|
76
77
|
attr_reader :orogen_options
|
@@ -121,12 +122,13 @@ def orogen_file
|
|
121
122
|
if @orogen_file
|
122
123
|
@orogen_file
|
123
124
|
else
|
124
|
-
return
|
125
|
-
|
125
|
+
return unless File.directory?(srcdir)
|
126
|
+
|
126
127
|
Dir.glob(File.join(srcdir, '*.orogen')) do |path|
|
127
128
|
return File.basename(path)
|
128
129
|
end
|
129
|
-
raise ArgumentError,
|
130
|
+
raise ArgumentError,
|
131
|
+
"cannot find an oroGen specification file in #{srcdir}"
|
130
132
|
end
|
131
133
|
end
|
132
134
|
|
@@ -141,7 +143,7 @@ def initialize(*args, &config)
|
|
141
143
|
|
142
144
|
def prepare_for_forced_build
|
143
145
|
super
|
144
|
-
FileUtils.rm_f genstamp
|
146
|
+
FileUtils.rm_f genstamp
|
145
147
|
end
|
146
148
|
|
147
149
|
def update_environment
|
@@ -158,9 +160,7 @@ def orogen_version
|
|
158
160
|
if !@orogen_version && (root = orogen_root)
|
159
161
|
version_file = File.join(root, 'lib', 'orogen', 'version.rb')
|
160
162
|
version_line = File.readlines(version_file).grep(/VERSION\s*=\s*"/).first
|
161
|
-
if version_line =~ /.*=\s+"(.+)"$/
|
162
|
-
@orogen_version = $1
|
163
|
-
end
|
163
|
+
@orogen_version = $1 if version_line =~ /.*=\s+"(.+)"$/
|
164
164
|
end
|
165
165
|
@orogen_version
|
166
166
|
end
|
@@ -168,9 +168,7 @@ def orogen_version
|
|
168
168
|
def orogen_root
|
169
169
|
if orogen_tool_path
|
170
170
|
root = File.expand_path(File.join('..', '..'), orogen_tool_path)
|
171
|
-
if File.directory?(File.join(root, 'lib', 'orogen'))
|
172
|
-
root
|
173
|
-
end
|
171
|
+
root if File.directory?(File.join(root, 'lib', 'orogen'))
|
174
172
|
end
|
175
173
|
end
|
176
174
|
|
@@ -187,7 +185,9 @@ def prepare
|
|
187
185
|
super
|
188
186
|
end
|
189
187
|
|
190
|
-
def genstamp
|
188
|
+
def genstamp
|
189
|
+
File.join(srcdir, '.orogen', 'orogen-stamp')
|
190
|
+
end
|
191
191
|
|
192
192
|
def add_cmd_to_cmdline(cmd, cmdline)
|
193
193
|
if cmd =~ /^([\w-]+)$/
|
@@ -210,31 +210,30 @@ def regen
|
|
210
210
|
cmdline << '--corba' if corba
|
211
211
|
|
212
212
|
ext_states = extended_states
|
213
|
-
|
213
|
+
unless ext_states.nil?
|
214
214
|
cmdline.delete_if { |str| str =~ /extended-states/ }
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
215
|
+
cmdline <<
|
216
|
+
if ext_states
|
217
|
+
'--extended-states'
|
218
|
+
else
|
219
|
+
'--no-extended-states'
|
220
|
+
end
|
220
221
|
end
|
221
222
|
|
222
|
-
@orogen_tool_path = find_in_path
|
223
|
-
if !orogen_tool_path
|
223
|
+
unless (@orogen_tool_path = find_in_path('orogen'))
|
224
224
|
raise ArgumentError, "cannot find 'orogen' in #{resolved_env['PATH']}"
|
225
225
|
end
|
226
226
|
|
227
|
-
version = orogen_version
|
228
|
-
if !version
|
227
|
+
unless (version = orogen_version)
|
229
228
|
raise ArgumentError, "cannot determine the orogen version"
|
230
229
|
end
|
231
230
|
|
232
|
-
if
|
231
|
+
if version >= "1.0" # rubocop:disable Style/IfUnlessModifier
|
233
232
|
cmdline << "--parallel-build=#{parallel_build_level}"
|
234
233
|
end
|
235
|
-
if
|
234
|
+
if version >= "1.1"
|
236
235
|
cmdline << "--type-export-policy=#{Orogen.default_type_export_policy}"
|
237
|
-
cmdline << "--transports=#{Orogen.transports.sort.uniq.join(
|
236
|
+
cmdline << "--transports=#{Orogen.transports.sort.uniq.join(',')}"
|
238
237
|
end
|
239
238
|
|
240
239
|
# Now, add raw options
|
@@ -269,9 +268,11 @@ def regen
|
|
269
268
|
needs_regen ||= !generation_uptodate?
|
270
269
|
|
271
270
|
if needs_regen
|
272
|
-
progress_start "generating oroGen %s",
|
271
|
+
progress_start "generating oroGen %s",
|
272
|
+
done_message: 'generated oroGen %s' do
|
273
273
|
in_dir(srcdir) do
|
274
|
-
run 'orogen', Autobuild.tool('ruby'), '-S',
|
274
|
+
run 'orogen', Autobuild.tool('ruby'), '-S',
|
275
|
+
orogen_tool_path, *cmdline
|
275
276
|
File.open(genstamp, 'w') do |io|
|
276
277
|
io.print cmdline.join("\n")
|
277
278
|
end
|
@@ -287,11 +288,11 @@ def generation_uptodate?
|
|
287
288
|
if !File.file?(genstamp)
|
288
289
|
true
|
289
290
|
elsif File.file?(File.join(builddir, 'Makefile'))
|
290
|
-
|
291
|
+
make = Autobuild.tool('make')
|
292
|
+
system("#{make} -C #{builddir} check-uptodate > /dev/null 2>&1")
|
291
293
|
else
|
292
294
|
true
|
293
295
|
end
|
294
296
|
end
|
295
297
|
end
|
296
298
|
end
|
297
|
-
|
@@ -16,9 +16,10 @@ def installstamp
|
|
16
16
|
return std_stamp if File.file?(std_stamp)
|
17
17
|
|
18
18
|
pcfile = File.join(pkgconfig.prefix, "lib", "pkgconfig", "#{name}.pc")
|
19
|
-
|
19
|
+
unless File.file?(pcfile)
|
20
20
|
raise "cannot find the .pc file for #{name}, tried #{pcfile}"
|
21
21
|
end
|
22
|
+
|
22
23
|
pcfile
|
23
24
|
end
|
24
25
|
end
|
@@ -26,4 +27,3 @@ def self.installed_pkgconfig(name, &block)
|
|
26
27
|
InstalledPkgConfig.new(name, &block)
|
27
28
|
end
|
28
29
|
end
|
29
|
-
|
@@ -56,13 +56,17 @@ def python_path
|
|
56
56
|
raise "Unable to set PYTHONPATH: #{e.message}"
|
57
57
|
end
|
58
58
|
|
59
|
-
|
60
|
-
|
59
|
+
if ret.value.success?
|
60
|
+
output.read.chomp
|
61
|
+
else
|
62
|
+
raise 'Unable to set PYTHONPATH: user site directory disabled?'
|
63
|
+
end
|
61
64
|
end
|
62
65
|
|
63
66
|
# Do the build in builddir
|
64
67
|
def build
|
65
68
|
return unless @install_mode
|
69
|
+
|
66
70
|
command = generate_build_command
|
67
71
|
command << '--force' if @forced
|
68
72
|
progress_start 'building %s [progress not available]',
|
@@ -75,6 +79,7 @@ def build
|
|
75
79
|
# Install the result in prefix
|
76
80
|
def install
|
77
81
|
return unless @install_mode
|
82
|
+
|
78
83
|
command = generate_install_command
|
79
84
|
command << '--force' if @forced
|
80
85
|
progress_start 'installing %s',
|
@@ -22,7 +22,7 @@ class Ruby < ImporterPackage
|
|
22
22
|
def initialize(*args)
|
23
23
|
self.rake_setup_task = "default"
|
24
24
|
self.rake_doc_task = "redocs"
|
25
|
-
self.rake_clean_task
|
25
|
+
self.rake_clean_task = "clean"
|
26
26
|
self.rake_test_task = "test"
|
27
27
|
self.rake_test_options = []
|
28
28
|
|
@@ -36,19 +36,23 @@ def initialize(*args)
|
|
36
36
|
|
37
37
|
def with_doc
|
38
38
|
doc_task do
|
39
|
-
progress_start "generating documentation for %s",
|
39
|
+
progress_start "generating documentation for %s",
|
40
|
+
done_message: 'generated documentation for %s' do
|
40
41
|
run 'doc',
|
41
|
-
Autobuild.tool_in_path('ruby'), '-S',
|
42
|
-
|
42
|
+
Autobuild.tool_in_path('ruby'), '-S',
|
43
|
+
Autobuild.tool('rake'), rake_doc_task,
|
44
|
+
working_directory: srcdir
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
47
49
|
def with_tests
|
48
50
|
test_utility.task do
|
49
|
-
progress_start "running tests for %s",
|
51
|
+
progress_start "running tests for %s",
|
52
|
+
done_message: 'tests passed for %s' do
|
50
53
|
run 'test',
|
51
|
-
Autobuild.tool_in_path('ruby'), '-S',
|
54
|
+
Autobuild.tool_in_path('ruby'), '-S',
|
55
|
+
Autobuild.tool('rake'), rake_test_task, *rake_test_options,
|
52
56
|
working_directory: srcdir
|
53
57
|
end
|
54
58
|
end
|
@@ -57,13 +61,15 @@ def with_tests
|
|
57
61
|
def invoke_rake(setup_task = rake_setup_task)
|
58
62
|
if setup_task && File.file?(File.join(srcdir, 'Rakefile'))
|
59
63
|
run 'post-install',
|
60
|
-
Autobuild.tool_in_path('ruby'), '-S',
|
61
|
-
|
64
|
+
Autobuild.tool_in_path('ruby'), '-S',
|
65
|
+
Autobuild.tool('rake'), setup_task,
|
66
|
+
working_directory: srcdir
|
62
67
|
end
|
63
68
|
end
|
64
69
|
|
65
70
|
def install
|
66
|
-
progress_start "setting up Ruby package %s",
|
71
|
+
progress_start "setting up Ruby package %s",
|
72
|
+
done_message: 'set up Ruby package %s' do
|
67
73
|
invoke_rake
|
68
74
|
end
|
69
75
|
super
|
@@ -71,10 +77,11 @@ def install
|
|
71
77
|
|
72
78
|
def prepare_for_forced_build # :nodoc:
|
73
79
|
super
|
74
|
-
%w
|
80
|
+
%w[ext tmp].each do |extdir|
|
75
81
|
if File.directory?(extdir)
|
76
82
|
Find.find(extdir) do |file|
|
77
83
|
next if file !~ /\<Makefile\>|\<CMakeCache.txt\>$/
|
84
|
+
|
78
85
|
FileUtils.rm_rf file
|
79
86
|
end
|
80
87
|
end
|
@@ -86,10 +93,11 @@ def prepare_for_rebuild # :nodoc:
|
|
86
93
|
if rake_clean_task && File.file?(File.join(srcdir, 'Rakefile'))
|
87
94
|
begin
|
88
95
|
run 'clean',
|
89
|
-
Autobuild.tool_in_path('ruby'), '-S',
|
90
|
-
|
96
|
+
Autobuild.tool_in_path('ruby'), '-S',
|
97
|
+
Autobuild.tool('rake'), rake_clean_task,
|
98
|
+
working_directory: srcdir
|
91
99
|
rescue Autobuild::SubcommandFailed => e
|
92
|
-
warn "%s:
|
100
|
+
warn "%s: clean failed. If this package does not need a clean target,"
|
93
101
|
warn "%s: set pkg.rake_clean_task = nil in the package definition."
|
94
102
|
warn "%s: see #{e.logfile} for more details"
|
95
103
|
end
|
@@ -99,9 +107,7 @@ def prepare_for_rebuild # :nodoc:
|
|
99
107
|
def update_environment
|
100
108
|
env_add_prefix srcdir
|
101
109
|
libdir = File.join(srcdir, 'lib')
|
102
|
-
if File.directory?(libdir)
|
103
|
-
env_add_path 'RUBYLIB', libdir
|
104
|
-
end
|
110
|
+
env_add_path 'RUBYLIB', libdir if File.directory?(libdir)
|
105
111
|
end
|
106
112
|
end
|
107
113
|
|
@@ -109,4 +115,3 @@ def self.ruby(spec, &proc)
|
|
109
115
|
Ruby.new(spec, &proc)
|
110
116
|
end
|
111
117
|
end
|
112
|
-
|
data/lib/autobuild/parallel.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
1
|
module Autobuild
|
4
2
|
# This is a rewrite of the Rake task invocation code to use parallelism
|
5
3
|
#
|
@@ -23,9 +21,11 @@ def initialize(level)
|
|
23
21
|
wio.fcntl(Fcntl::F_SETFD, 0)
|
24
22
|
put(level)
|
25
23
|
end
|
24
|
+
|
26
25
|
def get(token_count = 1)
|
27
26
|
@rio.read(token_count)
|
28
27
|
end
|
28
|
+
|
29
29
|
def put(token_count = 1)
|
30
30
|
@wio.write(" " * token_count)
|
31
31
|
end
|
@@ -36,7 +36,6 @@ def initialize(level = Autobuild.parallel_build_level)
|
|
36
36
|
@available_workers = Array.new
|
37
37
|
@finished_workers = Queue.new
|
38
38
|
@workers = Array.new
|
39
|
-
|
40
39
|
end
|
41
40
|
|
42
41
|
def wait_for_worker_to_end(state)
|
@@ -46,9 +45,12 @@ def wait_for_worker_to_end(state)
|
|
46
45
|
if error
|
47
46
|
if available_workers.size != workers.size
|
48
47
|
if finished_task.respond_to?(:package) && finished_task.package
|
49
|
-
Autobuild.error "got an error processing
|
48
|
+
Autobuild.error "got an error processing "\
|
49
|
+
"#{finished_task.package.name}, "\
|
50
|
+
"waiting for pending jobs to end"
|
50
51
|
else
|
51
|
-
Autobuild.error "got an error doing parallel processing,
|
52
|
+
Autobuild.error "got an error doing parallel processing, "\
|
53
|
+
"waiting for pending jobs to end"
|
52
54
|
end
|
53
55
|
end
|
54
56
|
begin
|
@@ -61,16 +63,14 @@ def wait_for_worker_to_end(state)
|
|
61
63
|
state.process_finished_task(finished_task)
|
62
64
|
end
|
63
65
|
|
64
|
-
def discover_dependencies(all_tasks, reverse_dependencies,
|
65
|
-
if
|
66
|
-
|
67
|
-
end
|
66
|
+
def discover_dependencies(all_tasks, reverse_dependencies, task)
|
67
|
+
return if task.already_invoked?
|
68
|
+
return if all_tasks.include?(task) # already discovered or being discovered
|
68
69
|
|
69
|
-
|
70
|
-
all_tasks << t
|
70
|
+
all_tasks << task
|
71
71
|
|
72
|
-
|
73
|
-
reverse_dependencies[dep_t] <<
|
72
|
+
task.prerequisite_tasks.each do |dep_t|
|
73
|
+
reverse_dependencies[dep_t] << task
|
74
74
|
discover_dependencies(all_tasks, reverse_dependencies, dep_t)
|
75
75
|
end
|
76
76
|
end
|
@@ -101,7 +101,7 @@ def push(task, base_priority = 1)
|
|
101
101
|
end
|
102
102
|
|
103
103
|
def find_task
|
104
|
-
if task = queue.
|
104
|
+
if (task = queue.min_by { |_t, p| p })
|
105
105
|
priorities[task.first] = task.last
|
106
106
|
task.first
|
107
107
|
end
|
@@ -146,7 +146,8 @@ def process_finished_task(task)
|
|
146
146
|
end
|
147
147
|
|
148
148
|
def trivial_task?(task)
|
149
|
-
(task.kind_of?(Autobuild::SourceTreeTask) ||
|
149
|
+
(task.kind_of?(Autobuild::SourceTreeTask) ||
|
150
|
+
task.kind_of?(Rake::FileTask)) && task.actions.empty?
|
150
151
|
end
|
151
152
|
end
|
152
153
|
|
@@ -163,11 +164,9 @@ def invoke_parallel(required_tasks)
|
|
163
164
|
# set of tasks that can be queued for execution.
|
164
165
|
state = ProcessingState.new(reverse_dependencies)
|
165
166
|
tasks.each do |t|
|
166
|
-
if state.ready?(t)
|
167
|
-
state.push(t)
|
168
|
-
end
|
167
|
+
state.push(t) if state.ready?(t)
|
169
168
|
end
|
170
|
-
|
169
|
+
|
171
170
|
# Build a reverse dependency graph (i.e. a mapping from a task to
|
172
171
|
# the tasks that depend on it)
|
173
172
|
|
@@ -175,9 +174,9 @@ def invoke_parallel(required_tasks)
|
|
175
174
|
# topological sort since we would then have to scan all tasks each
|
176
175
|
# time for tasks that have no currently running prerequisites
|
177
176
|
|
178
|
-
|
177
|
+
loop do
|
179
178
|
pending_task = state.pop
|
180
|
-
|
179
|
+
unless pending_task
|
181
180
|
# If we have pending workers, wait for one to be finished
|
182
181
|
# until either they are all finished or the queue is not
|
183
182
|
# empty anymore
|
@@ -186,9 +185,7 @@ def invoke_parallel(required_tasks)
|
|
186
185
|
pending_task = state.pop
|
187
186
|
end
|
188
187
|
|
189
|
-
if !pending_task && available_workers.size == workers.size
|
190
|
-
break
|
191
|
-
end
|
188
|
+
break if !pending_task && available_workers.size == workers.size
|
192
189
|
end
|
193
190
|
|
194
191
|
if state.trivial_task?(pending_task)
|
@@ -204,9 +201,7 @@ def invoke_parallel(required_tasks)
|
|
204
201
|
# Get a job server token
|
205
202
|
job_server.get
|
206
203
|
|
207
|
-
|
208
|
-
wait_for_worker_to_end(state)
|
209
|
-
end
|
204
|
+
wait_for_worker_to_end(state) until finished_workers.empty?
|
210
205
|
|
211
206
|
# We do have a job server token, so we are allowed to allocate a
|
212
207
|
# new worker if none are available
|
@@ -222,9 +217,9 @@ def invoke_parallel(required_tasks)
|
|
222
217
|
end
|
223
218
|
|
224
219
|
not_processed = tasks.find_all { |t| !t.already_invoked? }
|
225
|
-
|
220
|
+
unless not_processed.empty?
|
226
221
|
cycle = resolve_cycle(tasks, not_processed, reverse_dependencies)
|
227
|
-
raise "cycle in task graph: #{cycle.map(&:name).sort.join(
|
222
|
+
raise "cycle in task graph: #{cycle.map(&:name).sort.join(', ')}"
|
228
223
|
end
|
229
224
|
end
|
230
225
|
|
@@ -232,7 +227,7 @@ def resolve_cycle(all_tasks, tasks, reverse_dependencies)
|
|
232
227
|
cycle = tasks.dup
|
233
228
|
chain = []
|
234
229
|
next_task = tasks.first
|
235
|
-
|
230
|
+
loop do
|
236
231
|
task = next_task
|
237
232
|
chain << task
|
238
233
|
tasks.delete(next_task)
|
@@ -244,10 +239,12 @@ def resolve_cycle(all_tasks, tasks, reverse_dependencies)
|
|
244
239
|
true
|
245
240
|
end
|
246
241
|
end
|
247
|
-
|
248
|
-
Autobuild.fatal "parallel processing stopped prematurely,
|
249
|
-
|
250
|
-
Autobuild.fatal "
|
242
|
+
unless next_task
|
243
|
+
Autobuild.fatal "parallel processing stopped prematurely, "\
|
244
|
+
"but no cycle is present in the remaining tasks"
|
245
|
+
Autobuild.fatal "remaining tasks: #{cycle.map(&:name).join(', ')}"
|
246
|
+
Autobuild.fatal "known dependencies at initialization time that "\
|
247
|
+
"could block the processing of the remaining tasks"
|
251
248
|
reverse_dependencies.each do |parent_task, parents|
|
252
249
|
if cycle.include?(parent_task)
|
253
250
|
parents.each do |p|
|
@@ -255,13 +252,14 @@ def resolve_cycle(all_tasks, tasks, reverse_dependencies)
|
|
255
252
|
end
|
256
253
|
end
|
257
254
|
end
|
258
|
-
Autobuild.fatal "known dependencies right now that could block
|
255
|
+
Autobuild.fatal "known dependencies right now that could block "\
|
256
|
+
"the processing of the remaining tasks"
|
259
257
|
all_tasks.each do |p|
|
260
258
|
(cycle & p.prerequisite_tasks).each do |t|
|
261
259
|
Autobuild.fatal " #{p}: #{t}"
|
262
260
|
end
|
263
261
|
end
|
264
|
-
raise "failed to resolve cycle in #{cycle.map(&:name).join(
|
262
|
+
raise "failed to resolve cycle in #{cycle.map(&:name).join(', ')}"
|
265
263
|
end
|
266
264
|
end
|
267
265
|
chain
|
@@ -301,7 +299,7 @@ def do_task(task)
|
|
301
299
|
end
|
302
300
|
|
303
301
|
def last_result
|
304
|
-
|
302
|
+
[@last_finished_task, @last_error]
|
305
303
|
end
|
306
304
|
|
307
305
|
def queue(task)
|
@@ -321,5 +319,3 @@ class << self
|
|
321
319
|
attr_accessor :parallel_task_manager
|
322
320
|
end
|
323
321
|
end
|
324
|
-
|
325
|
-
|