rub 0.4.0
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.
- checksums.yaml +7 -0
- data/lib/rub/c.rb +276 -0
- data/lib/rub/d.rb +252 -0
- data/lib/rub/dirs.rb +30 -0
- data/lib/rub/help.rb +178 -0
- data/lib/rub/init.rb +91 -0
- data/lib/rub/l.rb +40 -0
- data/lib/rub/l/c.rb +476 -0
- data/lib/rub/l/c/compiler/clang.rb +94 -0
- data/lib/rub/l/c/compiler/gcc.rb +94 -0
- data/lib/rub/l/ld.rb +254 -0
- data/lib/rub/l/ld/linker/clang.rb +89 -0
- data/lib/rub/l/ld/linker/gcc.rb +89 -0
- data/lib/rub/l/ld/linker/ld.rb +91 -0
- data/lib/rub/l/template.rb +92 -0
- data/lib/rub/l/test.rb +256 -0
- data/lib/rub/l/util.rb +163 -0
- data/lib/rub/r.rb +42 -0
- data/lib/rub/r/command.rb +293 -0
- data/lib/rub/r/env.rb +71 -0
- data/lib/rub/r/i/commandline.rb +192 -0
- data/lib/rub/r/i/runner.rb +78 -0
- data/lib/rub/r/persist.rb +71 -0
- data/lib/rub/r/target.rb +250 -0
- data/lib/rub/r/targetgenerator.rb +80 -0
- data/lib/rub/r/tool.rb +159 -0
- data/lib/rub/r/version-git.rb +62 -0
- data/lib/rub/r/version.rb +145 -0
- metadata +127 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
# Copyright 2013 Kevin Cox
|
2
|
+
|
3
|
+
################################################################################
|
4
|
+
# #
|
5
|
+
# This software is provided 'as-is', without any express or implied #
|
6
|
+
# warranty. In no event will the authors be held liable for any damages #
|
7
|
+
# arising from the use of this software. #
|
8
|
+
# #
|
9
|
+
# Permission is granted to anyone to use this software for any purpose, #
|
10
|
+
# including commercial applications, and to alter it and redistribute it #
|
11
|
+
# freely, subject to the following restrictions: #
|
12
|
+
# #
|
13
|
+
# 1. The origin of this software must not be misrepresented; you must not #
|
14
|
+
# claim that you wrote the original software. If you use this software in #
|
15
|
+
# a product, an acknowledgment in the product documentation would be #
|
16
|
+
# appreciated but is not required. #
|
17
|
+
# #
|
18
|
+
# 2. Altered source versions must be plainly marked as such, and must not be #
|
19
|
+
# misrepresented as being the original software. #
|
20
|
+
# #
|
21
|
+
# 3. This notice may not be removed or altered from any source distribution. #
|
22
|
+
# #
|
23
|
+
################################################################################
|
24
|
+
|
25
|
+
module L::LD
|
26
|
+
LinkerGCC = Linker.clone
|
27
|
+
module LinkerGCC
|
28
|
+
def self.name
|
29
|
+
:gcc
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.available?
|
33
|
+
!!find
|
34
|
+
end
|
35
|
+
|
36
|
+
# Find the linker executable.
|
37
|
+
# @return [Pathname,nil] The path of the executable.
|
38
|
+
def self.find
|
39
|
+
C.find_command 'gcc'
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.link_command(opt, files, libs, out, format)
|
43
|
+
files = R::Tool.make_set_paths files
|
44
|
+
libs = R::Tool.make_set libs
|
45
|
+
out = C.path(out)
|
46
|
+
|
47
|
+
c = [find, "-o#{out}"]
|
48
|
+
|
49
|
+
c << opt.args
|
50
|
+
|
51
|
+
c << case format
|
52
|
+
when :exe
|
53
|
+
[]
|
54
|
+
when :shared
|
55
|
+
['-shared']
|
56
|
+
else
|
57
|
+
raise "Unknown/unsupported output #{format}."
|
58
|
+
end
|
59
|
+
|
60
|
+
c << case opt.optimize
|
61
|
+
when :none
|
62
|
+
D:debug ? '-Og' : '-O0'
|
63
|
+
when :some
|
64
|
+
'-O1'
|
65
|
+
when :full
|
66
|
+
'-O2'
|
67
|
+
when :max
|
68
|
+
'-O3'
|
69
|
+
else
|
70
|
+
raise "Invalid optimization level #{opt.optimize}."
|
71
|
+
end
|
72
|
+
|
73
|
+
c << if opt.static
|
74
|
+
'-static'
|
75
|
+
else
|
76
|
+
[]
|
77
|
+
end
|
78
|
+
|
79
|
+
c << opt.library_dirs.map{|d| "-L#{d}"}
|
80
|
+
|
81
|
+
#c << libs.map{|l| "-l#{l}" }
|
82
|
+
c << libs.map{|l| "#{l}" }
|
83
|
+
c << files.to_a
|
84
|
+
|
85
|
+
c.flatten
|
86
|
+
end
|
87
|
+
end
|
88
|
+
L::LD.linkers[:gcc] = LinkerGCC
|
89
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# Copyright 2013 Kevin Cox
|
2
|
+
|
3
|
+
################################################################################
|
4
|
+
# #
|
5
|
+
# This software is provided 'as-is', without any express or implied #
|
6
|
+
# warranty. In no event will the authors be held liable for any damages #
|
7
|
+
# arising from the use of this software. #
|
8
|
+
# #
|
9
|
+
# Permission is granted to anyone to use this software for any purpose, #
|
10
|
+
# including commercial applications, and to alter it and redistribute it #
|
11
|
+
# freely, subject to the following restrictions: #
|
12
|
+
# #
|
13
|
+
# 1. The origin of this software must not be misrepresented; you must not #
|
14
|
+
# claim that you wrote the original software. If you use this software in #
|
15
|
+
# a product, an acknowledgment in the product documentation would be #
|
16
|
+
# appreciated but is not required. #
|
17
|
+
# #
|
18
|
+
# 2. Altered source versions must be plainly marked as such, and must not be #
|
19
|
+
# misrepresented as being the original software. #
|
20
|
+
# #
|
21
|
+
# 3. This notice may not be removed or altered from any source distribution. #
|
22
|
+
# #
|
23
|
+
################################################################################
|
24
|
+
|
25
|
+
module L::LD
|
26
|
+
LinkerLD = Linker.clone
|
27
|
+
module LinkerLD
|
28
|
+
def self.name
|
29
|
+
:ld
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.available?
|
33
|
+
!!find
|
34
|
+
end
|
35
|
+
|
36
|
+
# Find the linker command.
|
37
|
+
# @return [Pathname,nil] The command.
|
38
|
+
def self.find
|
39
|
+
C.find_command 'ld'
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.link_command(opt, files, libs, out, format)
|
43
|
+
files = R::Tool.make_set_paths files
|
44
|
+
libs = R::Tool.make_set libs
|
45
|
+
out = C.path out
|
46
|
+
|
47
|
+
c = [find, "-o#{out}"]
|
48
|
+
|
49
|
+
c << opt.args
|
50
|
+
|
51
|
+
c << case format
|
52
|
+
when :exe
|
53
|
+
[]
|
54
|
+
when :shared
|
55
|
+
['-shared']
|
56
|
+
else
|
57
|
+
raise "Unknown/unsupported output #{format}."
|
58
|
+
end
|
59
|
+
|
60
|
+
c << case opt.optimize
|
61
|
+
when :none
|
62
|
+
'-O0'
|
63
|
+
when :some
|
64
|
+
'-O0'
|
65
|
+
when :full
|
66
|
+
'-O1'
|
67
|
+
when :max
|
68
|
+
'-O9'
|
69
|
+
else
|
70
|
+
raise "Invalid optimization level #{opt.optimize}."
|
71
|
+
end
|
72
|
+
|
73
|
+
c << if opt.static
|
74
|
+
'-static'
|
75
|
+
else
|
76
|
+
[]
|
77
|
+
end
|
78
|
+
|
79
|
+
c << opt.library_dirs.map{|d| "-L#{d}"}
|
80
|
+
|
81
|
+
#c << libs.map{|l| "-l#{l}" }
|
82
|
+
c << libs.map{|l| "#{l}" }
|
83
|
+
c << files.to_a
|
84
|
+
|
85
|
+
c.flatten
|
86
|
+
end
|
87
|
+
end
|
88
|
+
L::LD.linkers[:ld] = LinkerLD
|
89
|
+
|
90
|
+
D.append(:l_ld_linker, :ld)
|
91
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# Copyright 2013 Kevin Cox
|
2
|
+
|
3
|
+
################################################################################
|
4
|
+
# #
|
5
|
+
# This software is provided 'as-is', without any express or implied #
|
6
|
+
# warranty. In no event will the authors be held liable for any damages #
|
7
|
+
# arising from the use of this software. #
|
8
|
+
# #
|
9
|
+
# Permission is granted to anyone to use this software for any purpose, #
|
10
|
+
# including commercial applications, and to alter it and redistribute it #
|
11
|
+
# freely, subject to the following restrictions: #
|
12
|
+
# #
|
13
|
+
# 1. The origin of this software must not be misrepresented; you must not #
|
14
|
+
# claim that you wrote the original software. If you use this software in #
|
15
|
+
# a product, an acknowledgment in the product documentation would be #
|
16
|
+
# appreciated but is not required. #
|
17
|
+
# #
|
18
|
+
# 2. Altered source versions must be plainly marked as such, and must not be #
|
19
|
+
# misrepresented as being the original software. #
|
20
|
+
# #
|
21
|
+
# 3. This notice may not be removed or altered from any source distribution. #
|
22
|
+
# #
|
23
|
+
################################################################################
|
24
|
+
|
25
|
+
require 'erb'
|
26
|
+
require 'ostruct'
|
27
|
+
|
28
|
+
# Templates for generating files.
|
29
|
+
module L::Template
|
30
|
+
class Renderer < OpenStruct
|
31
|
+
def render(template, filename: 'ERB String')
|
32
|
+
t = ERB.new(template, nil, '-')
|
33
|
+
t.filename = filename.to_s
|
34
|
+
t.result(binding)
|
35
|
+
end
|
36
|
+
def render_file(f)
|
37
|
+
f = C.path f
|
38
|
+
|
39
|
+
render f.read, filename: f
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class TargetRenderer < R::TargetSmart
|
44
|
+
def initialize(inp, out, values)
|
45
|
+
super()
|
46
|
+
|
47
|
+
@template = inp
|
48
|
+
@resultf = out
|
49
|
+
|
50
|
+
if inp.is_a? Pathname
|
51
|
+
input << inp
|
52
|
+
end
|
53
|
+
output << out
|
54
|
+
|
55
|
+
@renderer = Renderer.new values
|
56
|
+
end
|
57
|
+
|
58
|
+
def build_self
|
59
|
+
r = if @template.is_a? String
|
60
|
+
@renderer.render @template
|
61
|
+
else
|
62
|
+
@renderer.render_file @template
|
63
|
+
end
|
64
|
+
|
65
|
+
@resultf.dirname.mkpath
|
66
|
+
@resultf.open('w') do |f|
|
67
|
+
f.write r
|
68
|
+
end
|
69
|
+
|
70
|
+
bs = R::BuildStep.new
|
71
|
+
bs.desc = "Rendering #{@resultf}"
|
72
|
+
bs.print
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#def render(template, values)
|
77
|
+
# Renderer.new(values).render(template)
|
78
|
+
#end
|
79
|
+
#def render_file(f, values)
|
80
|
+
# Renderer.new(values).render_file(f)
|
81
|
+
#end
|
82
|
+
|
83
|
+
def self.generate_file(inp, out, values={})
|
84
|
+
inp = C.path inp
|
85
|
+
out = R::Env.out_dir + 'l/template/' + C.unique_segment([inp, values]) + out
|
86
|
+
|
87
|
+
t = TargetRenderer.new(inp, out, values)
|
88
|
+
t.register
|
89
|
+
|
90
|
+
return out
|
91
|
+
end
|
92
|
+
end
|
data/lib/rub/l/test.rb
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
# Copyright 2013 Kevin Cox
|
2
|
+
|
3
|
+
################################################################################
|
4
|
+
# #
|
5
|
+
# This software is provided 'as-is', without any express or implied #
|
6
|
+
# warranty. In no event will the authors be held liable for any damages #
|
7
|
+
# arising from the use of this software. #
|
8
|
+
# #
|
9
|
+
# Permission is granted to anyone to use this software for any purpose, #
|
10
|
+
# including commercial applications, and to alter it and redistribute it #
|
11
|
+
# freely, subject to the following restrictions: #
|
12
|
+
# #
|
13
|
+
# 1. The origin of this software must not be misrepresented; you must not #
|
14
|
+
# claim that you wrote the original software. If you use this software in #
|
15
|
+
# a product, an acknowledgment in the product documentation would be #
|
16
|
+
# appreciated but is not required. #
|
17
|
+
# #
|
18
|
+
# 2. Altered source versions must be plainly marked as such, and must not be #
|
19
|
+
# misrepresented as being the original software. #
|
20
|
+
# #
|
21
|
+
# 3. This notice may not be removed or altered from any source distribution. #
|
22
|
+
# #
|
23
|
+
################################################################################
|
24
|
+
|
25
|
+
require 'singleton'
|
26
|
+
require 'stringio'
|
27
|
+
|
28
|
+
require 'minitest'
|
29
|
+
require 'minitest/spec'
|
30
|
+
require 'minitest/mock'
|
31
|
+
|
32
|
+
class Minitest::Runnable
|
33
|
+
@@rub_oldinherited = method :inherited
|
34
|
+
def self.inherited klass
|
35
|
+
::L::Test.make_test klass
|
36
|
+
|
37
|
+
@@rub_oldinherited.call klass
|
38
|
+
end
|
39
|
+
|
40
|
+
# The Rub target, this is set automatically.
|
41
|
+
#
|
42
|
+
# @return [R::Target]
|
43
|
+
cattr_accessor :rub_target
|
44
|
+
|
45
|
+
# Add a dependency
|
46
|
+
#
|
47
|
+
# Add a dependency to the test. It will be available before the test is
|
48
|
+
# run.
|
49
|
+
#
|
50
|
+
# @param d [Set<Pathname,String>,Array<Pathname,String>,Pathname,String]
|
51
|
+
# The dependencies.
|
52
|
+
def self.rub_require(d)
|
53
|
+
d = R::Tool.make_set_paths d
|
54
|
+
|
55
|
+
@rub_deps ||= Set.new
|
56
|
+
|
57
|
+
@rub_deps.merge d
|
58
|
+
end
|
59
|
+
|
60
|
+
# Get tests dependencies.
|
61
|
+
#
|
62
|
+
# @private
|
63
|
+
def self.rub_get_dependancies
|
64
|
+
@rub_deps || Set.new
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Testing.
|
69
|
+
#
|
70
|
+
# This testing is powered by Minitest. Look up the docs for that.
|
71
|
+
#
|
72
|
+
# All test are defined as regular Minitest tests and they will be automatically
|
73
|
+
# picked up and have tags created for them.
|
74
|
+
#
|
75
|
+
# When defining the test class there will be an additional method
|
76
|
+
# {Minitest::Runnable#rub_add_dependency} that will allow the test to depend
|
77
|
+
# on any target. Therefore you can ensure that what you are testing has been
|
78
|
+
# built.
|
79
|
+
#
|
80
|
+
# @example Defining dependencies.
|
81
|
+
#
|
82
|
+
# Minitest::Test
|
83
|
+
# rub_add_dependancy $myexe # Ensure $myexe will be available when test are run.
|
84
|
+
#
|
85
|
+
# def test_help
|
86
|
+
# c = R::Command.new [$myexe, '--help']
|
87
|
+
# c.run
|
88
|
+
#
|
89
|
+
# assert c.success?, 'Help exited with a good status code'
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
module L::Test
|
94
|
+
def self.make_test(klass)
|
95
|
+
@tests ||= {}
|
96
|
+
|
97
|
+
sklass = klass.to_s
|
98
|
+
if sklass =~ /^Test/
|
99
|
+
name = sklass
|
100
|
+
.gsub(/(?<=[a-z0-9])([A-Z])/, '-\1')
|
101
|
+
.gsub(/(?<=[^0-9])([0-9])/, '-\1')
|
102
|
+
.gsub('_', '-')
|
103
|
+
.downcase.to_sym
|
104
|
+
#pp name
|
105
|
+
|
106
|
+
@tests[name] ||= TargetTestCase.new(klass, name)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class Reporter < Minitest::AbstractReporter
|
111
|
+
def initialize(opt = {})
|
112
|
+
@passed = true
|
113
|
+
|
114
|
+
@io = opt[:io] || $stdout
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# Starts reporting on the run.
|
119
|
+
def start
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Record a result and output the Runnable#result_code. Stores the
|
124
|
+
# result of the run if the run did not pass.
|
125
|
+
def record(r)
|
126
|
+
pres = if r.skipped?
|
127
|
+
"\e[34;1mSKIP\e[0m"
|
128
|
+
elsif r.passed?
|
129
|
+
"\e[32;1mPASS\e[0m"
|
130
|
+
else
|
131
|
+
"\e[31;1mFAIL\e[0m"
|
132
|
+
end
|
133
|
+
|
134
|
+
@io.puts "[#{pres}] #{r.class}##{r.name}"
|
135
|
+
end
|
136
|
+
|
137
|
+
##
|
138
|
+
# Outputs the summary of the run.
|
139
|
+
def report
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# Did this run pass?
|
144
|
+
def passed?
|
145
|
+
@passed
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class TargetTest < R::Target
|
150
|
+
def input
|
151
|
+
Minitest::Runnable.runnables.map do |r|
|
152
|
+
r.rub_target
|
153
|
+
end.compact.map do |t|
|
154
|
+
t.input.to_a
|
155
|
+
end.flatten.to_set
|
156
|
+
end
|
157
|
+
|
158
|
+
def output
|
159
|
+
Set[:test]
|
160
|
+
end
|
161
|
+
|
162
|
+
def initialize
|
163
|
+
super()
|
164
|
+
|
165
|
+
register
|
166
|
+
end
|
167
|
+
|
168
|
+
def run_tests(reporter, options)
|
169
|
+
Minitest::Runnable.runnables.each do |r|
|
170
|
+
r.rub_target or next
|
171
|
+
|
172
|
+
r.rub_target.run_tests reporter, options
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def build_self
|
177
|
+
out = StringIO.new("", "w")
|
178
|
+
|
179
|
+
options = {
|
180
|
+
io: out,
|
181
|
+
verbose: true
|
182
|
+
}
|
183
|
+
|
184
|
+
reporter = Minitest::CompositeReporter.new
|
185
|
+
reporter << Minitest::SummaryReporter.new(options[:io], options)
|
186
|
+
|
187
|
+
reporter.start
|
188
|
+
out.string = '' # We don't want the start text.
|
189
|
+
|
190
|
+
run_tests reporter, options
|
191
|
+
reporter.report
|
192
|
+
|
193
|
+
bs = R::BuildStep.new
|
194
|
+
bs.desc = "Test Results"
|
195
|
+
bs.status = reporter.passed? ? 0 : 1
|
196
|
+
bs.out = out.string
|
197
|
+
bs.print
|
198
|
+
end
|
199
|
+
end
|
200
|
+
TargetTest.new # Create :test
|
201
|
+
|
202
|
+
class TargetTestCase < TargetTest
|
203
|
+
def input
|
204
|
+
@klass.rub_get_dependancies
|
205
|
+
end
|
206
|
+
|
207
|
+
def output
|
208
|
+
Set[@tag]
|
209
|
+
end
|
210
|
+
|
211
|
+
def initialize(klass, t)
|
212
|
+
@tag = t.to_sym
|
213
|
+
@klass = klass
|
214
|
+
|
215
|
+
klass.rub_target = self
|
216
|
+
|
217
|
+
super()
|
218
|
+
end
|
219
|
+
|
220
|
+
def run_tests(reporter, options)
|
221
|
+
out = StringIO.new("", "w")
|
222
|
+
options = {
|
223
|
+
io: out,
|
224
|
+
verbose: true
|
225
|
+
}
|
226
|
+
pr = Reporter.new(options)
|
227
|
+
reporter << pr
|
228
|
+
|
229
|
+
@klass.run reporter, options
|
230
|
+
|
231
|
+
reporter.reporters.delete pr
|
232
|
+
|
233
|
+
bs = R::BuildStep.new
|
234
|
+
bs.desc = "Running test case :#{@tag}"
|
235
|
+
bs.out = out.string
|
236
|
+
bs.status = pr.passed? ? 0 : 1
|
237
|
+
bs.print
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
class TargetTestExecutable < R::TargetGenerator
|
242
|
+
def build
|
243
|
+
build_dependancies
|
244
|
+
|
245
|
+
R::run(@cmd[0], "#@action #{@output.to_a.join", "}") or exit 1
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def self.external(cmd, name)
|
250
|
+
t = TargetTestExecutable.new
|
251
|
+
t.add_cmd cmd
|
252
|
+
t.output << name
|
253
|
+
|
254
|
+
t.register
|
255
|
+
end
|
256
|
+
end
|