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
@@ -1,49 +1,244 @@
1
1
  require 'cxxproject/buildingblocks/building_block'
2
2
  require 'cxxproject/buildingblocks/has_libraries_mixin'
3
3
  require 'cxxproject/buildingblocks/has_sources_mixin'
4
+ require 'cxxproject/buildingblocks/has_includes_mixin'
5
+ require 'cxxproject/utils/process'
6
+ require 'cxxproject/utils/utils'
4
7
 
5
- class Executable < BuildingBlock
6
- include HasLibraries
7
- include HasSources
8
+ require 'tmpdir'
9
+ require 'set'
10
+ require 'etc'
8
11
 
9
- attr_reader :linker_script
10
- attr_reader :mapfile
11
- attr_reader :output_file
12
+ module Cxxproject
12
13
 
13
- def set_linker_script(x)
14
- @linker_script = x
15
- self
16
- end
14
+ class Executable < BuildingBlock
15
+ include HasLibraries
16
+ include HasSources
17
+ include HasIncludes
17
18
 
18
- def set_mapfile(x)
19
- @mapfile = x
20
- self
21
- end
19
+ def set_linker_script(x)
20
+ @linker_script = x
21
+ self
22
+ end
22
23
 
23
- # set during creating the task - note: depends on the used tcs
24
- def set_output_file(x)
25
- @output_file = x
26
- self
27
- end
24
+ def set_mapfile(x)
25
+ @mapfile = x
26
+ self
27
+ end
28
+
29
+ def initialize(name)
30
+ super(name)
31
+ @linker_script = nil
32
+ @mapfile = nil
33
+ end
28
34
 
29
- def initialize(name)
30
- super(name)
31
- @linker_script = nil
32
- @mapfile = nil
33
- end
35
+ def set_executable_name(name) # ensure it's relative
36
+ @exe_name = name
37
+ end
34
38
 
35
- def linker_libs_string
36
- @linkerString ||= ""
37
- end
39
+ def get_executable_name() # relative path
40
+ return @exe_name if @exe_name
38
41
 
42
+ parts = [@output_dir]
39
43
 
40
- def get_executable_name()
41
- File.relFromTo(@complete_output_dir + "/" + @name + @tcs[:LINKER][:OUTPUT_ENDING], @project_dir)
42
- end
44
+ if @output_dir_abs
45
+ parts = [@output_dir_relPath] if @output_dir_relPath
46
+ end
43
47
 
44
- def get_task_name()
45
- get_executable_name()
46
- end
48
+ parts << "#{@name}#{@tcs[:LINKER][:OUTPUT_ENDING]}"
49
+
50
+ @exe_name = File.join(parts)
51
+ @exe_name
52
+ end
53
+
54
+ def get_task_name() # full path
55
+ @project_dir + "/" + get_executable_name
56
+ end
57
+
58
+ def collect_unique(array, set)
59
+ ret = []
60
+ array.each do |v|
61
+ if set.add?(v)
62
+ ret << v
63
+ end
64
+ end
65
+ ret
66
+ end
67
+
68
+ def adaptPath(v, d, prefix)
69
+ tmp = nil
70
+ if File.is_absolute?(v)
71
+ tmp = v
72
+ else
73
+ prefix ||= File.rel_from_to_project(@project_dir,d.project_dir)
74
+ tmp = File.add_prefix(prefix, v)
75
+ end
76
+ tmp = "\"" + tmp + "\"" if tmp.include?(" ")
77
+ [tmp, prefix]
78
+ end
79
+
80
+ def linker_lib_string()
81
+ @lib_path_set = Set.new
82
+ @dep_set = Set.new
83
+ calc_linker_lib_string_recursive(self)
84
+ end
85
+
86
+ def calc_linker_lib_string_recursive(d)
87
+ res = []
88
+
89
+ return res if @dep_set.include?d
90
+ @dep_set << d
91
+
92
+ if HasLibraries === d
93
+ prefix = nil
94
+ linker = @tcs[:LINKER]
95
+
96
+ d.lib_elements.each do |elem|
97
+ case elem[0]
98
+ when HasLibraries::LIB
99
+ res << "#{linker[:LIB_FLAG]}#{elem[1]}"
100
+ when HasLibraries::USERLIB
101
+ res << "#{linker[:USER_LIB_FLAG]}#{elem[1]}"
102
+ when HasLibraries::LIB_WITH_PATH
103
+ tmp, prefix = adaptPath(elem[1], d, prefix)
104
+ res << tmp
105
+ when HasLibraries::SEARCH_PATH
106
+ tmp, prefix = adaptPath(elem[1], d, prefix)
107
+ if not @lib_path_set.include?tmp
108
+ @lib_path_set << tmp
109
+ res << "#{linker[:LIB_PATH_FLAG]}#{tmp}"
110
+ end
111
+ when HasLibraries::DEPENDENCY
112
+ if ALL_BUILDING_BLOCKS.include?elem[1]
113
+ bb = ALL_BUILDING_BLOCKS[elem[1]]
114
+ res += calc_linker_lib_string_recursive(bb)
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ res
121
+ end
47
122
 
