cxxproject 0.2 → 0.4.6

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 (57) hide show
  1. data/Rakefile.rb +55 -33
  2. data/bin/cxx +10 -0
  3. data/lib/cxxproject/buildingblocks/binary_library.rb +16 -0
  4. data/lib/cxxproject/buildingblocks/building_block.rb +93 -0
  5. data/lib/cxxproject/buildingblocks/command_line.rb +30 -0
  6. data/lib/cxxproject/buildingblocks/custom_building_block.rb +17 -0
  7. data/lib/cxxproject/buildingblocks/executable.rb +49 -0
  8. data/lib/cxxproject/buildingblocks/has_dependencies_mixin.rb +57 -0
  9. data/lib/cxxproject/buildingblocks/has_libraries_mixin.rb +35 -0
  10. data/lib/cxxproject/buildingblocks/has_sources_mixin.rb +85 -0
  11. data/lib/cxxproject/buildingblocks/makefile.rb +35 -0
  12. data/lib/cxxproject/buildingblocks/module.rb +14 -0
  13. data/lib/cxxproject/buildingblocks/single_source.rb +11 -0
  14. data/lib/cxxproject/buildingblocks/source_library.rb +31 -0
  15. data/lib/cxxproject/extensions/file_ext.rb +47 -0
  16. data/lib/cxxproject/extensions/rake_dirty_ext.rb +30 -0
  17. data/lib/cxxproject/extensions/rake_ext.rb +158 -0
  18. data/lib/cxxproject/extensions/rake_listener_ext.rb +53 -0
  19. data/lib/cxxproject/extensions/stdout_ext.rb +35 -0
  20. data/lib/cxxproject/extensions/string_ext.rb +9 -0
  21. data/lib/cxxproject/task_maker.rb +418 -0
  22. data/lib/cxxproject/testinstanceeval.rb +65 -0
  23. data/lib/cxxproject/toolchain/base.rb +98 -0
  24. data/lib/cxxproject/toolchain/diab.rb +47 -0
  25. data/lib/cxxproject/toolchain/gcc.rb +39 -0
  26. data/lib/cxxproject/toolchain/provider.rb +18 -0
  27. data/lib/cxxproject/torake/compiler.rb +10 -0
  28. data/lib/cxxproject/torake.rb +152 -0
  29. data/lib/cxxproject/utils/dot/building_block_graph_writer.rb +19 -0
  30. data/lib/cxxproject/utils/dot/graph_writer.rb +53 -0
  31. data/lib/cxxproject/utils/dot/task_graph_writer.rb +34 -0
  32. data/lib/cxxproject/utils/ubigraph.rb +237 -0
  33. data/lib/cxxproject/{utils.rb → utils/utils.rb} +19 -1
  34. data/lib/cxxproject.rb +13 -223
  35. data/lib/tools/Rakefile.rb.template +10 -0
  36. data/lib/tools/project.rb.template +6 -0
  37. data/lib/tools/projectWizard.rb +44 -0
  38. data/spec/build_dependencies_spec.rb +169 -0
  39. data/spec/building_block_spec.rb +12 -0
  40. data/spec/dir_spec.rb +13 -0
  41. data/spec/project_path_spec.rb +73 -0
  42. data/spec/rake_listener_ext_spec.rb +25 -0
  43. data/spec/string_spec.rb +11 -0
  44. data/spec/testdata/basic/exe12/project.rb +5 -0
  45. data/spec/testdata/basic/lib1/project.rb +5 -0
  46. data/spec/testdata/basic/lib2/project.rb +8 -0
  47. data/spec/testdata/multiple_levels/libs/lib1/project.rb +5 -0
  48. data/spec/testdata/multiple_levels/libs/lib2/project.rb +19 -0
  49. data/spec/testdata/multiple_levels/mainproject/basic/project.rb +8 -0
  50. data/spec/testdata/onlyOneHeader/Rakefile.rb +4 -0
  51. data/spec/testdata/onlyOneHeader/project.rb +4 -0
  52. metadata +83 -19
  53. data/lib/cxxproject/compiler.rb +0 -80
  54. data/lib/cxxproject/dependencies.rb +0 -41
  55. data/spec/dependencies_spec.rb +0 -19
  56. /data/lib/cxxproject/{gcccompiler.rb → torake/gcccompiler.rb} +0 -0
  57. /data/lib/cxxproject/{osxcompiler.rb → torake/osxcompiler.rb} +0 -0
