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.
@@ -0,0 +1,30 @@
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
+ [
26
+ R::Env.src_dir,
27
+ R::Env.out_dir,
28
+ R::Env.global_cache,
29
+ R::Env.project_cache,
30
+ ].each{|d| d.mkpath }
@@ -0,0 +1,178 @@
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 'pathname'
26
+ require 'singleton'
27
+
28
+ module R
29
+ class TargetHelp < C::TargetTag
30
+ @@tag = nil
31
+ def gen_help
32
+ @@tag and return
33
+
34
+ @@tag = Set.new
35
+ @@bld = Set.new
36
+ @@ins = Set.new
37
+ @@src = Set.new
38
+
39
+ R.targets.each do |p, t|
40
+ if p.is_a? Symbol
41
+ @@tag << [p, t]
42
+ elsif p.to_s.start_with?(R::Env.out_dir.to_s)
43
+ @@bld << [p, t]
44
+ elsif (
45
+ p.to_s.start_with?(D[:prefix].to_s+'/') ||
46
+ !p.to_s.start_with?(R::Env.src_dir.to_s)
47
+ )
48
+ @@ins << [p, t]
49
+ else
50
+ @@src << [p, t]
51
+ end
52
+ end
53
+ end
54
+
55
+ def initialize(t)
56
+ super t.to_sym
57
+
58
+ register
59
+ end
60
+
61
+ def print_target(ta)
62
+ p, t = ta
63
+ ps = if p.is_a? Symbol
64
+ #p.inspect
65
+ ":#{p}"
66
+ else
67
+ p.to_s
68
+ end
69
+
70
+ if t.description
71
+ printf " %-20s - %s\n", ps, t.description
72
+ else
73
+ printf " %s\n", ps
74
+ end
75
+ end
76
+
77
+ def print_targets(tm)
78
+ tm.each do |t|
79
+ print_target t
80
+ end
81
+ end
82
+
83
+ def build
84
+ gen_help
85
+ end
86
+ end
87
+
88
+ class TargetHelpHelp < TargetHelp
89
+ include Singleton
90
+
91
+ def initialize
92
+ super :help
93
+ end
94
+
95
+ def build
96
+ super
97
+
98
+ puts <<'EOS'
99
+ Help:
100
+ Just displaying tags. If you want to see more see:
101
+ :help-tag
102
+ :help-installed
103
+ :help-built
104
+ :help-all
105
+ EOS
106
+ R.get_target('help-tag'.to_sym).build
107
+ end
108
+ end
109
+ TargetHelpHelp.instance
110
+
111
+ class TargetHelpTag < TargetHelp
112
+ include Singleton
113
+
114
+ def initialize
115
+ super 'help-tag'
116
+ end
117
+
118
+ def build
119
+ super
120
+
121
+ puts 'Tags:'
122
+ print_targets @@tag
123
+ end
124
+ end
125
+ TargetHelpTag.instance
126
+
127
+ class TargetHelpInstalled < TargetHelp
128
+ include Singleton
129
+
130
+ def initialize
131
+ super 'help-installed'
132
+ end
133
+
134
+ def build
135
+ super
136
+
137
+ puts 'Installed:'
138
+ print_targets @@ins
139
+ end
140
+ end
141
+ TargetHelpInstalled.instance
142
+
143
+ class TargetHelpBuilt < TargetHelp
144
+ include Singleton
145
+
146
+ def initialize
147
+ super 'help-built'
148
+ end
149
+
150
+ def build
151
+ super
152
+
153
+ puts 'Build Targets:'
154
+ print_targets @@bld
155
+ end
156
+ end
157
+ TargetHelpBuilt.instance
158
+
159
+ class TargetHelpAll < TargetHelp
160
+ include Singleton
161
+
162
+ def initialize
163
+ super 'help-all'
164
+ end
165
+
166
+ def build
167
+ super
168
+
169
+ [
170
+ 'help-tag',
171
+ 'help-installed',
172
+ 'help-built',
173
+ ].each{|t| R.get_target(t.to_sym).build }
174
+ end
175
+ end
176
+ TargetHelpAll.instance
177
+
178
+ end
@@ -0,0 +1,91 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # Copyright 2013 Kevin Cox
4
+
5
+ ################################################################################
6
+ # #
7
+ # This software is provided 'as-is', without any express or implied #
8
+ # warranty. In no event will the authors be held liable for any damages #
9
+ # arising from the use of this software. #
10
+ # #
11
+ # Permission is granted to anyone to use this software for any purpose, #
12
+ # including commercial applications, and to alter it and redistribute it #
13
+ # freely, subject to the following restrictions: #
14
+ # #
15
+ # 1. The origin of this software must not be misrepresented; you must not #
16
+ # claim that you wrote the original software. If you use this software in #
17
+ # a product, an acknowledgment in the product documentation would be #
18
+ # appreciated but is not required. #
19
+ # #
20
+ # 2. Altered source versions must be plainly marked as such, and must not be #
21
+ # misrepresented as being the original software. #
22
+ # #
23
+ # 3. This notice may not be removed or altered from any source distribution. #
24
+ # #
25
+ ################################################################################
26
+
27
+ ##### These libraries are guaranteed to be loaded.
28
+ require 'pathname'
29
+ require 'set'
30
+ require 'pp'
31
+ require 'digest/sha1'
32
+
33
+ require 'sysexits'
34
+ require 'xdg'
35
+
36
+ # This is first so we modify all of our classes.
37
+ '
38
+ class Object
39
+ def self.method_added name
40
+ return if name == :initialize
41
+ return if @__last_methods_added && @__last_methods_added.include?(name)
42
+
43
+ with = :"#{name}_with_before_each_method"
44
+ without = :"#{name}_without_before_each_method"
45
+
46
+ @__last_methods_added = [name, with, without]
47
+ define_method with do |*args, &block|
48
+ puts "#{self.class}##{name}"
49
+ pp args, &block
50
+ puts "calling..."
51
+
52
+ r = send without, *args, &block
53
+
54
+ puts "#{self.class}##{name} returned"
55
+
56
+ r
57
+ end
58
+ alias_method without, name
59
+ alias_method name, with
60
+ @__last_methods_added = nil
61
+ end
62
+ end
63
+ #'
64
+
65
+ ##### Load the namespaces.
66
+ require_relative 'd'
67
+ require_relative 'r'
68
+ require_relative 'l'
69
+ require_relative 'c'
70
+
71
+ # Odd jobs.
72
+ require_relative 'dirs'
73
+ require_relative 'help'
74
+
75
+ ##### Add the first two scripts.
76
+ R::I::Runner.do_file(R::Env.src_dir+"root.rub")
77
+ R::I::Runner.do_file(R::Env.cmd_dir+"dir.rub")
78
+
79
+ ##### Add default target if necessary.
80
+ ARGV.empty? and ARGV << ':all'
81
+
82
+ ##### Build requested targets.
83
+ ARGV.each do |t|
84
+ t = if t =~ /^:[^\/]*$/ # Is a tag.
85
+ t[1..-1].to_sym
86
+ else
87
+ C.path(t)
88
+ end
89
+ R::get_target(t).build
90
+ end
91
+
@@ -0,0 +1,40 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # Copyright 2013 Kevin Cox
4
+
5
+ ################################################################################
6
+ # #
7
+ # This software is provided 'as-is', without any express or implied #
8
+ # warranty. In no event will the authors be held liable for any damages #
9
+ # arising from the use of this software. #
10
+ # #
11
+ # Permission is granted to anyone to use this software for any purpose, #
12
+ # including commercial applications, and to alter it and redistribute it #
13
+ # freely, subject to the following restrictions: #
14
+ # #
15
+ # 1. The origin of this software must not be misrepresented; you must not #
16
+ # claim that you wrote the original software. If you use this software in #
17
+ # a product, an acknowledgment in the product documentation would be #
18
+ # appreciated but is not required. #
19
+ # #
20
+ # 2. Altered source versions must be plainly marked as such, and must not be #
21
+ # misrepresented as being the original software. #
22
+ # #
23
+ # 3. This notice may not be removed or altered from any source distribution. #
24
+ # #
25
+ ################################################################################
26
+
27
+ # Library Module
28
+ #
29
+ # Loaded libraries become available here.
30
+ module L
31
+ # Auto-load libraries.
32
+ def self.const_missing(n)
33
+ #pp n
34
+ p = "l/#{n.to_s.downcase}"
35
+
36
+ require_relative p
37
+ const_defined?(n, false) or raise "Library #{p} malformed, was expected to load into L::#{n}."
38
+ const_get(n, false)
39
+ end
40
+ end
@@ -0,0 +1,476 @@
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 'tempfile'
26
+
27
+ # C Library
28
+ module L::C
29
+ # @!scope class
30
+ # All available compilers.
31
+ # @return [Hash{Symbol=>Compiler}]
32
+ cattr_accessor :compilers
33
+ @compilers = {}
34
+
35
+ # Compiler
36
+ #
37
+ # The compiler to use.
38
+ #
39
+ # @return (see compiler)
40
+ # @see compiler
41
+ cattr_reader :compiler
42
+ def self.compiler=(name)
43
+ @compiler = get_compiler name
44
+ end
45
+
46
+ # @!scope class
47
+ # Default optimization level.
48
+ #
49
+ # This takes one of four optimization levels. The actual optimization
50
+ # done is linker dependant. For example, some linker may not have
51
+ # any optimization so all levels will be equivalent.
52
+ #
53
+ # One of the following:
54
+ # [+:none+] Perform no optimization. This should be fast and debuggable.
55
+ # [+:some+] Perform light optimization that is pretty fast.
56
+ # [+:full+] Perform a high level of optimization producing a fast binary.
57
+ # this may considerably slow down compilation.
58
+ # [+:max+] Perform all available optimizations. These may be
59
+ # experimental and very slow.
60
+ #
61
+ # This value defaults to +:full+ if +D:debug+ is set, otherwise +:none+.
62
+ #
63
+ # @return [Symbol]
64
+ cattr_accessor :optimize
65
+
66
+ # @!scope class
67
+ # Default optimization goal.
68
+ #
69
+ # This determines what the compiler should optimize for if it has the
70
+ # option.
71
+ #
72
+ # One of the following:
73
+ # [+:size+] The compiler should focus on creating a small binary.
74
+ # [+:speed+] The compiler should focus on creating a fast binary.
75
+ #
76
+ # @return [Symbol]
77
+ cattr_accessor :optimize_for
78
+
79
+ # @!scope class
80
+ # Default debug symbols setting.
81
+ #
82
+ # This determines if the compiler should produce debugging symbols.
83
+ #
84
+ # @return [true,false]
85
+ cattr_accessor :debug
86
+
87
+ # @!scope class
88
+ # Default profile symbols setting.
89
+ #
90
+ # This determines if the compiler should produce code suitable for
91
+ # profiling.
92
+ #
93
+ # @return [true,false]
94
+ cattr_accessor :profile
95
+
96
+ # @!scope class
97
+ # A list of directories to search for header files.
98
+ #
99
+ # These paths are searched in order.
100
+ #
101
+ # @return [Array<Pathname>]
102
+ cattr_accessor :include_dirs
103
+
104
+ # @!scope class
105
+ # A list of libraries to link.
106
+ #
107
+ # @return [Array<String,Pathname>]
108
+ cattr_accessor :libs
109
+
110
+ # @!scope class
111
+ # A list of macros to define. `nil` can be used to undefine a macro.
112
+ #
113
+ # @return [Hash{String=>String,true,nil}]
114
+ cattr_accessor :define
115
+
116
+ @debug = @profile = !!D[:debug]
117
+ @optimize = @debug ? :none : :full
118
+
119
+ @include_dirs = R::Tool::PathArray.new
120
+ @libs = L::LD::LibraryArray.new
121
+ @define = {
122
+ @debug ? 'DEBUG' : 'NDEBUG' => true,
123
+ }
124
+
125
+ # An Abstraction over different compilers.
126
+ module Compiler
127
+ # The name of the compiler.
128
+ #
129
+ # @return [Symbol]
130
+ def self.name
131
+ :default
132
+ end
133
+
134
+ # If the compiler is available on the current system.
135
+ #
136
+ # @return [true,false]
137
+ def self.available?
138
+ false
139
+ end
140
+
141
+ # Return the preferred linker.
142
+ #
143
+ # Some compilers create objects that need to be linked with their
144
+ # linker. This allows the compiler to specify the linker is wishes to
145
+ # be used.
146
+ def self.linker
147
+ nil
148
+ end
149
+
150
+ # Compile source files.
151
+ #
152
+ # @param src [Set<Pathname>] The source files to link and generated headers.
153
+ # @param obj [Pathname] The path of the output file.
154
+ # @param opt [Options] An options object.
155
+ # @return [Pathname] The output file.
156
+ def self.compile_command(opt, src, obj)
157
+ raise "Not implemented!"
158
+ end
159
+
160
+ # Compile a file.
161
+ #
162
+ # @param (see compile_command)
163
+ # @return [R::Command] the process that compiled the file.
164
+ def self.do_compile_file(opt, f, obj)
165
+ c = R::Command.new(compile_command(opt, f, obj))
166
+ c.run
167
+ c
168
+ end
169
+
170
+ # Compile a string.
171
+ #
172
+ # @param str [String] A string containing the complete source to compile.
173
+ # @param obj [Pathname] The path of the output file.
174
+ # @param opt [Options] An options object.
175
+ # @return [R::Command] the process that compiled the string.
176
+ def self.do_compile_string(opt, str, obj)
177
+ f = Tempfile.new(['rub.l.c.testcompile', '.c'])
178
+ f.write(str)
179
+ f.close
180
+ c = do_compile_file(opt, f.path, obj)
181
+ f.unlink
182
+ c
183
+ end
184
+
185
+ # Peform a test compile.
186
+ #
187
+ # @param (see do_compile_file)
188
+ # @return [true,false] true if the compilation succeeded.
189
+ def self.test_compile(opt, src)
190
+ c = do_compile_file(opt, src, File::NULL)
191
+ #p c.success?, c.stdin, c.stdout, c.stderr
192
+ c.success?
193
+ end
194
+
195
+ # Peform a test compile.
196
+ #
197
+ # @param (see do_compile_string)
198
+ # @return [true,false] true if the compilation succeeded.
199
+ def self.test_compile_string(opt, src)
200
+ c = do_compile_string(opt, src, File::NULL)
201
+ #p c.success?, c.stdin, c.stdout, c.stderr
202
+ c.success?
203
+ end
204
+
205
+ # Check to see if a macro is defined.
206
+ #
207
+ # @param name [String] macro identifier.
208
+ # @return [true,false] true if the macro is defined.
209
+ def self.test_macro(opt, name)
210
+ test_compile_string opt, <<EOF
211
+ #ifndef #{name}
212
+ #error "#{name}Not Defined"
213
+ #endif
214
+ EOF
215
+ end
216
+
217
+ def self.include_directories(opt)
218
+ @include_directories and return @include_directories.dup
219
+
220
+ cmd = [C.find_command('cpp'), '-v', '-o', File::NULL, File::NULL]
221
+ c = R::Command.new cmd
222
+ c.run
223
+
224
+ l = c.stderr.lines.map &:chomp
225
+
226
+ #qb = l.find_index('#include "..." search starts here:') + 1
227
+ sb = l.find_index('#include <...> search starts here:') + 1
228
+ se = l.find_index 'End of search list.'
229
+
230
+ @include_directories = l[sb...se].map{|d| Pathname.new d[1..-1] }
231
+
232
+ @include_directories.dup
233
+ end
234
+ end
235
+
236
+ def self.get_compiler(name)
237
+ if name.is_a? Symbol
238
+ compilers[name]
239
+ else
240
+ name
241
+ end
242
+ end
243
+
244
+ R::Tool.load_dir(Pathname.new(__FILE__).realpath.dirname+"c/compiler/")
245
+
246
+ tdir = Pathname.new(__FILE__).realpath.dirname + "c/test/"
247
+
248
+ @compilers.keep_if do |n, c|
249
+ c.available? or next false
250
+
251
+ r = (
252
+ c.test_compile(self, tdir+'basic.c') and
253
+ not c.test_compile(self, tdir+'undefined.c') and
254
+ c.test_macro(self, '__LINE__')
255
+ )
256
+
257
+ r or $stderr.puts "Ignoring compiler #{n} because it failed the tests."
258
+
259
+ r
260
+ end
261
+
262
+ D[:l_c_compiler].map! {|c| c.to_sym}
263
+ @compiler = compilers[ D[:l_c_compiler].find{|c| compilers.has_key? c} ]
264
+
265
+ # Compile source files.
266
+ #
267
+ # @param src [Set<Pathname,String>,Array<Pathname,String>,Pathname,String]
268
+ # The source files to compile and generated headers.
269
+ # @param opt [Options] An options object.
270
+ # @return [Set<Pathname>] The resulting object files.
271
+ def self.compile(src)
272
+ src = R::Tool.make_set_paths src
273
+
274
+ headers = Set.new
275
+ src.keep_if do |s|
276
+ if s.extname.match /[H]/i
277
+ headers << s
278
+ false
279
+ else
280
+ true
281
+ end
282
+ end
283
+
284
+ src.map! do |s|
285
+ out = R::Env.out_dir + 'l/c/' + C.unique_segment(self) + "#{s.basename}.o"
286
+
287
+ R.find_target(s) or TargetCSource.new(self, s, headers)
288
+ ::C.generator(s, compiler.compile_command(self, s, out), out, desc:"Compiling")
289
+ end
290
+ src.flatten!
291
+ src
292
+ end
293
+
294
+ # A C source file.
295
+ class TargetCSource < R::Target
296
+ def initialize(opt, f, input = [])
297
+ #TargetC.initialize
298
+
299
+ @f = C.path(f)
300
+ @opt = opt
301
+ @input = input
302
+
303
+ register
304
+ end
305
+
306
+ def included_files(opt, set=Set.new)
307
+ set.include?(@f) and return
308
+
309
+ set << @f
310
+ @incs ||= @f.readlines.map do |l|
311
+ l =~ /\s*#\s*include\s*("(.*)"|<(.*)>)/ or next
312
+ if $3 and !D[:l_c_system_headers]
313
+ next
314
+ end
315
+
316
+ p = Pathname.new( $2 || $3 )
317
+ ip = opt.compiler.include_directories(opt)
318
+
319
+ if $2
320
+ ip << @f.dirname
321
+ end
322
+
323
+ h = nil
324
+ ip.each do |d|
325
+ hg = d.join(p)
326
+
327
+ if hg.exist?
328
+ h = hg
329
+ break
330
+ end
331
+ end
332
+
333
+ h # Ignoring missing headers for now.
334
+ end.compact
335
+
336
+ @incs.each do |h|
337
+ icd = R::find_target(h) || TargetCSource.new(opt, h, @input)
338
+
339
+ if icd.respond_to? :included_files
340
+ icd.included_files opt, set
341
+ else
342
+ set << h
343
+ end
344
+ end
345
+ end
346
+
347
+ def input
348
+ @input + included_files(@opt)
349
+ end
350
+
351
+ def output
352
+ Set[@f]
353
+ end
354
+
355
+ def build
356
+ @depsbuilt and return
357
+
358
+ @depsbuilt = true
359
+ build_dependancies
360
+ end
361
+ end
362
+
363
+ def self.to_c_identifier(s)
364
+ s.delete('`!@#$%^&*()+=[]{};"\'<>?')
365
+ .gsub(/[\~\-\\\|\:\,\.\/]/, '_')
366
+ .gsub(/^[0-9]/, '_\0')
367
+ end
368
+
369
+ class TargetGeneratedHeader < R::TargetSmart
370
+ def initialize(opt, name, h, c, values)
371
+ super()
372
+
373
+ @n = name
374
+ @h = h
375
+ @c = c
376
+
377
+ @val = values
378
+
379
+ output << @h << @c
380
+ end
381
+
382
+ def hash_input
383
+ Digest::SHA1.digest(@val.inspect)
384
+ end
385
+
386
+ def hash_output(t)
387
+ Digest::SHA1.digest(t.readlines.drop(2).join('\n'))
388
+ end
389
+
390
+ def build_self
391
+ @h.dirname.mkpath
392
+ @c.dirname.mkpath
393
+
394
+ h = @h.open('w')
395
+ c = @c.open('w')
396
+
397
+ notice = <<"EOS"
398
+ /* THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT! */
399
+ /* This file was generated by Rub on #{DateTime.now.iso8601} */
400
+
401
+ EOS
402
+ h.print notice
403
+ c.print notice
404
+
405
+ hname = L::C.to_c_identifier(@h.basename.to_s).upcase
406
+ h.puts "#ifndef RUB_L_C_GENERATE_HEADER___#{hname}"
407
+ h.puts "#define RUB_L_C_GENERATE_HEADER___#{hname}"
408
+ h.puts ''
409
+
410
+ c.puts %|#include "#{@n}.h"|
411
+ c.puts ''
412
+
413
+ @val.each do |k, v|
414
+ type, v = if v.is_a?(Array)
415
+ [v[0], v[1]]
416
+ elsif v.is_a? Numeric
417
+ ['int', v.to_s]
418
+ elsif v.equal?(true) || v.equal?(false)
419
+ ['short unsigned int', v ? 1 : 0]
420
+ elsif v.respond_to? :to_s
421
+ ['const char *', v.to_s.inspect] # @TODO: make this quote for C rather then ruby.
422
+ end
423
+
424
+ h.puts "extern #{type} #{k};"
425
+ c.puts "#{type} #{k} = #{v};"
426
+ end
427
+
428
+ h.puts ''
429
+ h.puts "#endif /* RUB_L_C_GENERATE_HEADER___#{hname} */"
430
+
431
+ h.close
432
+ c.close
433
+
434
+ bs = R::BuildStep.new
435
+ bs.desc = "Generating #{@h} and #{@c}"
436
+ bs.print
437
+ end
438
+ end
439
+
440
+ # Generate a header
441
+ #
442
+ # Generates a header with information in it.
443
+ def self.generate_header(name, vals)
444
+ h = C.unique_path("#{name}.h", vals)
445
+ c = C.unique_path("#{name}.c", vals)
446
+
447
+ t = TargetGeneratedHeader.new(self, name, h, c, vals)
448
+ t.register
449
+
450
+ include_dirs << h.dirname
451
+
452
+ t.output
453
+ end
454
+
455
+ # Compile and link an executable.
456
+ #
457
+ # @param src [Set<Pathname,String>,Array<Pathname,String>,Pathname,String]
458
+ # The source files to compile and generated headers.
459
+ # @param name [Pathname,String] The basename of the output file.
460
+ # @return [Pathname] The resulting executable.
461
+ def self.program(src, name)
462
+ obj = compile(src)
463
+ linker = L::LD.clone
464
+
465
+ linker.set_linker compiler.linker
466
+ linker.link(obj, libs, name, format: :exe)
467
+ end
468
+
469
+ def self.initialize_copy(s)
470
+ super
471
+
472
+ self.include_dirs = s.include_dirs.dup
473
+ self.libs = s.libs.dup
474
+ self.define = s.define.dup
475
+ end
476
+ end