123
+ # create a task that will link an executable from a set of object files
124
+ #
125
+ def convert_to_rake()
126
+ object_multitask = prepare_tasks_for_objects()
48
127
 
128
+ linker = @tcs[:LINKER]
129
+
130
+ res = typed_file_task Rake::Task::EXECUTABLE, get_task_name => object_multitask do
131
+ Dir.chdir(@project_dir) do
132
+
133
+ cmd = [linker[:COMMAND]] # g++
134
+ cmd += linker[:MUST_FLAGS].split(" ")
135
+ cmd += linker[:FLAGS].gsub(/\"/,"").split(" ") # double quotes within string do not work on windows...
136
+ cmd << linker[:EXE_FLAG]
137
+ cmd << get_executable_name # -o debug/x.exe
138
+ cmd += @objects
139
+ cmd << linker[:SCRIPT] if @linker_script # -T
140
+ cmd << @linker_script if @linker_script # xy/xy.dld
141
+ cmd << linker[:MAP_FILE_FLAG] if @mapfile # -Wl,-m6
142
+ cmd += linker[:LIB_PREFIX_FLAGS].split(" ") # "-Wl,--whole-archive "
143
+ cmd += linker_lib_string
144
+ cmd += linker[:LIB_POSTFIX_FLAGS].split(" ") # "-Wl,--no-whole-archive "
145
+
146
+ mapfileStr = @mapfile ? " >#{@mapfile}" : ""
147
+ if Cxxproject::Utils.old_ruby?
148
+ cmd.map! {|c| ((c.include?" ") ? ("\""+c+"\"") : c )}
149
+
150
+ # TempFile used, because some compilers, e.g. diab, uses ">" for piping to map files:
151
+ cmdLine = cmd.join(" ") + " 2>" + get_temp_filename
152
+ if cmdLine.length > 8000
153
+ inputName = get_executable_name+".tmp"
154
+ File.open(inputName,"wb") { |f| f.write(cmd[1..-1].join(" ")) }
155
+ inputName = "\""+inputName+"\"" if inputName.include?" "
156
+ consoleOutput = `#{linker[:COMMAND] + " @" + inputName + mapfileStr + " 2>" + get_temp_filename}`
157
+ else
158
+ consoleOutput = `#{cmd.join(" ") + mapfileStr + " 2>" + get_temp_filename}`
159
+ end
160
+ consoleOutput.concat(read_file_or_empty_string(get_temp_filename))
161
+ else
162
+ rd, wr = IO.pipe
163
+ cmd << {
164
+ :out=> @mapfile ? "#{@mapfile}" : wr, # > xy.map
165
+ :err=>wr
166
+ }
167
+ sp = spawn(*cmd)
168
+ cmd.pop
169
+
170
+ # for console print
171
+ cmd << " >#{@mapfile}" if @mapfile
172
+ consoleOutput = ProcessHelper.readOutput(sp, rd, wr)
173
+ end
174
+
175
+ process_result(cmd, consoleOutput, linker[:ERROR_PARSER], "Linking #{get_executable_name}")
176
+
177
+ check_config_file()
178
+ end
179
+ end
180
+ res.enhance(@config_files)
181
+ res.enhance([@project_dir + "/" + @linker_script]) if @linker_script
182
+
183
+ add_output_dir_dependency(get_task_name, res, true)
184
+ add_grouping_tasks(get_task_name)
185
+ setup_rake_dependencies(res, object_multitask)
186
+
187
+ # check that all source libs are checked even if they are not a real rake dependency (can happen if "build this project only")
188
+ begin
189
+ libChecker = task get_task_name+"LibChecker" do
190
+ if File.exists?(get_task_name) # otherwise the task will be executed anyway
191
+ all_dependencies.each do |bb|
192
+ if bb and SourceLibrary === bb
193
+ f = bb.get_task_name # = abs path of library
194
+ if not File.exists?(f) or File.mtime(f) > File.mtime(get_task_name)
195
+ def res.needed?
196
+ true
197
+ end
198
+ break
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+ rescue
205
+ def res.needed?
206
+ true
207
+ end
208
+ end
209
+ libChecker.transparent_timestamp = true
210
+ res.enhance([libChecker])
211
+
212
+
213
+ return res
214
+ end
215
+
216
+ def add_grouping_tasks(executable)
217
+ namespace 'exe' do
218
+ desc executable
219
+ task @name => executable
220
+ end
221
+ create_run_task(executable, @name)
222
+ end
223
+
224
+ def create_run_task(executable, name)
225
+ namespace 'run' do
226
+ desc "run executable #{executable}"
227
+ res = task name => executable do |t|
228
+ run_command(t, executable)
229
+ end
230
+ res.type = Rake::Task::RUN
231
+ res
232
+ end
233
+ end
234
+
235
+ def run_command(task, command)
236
+ sh "#{command}"
237
+ end
238
+
239
+ def get_temp_filename
240
+ Dir.tmpdir + "/lake.tmp"
241
+ end
242
+
243
+ end
49
244
  end
@@ -1,57 +1,83 @@
1
- module HasDependencies
1
+ module Cxxproject
2
+ module HasDependencies
2
3
 
3
- def dependencies
4
- @dependencies ||= []
5
- end
6
- def set_dependencies(deps)
7
- @dependencies = deps.map { |dep| dep.instance_of?(String) ? dep : dep.name }
8
- self
9
- end
4
+ def dependencies
5
+ @dependencies ||= []
6
+ end
10
7
 
11
- # if set, includes and libs are taken from this array, not from @dependencies.
12
- # task deps are still taken from @dependencies.
13
- # use case: circular deps are allowed on "include-level", but not on "task-level".
14
- def helper_dependencies
15
- @helper_dependencies ||= []
16
- end
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
17
21
 
18
- def set_helper_dependencies(deps)
19
- @helper_dependencies = deps.map { |dep| dep.instance_of?(String) ? dep : dep.name }
20
- end
22
+ def direct_deps
23
+ return @direct_deps if @direct_deps
21
24
 
22
- # will be calculated at the beginning of creating the building block task
23
- def all_dependencies
24
- @all_dependencies ||= []
25
- end
25
+ @all_dependencies_set = Set.new
26
+ @all_dependencies_set << self
27
+ @all_dependencies = [self]
26
28
 
27
- # inclusive self!!
28
- def calc_transitive_dependencies
29
- deps = [self.name]
30
- @all_dependencies = get_transitive_dependencies_internal(deps)
31
- end
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
32
49
 
33
- def get_transitive_dependencies_internal(deps)
34
- depsToCheck = []
35
- depList = helper_dependencies.length > 0 ? helper_dependencies : dependencies
36
- depList.each do |d|
37
- if not deps.include?d
38
- deps << d
39
- depsToCheck << d
40
50
  end
51
+
52
+ @direct_deps = @all_dependencies.dup
53
+ @direct_deps
41
54
  end
42
55
 
43
- # two-step needed to keep order of dependencies for includes, lib dirs, etc
44
- depsToCheck.each do |d|
45
- begin
46
- raise "ERROR: while reading config file for #{self.name}: dependent building block \"#{d}\" was specified but not found!" unless ALL_BUILDING_BLOCKS[d]
47
- ALL_BUILDING_BLOCKS[d].get_transitive_dependencies_internal(deps)
48
- rescue Exception => e
49
- puts e
50
- exit
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)
51
61
  end
62
+
63
+ @all_deps_calculated = true
64
+ @all_dependencies
52
65
  end
53
- deps
54
66
 
55
- end
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
56
81
 
82
+ end
57
83
  end
@@ -0,0 +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,35 +1,34 @@
1
- module HasLibraries
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
2
12
 
3
- def user_libs
4
- @user_libs ||= []
5
- end
6
- def set_user_libs(x)
7
- @user_libs = x
8
- self
9
- end
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
10
22
 
11
- def libs_to_search
12
- @libs_to_search ||= []
13
- end
14
- def set_libs_to_search(x)
15
- @libs_to_search = x
16
- self
17
- end
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
18
32
 
19
- def lib_searchpaths
20
- @lib_searchpaths ||= []
21
- end
22
- def set_lib_searchpaths(x)
23
- @lib_searchpaths = x
24
- self
25
33
  end
26
-
27
- def libs_with_path
28
- @libs_with_path ||= []
29
- end
30
- def set_libs_with_path(x)
31
- @libs_with_path = x
32
- self
33
- end
34
-
35
34
  end