cxxproject 0.4.6 → 0.5.47
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile.rb +101 -54
- data/bin/cxx +4 -4
- data/lib/cxxproject/buildingblocks/binary_library.rb +32 -9
- data/lib/cxxproject/buildingblocks/building_block.rb +220 -74
- data/lib/cxxproject/buildingblocks/command_line.rb +70 -21
- data/lib/cxxproject/buildingblocks/custom_building_block.rb +33 -9
- data/lib/cxxproject/buildingblocks/executable.rb +228 -33
- data/lib/cxxproject/buildingblocks/has_dependencies_mixin.rb +69 -43
- data/lib/cxxproject/buildingblocks/has_includes_mixin.rb +20 -0
- data/lib/cxxproject/buildingblocks/has_libraries_mixin.rb +29 -30
- data/lib/cxxproject/buildingblocks/has_sources_mixin.rb +343 -64
- data/lib/cxxproject/buildingblocks/makefile.rb +142 -24
- data/lib/cxxproject/buildingblocks/module.rb +27 -6
- data/lib/cxxproject/buildingblocks/single_source.rb +26 -4
- data/lib/cxxproject/buildingblocks/source_library.rb +113 -20
- data/lib/cxxproject/errorparser/diab_compiler_error_parser.rb +40 -0
- data/lib/cxxproject/errorparser/diab_linker_error_parser.rb +33 -0
- data/lib/cxxproject/errorparser/error_parser.rb +50 -0
- data/lib/cxxproject/errorparser/gcc_compiler_error_parser.rb +30 -0
- data/lib/cxxproject/errorparser/gcc_linker_error_parser.rb +29 -0
- data/lib/cxxproject/errorparser/ti_compiler_error_parser.rb +30 -0
- data/lib/cxxproject/errorparser/ti_linker_error_parser.rb +29 -0
- data/lib/cxxproject/eval_context.rb +136 -0
- data/lib/cxxproject/ext/file.rb +71 -0
- data/lib/cxxproject/ext/filelist.rb +6 -0
- data/lib/cxxproject/ext/progressbar.rb +20 -0
- data/lib/cxxproject/ext/rake.rb +397 -0
- data/lib/cxxproject/{extensions/rake_listener_ext.rb → ext/rake_listener.rb} +18 -12
- data/lib/cxxproject/ext/stdout.rb +44 -0
- data/lib/cxxproject/ide_interface.rb +181 -0
- data/lib/cxxproject/toolchain/clang.rb +39 -0
- data/lib/cxxproject/toolchain/colorizing_formatter.rb +99 -0
- data/lib/cxxproject/toolchain/diab.rb +36 -33
- data/lib/cxxproject/toolchain/gcc.rb +16 -8
- data/lib/cxxproject/toolchain/provider.rb +112 -2
- data/lib/cxxproject/toolchain/ti.rb +50 -0
- data/lib/cxxproject/toolchain/toolchain.rb +38 -0
- data/lib/cxxproject/toolchain/toolchain_benchmark.rb +23 -0
- data/lib/cxxproject/torake.rb +181 -123
- data/lib/cxxproject/utils/cleanup.rb +20 -0
- data/lib/cxxproject/utils/console.rb +6 -0
- data/lib/cxxproject/utils/exit_helper.rb +40 -0
- data/lib/cxxproject/utils/graphstream.rb +154 -0
- data/lib/cxxproject/utils/optional.rb +16 -0
- data/lib/cxxproject/utils/printer.rb +50 -0
- data/lib/cxxproject/utils/process.rb +53 -0
- data/lib/cxxproject/utils/progress.rb +66 -0
- data/lib/cxxproject/utils/progress_helper.rb +77 -0
- data/lib/cxxproject/utils/rbcurse.rb +284 -0
- data/lib/cxxproject/utils/rbcurse_executable_ext.rb +14 -0
- data/lib/cxxproject/utils/rbcurse_progress.rb +71 -0
- data/lib/cxxproject/utils/rbcurse_tasktable.rb +51 -0
- data/lib/cxxproject/utils/stats.rb +60 -0
- data/lib/cxxproject/utils/ubigraph.rb +179 -188
- data/lib/cxxproject/utils/utils.rb +29 -25
- data/lib/cxxproject/version.rb +7 -0
- data/lib/cxxproject.rb +13 -7
- data/lib/tools/project_wizard.rb +66 -0
- data/spec/building_block_spec.rb +50 -6
- data/spec/{build_dependencies_spec.rb → cxxproject_2_rake_spec.rb} +82 -65
- data/spec/file_ext_spec.rb +30 -0
- data/spec/ide_interface_spec.rb +41 -0
- data/spec/object_dependency_spec.rb +83 -0
- data/spec/project_path_spec.rb +14 -16
- data/spec/rake_listener_ext_spec.rb +38 -5
- data/spec/spec_helper.rb +18 -0
- data/spec/testdata/basic/lib2/project.rb +1 -1
- data/spec/testdata/multiple_levels/libs/lib2/project.rb +1 -1
- data/spec/toolchain_spec.rb +29 -0
- metadata +91 -58
- data/lib/cxxproject/extensions/file_ext.rb +0 -47
- data/lib/cxxproject/extensions/rake_ext.rb +0 -158
- data/lib/cxxproject/extensions/stdout_ext.rb +0 -35
- data/lib/cxxproject/task_maker.rb +0 -418
- data/lib/cxxproject/testinstanceeval.rb +0 -65
- data/lib/cxxproject/toolchain/base.rb +0 -98
- data/lib/cxxproject/torake/compiler.rb +0 -10
- data/lib/cxxproject/torake/gcccompiler.rb +0 -7
- data/lib/cxxproject/torake/osxcompiler.rb +0 -7
- data/lib/cxxproject/utils/dot/building_block_graph_writer.rb +0 -19
- data/lib/cxxproject/utils/dot/graph_writer.rb +0 -53
- data/lib/cxxproject/utils/dot/task_graph_writer.rb +0 -34
- data/lib/tools/projectWizard.rb +0 -44
- data/spec/dir_spec.rb +0 -13
- /data/lib/cxxproject/{extensions/rake_dirty_ext.rb → ext/rake_dirty.rb} +0 -0
- /data/lib/cxxproject/{extensions/string_ext.rb → ext/string.rb} +0 -0
@@ -0,0 +1,397 @@
|
|
1
|
+
require 'cxxproject/ext/stdout'
|
2
|
+
require 'cxxproject/utils/exit_helper'
|
3
|
+
require 'cxxproject/errorparser/error_parser'
|
4
|
+
|
5
|
+
|
6
|
+
require 'rake'
|
7
|
+
require 'stringio'
|
8
|
+
require 'thread'
|
9
|
+
|
10
|
+
require 'cxxproject/utils/printer'
|
11
|
+
|
12
|
+
module Cxxproject
|
13
|
+
class SystemCommandFailed < Exception
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Rake
|
18
|
+
|
19
|
+
class Application
|
20
|
+
attr_writer :max_parallel_tasks
|
21
|
+
attr_writer :check_unnecessary_includes
|
22
|
+
attr_writer :deriveIncludes
|
23
|
+
attr_writer :consoleOutput_fullnames
|
24
|
+
def max_parallel_tasks
|
25
|
+
@max_parallel_tasks ||= 8
|
26
|
+
end
|
27
|
+
|
28
|
+
def check_unnecessary_includes
|
29
|
+
@check_unnecessary_includes ||= false
|
30
|
+
end
|
31
|
+
|
32
|
+
def idei
|
33
|
+
@idei ||= Cxxproject::IDEInterface.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def idei=(value)
|
37
|
+
@idei = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def command_line_number
|
41
|
+
@command_line_number ||= 1
|
42
|
+
res = @command_line_number
|
43
|
+
@command_line_number += 1
|
44
|
+
res
|
45
|
+
end
|
46
|
+
|
47
|
+
def makefile_number
|
48
|
+
@makefile_number ||= 1
|
49
|
+
res = @makefile_number
|
50
|
+
@makefile_number += 1
|
51
|
+
res
|
52
|
+
end
|
53
|
+
|
54
|
+
def deriveIncludes
|
55
|
+
@deriveIncludes ||= false
|
56
|
+
end
|
57
|
+
|
58
|
+
def consoleOutput_fullnames
|
59
|
+
@consoleOutput_fullnames ||= false
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
class Jobs
|
65
|
+
def initialize(jobs, max, &block)
|
66
|
+
nr_of_threads = [max, jobs.length].min
|
67
|
+
@jobs = jobs
|
68
|
+
@threads = []
|
69
|
+
nr_of_threads.times do
|
70
|
+
@threads << Thread.new do
|
71
|
+
block.call(self)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_next_or_nil
|
77
|
+
the_next = nil
|
78
|
+
mutex.synchronize {
|
79
|
+
the_next = @jobs.shift
|
80
|
+
}
|
81
|
+
the_next
|
82
|
+
end
|
83
|
+
def join
|
84
|
+
@threads.each{|t| while not t.join(2) do end}
|
85
|
+
end
|
86
|
+
def mutex
|
87
|
+
@mutex ||= Mutex.new
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
#############
|
92
|
+
# - Limit parallel tasks
|
93
|
+
#############
|
94
|
+
class MultiTask < Task
|
95
|
+
def set_building_block(bb)
|
96
|
+
@bb = bb
|
97
|
+
end
|
98
|
+
|
99
|
+
def invoke_prerequisites(args, invocation_chain)
|
100
|
+
super(args, invocation_chain)
|
101
|
+
|
102
|
+
return if @failure # pre step has failed
|
103
|
+
|
104
|
+
Dir.chdir(@bb.project_dir) do
|
105
|
+
if Dir.pwd != @bb.project_dir and File.dirname(Dir.pwd) != File.dirname(@bb.project_dir)
|
106
|
+
isSym = false
|
107
|
+
begin
|
108
|
+
isSym = File.symlink?(@bb.project_dir)
|
109
|
+
rescue
|
110
|
+
end
|
111
|
+
if isSym
|
112
|
+
message = "Symlinks only allowed with the same parent dir as the target: #{@bb.project_dir} --> #{Dir.pwd}"
|
113
|
+
res = Cxxproject::ErrorDesc.new
|
114
|
+
res.file_name = @bb.project_dir
|
115
|
+
res.line_number = 0
|
116
|
+
res.severity = Cxxproject::ErrorParser::SEVERITY_ERROR
|
117
|
+
res.message = message
|
118
|
+
Rake.application.idei.set_errors([res])
|
119
|
+
Cxxproject::Printer.printError message
|
120
|
+
set_failed
|
121
|
+
return
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
file_tasks = @bb.create_object_file_tasks
|
126
|
+
|
127
|
+
if file_tasks == nil # = error
|
128
|
+
set_failed
|
129
|
+
return
|
130
|
+
end
|
131
|
+
|
132
|
+
enhance(file_tasks)
|
133
|
+
return if file_tasks.length == 0
|
134
|
+
|
135
|
+
@error_strings = {}
|
136
|
+
|
137
|
+
Jobs.new(file_tasks, application.max_parallel_tasks) do |jobs|
|
138
|
+
handle_jobs(jobs, args, invocation_chain)
|
139
|
+
end.join
|
140
|
+
|
141
|
+
# can only happen in case of bail_on_first_error.
|
142
|
+
# if not sorted, it may be confusing when builing more than once and the order of the error appearances changes from build to build
|
143
|
+
# (it is not deterministic which file compilation finishes first)
|
144
|
+
@error_strings.sort.each {|es| puts es[1]}
|
145
|
+
|
146
|
+
if Rake.application.check_unnecessary_includes
|
147
|
+
if not @failure # otherwise the dependency files might be incorrect or not complete
|
148
|
+
@bb.incArray.each do |i|
|
149
|
+
next if i=="."
|
150
|
+
if not @bb.deps_in_depFiles.any? { |d| d.index(i) == 0 }
|
151
|
+
msg = "Info: Include to #{i} seems to be unnecessary"
|
152
|
+
Cxxproject::Printer.printInfo msg
|
153
|
+
res = Cxxproject::ErrorDesc.new
|
154
|
+
res.file_name = @project_dir
|
155
|
+
res.line_number = 0
|
156
|
+
res.severity = Cxxproject::ErrorParser::SEVERITY_INFO
|
157
|
+
res.message = msg
|
158
|
+
Rake.application.idei.set_errors([res])
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
def handle_jobs(jobs, args, invocation_chain)
|
170
|
+
while true do
|
171
|
+
job = jobs.get_next_or_nil
|
172
|
+
break unless job
|
173
|
+
|
174
|
+
prereq = application[job]
|
175
|
+
prereq.output_after_execute = false
|
176
|
+
prereq.invoke_with_call_chain(args, invocation_chain)
|
177
|
+
set_failed if prereq.failure
|
178
|
+
output(prereq, prereq.output_string)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def output(prereq, to_output)
|
183
|
+
return if Rake::Task.output_disabled
|
184
|
+
return unless output_after_execute
|
185
|
+
|
186
|
+
mutex.synchronize do
|
187
|
+
if to_output and to_output.length > 0
|
188
|
+
if Rake::Task.bail_on_first_error and prereq and prereq.failure
|
189
|
+
@error_strings[prereq.name] = to_output
|
190
|
+
else
|
191
|
+
puts to_output
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def mutex
|
198
|
+
@mutex ||= Mutex.new
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
class Task
|
204
|
+
class << self
|
205
|
+
attr_accessor :bail_on_first_error
|
206
|
+
attr_accessor :output_disabled
|
207
|
+
end
|
208
|
+
|
209
|
+
attr_accessor :failure # specified if that task has failed
|
210
|
+
attr_accessor :deps # used to store deps by depfile task for the apply task (no re-read of depsfile)
|
211
|
+
attr_accessor :type
|
212
|
+
attr_accessor :transparent_timestamp
|
213
|
+
attr_accessor :progress_count
|
214
|
+
attr_accessor :output_string
|
215
|
+
attr_accessor :output_after_execute
|
216
|
+
attr_accessor :immediate_output
|
217
|
+
|
218
|
+
UNKNOWN = 0x0000 #
|
219
|
+
OBJECT = 0x0001 #
|
220
|
+
SOURCEMULTI = 0x0002 # x
|
221
|
+
DEPFILE = 0x0004 #
|
222
|
+
LIBRARY = 0x0008 # x
|
223
|
+
EXECUTABLE = 0x0010 # x
|
224
|
+
CONFIG = 0x0020 #
|
225
|
+
APPLY = 0x0040 #
|
226
|
+
UTIL = 0x0080 #
|
227
|
+
BINARY = 0x0100 # x
|
228
|
+
MODULE = 0x0200 # x
|
229
|
+
MAKE = 0x0400 # x
|
230
|
+
RUN = 0x0800 #
|
231
|
+
CUSTOM = 0x1000 # x
|
232
|
+
COMMANDLINE = 0x2000 # x
|
233
|
+
|
234
|
+
STANDARD = 0x371A # x above means included in STANDARD
|
235
|
+
attr_reader :ignore
|
236
|
+
execute_org = self.instance_method(:execute)
|
237
|
+
initialize_org = self.instance_method(:initialize)
|
238
|
+
timestamp_org = self.instance_method(:timestamp)
|
239
|
+
invoke_prerequisites_org = self.instance_method(:invoke_prerequisites)
|
240
|
+
invoke_org = self.instance_method(:invoke)
|
241
|
+
|
242
|
+
define_method(:initialize) do |task_name, app|
|
243
|
+
initialize_org.bind(self).call(task_name, app)
|
244
|
+
@type = UNKNOWN
|
245
|
+
@deps = nil
|
246
|
+
@transparent_timestamp = false
|
247
|
+
@progress_count = 0
|
248
|
+
@ignore = false
|
249
|
+
@failure = false
|
250
|
+
@output_after_execute = true
|
251
|
+
@immediate_output = false
|
252
|
+
end
|
253
|
+
|
254
|
+
define_method(:invoke) do |*args|
|
255
|
+
Cxxproject::ExitHelper.set_exit_code(0)
|
256
|
+
invoke_org.bind(self).call(*args)
|
257
|
+
if @failure or Rake.application.idei.get_abort
|
258
|
+
Cxxproject::ExitHelper.set_exit_code(1)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
define_method(:invoke_prerequisites) do |task_args, invocation_chain|
|
263
|
+
new_invoke_prerequisites(task_args, invocation_chain)
|
264
|
+
end
|
265
|
+
|
266
|
+
def new_invoke_prerequisites(task_args, invocation_chain)
|
267
|
+
orgLength = 0
|
268
|
+
while @prerequisites.length > orgLength do
|
269
|
+
orgLength = @prerequisites.length
|
270
|
+
|
271
|
+
@prerequisites.dup.each do |n| # dup needed when apply tasks changes that array
|
272
|
+
break if Rake.application.idei.get_abort
|
273
|
+
#break if @failure
|
274
|
+
|
275
|
+
prereq = nil
|
276
|
+
begin
|
277
|
+
prereq = application[n, @scope]
|
278
|
+
prereq_args = task_args.new_scope(prereq.arg_names)
|
279
|
+
prereq.invoke_with_call_chain(prereq_args, invocation_chain)
|
280
|
+
set_failed if prereq.failure
|
281
|
+
rescue Cxxproject::ExitHelperException
|
282
|
+
raise
|
283
|
+
rescue Exception => e
|
284
|
+
if prereq and Rake::Task[n].ignore
|
285
|
+
@prerequisites.delete(n)
|
286
|
+
def self.needed?
|
287
|
+
true
|
288
|
+
end
|
289
|
+
return
|
290
|
+
end
|
291
|
+
Cxxproject::Printer.printError "Error #{name}: #{e.message}"
|
292
|
+
if RakeFileUtils.verbose
|
293
|
+
puts e.backtrace
|
294
|
+
end
|
295
|
+
set_failed
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def set_failed()
|
303
|
+
@failure = true
|
304
|
+
if Rake::Task.bail_on_first_error
|
305
|
+
Rake.application.idei.set_abort(true)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
define_method(:execute) do |arg|
|
310
|
+
break if @failure # check if a prereq has failed
|
311
|
+
break if Rake.application.idei.get_abort
|
312
|
+
new_execute(execute_org, arg)
|
313
|
+
end
|
314
|
+
|
315
|
+
def new_execute(execute_org, arg)
|
316
|
+
if not @immediate_output
|
317
|
+
s = name == 'console' ? nil : StringIO.new
|
318
|
+
tmp = Thread.current[:stdout]
|
319
|
+
Thread.current[:stdout] = s unless tmp
|
320
|
+
end
|
321
|
+
|
322
|
+
begin
|
323
|
+
execute_org.bind(self).call(arg)
|
324
|
+
rescue Cxxproject::ExitHelperException
|
325
|
+
raise
|
326
|
+
rescue Cxxproject::SystemCommandFailed => scf
|
327
|
+
handle_error(scf, true)
|
328
|
+
rescue SystemExit => exSys
|
329
|
+
Rake.application.idei.set_abort(true)
|
330
|
+
rescue Exception => ex1
|
331
|
+
handle_error(ex1, false)
|
332
|
+
end
|
333
|
+
|
334
|
+
if not @immediate_output
|
335
|
+
self.output_string = s.string
|
336
|
+
Thread.current[:stdout] = tmp
|
337
|
+
output(nil, self.output_string)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def handle_error(ex1, isSysCmd)
|
342
|
+
if not Rake.application.idei.get_abort()
|
343
|
+
if not isSysCmd
|
344
|
+
Cxxproject::Printer.printError "Error for task #{@name}: #{ex1.message}"
|
345
|
+
end
|
346
|
+
end
|
347
|
+
begin
|
348
|
+
FileUtils.rm(@name) if File.exists?(@name)
|
349
|
+
rescue Exception => ex2
|
350
|
+
Cxxproject::Printer.printError "Error: Could not delete #{@name}: #{ex2.message}"
|
351
|
+
end
|
352
|
+
set_failed
|
353
|
+
end
|
354
|
+
|
355
|
+
def output(name, to_output)
|
356
|
+
return if Rake::Task.output_disabled
|
357
|
+
return unless output_after_execute
|
358
|
+
|
359
|
+
if to_output and to_output.length > 0
|
360
|
+
puts to_output
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
reenable_org = self.instance_method(:reenable)
|
365
|
+
define_method(:reenable) do
|
366
|
+
reenable_org.bind(self).call
|
367
|
+
@failure = false
|
368
|
+
end
|
369
|
+
|
370
|
+
define_method(:timestamp) do
|
371
|
+
if @transparent_timestamp
|
372
|
+
ts = Rake::EARLY
|
373
|
+
@prerequisites.each do |pre|
|
374
|
+
prereq_timestamp = Rake.application[pre].timestamp
|
375
|
+
ts = prereq_timestamp if prereq_timestamp > ts
|
376
|
+
end
|
377
|
+
else
|
378
|
+
ts = timestamp_org.bind(self).call()
|
379
|
+
end
|
380
|
+
ts
|
381
|
+
end
|
382
|
+
|
383
|
+
def ignore_missing_file
|
384
|
+
@ignore = true
|
385
|
+
end
|
386
|
+
|
387
|
+
def visit(&block)
|
388
|
+
if block.call(self)
|
389
|
+
prerequisite_tasks.each do |t|
|
390
|
+
t.visit(&block)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
end
|
396
|
+
|
397
|
+
end
|
@@ -4,47 +4,53 @@ module Rake
|
|
4
4
|
|
5
5
|
def self.add_listener(l)
|
6
6
|
get_listener() << l
|
7
|
-
puts "add->" + @@listener.inspect
|
8
7
|
end
|
9
8
|
|
10
9
|
def self.get_listener
|
11
|
-
|
10
|
+
@listener ||= []
|
12
11
|
end
|
12
|
+
|
13
13
|
def self.remove_listener(l)
|
14
14
|
get_listener().delete(l)
|
15
|
-
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.notify_listener(symbol, name)
|
18
|
+
Rake::get_listener().each do |l|
|
19
|
+
if l.respond_to?(symbol)
|
20
|
+
l.send(symbol, name)
|
21
|
+
end
|
22
|
+
end
|
16
23
|
end
|
17
24
|
|
18
25
|
class MultiTask
|
19
26
|
invoke_prerequisites_original = self.instance_method(:invoke_prerequisites)
|
20
27
|
define_method(:invoke_prerequisites) do |task_args, invocation_chain|
|
21
|
-
Rake::
|
28
|
+
Rake::notify_listener(:before_prerequisites, name)
|
22
29
|
invoke_prerequisites_original.bind(self).call(task_args, invocation_chain)
|
23
|
-
Rake::
|
30
|
+
Rake::notify_listener(:after_prerequisites, name)
|
24
31
|
if !needed?
|
25
|
-
Rake::
|
32
|
+
Rake::notify_listener(:after_execute, name)
|
26
33
|
end
|
27
34
|
end
|
28
35
|
end
|
29
36
|
|
30
37
|
class Task
|
31
|
-
|
32
38
|
invoke_prerequisites_original = self.instance_method(:invoke_prerequisites)
|
33
39
|
execute_original = self.instance_method(:execute)
|
34
40
|
|
35
41
|
define_method (:invoke_prerequisites) do |task_args, invocation_chain|
|
36
|
-
Rake::
|
42
|
+
Rake::notify_listener(:before_prerequisites, name)
|
37
43
|
invoke_prerequisites_original.bind(self).call(task_args, invocation_chain)
|
38
|
-
Rake::
|
44
|
+
Rake::notify_listener(:after_prerequisites, name)
|
39
45
|
if !needed?
|
40
|
-
Rake::
|
46
|
+
Rake::notify_listener(:after_execute, name)
|
41
47
|
end
|
42
48
|
end
|
43
49
|
|
44
50
|
define_method(:execute) do |args|
|
45
|
-
Rake::
|
51
|
+
Rake::notify_listener(:before_execute, name)
|
46
52
|
execute_original.bind(self).call(args)
|
47
|
-
Rake::
|
53
|
+
Rake::notify_listener(:after_execute, name)
|
48
54
|
end
|
49
55
|
|
50
56
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
class ThreadOut
|
4
|
+
|
5
|
+
def initialize(out)
|
6
|
+
@out = out
|
7
|
+
end
|
8
|
+
|
9
|
+
def write(stuff='')
|
10
|
+
if Thread.current[:stdout] then
|
11
|
+
Thread.current[:stdout].write stuff
|
12
|
+
else
|
13
|
+
@out.write stuff
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def puts(stuff='')
|
18
|
+
if Thread.current[:stdout] then
|
19
|
+
Thread.current[:stdout].puts stuff
|
20
|
+
else
|
21
|
+
@out.puts stuff
|
22
|
+
end
|
23
|
+
end
|
24
|
+
def print(stuff='')
|
25
|
+
if Thread.current[:stdout] then
|
26
|
+
Thread.current[:stdout].puts stuff
|
27
|
+
else
|
28
|
+
@out.print stuff
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def flush
|
33
|
+
if Thread.current[:stdout] then
|
34
|
+
Thread.current[:stdout].flush
|
35
|
+
else
|
36
|
+
@out.flush
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
STDOUT.sync = true
|
42
|
+
STDERR.sync = true
|
43
|
+
$stdout = ThreadOut.new(STDOUT)
|
44
|
+
$stderr = ThreadOut.new(STDERR)
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'cxxproject/errorparser/error_parser'
|
2
|
+
require 'cxxproject/utils/printer'
|
3
|
+
require 'thread'
|
4
|
+
|
5
|
+
module Cxxproject
|
6
|
+
|
7
|
+
# header of tcp msg from lake to eclipse:
|
8
|
+
# 1 byte = type (problem = 0x01)
|
9
|
+
# 4 bytes = length of msg
|
10
|
+
|
11
|
+
# payload of problem type:
|
12
|
+
# 4 bytes = length filename
|
13
|
+
# x bytes = filename
|
14
|
+
# 4 bytes = linenumber
|
15
|
+
# 1 byte = severity (0..2)
|
16
|
+
# rest = error msg
|
17
|
+
class IDEInterface < ErrorParser
|
18
|
+
|
19
|
+
def initialize()
|
20
|
+
@socket = nil
|
21
|
+
@abort = false
|
22
|
+
@thread = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def mutex
|
26
|
+
@mutex ||= Mutex.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def connect(port)
|
30
|
+
begin
|
31
|
+
@socket = TCPSocket.new('localhost', port)
|
32
|
+
|
33
|
+
@thread = Thread.new do
|
34
|
+
begin
|
35
|
+
@socket.recv(1)
|
36
|
+
set_abort(true)
|
37
|
+
rescue Exception => e
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
rescue Exception => e
|
42
|
+
Printer.printError "Error: #{e.message}"
|
43
|
+
ExitHelper.exit(1)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def disconnect()
|
48
|
+
if @socket
|
49
|
+
sleep 0.1 # hack to let ruby send all data via streams before closing ... strange .. perhaps this should be synchronized!
|
50
|
+
begin
|
51
|
+
@socket.shutdown
|
52
|
+
@socket.close
|
53
|
+
rescue Exception => e
|
54
|
+
Printer.printError "Error: #{e.message}"
|
55
|
+
ExitHelper.exit(1)
|
56
|
+
end
|
57
|
+
@socket = nil
|
58
|
+
end
|
59
|
+
|
60
|
+
begin
|
61
|
+
@thread.join if @thread
|
62
|
+
rescue
|
63
|
+
end
|
64
|
+
@thread = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def write_long(packet, l)
|
68
|
+
4.times do
|
69
|
+
packet << (l & 0xff)
|
70
|
+
l = l >> 8
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def force_encoding(s)
|
75
|
+
s.force_encoding("binary") if s.respond_to?("force_encoding") # for ruby >= 1.9
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_length_in_header(packet)
|
79
|
+
l = packet.length - 5
|
80
|
+
if packet.respond_to?("setbyte")
|
81
|
+
(1..4).each { |i| packet.setbyte(i, (l & 0xFF)); l = l >> 8 } # ruby >= 1.9
|
82
|
+
else
|
83
|
+
(1..4).each { |i| packet[i] = (l & 0xFF); l = l >> 8 } # ruby < 1.9
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def write_string(packet, s)
|
88
|
+
write_long(packet, s.length)
|
89
|
+
packet << s
|
90
|
+
end
|
91
|
+
|
92
|
+
def set_errors(error_array)
|
93
|
+
if @socket
|
94
|
+
|
95
|
+
merged_messages = []
|
96
|
+
last_msg = nil
|
97
|
+
error_array.each do |msg|
|
98
|
+
if msg.file_name.nil?
|
99
|
+
last_msg.message += "\r\n#{msg.message}" if last_msg
|
100
|
+
else
|
101
|
+
last_msg = msg.dup
|
102
|
+
merged_messages << last_msg
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
merged_messages.each do |msg|
|
107
|
+
msg.message.rstrip!
|
108
|
+
packet = create_error_packet(msg)
|
109
|
+
begin
|
110
|
+
mutex.synchronize { @socket.write(packet) }
|
111
|
+
rescue Exception => e
|
112
|
+
Printer.printError "Error: #{e.message}"
|
113
|
+
set_abort(true)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def create_error_packet(msg)
|
121
|
+
packet = ""
|
122
|
+
[packet, msg.file_name, msg.message].each {|s|force_encoding(s)}
|
123
|
+
|
124
|
+
packet << 1 # error type
|
125
|
+
write_long(packet,0) # length (will be corrected below)
|
126
|
+
|
127
|
+
write_string(packet, msg.file_name)
|
128
|
+
write_long(packet,msg.line_number)
|
129
|
+
packet << (msg.severity & 0xFF)
|
130
|
+
packet << msg.message
|
131
|
+
|
132
|
+
set_length_in_header(packet)
|
133
|
+
packet
|
134
|
+
end
|
135
|
+
|
136
|
+
def set_build_info(name_attr, config_name_attr, num = -1)
|
137
|
+
@num = num if (num >= 0)
|
138
|
+
name = String.new(name_attr)
|
139
|
+
config_name = String.new(config_name_attr)
|
140
|
+
|
141
|
+
packet = ""
|
142
|
+
[packet, name, config_name].each {|s|force_encoding(s)}
|
143
|
+
|
144
|
+
lname = name.length
|
145
|
+
lconfig = config_name.length
|
146
|
+
lsum = 4 + lname + 4 + lconfig + 4
|
147
|
+
|
148
|
+
packet << 10 # build info type
|
149
|
+
|
150
|
+
write_long(packet, lsum)
|
151
|
+
write_long(packet, lname)
|
152
|
+
packet << name
|
153
|
+
write_long(packet, lconfig)
|
154
|
+
packet << config_name
|
155
|
+
write_long(packet, num >=0 ? num : 0)
|
156
|
+
|
157
|
+
begin
|
158
|
+
mutex.synchronize { @socket.write(packet) if @socket }
|
159
|
+
rescue Exception => e
|
160
|
+
Printer.printError "Error: #{e.message}"
|
161
|
+
set_abort(true)
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
def get_number_of_projects
|
167
|
+
@num ||= 0
|
168
|
+
end
|
169
|
+
|
170
|
+
def get_abort()
|
171
|
+
@abort
|
172
|
+
end
|
173
|
+
|
174
|
+
def set_abort(value)
|
175
|
+
@abort = value
|
176
|
+
ProcessHelper.killProcess if @abort
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|