cxxproject 0.4.6 → 0.5.47

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/Rakefile.rb +101 -54
  2. data/bin/cxx +4 -4
  3. data/lib/cxxproject/buildingblocks/binary_library.rb +32 -9
  4. data/lib/cxxproject/buildingblocks/building_block.rb +220 -74
  5. data/lib/cxxproject/buildingblocks/command_line.rb +70 -21
  6. data/lib/cxxproject/buildingblocks/custom_building_block.rb +33 -9
  7. data/lib/cxxproject/buildingblocks/executable.rb +228 -33
  8. data/lib/cxxproject/buildingblocks/has_dependencies_mixin.rb +69 -43
  9. data/lib/cxxproject/buildingblocks/has_includes_mixin.rb +20 -0
  10. data/lib/cxxproject/buildingblocks/has_libraries_mixin.rb +29 -30
  11. data/lib/cxxproject/buildingblocks/has_sources_mixin.rb +343 -64
  12. data/lib/cxxproject/buildingblocks/makefile.rb +142 -24
  13. data/lib/cxxproject/buildingblocks/module.rb +27 -6
  14. data/lib/cxxproject/buildingblocks/single_source.rb +26 -4
  15. data/lib/cxxproject/buildingblocks/source_library.rb +113 -20
  16. data/lib/cxxproject/errorparser/diab_compiler_error_parser.rb +40 -0
  17. data/lib/cxxproject/errorparser/diab_linker_error_parser.rb +33 -0
  18. data/lib/cxxproject/errorparser/error_parser.rb +50 -0
  19. data/lib/cxxproject/errorparser/gcc_compiler_error_parser.rb +30 -0
  20. data/lib/cxxproject/errorparser/gcc_linker_error_parser.rb +29 -0
  21. data/lib/cxxproject/errorparser/ti_compiler_error_parser.rb +30 -0
  22. data/lib/cxxproject/errorparser/ti_linker_error_parser.rb +29 -0
  23. data/lib/cxxproject/eval_context.rb +136 -0
  24. data/lib/cxxproject/ext/file.rb +71 -0
  25. data/lib/cxxproject/ext/filelist.rb +6 -0
  26. data/lib/cxxproject/ext/progressbar.rb +20 -0
  27. data/lib/cxxproject/ext/rake.rb +397 -0
  28. data/lib/cxxproject/{extensions/rake_listener_ext.rb → ext/rake_listener.rb} +18 -12
  29. data/lib/cxxproject/ext/stdout.rb +44 -0
  30. data/lib/cxxproject/ide_interface.rb +181 -0
  31. data/lib/cxxproject/toolchain/clang.rb +39 -0
  32. data/lib/cxxproject/toolchain/colorizing_formatter.rb +99 -0
  33. data/lib/cxxproject/toolchain/diab.rb +36 -33
  34. data/lib/cxxproject/toolchain/gcc.rb +16 -8
  35. data/lib/cxxproject/toolchain/provider.rb +112 -2
  36. data/lib/cxxproject/toolchain/ti.rb +50 -0
  37. data/lib/cxxproject/toolchain/toolchain.rb +38 -0
  38. data/lib/cxxproject/toolchain/toolchain_benchmark.rb +23 -0
  39. data/lib/cxxproject/torake.rb +181 -123
  40. data/lib/cxxproject/utils/cleanup.rb +20 -0
  41. data/lib/cxxproject/utils/console.rb +6 -0
  42. data/lib/cxxproject/utils/exit_helper.rb +40 -0
  43. data/lib/cxxproject/utils/graphstream.rb +154 -0
  44. data/lib/cxxproject/utils/optional.rb +16 -0
  45. data/lib/cxxproject/utils/printer.rb +50 -0
  46. data/lib/cxxproject/utils/process.rb +53 -0
  47. data/lib/cxxproject/utils/progress.rb +66 -0
  48. data/lib/cxxproject/utils/progress_helper.rb +77 -0
  49. data/lib/cxxproject/utils/rbcurse.rb +284 -0
  50. data/lib/cxxproject/utils/rbcurse_executable_ext.rb +14 -0
  51. data/lib/cxxproject/utils/rbcurse_progress.rb +71 -0
  52. data/lib/cxxproject/utils/rbcurse_tasktable.rb +51 -0
  53. data/lib/cxxproject/utils/stats.rb +60 -0
  54. data/lib/cxxproject/utils/ubigraph.rb +179 -188
  55. data/lib/cxxproject/utils/utils.rb +29 -25
  56. data/lib/cxxproject/version.rb +7 -0
  57. data/lib/cxxproject.rb +13 -7
  58. data/lib/tools/project_wizard.rb +66 -0
  59. data/spec/building_block_spec.rb +50 -6
  60. data/spec/{build_dependencies_spec.rb → cxxproject_2_rake_spec.rb} +82 -65
  61. data/spec/file_ext_spec.rb +30 -0
  62. data/spec/ide_interface_spec.rb +41 -0
  63. data/spec/object_dependency_spec.rb +83 -0
  64. data/spec/project_path_spec.rb +14 -16
  65. data/spec/rake_listener_ext_spec.rb +38 -5
  66. data/spec/spec_helper.rb +18 -0
  67. data/spec/testdata/basic/lib2/project.rb +1 -1
  68. data/spec/testdata/multiple_levels/libs/lib2/project.rb +1 -1
  69. data/spec/toolchain_spec.rb +29 -0
  70. metadata +91 -58
  71. data/lib/cxxproject/extensions/file_ext.rb +0 -47
  72. data/lib/cxxproject/extensions/rake_ext.rb +0 -158
  73. data/lib/cxxproject/extensions/stdout_ext.rb +0 -35
  74. data/lib/cxxproject/task_maker.rb +0 -418
  75. data/lib/cxxproject/testinstanceeval.rb +0 -65
  76. data/lib/cxxproject/toolchain/base.rb +0 -98
  77. data/lib/cxxproject/torake/compiler.rb +0 -10
  78. data/lib/cxxproject/torake/gcccompiler.rb +0 -7
  79. data/lib/cxxproject/torake/osxcompiler.rb +0 -7
  80. data/lib/cxxproject/utils/dot/building_block_graph_writer.rb +0 -19
  81. data/lib/cxxproject/utils/dot/graph_writer.rb +0 -53
  82. data/lib/cxxproject/utils/dot/task_graph_writer.rb +0 -34
  83. data/lib/tools/projectWizard.rb +0 -44
  84. data/spec/dir_spec.rb +0 -13
  85. /data/lib/cxxproject/{extensions/rake_dirty_ext.rb → ext/rake_dirty.rb} +0 -0
  86. /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
