cxxproject 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile.rb ADDED
@@ -0,0 +1,47 @@
1
+ require 'rake/gempackagetask'
2
+ require 'roodi'
3
+ require 'roodi_task'
4
+ require 'spec/rake/spectask'
5
+
6
+ desc "Default Task"
7
+ task :default => [:package, :roodi]
8
+
9
+ PKG_VERSION = '0.2'
10
+ PKG_FILES = FileList[
11
+ 'lib/**/*.rb',
12
+ 'Rakefile.rb',
13
+ 'spec/**/*.rb'
14
+ # 'doc/**/*'
15
+ ]
16
+
17
+ spec = Gem::Specification.new do |s|
18
+ s.name = 'cxxproject'
19
+ s.version = PKG_VERSION
20
+ s.summary = "Cpp Support for Rake."
21
+ s.description = <<-EOF
22
+ Some more high level building blocks for cpp projects.
23
+ EOF
24
+ s.files = PKG_FILES.to_a
25
+ s.require_path = 'lib'
26
+ s.author = ''
27
+ s.email = ''
28
+ s.homepage = ''
29
+ end
30
+
31
+ RoodiTask.new
32
+ Rake::GemPackageTask.new(spec) {|pkg|}
33
+
34
+ task :gem => [:spec, :roodi]
35
+
36
+ desc "Run all examples"
37
+ Spec::Rake::SpecTask.new() do |t|
38
+ t.spec_files = FileList['spec/**/*.rb']
39
+ end
40
+
41
+ task :default => [:install]
42
+
43
+ desc "install gem globally"
44
+ task :install => :gem do
45
+ sh "gem install pkg/#{spec.name}-#{spec.version}.gem"
46
+ end
47
+
@@ -0,0 +1,80 @@
1
+ class Compiler
2
+ def initialize(output_path)
3
+ @output_path = output_path
4
+ end
5
+
6
+ def include(name)
7
+ CLEAN.include(name)
8
+ # ALL.include(name)
9
+ end
10
+
11
+ def transitive_includes(lib)
12
+ res = Dependencies.transitive_dependencies([lib.name]).map do |i|
13
+ i.includes.map { |include| File.join(i.base, include) }
14
+ end
15
+ return res.flatten
16
+ end
17
+ def transitive_libs(from)
18
+ res = Dependencies.transitive_dependencies([from.name]).delete_if{|i|i.instance_of?(Exe)}.map do |i|
19
+ "#{@output_path}/lib#{i.name}.a"
20
+ end
21
+ return res
22
+ end
23
+
24
+ def create_object_file(lib, relative_source)
25
+ source = File.join(lib.base, relative_source)
26
+ out = File.join(@output_path, "#{source}.o")
27
+ outputdir = File.dirname(out)
28
+ directory outputdir
29
+ include(out)
30
+ desc "compiling #{source}"
31
+ res = file out => [source, outputdir] do |t|
32
+ includes = transitive_includes(lib)
33
+ include_string = includes.inject('') { | res, i | "#{res} -I#{i} " }
34
+ sh "g++ -c #{source} #{include_string} -o #{t.name}"
35
+ end
36
+ return res
37
+ end
38
+
39
+ def static_lib_path(name)
40
+ libname = "lib#{name}.a"
41
+ fullpath = File.join(@output_path, libname)
42
+ return fullpath
43
+ end
44
+
45
+ def create_source_lib(lib, objects)
46
+ fullpath = static_lib_path(lib.name)
47
+ command = objects.inject("ar -r #{fullpath}") do |command, o|
48
+ "#{command} #{o}"
49
+ end
50
+ include(fullpath)
51
+ deps = objects.dup
52
+ deps += lib.dependencies.map {|dep|static_lib_path(dep)}
53
+ desc "link lib #{lib.name}"
54
+ res = file fullpath => deps do
55
+ sh command
56
+ end
57
+ return res
58
+ end
59
+
60
+ def create_exe(exe, objects)
61
+ exename = "#{exe.name}.exe"
62
+ fullpath = File.join(@output_path, exename)
63
+ command = objects.inject("g++ -o #{fullpath}") do |command, o|
64
+ "#{command} #{o}"
65
+ end
66
+
67
+ dep_paths = exe.dependencies.map {|dep|static_lib_path(dep)}
68
+ include(fullpath)
69
+ deps = objects.dup
70
+ deps += dep_paths
71
+ desc "link exe #{exe.name}"
72
+ res = file fullpath => deps do
73
+ libs = transitive_libs(exe)
74
+ command = libs.inject(command) { |command, l| "#{command} #{l}" }
75
+ sh command
76
+ end
77
+ return res
78
+ end
79
+ end
80
+
@@ -0,0 +1,41 @@
1
+ class Dependencies
2
+
3
+ attr_reader :all_libs
4
+
5
+ def initialize(lib_strings)
6
+ @all_libs = []
7
+ lib_strings.each do |lib_string|
8
+ add(lib_string)
9
+ end
10
+ end
11
+
12
+ def self.transitive_dependencies(lib)
13
+ return Dependencies.new(lib).all_libs
14
+ end
15
+
16
+
17
+
18
+ def self.tr_libs(libs)
19
+ return LibHelper.new(libs).all_libs
20
+ end
21
+
22
+ def add_unique(lib)
23
+ @all_libs.delete(lib)
24
+ @all_libs.push(lib)
25
+ end
26
+
27
+ def add(lib)
28
+ bb = ALL_BUILDING_BLOCKS[lib]
29
+ if !bb
30
+ raise "dependency not found #{lib}"
31
+ end
32
+ add_unique(bb)
33
+ bb.dependencies.each do |dep|
34
+ add(dep)
35
+ end
36
+ end
37
+
38
+
39
+
40
+
41
+ end
@@ -0,0 +1,7 @@
1
+
2
+ class GccCompiler < Compiler
3
+ def initialize(output_path)
4
+ super(output_path)
5
+ end
6
+ end
7
+
@@ -0,0 +1,7 @@
1
+
2
+ class OsxCompiler < Compiler
3
+ def initialize(output_path)
4
+ super(output_path)
5
+ end
6
+ end
7
+
@@ -0,0 +1,15 @@
1
+
2
+ module OS
3
+ def OS.windows?
4
+ (RUBY_PLATFORM =~ /cygwin|mswin|mingw|bccwin|wince|emx/) != nil
5
+ end
6
+ def OS.mac?
7
+ (RUBY_PLATFORM =~ /darwin/) != nil
8
+ end
9
+ def OS.unix?
10
+ !OS.windows?
11
+ end
12
+ def OS.linux?
13
+ OS.unix? and not OS.mac?
14
+ end
15
+ end
data/lib/cxxproject.rb ADDED
@@ -0,0 +1,227 @@
1
+ require 'rake/clean'
2
+ require 'cxxproject/utils'
3
+ require 'cxxproject/dependencies'
4
+ require 'cxxproject/compiler'
5
+ require 'cxxproject/gcccompiler'
6
+ require 'cxxproject/osxcompiler'
7
+
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
22
+
23
+ ALL_BUILDING_BLOCKS = {}
24
+
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,19 @@
1
+ require 'cxxproject'
2
+
3
+ describe Dependencies do
4
+ it 'should build the right dependency-chain' do
5
+ lib1 = SourceLibrary.new('1')
6
+ lib2 = SourceLibrary.new('2')
7
+ lib2.dependencies = ['1']
8
+ lib3 = SourceLibrary.new('3')
9
+ lib3.dependencies = ['1']
10
+ lib4 = SourceLibrary.new('4')
11
+ lib4.dependencies = ['2', '3']
12
+ deps = Dependencies.transitive_dependencies(['4'])
13
+ deps.map {|d|d.name}.should == ['4', '2', '3', '1']
14
+ end
15
+ it 'should create .d files' do
16
+ pending
17
+ 1.should == 0
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cxxproject
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ version: "0.2"
9
+ platform: ruby
10
+ authors:
11
+ - ""
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-04-09 00:00:00 +02:00
17
+ default_executable:
18
+ dependencies: []
19
+
20
+ description: " Some more high level building blocks for cpp projects.\n"
21
+ email: ""
22
+ executables: []
23
+
24
+ extensions: []
25
+
26
+ extra_rdoc_files: []
27
+
28
+ files:
29
+ - lib/cxxproject/compiler.rb
30
+ - lib/cxxproject/dependencies.rb
31
+ - lib/cxxproject/gcccompiler.rb
32
+ - lib/cxxproject/osxcompiler.rb
33
+ - lib/cxxproject/utils.rb
34
+ - lib/cxxproject.rb
35
+ - Rakefile.rb
36
+ - spec/dependencies_spec.rb
37
+ has_rdoc: true
38
+ homepage: ""
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ segments:
51
+ - 0
52
+ version: "0"
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.6
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Cpp Support for Rake.
67
+ test_files: []
68
+