cxxproject 0.2
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.
- data/Rakefile.rb +47 -0
- data/lib/cxxproject/compiler.rb +80 -0
- data/lib/cxxproject/dependencies.rb +41 -0
- data/lib/cxxproject/gcccompiler.rb +7 -0
- data/lib/cxxproject/osxcompiler.rb +7 -0
- data/lib/cxxproject/utils.rb +15 -0
- data/lib/cxxproject.rb +227 -0
- data/spec/dependencies_spec.rb +19 -0
- metadata +68 -0
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,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
|
+
|