- @@listener ||= []
10
+ @listener ||= []
12
11
  end
12
+
13
13
  def self.remove_listener(l)
14
14
  get_listener().delete(l)
15
- puts "remove->" + @@listener.inspect
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::get_listener().each {|l|l.before_prerequisites(name)}
28
+ Rake::notify_listener(:before_prerequisites, name)
22
29
  invoke_prerequisites_original.bind(self).call(task_args, invocation_chain)
23
- Rake::get_listener().each {|l|l.after_prerequisites(name)}
30
+ Rake::notify_listener(:after_prerequisites, name)
24
31
  if !needed?
25
- Rake::get_listener().each{|l|l.after_execute(name)}
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::get_listener().each {|l|l.before_prerequisites(name)}
42
+ Rake::notify_listener(:before_prerequisites, name)
37
43
  invoke_prerequisites_original.bind(self).call(task_args, invocation_chain)
38
- Rake::get_listener().each {|l|l.after_prerequisites(name)}
44
+ Rake::notify_listener(:after_prerequisites, name)
39
45
  if !needed?
40
- Rake::get_listener().each{|l|l.after_execute(name)}
46
+ Rake::notify_listener(:after_execute, name)
41
47
  end
42
48
  end
43
49
 
44
50
  define_method(:execute) do |args|
45
- Rake::get_listener.each {|l|l.before_execute(name)}
51
+ Rake::notify_listener(:before_execute, name)
46
52
  execute_original.bind(self).call(args)
47
- Rake::get_listener.each {|l|l.after_execute(name)}
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
+