cxxproject 0.5.48 → 0.5.59

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/Rakefile.rb +116 -116
  2. data/bin/cxx +10 -10
  3. data/lib/cxxproject.rb +23 -23
  4. data/lib/cxxproject/buildingblocks/binary_library.rb +39 -39
  5. data/lib/cxxproject/buildingblocks/building_block.rb +251 -239
  6. data/lib/cxxproject/buildingblocks/command_line.rb +79 -79
  7. data/lib/cxxproject/buildingblocks/custom_building_block.rb +39 -41
  8. data/lib/cxxproject/buildingblocks/executable.rb +257 -249
  9. data/lib/cxxproject/buildingblocks/has_dependencies_mixin.rb +83 -83
  10. data/lib/cxxproject/buildingblocks/has_includes_mixin.rb +20 -20
  11. data/lib/cxxproject/buildingblocks/has_libraries_mixin.rb +34 -34
  12. data/lib/cxxproject/buildingblocks/has_sources_mixin.rb +371 -364
  13. data/lib/cxxproject/buildingblocks/makefile.rb +153 -153
  14. data/lib/cxxproject/buildingblocks/module.rb +35 -35
  15. data/lib/cxxproject/buildingblocks/single_source.rb +33 -33
  16. data/lib/cxxproject/buildingblocks/source_library.rb +124 -124
  17. data/lib/cxxproject/errorparser/diab_compiler_error_parser.rb +40 -40
  18. data/lib/cxxproject/errorparser/diab_linker_error_parser.rb +41 -33
  19. data/lib/cxxproject/errorparser/error_parser.rb +50 -50
  20. data/lib/cxxproject/errorparser/gcc_compiler_error_parser.rb +35 -30
  21. data/lib/cxxproject/errorparser/gcc_linker_error_parser.rb +35 -29
  22. data/lib/cxxproject/errorparser/ti_compiler_error_parser.rb +30 -30
  23. data/lib/cxxproject/errorparser/ti_linker_error_parser.rb +30 -29
  24. data/lib/cxxproject/eval_context.rb +144 -136
  25. data/lib/cxxproject/ext/file.rb +71 -71
  26. data/lib/cxxproject/ext/filelist.rb +6 -6
  27. data/lib/cxxproject/ext/progressbar.rb +20 -20
  28. data/lib/cxxproject/ext/rake.rb +419 -397
  29. data/lib/cxxproject/ext/rake_dirty.rb +30 -30
  30. data/lib/cxxproject/ext/rake_listener.rb +59 -59
  31. data/lib/cxxproject/ext/stdout.rb +44 -44
  32. data/lib/cxxproject/ext/string.rb +9 -9
  33. data/lib/cxxproject/ide_interface.rb +187 -181
  34. data/lib/cxxproject/toolchain/clang.rb +39 -39
  35. data/lib/cxxproject/toolchain/colorizing_formatter.rb +99 -99
  36. data/lib/cxxproject/toolchain/diab.rb +3 -1
  37. data/lib/cxxproject/toolchain/gcc.rb +2 -1
  38. data/lib/cxxproject/toolchain/provider.rb +131 -128
  39. data/lib/cxxproject/toolchain/toolchain.rb +38 -38
  40. data/lib/cxxproject/toolchain/toolchain_benchmark.rb +23 -23
  41. data/lib/cxxproject/torake.rb +218 -216
  42. data/lib/cxxproject/utils/cleanup.rb +20 -20
  43. data/lib/cxxproject/utils/console.rb +6 -6
  44. data/lib/cxxproject/utils/exit_helper.rb +40 -40
  45. data/lib/cxxproject/utils/graphstream.rb +154 -154
  46. data/lib/cxxproject/utils/optional.rb +16 -16
  47. data/lib/cxxproject/utils/printer.rb +50 -50
  48. data/lib/cxxproject/utils/process.rb +52 -52
  49. data/lib/cxxproject/utils/progress.rb +66 -66
  50. data/lib/cxxproject/utils/progress_helper.rb +77 -77
  51. data/lib/cxxproject/utils/rbcurse.rb +284 -284
  52. data/lib/cxxproject/utils/rbcurse_executable_ext.rb +14 -14
  53. data/lib/cxxproject/utils/rbcurse_progress.rb +71 -71
  54. data/lib/cxxproject/utils/rbcurse_tasktable.rb +51 -51
  55. data/lib/cxxproject/utils/stats.rb +60 -60
  56. data/lib/cxxproject/utils/ubigraph.rb +228 -228
  57. data/lib/cxxproject/utils/utils.rb +60 -37
  58. data/lib/cxxproject/utils/valgrind.rb +11 -11
  59. data/lib/cxxproject/version.rb +7 -7
  60. data/lib/tools/Rakefile.rb.template +10 -10
  61. data/lib/tools/project.rb.template +6 -6
  62. data/lib/tools/project_wizard.rb +66 -66
  63. data/spec/building_block_spec.rb +56 -56
  64. data/spec/cxxproject_2_rake_spec.rb +186 -186
  65. data/spec/file_ext_spec.rb +30 -30
  66. data/spec/ide_interface_spec.rb +41 -41
  67. data/spec/object_dependency_spec.rb +83 -83
  68. data/spec/project_path_spec.rb +71 -71
  69. data/spec/rake_listener_ext_spec.rb +58 -58
  70. data/spec/spec_helper.rb +18 -18
  71. data/spec/string_spec.rb +11 -11
  72. data/spec/testdata/basic/exe12/project.rb +5 -5
  73. data/spec/testdata/basic/lib1/project.rb +5 -5
  74. data/spec/testdata/basic/lib2/project.rb +8 -8
  75. data/spec/testdata/multiple_levels/libs/lib1/project.rb +5 -5
  76. data/spec/testdata/multiple_levels/libs/lib2/project.rb +19 -19
  77. data/spec/testdata/multiple_levels/mainproject/basic/project.rb +8 -8
  78. data/spec/testdata/onlyOneHeader/Rakefile.rb +4 -4
  79. data/spec/testdata/onlyOneHeader/project.rb +4 -4
  80. data/spec/toolchain_spec.rb +29 -29
  81. metadata +58 -58
