rub 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,94 @@
|
|
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
|
+
L::C::CompilerClang = L::C::Compiler.clone
|
26
|
+
|
27
|
+
# The Clang Compiler
|
28
|
+
module L::C::CompilerClang
|
29
|
+
def self.name
|
30
|
+
:clang
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.available?
|
34
|
+
!!find
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.find
|
38
|
+
@exe and return @exe
|
39
|
+
|
40
|
+
@exe = ::C.find_command 'clang'
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.linker
|
44
|
+
:clang
|
45
|
+
end
|
46
|
+
|
47
|
+
@@o_flags = {
|
48
|
+
:none=>'-O0',
|
49
|
+
:some=>'-O1',
|
50
|
+
:full=>'-O3',
|
51
|
+
:max =>'-O4',
|
52
|
+
}
|
53
|
+
@@of_flags = {
|
54
|
+
nil=>[],
|
55
|
+
:speed=>[],
|
56
|
+
:size=>'-Os',
|
57
|
+
}
|
58
|
+
|
59
|
+
def self.generate_flags(opt)
|
60
|
+
f = []
|
61
|
+
|
62
|
+
#f << '-emit-llvm'
|
63
|
+
|
64
|
+
f << (@@o_flags[opt.optimize ] || [])
|
65
|
+
f << (@@o_flags[opt.optimize_for] || [])
|
66
|
+
|
67
|
+
f << opt.include_dirs.map do |d|
|
68
|
+
"-I#{d}"
|
69
|
+
end
|
70
|
+
f << opt.define.map do |k, v|
|
71
|
+
if v
|
72
|
+
# -Dk if v is true else -Dk=v.
|
73
|
+
"-D#{k}#{v.equal?(true)?"":"=#{v}"}"
|
74
|
+
else
|
75
|
+
"-U#{k}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
f.flatten!
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.compile_command(opt, src, obj)
|
83
|
+
[find, '-c', *generate_flags(opt), "-o#{obj}", *src]
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.do_compile_string(opt, str, obj)
|
87
|
+
c = R::Command.new [find, '-c', '-xc', *generate_flags(opt), '-o', obj, '-']
|
88
|
+
c.stdin = str
|
89
|
+
c.run
|
90
|
+
c
|
91
|
+
end
|
92
|
+
end
|
93
|
+
L::C.compilers[:clang] = L::C::CompilerClang
|
94
|
+
D.append(:l_c_compiler, :clang)
|
@@ -0,0 +1,94 @@
|
|
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
|
+
L::C::CompilerGCC = L::C::Compiler.clone
|
26
|
+
|
27
|
+
# GNU Compiler Collection
|
28
|
+
module L::C::CompilerGCC
|
29
|
+
|
30
|
+
def self.name
|
31
|
+
:gcc
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.available?
|
35
|
+
!!find
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.find
|
39
|
+
@exe and return @exe
|
40
|
+
|
41
|
+
@exe = ::C.find_command 'gcc'
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.linker
|
45
|
+
:gcc
|
46
|
+
end
|
47
|
+
|
48
|
+
@@o_flags = {
|
49
|
+
:none=> D[:debug] ? '-Og' : '-O0',
|
50
|
+
:some=>'-O1',
|
51
|
+
:full=>'-O2',
|
52
|
+
:max =>'-O3',
|
53
|
+
}
|
54
|
+
@@of_flags = {
|
55
|
+
nil=>[],
|
56
|
+
:speed=>'-Ofast',
|
57
|
+
:size=>'-Os',
|
58
|
+
}
|
59
|
+
|
60
|
+
def self.generate_flags(opt)
|
61
|
+
f = []
|
62
|
+
|
63
|
+
f << (@@o_flags[opt.optimize ] || [])
|
64
|
+
f << (@@o_flags[opt.optimize_for] || [])
|
65
|
+
|
66
|
+
f << opt.include_dirs.map do |d|
|
67
|
+
"-I#{d}"
|
68
|
+
end
|
69
|
+
f << opt.define.map do |k, v|
|
70
|
+
if v
|
71
|
+
# -Dk if v is true else -Dk=v.
|
72
|
+
"-D#{k}#{v.eql?(true)?"":"=#{v}"}"
|
73
|
+
else
|
74
|
+
"-U#{k}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
f.flatten!
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.compile_command(opt, src, obj)
|
82
|
+
[find, '-c', *generate_flags(opt), "-o#{obj}", *src]
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.do_compile_string(opt, str, obj)
|
86
|
+
c = R::Command.new [find, '-c', '-xc', *generate_flags(opt), '-o', obj, '-']
|
87
|
+
c.stdin = str
|
88
|
+
c.run
|
89
|
+
c
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
L::C.compilers[:gcc] = L::C::CompilerGCC
|
94
|
+
D.append(:l_c_compiler, :gcc)
|
data/lib/rub/l/ld.rb
ADDED
@@ -0,0 +1,254 @@
|
|
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 'valid_array'
|
26
|
+
|
27
|
+
# Linker Library
|
28
|
+
module L::LD
|
29
|
+
# @!scope class
|
30
|
+
# All available linkers.
|
31
|
+
# @return [Hash{Symbol=>Linker}]
|
32
|
+
cattr_reader :linkers
|
33
|
+
@linkers = {}
|
34
|
+
|
35
|
+
# @!scope class
|
36
|
+
# The linker being used.
|
37
|
+
# @return [Linker]
|
38
|
+
cattr_accessor :linker
|
39
|
+
|
40
|
+
# @!scope class
|
41
|
+
# Default optimization level.
|
42
|
+
#
|
43
|
+
# This takes one of four optimization levels. The actual optimization
|
44
|
+
# done is linker dependant. For example, some linker may not have
|
45
|
+
# any optimization so all levels will be equivalent.
|
46
|
+
#
|
47
|
+
# One of the following:
|
48
|
+
# [+:none+] Perform no optimization. This should be fast and debuggable.
|
49
|
+
# [+:some+] Perform light optimization that is pretty fast.
|
50
|
+
# [+:full+] Perform a high level of optimization producing a fast binary.
|
51
|
+
# this may considerably slow down compilation.
|
52
|
+
# [+:max+] Perform all available optimizations. These may be
|
53
|
+
# experimental and very slow.
|
54
|
+
#
|
55
|
+
# This value defaults to +:full+ if +D:debug+ is set, otherwise +:none+.
|
56
|
+
#
|
57
|
+
# @return [Symbol]
|
58
|
+
cattr_accessor :optimize
|
59
|
+
|
60
|
+
# @!scope class
|
61
|
+
# A list of library search directories to be added to the default search
|
62
|
+
# path.
|
63
|
+
#
|
64
|
+
# These paths are searched in order.
|
65
|
+
#
|
66
|
+
# @return [Array<Pathname>]
|
67
|
+
cattr_accessor :library_dirs
|
68
|
+
|
69
|
+
# @!scope class
|
70
|
+
# The default for static linking.
|
71
|
+
#
|
72
|
+
# If set to true shared libraries won't be used. Defaults to false.
|
73
|
+
#
|
74
|
+
# @return [true,false]
|
75
|
+
cattr_accessor :static
|
76
|
+
|
77
|
+
# @!scope class
|
78
|
+
# Default arguments to add to the linker command.
|
79
|
+
#
|
80
|
+
# @note This adds raw arguments to the linker command and is a quick n'
|
81
|
+
# easy way to reduce portability. If you can, use the other
|
82
|
+
# options provided by this class in order to maintain portability.
|
83
|
+
#
|
84
|
+
# @return [Array<String>] A list of arguments to add.
|
85
|
+
cattr_accessor :args
|
86
|
+
|
87
|
+
@optimize = D[:debug] ? :none : :full
|
88
|
+
@library_dirs = []
|
89
|
+
@static = false
|
90
|
+
@args = []
|
91
|
+
|
92
|
+
def self.set_linker(name)
|
93
|
+
self.linker = linkers[name]
|
94
|
+
end
|
95
|
+
|
96
|
+
# An abstraction for a linker.
|
97
|
+
module Linker
|
98
|
+
# The name of the linker.
|
99
|
+
# @return [Symbol]
|
100
|
+
def self.name
|
101
|
+
:default
|
102
|
+
end
|
103
|
+
|
104
|
+
# Is this linker available on this system?
|
105
|
+
#
|
106
|
+
# @return [true,false] true if the linker is available.
|
107
|
+
def self.available?
|
108
|
+
false
|
109
|
+
end
|
110
|
+
|
111
|
+
# Return the linker's builtin library path.
|
112
|
+
#
|
113
|
+
# @return [Array<Pathname>]
|
114
|
+
def self.builtin_library_path
|
115
|
+
@builtin_library_path ||= [
|
116
|
+
'/lib/',
|
117
|
+
'/usr/lib/',
|
118
|
+
'/usr/local/lib/',
|
119
|
+
'~/.local/lib/',
|
120
|
+
].map do |l|
|
121
|
+
C.path(l)
|
122
|
+
end.uniq
|
123
|
+
end
|
124
|
+
|
125
|
+
# Return the path which to search for libraries.
|
126
|
+
#
|
127
|
+
# @return [Array<Pathname>]
|
128
|
+
def self.library_path(opt)
|
129
|
+
opt.library_dirs + builtin_library_path
|
130
|
+
end
|
131
|
+
|
132
|
+
# Generate a command to perform the link.
|
133
|
+
#
|
134
|
+
# @param files [Set<Pathname,String>,Array<Pathname,String>,Pathname,String]
|
135
|
+
# The object files to link.
|
136
|
+
# @param libs [Set<String>,Array<String>,String] Libraries to link with.
|
137
|
+
# @param out [Pathname,String] The output file.
|
138
|
+
# @param format [Symbol] The type of output to produce.
|
139
|
+
# One of:
|
140
|
+
# [+:exe+] An executable binary.
|
141
|
+
# [+:shared+] A shared library.
|
142
|
+
# @param opt [Options] An options object.
|
143
|
+
# @return [Set<Pathname>] The output file.
|
144
|
+
def self.link_command(opt, files, libs, out, format)
|
145
|
+
raise NotImplementedError
|
146
|
+
end
|
147
|
+
|
148
|
+
# Perform a link.
|
149
|
+
#
|
150
|
+
# @param (see link_command)
|
151
|
+
# @return [R::Command] the process that linked the file.
|
152
|
+
def self.do_link(opt, files, libs, out, format)
|
153
|
+
c = R::Command.new(link_command(opt, files, libs, out, format))
|
154
|
+
c.run
|
155
|
+
c
|
156
|
+
end
|
157
|
+
|
158
|
+
# Peform a test link.
|
159
|
+
#
|
160
|
+
# @param (see link_command)
|
161
|
+
# @return [true,false] true if the link succeeded.
|
162
|
+
def self.test_link(opt, files, libs, format)
|
163
|
+
c = do_link(opt, files, libs, File::NULL, format)
|
164
|
+
#p c.success?, c.stdin, c.stdout, c.stderr
|
165
|
+
c.success?
|
166
|
+
end
|
167
|
+
|
168
|
+
@@name_map = {
|
169
|
+
exe: '%s',
|
170
|
+
shared: 'lib%s.so',
|
171
|
+
static: 'lib%s.a',
|
172
|
+
}
|
173
|
+
|
174
|
+
# Generate an appropriate name.
|
175
|
+
#
|
176
|
+
# @param base [String] The basename.
|
177
|
+
# @param type [Symbol] The output format.
|
178
|
+
# @return [String] A suitable name for the output type on the
|
179
|
+
# current machine.
|
180
|
+
def self.full_name(base, type)
|
181
|
+
@@name_map[type] % base
|
182
|
+
end
|
183
|
+
|
184
|
+
# Locate a library.
|
185
|
+
#
|
186
|
+
# Locates the library that would be used with when linking.
|
187
|
+
#
|
188
|
+
# @param name [String] The basename of the library.
|
189
|
+
# @param options [Options] The options to use when linking.
|
190
|
+
# @return [Pathname] The path to the library.
|
191
|
+
def self.find_lib(opt, name)
|
192
|
+
sp = library_path(opt)
|
193
|
+
if name.to_s.include? '/'
|
194
|
+
return C.path name
|
195
|
+
end
|
196
|
+
name = full_name name, (opt.static ? :static : :shared)
|
197
|
+
|
198
|
+
sp.each do |d|
|
199
|
+
l = d + name
|
200
|
+
|
201
|
+
l.exist? and return l
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
R::Tool.load_dir(Pathname.new(__FILE__).realpath.dirname+"ld/linker/")
|
207
|
+
@linkers.keep_if do |n, l|
|
208
|
+
l.available? or next false
|
209
|
+
end
|
210
|
+
|
211
|
+
D[:l_ld_linker].map! {|l| l.to_sym}
|
212
|
+
@linker = D[:l_ld_linker].find {|l| @linkers.has_key? l}
|
213
|
+
@linker = @linkers[@linker]
|
214
|
+
|
215
|
+
class LibraryArray < Array
|
216
|
+
extend ValidArray
|
217
|
+
|
218
|
+
def self.validate(l)
|
219
|
+
L::LD.linker.find_lib(L::LD, l) or raise "Can't find library #{l}"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Link object files.
|
224
|
+
#
|
225
|
+
# @param src [Set<Pathname,String>,Array<Pathname,String>,Pathname,String]
|
226
|
+
# The object files to link.
|
227
|
+
# @param libs [Set<String>,Array<String>,String] Libraries to link with.
|
228
|
+
# @param name [Pathname,String] The basename of the output file.
|
229
|
+
# @param format [Symbol] The type of output to produce.
|
230
|
+
# One of:
|
231
|
+
# [+:exe+] An executable binary.
|
232
|
+
# [+:shared+] A shared library.
|
233
|
+
# @param linker [Symbol] The linker to use. If nil, use the default.
|
234
|
+
# @return [Pathname] The output file.
|
235
|
+
def self.link(src, libs, name, format: :exe)
|
236
|
+
src = R::Tool.make_set_paths src
|
237
|
+
libs = R::Tool.make_set libs
|
238
|
+
|
239
|
+
libfs = libs.map {|l| linker.find_lib(self, l) or raise "Can't find library #{l}."}
|
240
|
+
|
241
|
+
out = linker.full_name name, format
|
242
|
+
out = R::Env.out_dir + 'l/ld/' + C.unique_segment(src, libs, self) + out
|
243
|
+
|
244
|
+
C::generator(src+libfs, linker.link_command(self, src, libs, out, format), out)
|
245
|
+
|
246
|
+
out
|
247
|
+
end
|
248
|
+
|
249
|
+
def self.initialize_copy(s)
|
250
|
+
super
|
251
|
+
|
252
|
+
self.library_dirs = s.library_dirs.dup
|
253
|
+
end
|
254
|
+
end
|
@@ -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
|
+
LinkerClang = Linker.clone
|
27
|
+
module LinkerClang
|
28
|
+
def self.name
|
29
|
+
:clang
|
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 'clang'
|
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
|
+
'-O2'
|
65
|
+
when :full
|
66
|
+
'-O3'
|
67
|
+
when :max
|
68
|
+
'-O4'
|
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[:clang] = LinkerClang
|
89
|
+
end
|