@@ -0,0 +1,237 @@
1
+ begin
2
+
3
+ require 'rubigraph'
4
+
5
+ def apply?(name)
6
+ name.match(/.*\.apply\Z/) != nil
7
+ end
8
+
9
+
10
+ module Rubigraph
11
+ class Vertex
12
+ alias_method :initialize_original, :initialize
13
+ def initialize(id = nil)
14
+ if id != nil
15
+ @id = id
16
+ else
17
+ initialize_original
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ class IdsAndEdges
24
+ attr_reader :ids, :edges
25
+ def initialize
26
+ @ids = Hash.new
27
+ @edges = Hash.new
28
+ end
29
+ end
30
+
31
+ class V
32
+
33
+ def self.shutdown
34
+ File.open('id_cache', 'w') do |f|
35
+ f.write(@@ids_and_edges.to_yaml)
36
+ end
37
+ end
38
+
39
+ def self.reset
40
+ begin
41
+ File.delete('id_cache')
42
+ rescue StandardError => e
43
+ puts e
44
+ puts 'problem deleting id_cache'
45
+ end
46
+ @@ids_and_edges = IdsAndEdges.new
47
+ end
48
+
49
+ def self.startup
50
+ begin
51
+ @@ids_and_edges = YAML.load_file('id_cache')
52
+ rescue
53
+ @@ids_and_edges = IdsAndEdges.new
54
+ end
55
+ end
56
+
57
+ attr_reader :v
58
+
59
+ def initialize(name)
60
+ h = @@ids_and_edges.ids
61
+ id = h[name]
62
+ if !id
63
+ @v = Rubigraph::Vertex.new
64
+ @@ids_and_edges.ids()[name] = @v.id
65
+ else
66
+ @v = Rubigraph::Vertex.new(id)
67
+ end
68
+ end
69
+ def self.create_edge(edge_and_task1, edge_and_task2)
70
+ complete_name = "#{edge_and_task1[:task].name}->#{edge_and_task2[:task].name}"
71
+ if @@ids_and_edges.edges.has_key?(complete_name)
72
+ return nil
73
+ else
74
+ e = Rubigraph::Edge.new(edge_and_task1[:vertex].v, edge_and_task2[:vertex].v)
75
+ @@ids_and_edges.edges[complete_name] = true
76
+ return e
77
+ end
78
+ end
79
+ end
80
+
81
+ class UbiGraphSupport
82
+
83
+ def object?(name)
84
+ name.match(/.*\.o\Z/) != nil
85
+ end
86
+
87
+ def exe?(name)
88
+ name.match(/.*\.exe\Z/) != nil
89
+ end
90
+ def library?(name)
91
+ name.match(/.*\.a\Z/) != nil
92
+ end
93
+ def multitask?(name)
94
+ name.index("Sources") == 0
95
+ end
96
+ def interesting?(name)
97
+ exe?(name) || object?(name) || library?(name) || multitask?(name)
98
+ end
99
+
100
+ def initialize
101
+ Rake::Task.tasks.each do |t|
102
+ if apply?(t.name)
103
+ t.invoke
104
+ end
105
+ end
106
+
107
+ interesting_tasks = Rake::Task.tasks.select { |i| interesting?(i.name) }
108
+ @vertices = {}
109
+
110
+ # create vertices
111
+ interesting_tasks.each do |task|
112
+ v = V.new(task.name)
113
+ @vertices[task.name] = {:vertex=>v, :task=>task}
114
+ end
115
+
116
+ # create edges
117
+ interesting_tasks.each do |task|
118
+ name = task.name
119
+ v1 = @vertices[name]
120
+ task.prerequisites.each do |p|
121
+ v2 = @vertices[p]
122
+ if (v2 != nil)
123
+ e = V.create_edge(v1, v2)
124
+ e.width=2 if e
125
+ end
126
+ end
127
+ end
128
+
129
+ @vertices.each do |k, value|
130
+ v = value[:vertex]
131
+ v.v.label = k
132
+ set_attributes(v, k)
133
+ end
134
+
135
+ end
136
+
137
+ def update_colors
138
+ @vertices.each_key do |k|
139
+ set_attributes(v, k)
140
+ end
141
+ end
142
+
143
+ def set_attributes(v, name)
144
+ v.v.color = state2color(name)
145
+ v.v.shape = name2shape(name)
146
+ v.v.size = name2size(name)
147
+ end
148
+
149
+ def name2shape(name)
150
+ if object?(name)
151
+ return 'cube'
152
+ elsif exe?(name)
153
+ return 'sphere'
154
+ elsif multitask?(name)
155
+ return 'torus'
156
+ else
157
+ return 'octahedron'
158
+ end
159
+ end
160
+ def name2size(name)
161
+ if object?(name)
162
+ return 0.7
163
+ elsif exe?(name)
164
+ return 1.2
165
+ else
166
+ return 1.0
167
+ end
168
+ end
169
+ def state2color(name)
170
+ t = @vertices[name][:task]
171
+ begin
172
+ if t.dirty?
173
+ return '#ff0000'
174
+ else
175
+ return '#00ff00'
176
+ end
177
+ rescue StandardError => bang
178
+ puts bang
179
+ return '#ff00ff'
180
+ end
181
+ end
182
+
183
+ def update(name, color)
184
+ @vertices[name][:vertex].v.color = color if @vertices[name]
185
+ end
186
+
187
+ YELLOW = '#ffff00'
188
+ def before_prerequisites(name)
189
+ update(name, YELLOW)
190
+ end
191
+
192
+ ORANGE = '#ff7f00'
193
+ def after_prerequisites(name)
194
+ update(name, ORANGE)
195
+ end
196
+
197
+ BLUE = '#0000ff'
198
+ def before_execute(name)
199
+ update(name, BLUE)
200
+ end
201
+
202
+ GREEN = '#00ff00'
203
+ def after_execute(name)
204
+ update(name, GREEN)
205
+ end
206
+ end
207
+
208
+ namespace :rubygraph do
209
+ task :init do
210
+ Rubigraph.init
211
+ V.startup
212
+ at_exit do
213
+ V.shutdown
214
+ end
215
+ end
216
+
217
+ desc 'clear rubygraph'
218
+ task :clear => :init do
219
+ Rubigraph.clear
220
+ V.reset
221
+ end
222
+
223
+ desc 'update rubygraph'
224
+ task :update => :init do
225
+ begin
226
+ require 'cxxproject/extensions/rake_listener_ext'
227
+ require 'cxxproject/extensions/rake_dirty_ext'
228
+ Rake::add_listener(UbiGraphSupport.new)
229
+ rescue StandardError => e
230
+ puts e
231
+ end
232
+ end
233
+ end
234
+
235
+ rescue Exception => e
236
+ puts e
237
+ end
@@ -1,15 +1,33 @@
1
-
1
+ # Simple helper query the operating system we are running in
2
2
  module OS