@@ -1,83 +1,83 @@
1
- module Cxxproject
2
- module HasDependencies
3
-
4
- def dependencies
5
- @dependencies ||= []
6
- end
7
-
8
- def helper_dependencies
9
- @helper_dependencies ||= []
10
- end
11
-
12
- def set_dependencies(deps)
13
- @dependencies = deps.map { |dep| dep.instance_of?(String) ? dep : dep.name }
14
- self
15
- end
16
-
17
- def set_helper_dependencies(deps)
18
- @helper_dependencies = deps.map { |dep| dep.instance_of?(String) ? dep : dep.name }
19
- self
20
- end
21
-
22
- def direct_deps
23
- return @direct_deps if @direct_deps
24
-
25
- @all_dependencies_set = Set.new
26
- @all_dependencies_set << self
27
- @all_dependencies = [self]
28
-
29
- depList = helper_dependencies.length > 0 ? helper_dependencies : dependencies
30
-
31
- depList.each do |d|
32
- bb = ALL_BUILDING_BLOCKS[d]
33
- if not bb
34
- raise "Error: while reading config file for #{self.name}: dependent building block \"#{d}\" was specified but not found!"
35
- end
36
- next if @all_dependencies_set.include?bb
37
-
38
- @all_dependencies << bb
39
- @all_dependencies_set << bb
40
-
41
- # deps in modules may be splitted into its contents
42
- if ModuleBuildingBlock === bb
43
- bb.contents.each do |c|
44
- next if @all_dependencies_set.include?c
45
- @all_dependencies << c
46
- @all_dependencies_set << c
47
- end
48
- end
49
-
50
- end
51
-
52
- @direct_deps = @all_dependencies.dup
53
- @direct_deps
54
- end
55
-
56
- def all_dependencies()
57
- return @all_dependencies if @all_deps_calculated
58
-
59
- direct_deps.each do |d|
60
- d.all_dependencies_recursive(@all_dependencies, @all_dependencies_set)
61
- end
62
-
63
- @all_deps_calculated = true
64
- @all_dependencies
65
- end
66
-
67
- def all_dependencies_recursive(all_deps, all_deps_set)
68
- deps = [] # needed to keep order
69
-
70
- direct_deps.each do |d|
71
- next if all_deps_set.include?d
72
- all_deps << d
73
- all_deps_set << d
74
- deps << d
75
- end
76
-
77
- deps.each do |d|
78
- d.all_dependencies_recursive(all_deps, all_deps_set)
79
- end
80
- end
81
-
82
- end
83
- end
1
+ module Cxxproject
2
+ module HasDependencies
3
+
4
+ def dependencies
5
+ @dependencies ||= []
6
+ end
7
+
8
+ def helper_dependencies
9
+ @helper_dependencies ||= []
10
+ end
11
+
12
+ def set_dependencies(deps)
13
+ @dependencies = deps.map { |dep| dep.instance_of?(String) ? dep : dep.name }
14
+ self
15
+ end
16
+
17
+ def set_helper_dependencies(deps)
18
+ @helper_dependencies = deps.map { |dep| dep.instance_of?(String) ? dep : dep.name }
19
+ self
20
+ end
21
+
22
+ def direct_deps
23
+ return @direct_deps if @direct_deps
24
+
25
+ @all_dependencies_set = Set.new
26
+ @all_dependencies_set << self
27
+ @all_dependencies = [self]
28
+
29
+ depList = helper_dependencies.length > 0 ? helper_dependencies : dependencies
30
+
31
+ depList.each do |d|
32
+ bb = ALL_BUILDING_BLOCKS[d]
33
+ if not bb
34
+ raise "Error: while reading config file for #{self.name}: dependent building block \"#{d}\" was specified but not found!"
35
+ end
36
+ next if @all_dependencies_set.include?bb
37
+
38
+ @all_dependencies << bb
39
+ @all_dependencies_set << bb
40
+
41
+ # deps in modules may be splitted into its contents
42
+ if ModuleBuildingBlock === bb
43
+ bb.contents.each do |c|
44
+ next if @all_dependencies_set.include?c
45
+ @all_dependencies << c
46
+ @all_dependencies_set << c
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ @direct_deps = @all_dependencies.dup
53
+ @direct_deps
54
+ end
55
+
56
+ def all_dependencies()
57
+ return @all_dependencies if @all_deps_calculated
58
+
59
+ direct_deps.each do |d|
60
+ d.all_dependencies_recursive(@all_dependencies, @all_dependencies_set)
61
+ end
62
+
63
+ @all_deps_calculated = true
64
+ @all_dependencies
65
+ end
66
+
67
+ def all_dependencies_recursive(all_deps, all_deps_set)
68
+ deps = [] # needed to keep order
69
+
70
+ direct_deps.each do |d|
71
+ next if all_deps_set.include?d
72
+ all_deps << d
73
+ all_deps_set << d
74
+ deps << d
75
+ end
76
+
77
+ deps.each do |d|
78
+ d.all_dependencies_recursive(all_deps, all_deps_set)
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -1,20 +1,20 @@
1
- module Cxxproject
2
- module HasIncludes
3
- def includes
4
- @includes ||= []
5
- end
6
- def set_includes(x)
7
- @includes = x
8
- self
9
- end
10
-
11
- def local_includes
12
- @local_includes ||= []
13
- end
14
- def set_local_includes(x)
15
- @local_includes = x
16
- self
17
- end
18
-
19
- end
20
- end
1
+ module Cxxproject
2
+ module HasIncludes
3
+ def includes
4
+ @includes ||= []
5
+ end
6
+ def set_includes(x)
7
+ @includes = x
8
+ self
9
+ end
10
+
11
+ def local_includes
12
+ @local_includes ||= []
13
+ end
14
+ def set_local_includes(x)
15
+ @local_includes = x
16
+ self
17
+ end
18
+
19
+ end
20
+ end
@@ -1,34 +1,34 @@
1
- module Cxxproject
2
- module HasLibraries
3
- LIB = 1
4
- USERLIB = 2
5
- LIB_WITH_PATH = 3
6
- SEARCH_PATH = 4
7
- DEPENDENCY = 5
8
-
9
- def lib_elements
10
- @lib_elements ||= []
11
- end
12
-
13
- # value: can be string or building block
14
- def add_lib_element(type, value, front = false)
15
- elem = [type, value.instance_of?(String) ? value : value.name]
16
- if front
17
- lib_elements.unshift(elem)
18
- else
19
- lib_elements << elem
20
- end
21
- end
22
-
23
- # 1. element: type
24
- # 2. element: name, must not be a building block
25
- def add_lib_elements(array_of_tuples, front = false)
26
- if front
27
- @lib_elements = array_of_tuples+lib_elements
28
- else
29
- lib_elements.concat(array_of_tuples)
30
- end
31
- end
32
-
33
- end
34
- end
1
+ module Cxxproject
2
+ module HasLibraries
3
+ LIB = 1
4
+ USERLIB = 2
5
+ LIB_WITH_PATH = 3
6
+ SEARCH_PATH = 4
7
+ DEPENDENCY = 5
8
+
9
+ def lib_elements
10
+ @lib_elements ||= []
11
+ end
12
+
13
+ # value: can be string or building block
14
+ def add_lib_element(type, value, front = false)
15
+ elem = [type, value.instance_of?(String) ? value : value.name]
16
+ if front
17
+ lib_elements.unshift(elem)
18
+ else
19
+ lib_elements << elem
20
+ end
21
+ end
22
+
23
+ # 1. element: type
24
+ # 2. element: name, must not be a building block
25
+ def add_lib_elements(array_of_tuples, front = false)
26
+ if front
27
+ @lib_elements = array_of_tuples+lib_elements
28
+ else
29
+ lib_elements.concat(array_of_tuples)
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -1,364 +1,371 @@
1
- require 'yaml'
2
- require 'cxxproject/utils/process'
3
- require 'cxxproject/utils/utils'
4
- require 'cxxproject/utils/printer'
5
-
6
- module Cxxproject
7
- module HasSources
8
-
9
- attr_writer :file_dependencies
10
- attr_reader :incArray
11
-
12
- def file_dependencies
13
- @file_dependencies ||= []
14
- end
15
-
16
- def sources
17
- @sources ||= []
18
- end
19
- def set_sources(x)
20
- @sources = x
21
- self
22
- end
23
-
24
- def deps_in_depFiles
25
- @deps_in_depFiles ||= Set.new
26
- end
27
-
28
- def source_patterns
29
- @source_patterns ||= []
30
- end
31
- def set_source_patterns(x)
32
- @source_patterns = x
33
- self
34
- end
35
-
36
- def exclude_sources
37
- @exclude_sources ||= []
38
- end
39
- def set_exclude_sources(x)
40
- @exclude_sources = x
41
- self
42
- end
43
-
44
- # used when a source file shall have different tcs than the project default
45
- def tcs4source(source)
46
- @tcs4source ||= {}
47
-
48
- if @tcs4source.include?(source)
49
- @tcs4source[source]
50
- else
51
- @tcs
52
- end
53
- end
54
-
55
- def set_tcs4source(x)
56
- @tcs4source = x
57
- self
58
- end
59
-
60
- def include_string(type)
61
- @include_string[type] ||= ""
62
- end
63
-
64
- def define_string(type)
65
- @define_string[type] ||= ""
66
- end
67
-
68
- def calc_compiler_strings()
69
- @include_string = {}
70
- @define_string = {}
71
-
72
- @incArray = local_includes.dup
73
- @incArray.concat(includes)
74
-
75
- if Rake::application.deriveIncludes
76
- all_dependencies.each_with_index do |d,i|
77
- next if not HasIncludes === d
78
- next if i == 0
79
- prefix = File.rel_from_to_project(@project_dir,d.project_dir)
80
- next if not prefix
81
- @incArray.concat(d.includes.map {|inc| File.add_prefix(prefix,inc)})
82
- end
83
- @incArray.uniq!
84
- end
85
-
86
- [:CPP, :C, :ASM].each do |type|
87
- @include_string[type] = get_include_string(@tcs, type)
88
- @define_string[type] = get_define_string(@tcs, type)
89
- end
90
- end
91
-
92
- def get_include_string(tcs, type)
93
- @incArray.map {|k| "#{tcs[:COMPILER][type][:INCLUDE_PATH_FLAG]}#{k}"}
94
- end
95
-
96
- def get_define_string(tcs, type)
97
- tcs[:COMPILER][type][:DEFINES].map {|k| "#{tcs[:COMPILER][type][:DEFINE_FLAG]}#{k}"}
98
- end
99
-
100
- def get_object_file(sourceRel)
101
- parts = [@output_dir]
102
- if @output_dir_abs
103
- parts = [@output_dir_relPath] if @output_dir_relPath
104
- parts << 'objects'
105
- parts << @name
106
- end
107
-
108
- parts << sourceRel.chomp(File.extname(sourceRel))
109
- File.join(parts) + ".o"
110
- end
111
-
112
- def get_dep_file(object)
113
- object + ".d"
114
- end
115
-
116
- def get_source_type(source)
117
- ex = File.extname(source)
118
- [:CPP, :C, :ASM].each do |t|
119
- return t if tcs[:COMPILER][t][:SOURCE_FILE_ENDINGS].include?(ex)
120
- end
121
- nil
122
- end
123
-
124
- def get_sources_task_name
125
- "Objects of #{name}"
126
- end
127
-
128
- def parse_includes(deps)
129
- #deps look like "test.o: test.cpp test.h" -> remove .o and .cpp from list
130
- return deps.gsub(/\\\n/,'').split()[2..-1]
131
- end
132
-
133
- def convert_depfile(depfile)
134
- deps_string = read_file_or_empty_string(depfile)
135
- deps = parse_includes(deps_string)
136
- if deps.nil?
137
- return # ok, because next run the source will be recompiled due to invalid depfile
138
- end
139
- expanded_deps = deps.map do |d|
140
- tmp = d.gsub(/[\\]/,'/')
141
- deps_in_depFiles << tmp
142
- tmp
143
- end
144
-
145
- FileUtils.mkpath File.dirname(depfile)
146
- File.open(depfile, 'wb') do |f|
147
- f.write(expanded_deps.to_yaml)
148
- end
149
- end
150
-
151
- def apply_depfile(depfile,outfileTask)
152
- deps = nil
153
- begin
154
- deps = YAML.load_file(depfile)
155
- deps.each do |d|
156
- deps_in_depFiles << d
157
- f = file d
158
- f.ignore_missing_file
159
- end
160
- outfileTask.enhance(deps)
161
- rescue
162
- # may happen if depfile was not converted the last time
163
- def outfileTask.needed?
164
- true
165
- end
166
- end
167
- end
168
-
169
- def create_object_file_tasks()
170
-
171
- sources_to_build = {}
172
-
173
- exclude_files = Set.new
174
- exclude_sources.each do |p|
175
- if p.include?".."
176
- Printer.printError "Error: Exclude source file pattern '#{p}' must not include '..'"
177
- return nil
178
- end
179
-
180
- Dir.glob(p).each {|f| exclude_files << f}
181
- end
182
- files = Set.new # do not build the same file twice
183
-
184
- sources.each do |f|
185
- if f.include?".."
186
- Printer.printError "Error: Source file '#{f}' must not include '..'"
187
- return nil
188
- end
189
-
190
- next if exclude_files.include?(f)
191
- next if files.include?(f)
192
- files << f
193
- sources_to_build[f] = tcs4source(f)
194
- end
195
-
196
- source_patterns.each do |p|
197
- if p.include?".."
198
- Printer.printError "Error: Source file pattern '#{p}' must not include '..'"
199
- return nil
200
- end
201
-
202
- globRes = Dir.glob(p)
203
- if (globRes.length == 0)
204
- Printer.printWarning "Warning: Source file pattern '#{p}' did not match to any file"
205
- end
206
- globRes.each do |f|
207
- next if exclude_files.include?(f)
208
- next if files.include?(f)
209
- files << f
210
- t = tcs4source(f)
211
- t = tcs4source(p) if t == nil
212
- sources_to_build[f] = t
213
- end
214
- end
215
-
216
- ordered = sources_to_build.keys.sort()
217
- dirs = []
218
- filemap = {}
219
- ordered.reverse.each do |o|
220
- d = File.dirname(o)
221
- if filemap.include?(d)
222
- filemap[d] << o
223
- else
224
- filemap[d] = [o]
225
- dirs << d
226
- end
227
- end
228
-
229
- obj_tasks = []
230
- dirs.each do |d|
231
- filemap[d].reverse.each do |f|
232
- obj_task = create_object_file_task(f, sources_to_build[f])
233
- obj_tasks << obj_task unless obj_task.nil?
234
- end
235
- end
236
- obj_tasks
237
- end
238
-
239
- def create_object_file_task(sourceRel, the_tcs)
240
- if File.is_absolute?(sourceRel)
241
- sourceRel = File.rel_from_to_project(@project_dir, sourceRel, false)
242
- end
243
-
244
- type = get_source_type(sourceRel)
245
- return nil if type.nil?
246
-
247
- objectRel = get_object_file(sourceRel)
248
- @objects << objectRel
249
- object = File.expand_path(objectRel)
250
- source = File.expand_path(sourceRel)
251
-
252
- depStr = ""
253
- dep_file = nil
254
- if type != :ASM
255
- dep_file = get_dep_file(objectRel)
256
- dep_file = "\""+dep_file+"\"" if dep_file.include?" "
257
- depStr = the_tcs[:COMPILER][type][:DEP_FLAGS]
258
- end
259
-
260
- res = typed_file_task Rake::Task::OBJECT, object => source do
261
- i_array = the_tcs == @tcs ? @include_string[type] : get_include_string(the_tcs, type)
262
- d_array = the_tcs == @tcs ? @define_string[type] : get_define_string(the_tcs, type)
263
-
264
- compiler = the_tcs[:COMPILER][type]
265
- cmd = [compiler[:COMMAND]]
266
- cmd += compiler[:COMPILE_FLAGS].split(" ")
267
- if dep_file
268
- cmd += depStr.split(" ")
269
- if the_tcs[:COMPILER][type][:DEP_FLAGS_SPACE]
270
- cmd << dep_file
271
- else
272
- cmd[cmd.length-1] << dep_file
273
- end
274
- end
275
- cmd += compiler[:FLAGS].gsub(/\"/,"").split(" ") # double quotes within string do not work on windows...
276
- cmd += i_array
277
- cmd += d_array
278
- cmd += (compiler[:OBJECT_FILE_FLAG] + objectRel).split(" ")
279
- cmd << sourceRel
280
-
281
- if Cxxproject::Utils.old_ruby?
282
- cmd.map! {|c| ((c.include?" ") ? ("\""+c+"\"") : c )}
283
- cmdLine = cmd.join(" ")
284
- if cmdLine.length > 8000
285
- inputName = objectRel+".tmp"
286
- File.open(inputName,"wb") { |f| f.write(cmd[1..-1].join(" ")) }
287
- inputName = "\""+inputName+"\"" if inputName.include?" "
288
- consoleOutput = `#{compiler[:COMMAND] + " @" + inputName}`
289
- else
290
- consoleOutput = `#{cmd.join(" ")} 2>&1`
291
- end
292
- else
293
- rd, wr = IO.pipe
294
- cmd << {
295
- :err=>wr,
296
- :out=>wr
297
- }
298
- sp = spawn(*cmd)
299
- cmd.pop
300
- consoleOutput = ProcessHelper.readOutput(sp, rd, wr)
301
- end
302
-
303
- process_result(cmd, consoleOutput, compiler[:ERROR_PARSER], "Compiling #{sourceRel}")
304
-
305
- convert_depfile(dep_file) if dep_file
306
-
307
- check_config_file()
308
- end
309
- enhance_with_additional_files(res)
310
- add_output_dir_dependency(object, res, false)
311
- apply_depfile(dep_file, res) if depStr != ""
312
- res
313
- end
314
-
315
- def enhance_with_additional_files(task)
316
- task.enhance(file_dependencies)
317
- task.enhance(@config_files)
318
- end
319
-
320
- def process_console_output(console_output, error_parser)
321
- ret = false
322
- if not console_output.empty?
323
- if error_parser
324
- begin
325
- error_descs, console_output_full = error_parser.scan_lines(console_output, @project_dir)
326
-
327
- console_output = console_output_full if Rake::application.consoleOutput_fullnames
328
-
329
- ret = error_descs.any? { |e| e.severity == ErrorParser::SEVERITY_ERROR }
330
-
331
- console_output.gsub!(/[\r]/, "")
332
- highlighter = @tcs[:CONSOLE_HIGHLIGHTER]
333
- if (highlighter and highlighter.enabled?)
334
- puts highlighter.format(console_output, error_descs, error_parser)
335
- else
336
- puts console_output
337
- end
338
-
339
- Rake.application.idei.set_errors(error_descs)
340
- rescue Exception => e
341
- Printer.printWarning "Parsing output failed (maybe language not set to English?): " + e.message
342
- puts "Original output:"
343
- puts console_output
344
- end
345
- end
346
- end
347
- ret
348
- end
349
-
350
- def prepare_tasks_for_objects
351
- if (@output_dir_abs)
352
- CLEAN.include(@output_dir + "/objects/" + @name)
353
- end
354
-
355
- @objects = []
356
- t = multitask get_sources_task_name
357
- t.type = Rake::Task::SOURCEMULTI
358
- t.transparent_timestamp = true
359
- t.set_building_block(self)
360
- t
361
- end
362
-
363
- end
364
- end
1
+ require 'yaml'
2
+ require 'cxxproject/utils/process'
3
+ require 'cxxproject/utils/utils'
4
+ require 'cxxproject/utils/printer'
5
+
6
+ module Cxxproject
7
+ module HasSources
8
+
9
+ attr_writer :file_dependencies
10
+ attr_reader :incArray
11
+
12
+ def file_dependencies
13
+ @file_dependencies ||= []
14
+ end
15
+
16
+ def sources
17
+ @sources ||= []
18
+ end
19
+ def set_sources(x)
20
+ @sources = x
21
+ self
22
+ end
23
+
24
+ def deps_in_depFiles
25
+ @deps_in_depFiles ||= Set.new
26
+ end
27
+
28
+ def source_patterns
29
+ @source_patterns ||= []
30
+ end
31
+ def set_source_patterns(x)
32
+ @source_patterns = x
33
+ self
34
+ end
35
+
36
+ def exclude_sources
37
+ @exclude_sources ||= []
38
+ end
39
+ def set_exclude_sources(x)
40
+ @exclude_sources = x
41
+ self
42
+ end
43
+
44
+ # used when a source file shall have different tcs than the project default
45
+ def tcs4source(source)
46
+ @tcs4source ||= {}
47
+
48
+ if @tcs4source.include?(source)
49
+ @tcs4source[source]
50
+ else
51
+ @tcs
52
+ end
53
+ end
54
+
55
+ def set_tcs4source(x)
56
+ @tcs4source = x
57
+ self
58
+ end
59
+
60
+ def include_string(type)
61
+ @include_string[type] ||= ""
62
+ end
63
+
64
+ def define_string(type)
65
+ @define_string[type] ||= ""
66
+ end
67
+
68
+ def calc_compiler_strings()
69
+ @include_string = {}
70
+ @define_string = {}
71
+
72
+ @incArray = local_includes.dup
73
+ @incArray.concat(includes)
74
+
75
+ if Rake::application.deriveIncludes
76
+ all_dependencies.each_with_index do |d,i|
77
+ next if not HasIncludes === d
78
+ next if i == 0
79
+ prefix = File.rel_from_to_project(@project_dir,d.project_dir)
80
+ next if not prefix
81
+ @incArray.concat(d.includes.map {|inc| File.add_prefix(prefix,inc)})
82
+ end
83
+ @incArray.uniq!
84
+ end
85
+
86
+ [:CPP, :C, :ASM].each do |type|
87
+ @include_string[type] = get_include_string(@tcs, type)
88
+ @define_string[type] = get_define_string(@tcs, type)
89
+ end
90
+ end
91
+
92
+ def get_include_string(tcs, type)
93
+ @incArray.map {|k| "#{tcs[:COMPILER][type][:INCLUDE_PATH_FLAG]}#{k}"}
94
+ end
95
+
96
+ def get_define_string(tcs, type)
97
+ tcs[:COMPILER][type][:DEFINES].map {|k| "#{tcs[:COMPILER][type][:DEFINE_FLAG]}#{k}"}
98
+ end
99
+
100
+ def get_object_file(sourceRel)
101
+ parts = [@output_dir]
102
+ if @output_dir_abs
103
+ parts = [@output_dir_relPath] if @output_dir_relPath
104
+ parts << 'objects'
105
+ parts << @name
106
+ end
107
+
108
+ parts << sourceRel.chomp(File.extname(sourceRel))
109
+ File.join(parts) + (Rake::application.preproFlags ? ".i" : ".o")
110
+ end
111
+
112
+ def get_dep_file(object)
113
+ object[0..-3] + ".o.d"
114
+ end
115
+
116
+ def get_source_type(source)
117
+ ex = File.extname(source)
118
+ [:CPP, :C, :ASM].each do |t|
119
+ return t if tcs[:COMPILER][t][:SOURCE_FILE_ENDINGS].include?(ex)
120
+ end
121
+ nil
122
+ end
123
+
124
+ def get_sources_task_name
125
+ "Objects of #{name}"
126
+ end
127
+
128
+ def parse_includes(deps)
129
+ #deps look like "test.o: test.cpp test.h" -> remove .o and .cpp from list
130
+ return deps.gsub(/\\\n/,'').split()[2..-1]
131
+ end
132
+
133
+ def convert_depfile(depfile)
134
+ deps_string = read_file_or_empty_string(depfile)
135
+ deps = parse_includes(deps_string)
136
+ if deps.nil?
137
+ return # ok, because next run the source will be recompiled due to invalid depfile
138
+ end
139
+ expanded_deps = deps.map do |d|
140
+ tmp = d.gsub(/[\\]/,'/')
141
+ deps_in_depFiles << tmp
142
+ tmp
143
+ end
144
+
145
+ FileUtils.mkpath File.dirname(depfile)
146
+ File.open(depfile, 'wb') do |f|
147
+ f.write(expanded_deps.to_yaml)
148
+ end
149
+ end
150
+
151
+ def apply_depfile(depfile,outfileTask)
152
+ deps = nil
153
+ begin
154
+ deps = YAML.load_file(depfile)
155
+ deps.each do |d|
156
+ deps_in_depFiles << d
157
+ f = file d
158
+ f.ignore_missing_file
159
+ end
160
+ outfileTask.enhance(deps)
161
+ rescue
162
+ # may happen if depfile was not converted the last time
163
+ def outfileTask.needed?
164
+ true
165
+ end
166
+ end
167
+ end
168
+
169
+ def create_object_file_tasks()
170
+
171
+ sources_to_build = {}
172
+
173
+ exclude_files = Set.new
174
+ exclude_sources.each do |p|
175
+ if p.include?".."
176
+ Printer.printError "Error: Exclude source file pattern '#{p}' must not include '..'"
177
+ return nil
178
+ end
179
+
180
+ Dir.glob(p).each {|f| exclude_files << f}
181
+ end
182
+ files = Set.new # do not build the same file twice
183
+
184
+ sources.each do |f|
185
+ if f.include?".."
186
+ Printer.printError "Error: Source file '#{f}' must not include '..'"
187
+ return nil
188
+ end
189
+
190
+ next if exclude_files.include?(f)
191
+ next if files.include?(f)
192
+ files << f
193
+ sources_to_build[f] = tcs4source(f)
194
+ end
195
+
196
+ source_patterns.each do |p|
197
+ if p.include?".."
198
+ Printer.printError "Error: Source file pattern '#{p}' must not include '..'"
199
+ return nil
200
+ end
201
+
202
+ globRes = Dir.glob(p)
203
+ if (globRes.length == 0)
204
+ Printer.printWarning "Warning: Source file pattern '#{p}' did not match to any file"
205
+ end
206
+ globRes.each do |f|
207
+ next if exclude_files.include?(f)
208
+ next if files.include?(f)
209
+ files << f
210
+ t = tcs4source(f)
211
+ t = tcs4source(p) if t == nil
212
+ sources_to_build[f] = t
213
+ end
214
+ end
215
+
216
+ ordered = sources_to_build.keys.sort()
217
+ dirs = []
218
+ filemap = {}
219
+ ordered.reverse.each do |o|
220
+ d = File.dirname(o)
221
+ if filemap.include?(d)
222
+ filemap[d] << o
223
+ else
224
+ filemap[d] = [o]
225
+ dirs << d
226
+ end
227
+ end
228
+
229
+ obj_tasks = []
230
+ dirs.each do |d|
231
+ filemap[d].reverse.each do |f|
232
+ obj_task = create_object_file_task(f, sources_to_build[f])
233
+ obj_tasks << obj_task unless obj_task.nil?
234
+ end
235
+ end
236
+ obj_tasks
237
+ end
238
+
239
+ def create_object_file_task(sourceRel, the_tcs)
240
+ if File.is_absolute?(sourceRel)
241
+ sourceRel = File.rel_from_to_project(@project_dir, sourceRel, false)
242
+ end
243
+
244
+ type = get_source_type(sourceRel)
245
+ return nil if type.nil?
246
+
247
+ objectRel = get_object_file(sourceRel)
248
+ @objects << objectRel
249
+ object = File.expand_path(objectRel)
250
+ source = File.expand_path(sourceRel)
251
+
252
+ depStr = ""
253
+ dep_file = nil
254
+ if type != :ASM
255
+ dep_file = get_dep_file(objectRel)
256
+ dep_file = "\""+dep_file+"\"" if dep_file.include?" "
257
+ depStr = the_tcs[:COMPILER][type][:DEP_FLAGS]
258
+ end
259
+
260
+ res = typed_file_task Rake::Task::OBJECT, object => source do
261
+ compiler = the_tcs[:COMPILER][type]
262
+
263
+ if Rake::application.preproFlags and compiler[:PREPRO_FLAGS] == ""
264
+ Printer.printInfo("Info: No preprocessor option available for " + sourceRel)
265
+ else
266
+
267
+ i_array = the_tcs == @tcs ? @include_string[type] : get_include_string(the_tcs, type)
268
+ d_array = the_tcs == @tcs ? @define_string[type] : get_define_string(the_tcs, type)
269
+
270
+ cmd = [compiler[:COMMAND]]
271
+ cmd += compiler[:COMPILE_FLAGS].split(" ")
272
+ if dep_file
273
+ cmd += depStr.split(" ")
274
+ if the_tcs[:COMPILER][type][:DEP_FLAGS_SPACE]
275
+ cmd << dep_file
276
+ else
277
+ cmd[cmd.length-1] << dep_file
278
+ end
279
+ end
280
+ cmd += Cxxproject::Utils::flagSplit(compiler[:FLAGS])
281
+ cmd += i_array
282
+ cmd += d_array
283
+ cmd += (compiler[:OBJECT_FILE_FLAG] + objectRel).split(" ")
284
+ cmd += compiler[:PREPRO_FLAGS].split(" ") if Rake::application.preproFlags
285
+ cmd << sourceRel
286
+
287
+ if Cxxproject::Utils.old_ruby?
288
+ cmd.map! {|c| ((c.include?" ") ? ("\""+c+"\"") : c )}
289
+ cmdLine = cmd.join(" ")
290
+ if cmdLine.length > 8000
291
+ inputName = objectRel+".tmp"
292
+ File.open(inputName,"wb") { |f| f.write(cmd[1..-1].join(" ")) }
293
+ inputName = "\""+inputName+"\"" if inputName.include?" "
294
+ consoleOutput = `#{compiler[:COMMAND] + " @" + inputName}`
295
+ else
296
+ consoleOutput = `#{cmd.join(" ")} 2>&1`
297
+ end
298
+ else
299
+ rd, wr = IO.pipe
300
+ cmd << {
301
+ :err=>wr,
302
+ :out=>wr
303
+ }
304
+ sp = spawn(*cmd)
305
+ cmd.pop
306
+ consoleOutput = ProcessHelper.readOutput(sp, rd, wr)
307
+ end
308
+
309
+ process_result(cmd, consoleOutput, compiler[:ERROR_PARSER], "Compiling #{sourceRel}")
310
+
311
+ convert_depfile(dep_file) if dep_file
312
+
313
+ check_config_file()
314
+ end
315
+ end
316
+ enhance_with_additional_files(res)
317
+ add_output_dir_dependency(object, res, false)
318
+ apply_depfile(dep_file, res) if depStr != ""
319
+ res
320
+ end
321
+
322
+ def enhance_with_additional_files(task)
323
+ task.enhance(file_dependencies)
324
+ task.enhance(@config_files)
325
+ end
326
+
327
+ def process_console_output(console_output, error_parser)
328
+ ret = false
329
+ if not console_output.empty?
330
+ if error_parser
331
+ begin
332
+ error_descs, console_output_full = error_parser.scan_lines(console_output, @project_dir)
333
+
334
+ console_output = console_output_full if Rake::application.consoleOutput_fullnames
335
+
336
+ ret = error_descs.any? { |e| e.severity == ErrorParser::SEVERITY_ERROR }
337
+
338
+ console_output.gsub!(/[\r]/, "")
339
+ highlighter = @tcs[:CONSOLE_HIGHLIGHTER]
340
+ if (highlighter and highlighter.enabled?)
341
+ puts highlighter.format(console_output, error_descs, error_parser)
342
+ else
343
+ puts console_output
344
+ end
345
+
346
+ Rake.application.idei.set_errors(error_descs)
347
+ rescue Exception => e
348
+ Printer.printWarning "Parsing output failed (maybe language not set to English?): " + e.message
349
+ puts "Original output:"
350
+ puts console_output
351
+ end
352
+ end
353
+ end
354
+ ret
355
+ end
356
+
357
+ def prepare_tasks_for_objects
358
+ if (@output_dir_abs)
359
+ CLEAN.include(@output_dir + "/objects/" + @name)
360
+ end
361
+
362
+ @objects = []
363
+ t = multitask get_sources_task_name
364
+ t.type = Rake::Task::SOURCEMULTI
365
+ t.transparent_timestamp = true
366
+ t.set_building_block(self)
367
+ t
368
+ end
369
+
370
+ end
371
+ end