cxxproject 0.5.48 → 0.5.59

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.
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