3
+
4
+ # Is it windows
3
5
  def OS.windows?
4
6
  (RUBY_PLATFORM =~ /cygwin|mswin|mingw|bccwin|wince|emx/) != nil
5
7
  end
8
+
9
+ # Is it osx
6
10
  def OS.mac?
7
11
  (RUBY_PLATFORM =~ /darwin/) != nil
8
12
  end
13
+
14
+ # Is it kind of unix
9
15
  def OS.unix?
10
16
  !OS.windows?
11
17
  end
18
+
19
+ # Is it linux
12
20
  def OS.linux?
13
21
  OS.unix? and not OS.mac?
14
22
  end
23
+
15
24
  end
25
+
26
+ module Utils
27
+
28
+ def self.deep_copy(x)
29
+ Marshal.load(Marshal.dump(x))
30
+ end
31
+
32
+
33
+ end
data/lib/cxxproject.rb CHANGED
@@ -1,227 +1,17 @@
1
+ # Just the default file wich is auto-required in the gem and which requires all needed stuff
2
+ require 'rubygems'
3
+ require 'yaml'
1
4
  require 'rake/clean'
2
- require 'cxxproject/utils'
3
- require 'cxxproject/dependencies'
4
- require 'cxxproject/compiler'
5
- require 'cxxproject/gcccompiler'
6
- require 'cxxproject/osxcompiler'
7
5
 
8
- module OS
9
- def OS.windows?
10
- (RUBY_PLATFORM =~ /cygwin|mswin|mingw|bccwin|wince|emx/) != nil
11
- end
12
- def OS.mac?
13
- (RUBY_PLATFORM =~ /darwin/) != nil
14
- end
15
- def OS.unix?
16
- !OS.windows?
17
- end
18
- def OS.linux?
19
- OS.unix? and not OS.mac?
20
- end
21
- end
6
+ require 'cxxproject/extensions/string_ext'
7
+ require 'cxxproject/task_maker'
8
+ require 'cxxproject/utils/utils'
9
+ require 'cxxproject/torake'
10
+ require 'cxxproject/task_maker'
11
+ require 'cxxproject/torake/compiler'
12
+ require 'cxxproject/torake/gcccompiler'
13
+ require 'cxxproject/torake/osxcompiler'
14
+ require 'cxxproject/utils/ubigraph'
22
15
 
23
- ALL_BUILDING_BLOCKS = {}
16
+ include Cxxproject::Toolchain
24
17
 
25
- ALL = FileList.new
26
-
27
- class BuildingBlock
28
- attr_accessor :name, :base, :dependencies
29
- def initialize(name)
30
- @name = name
31
- @dependencies = []
32
- ALL_BUILDING_BLOCKS[@name] = self
33
- end
34
- def to_s
35
- inspect
36
- end
37
- end
38
-
39
- class LibraryBuildingBlock < BuildingBlock
40
- attr_accessor :includes
41
- def initialize(name)
42
- super
43
- @includes = ['.']
44
- end
45
- end
46
-
47
- class SourceBuildingBlock < LibraryBuildingBlock
48
- attr_accessor :sources
49
-
50
- def initialize(name)
51
- super(name)
52
- @sources = []
53
- @dependencies = []
54
- end
55
- end
56
-
57
- class SourceLibrary < SourceBuildingBlock
58
- attr_accessor :defines
59
- def initialize(name)
60
- super(name)
61
- @defines = []
62
- end
63
- end
64
-
65
- class Exe < SourceBuildingBlock
66
- def initialize(name)
67
- super(name)
68
- end
69
- end
70
-
71
- class BinaryLibrary < LibraryBuildingBlock
72
- def initialize(name)
73
- super
74
- @includes = ['']
75
- end
76
- end
77
-
78
- class OsxCompiler
79
- def initialize(output_path)
80
- @output_path = output_path
81
- end
82
-
83
- def register(name)
84
- CLEAN.include(name)
85
- ALL.include(name)
86
- end
87
-
88
- def transitive_includes(lib)
89
- res = Dependencies.transitive_dependencies([lib.name]).map do |i|
90
- if (i.instance_of?(BinaryLibrary))
91
- i.includes
92
- else
93
- i.includes.map { |include| File.join(i.base, include) }
94
- end
95
- end
96
- return res.flatten.delete_if{|i|i.size == 0}
97
- end
98
-
99
- def transitive_libs(from)
100
- res = Dependencies.transitive_dependencies([from.name]).delete_if{|i|i.instance_of?(Exe)}.map do |i|
101
- if (i.instance_of?(BinaryLibrary))
102
- "-L/opt/local/lib -l#{i.name}"
103
- else
104
- "osx/lib#{i.name}.a"
105
- end
106
- end
107
- return res
108
- end
109
-
110
- def create_object_file(lib, relative_source)
111
- source = File.join(lib.base, relative_source)
112
- out = File.join(@output_path, "#{source}.o")
113
- outputdir = File.dirname(out)
114
- directory outputdir
115
- register(out)
116
- desc "compiling #{source}"
117
- res = file out => [source, outputdir] do |t|
118
- includes = transitive_includes(lib)
119
- include_string = includes.inject('') { | res, i | "#{res} -I#{i} " }
120
- sh "g++ -c #{source} #{include_string} -o #{t.name}"
121
- end
122
- return res
123
- end
124
-
125
- def static_lib_path(name)
126
- libname = "lib#{name}.a"
127
- fullpath = File.join(@output_path, libname)
128
- return fullpath
129
- end
130
-
131
- def create_source_lib(lib, objects)
132
- fullpath = static_lib_path(lib.name)
133
- command = objects.inject("ar -r #{fullpath}") do |command, o|
134
- "#{command} #{o}"
135
- end
136
- register(fullpath)
137
- deps = objects.dup
138
- deps += lib.dependencies.map {|dep|get_path_for_lib(dep)}
139
- desc "link lib #{lib.name}"
140
- res = file fullpath => deps do
141
- sh command
142
- end
143
- return res
144
- end
145
-
146
- def get_path_for_lib(l)
147
- lib = ALL_BUILDING_BLOCKS[l]
148
- if !lib
149
- raise "could not find buildingblock with name '#{l}'"
150
- end
151
- if (lib.instance_of?(BinaryLibrary))
152
- "/opt/local/lib/lib#{lib.name}.a"
153
- else
154
- static_lib_path(lib.name)
155
- end
156
- end
157
-
158
- def create_exe(exe, objects)
159
- exename = "#{exe.name}.exe"
160
- fullpath = File.join(@output_path, exename)
161
- command = objects.inject("g++ -all_load -o #{fullpath}") do |command, o|
162
- "#{command} #{o}"
163
- end
164
-
165
- dep_paths = exe.dependencies.map {|dep|get_path_for_lib(dep)}
166
- register(fullpath)
167
- deps = objects.dup
168
- deps += dep_paths
169
- desc "link exe #{exe.name}"
170
- res = file fullpath => deps do
171
- sh transitive_libs(exe).inject(command) {|command,l|"#{command} #{l}"}
172
- end
173
- return res
174
- end
175
- end
176
-
177
-
178
- def build_source_lib(lib)
179
- objects = lib.sources.map do |s|
180
- Compiler.create_object_file(lib, File.basename(s))
181
- end
182
- Compiler.create_source_lib(lib, objects)
183
- end
184
-
185
- def build_exe(exe)
186
- objects = exe.sources.map do |s|
187
- Compiler.create_object_file(exe, File.basename(s))
188
- end
189
- Compiler.create_exe(exe, objects)
190
- end
191
-
192
- class CxxProject2Rake
193
-
194
- def initialize(projects)
195
- register_projects(projects)
196
- convert_to_rake
197
- end
198
-
199
- def register_projects(projects)
200
- projects.each do |project_file|
201
- loadContext = Class.new
202
- loadContext.module_eval(File.read(project_file))
203
- c = loadContext.new
204
- raise "no 'define_project' defined in project.rb" unless c.respond_to?(:define_project)
205
- cd File.dirname(project_file) do | base_dir |
206
- project = c.define_project
207
- ALL_BUILDING_BLOCKS[project.name] = project
208
- project.base = base_dir
209
- project.to_s
210
- end
211
- end
212
- end
213
- def convert_to_rake
214
- ALL_BUILDING_BLOCKS.values.each do |building_block|
215
- if (building_block.instance_of?(SourceLibrary)) then
216
- build_source_lib(building_block)
217
- elsif (building_block.instance_of?(Exe)) then
218
- build_exe(building_block)
219
- elsif (building_block.instance_of?(BinaryLibrary)) then
220
- else
221
- raise 'unknown building_block'
222
- end
223
- end
224
- task :default => ALL.to_a do
225
- end
226
- end
227
- end
@@ -0,0 +1,10 @@
1
+ require 'cxxproject'
2
+ BuildDir = "BuildDir"
3
+
4
+ unittest_flags = {
5
+ :DEFINES => ['UNIT_TEST','CPPUNIT_MAIN=main'],
6
+ :FLAGS => "-O0 -g3 -Wall"
7
+ }
8
+ toolchain = Provider.modify_cpp_compiler("GCC", unittest_flags)
9
+ dependent_projects = ['./project.rb']
10
+ CxxProject2Rake.new(dependent_projects, BuildDir, toolchain, './')
@@ -0,0 +1,6 @@
1
+ cxx_configuration do
2
+ <%= building_block %> "<%= name %>",
3
+ :sources => FileList['**/*.cpp'],
4
+ :includes => ['include'],
5
+ :dependencies => []
6
+ end
@@ -0,0 +1,44 @@
1
+ require 'rake'
2
+ require 'erb'
3
+
4
+ def prepare_project(d)
5
+ require 'highline/import'
6
+ if agree("This will create a new cxx-project config in dir \"#{d}\" \nAre you sure you want to continue? [yn] ")
7
+ bb = nil
8
+ choose do |menu|
9
+ menu.prompt = "what building block do you want to start with?"
10
+
11
+ menu.choice(:exe) { bb = "exe" }
12
+ menu.choices(:lib) { bb = "source_lib" }
13
+ end
14
+
15
+ create_project(d, bb)
16
+ else
17
+ say "stopped project creation"
18
+ end
19
+ end
20
+
21
+ def create_project(d, bb)
22
+ rakefile_template = File.join(File.dirname(__FILE__),"..","tools","Rakefile.rb.template")
23
+ projectrb_template = File.join(File.dirname(__FILE__),"..","tools","project.rb.template")
24
+ s1 = IO.read(rakefile_template)
25
+ s2 = IO.read(projectrb_template)
26
+ name = "testme"
27
+ building_block = bb
28
+ template1 = ERB.new s1
29
+ template2 = ERB.new s2
30
+ mkdir_p(d, :verbose => false)
31
+ cd(d,:verbose => false) do
32
+ if ((File.exists? "Rakefile.rb") || (File.exists? "project.rb"))
33
+ abort "cannot create project in this directory, existing files would be overwritten!"
34
+ end
35
+ File.open("Rakefile.rb", 'w') do |f|
36
+ f.write template1.result(binding)
37
+ end
38
+ File.open("project.rb", 'w') do |f|
39
+ f.write template2.result(binding)
40
+ end
41
+ end
42
+ end
43
+
44
+