rscons 1.4.3 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/lib/rscons.rb +75 -5
  2. data/lib/rscons/build_target.rb +36 -0
  3. data/lib/rscons/builder.rb +41 -3
  4. data/lib/rscons/builders/cfile.rb +15 -0
  5. data/lib/rscons/builders/disassemble.rb +15 -0
  6. data/lib/rscons/builders/library.rb +17 -2
  7. data/lib/rscons/builders/object.rb +37 -5
  8. data/lib/rscons/builders/preprocess.rb +15 -0
  9. data/lib/rscons/builders/program.rb +42 -2
  10. data/lib/rscons/cache.rb +26 -6
  11. data/lib/rscons/environment.rb +259 -19
  12. data/lib/rscons/varset.rb +33 -10
  13. data/lib/rscons/version.rb +1 -1
  14. data/rscons.gemspec +8 -10
  15. metadata +38 -103
  16. checksums.yaml +0 -15
  17. data/.gitignore +0 -18
  18. data/.rspec +0 -2
  19. data/Gemfile +0 -4
  20. data/README.md +0 -384
  21. data/Rakefile.rb +0 -26
  22. data/build_tests/build_dir/src/one/one.c +0 -6
  23. data/build_tests/build_dir/src/two/two.c +0 -7
  24. data/build_tests/build_dir/src/two/two.h +0 -6
  25. data/build_tests/clone_env/src/program.c +0 -6
  26. data/build_tests/custom_builder/program.c +0 -7
  27. data/build_tests/d/main.d +0 -6
  28. data/build_tests/header/header.c +0 -7
  29. data/build_tests/header/header.h +0 -6
  30. data/build_tests/library/one.c +0 -8
  31. data/build_tests/library/three.c +0 -0
  32. data/build_tests/library/two.c +0 -0
  33. data/build_tests/simple/simple.c +0 -6
  34. data/build_tests/simple_cc/simple.cc +0 -8
  35. data/build_tests/two_sources/one.c +0 -8
  36. data/build_tests/two_sources/two.c +0 -3
  37. data/spec/build_tests_spec.rb +0 -527
  38. data/spec/rscons/builders/cfile_spec.rb +0 -28
  39. data/spec/rscons/builders/disassemble_spec.rb +0 -17
  40. data/spec/rscons/builders/library_spec.rb +0 -18
  41. data/spec/rscons/builders/object_spec.rb +0 -23
  42. data/spec/rscons/builders/preprocess_spec.rb +0 -18
  43. data/spec/rscons/builders/program_spec.rb +0 -18
  44. data/spec/rscons/cache_spec.rb +0 -271
  45. data/spec/rscons/environment_spec.rb +0 -361
  46. data/spec/rscons/varset_spec.rb +0 -163
  47. data/spec/rscons_spec.rb +0 -26
  48. data/spec/spec_helper.rb +0 -7
@@ -1,7 +0,0 @@
1
- #include <stdio.h>
2
- #include "inc.h"
3
-
4
- int main(int argc, char *argv[])
5
- {
6
- printf("The value is %d\n", THE_VALUE);
7
- }
@@ -1,6 +0,0 @@
1
- import std.stdio;
2
-
3
- void main()
4
- {
5
- writeln("Hello from D!");
6
- }
@@ -1,7 +0,0 @@
1
- #include <stdio.h>
2
- #include "header.h"
3
-
4
- int main(int argc, char *argv[])
5
- {
6
- printf("The value is %d\n", VALUE);
7
- }
@@ -1,6 +0,0 @@
1
- #ifndef HEADER_H
2
- #define HEADER_H
3
-
4
- #define VALUE 2
5
-
6
- #endif
@@ -1,8 +0,0 @@
1
- #include <stdio.h>
2
-
3
- #ifdef make_lib
4
- int main(int argc, char *argv[])
5
- {
6
- printf("Library\n");
7
- }
8
- #endif
File without changes
File without changes
@@ -1,6 +0,0 @@
1
- #include <stdio.h>
2
-
3
- int main(int argc, char *argv[])
4
- {
5
- printf("This is a simple C program\n");
6
- }
@@ -1,8 +0,0 @@
1
- #include <iostream>
2
-
3
- using namespace std;
4
-
5
- int main(int argc, char *argv[])
6
- {
7
- cout << "This is a simple C++ program" << endl;
8
- }
@@ -1,8 +0,0 @@
1
- #include <stdio.h>
2
-
3
- #ifdef ONE
4
- int main(int argc, char *argv[])
5
- {
6
- printf("This is a C program with two sources.\n");
7
- }
8
- #endif
@@ -1,3 +0,0 @@
1
- #ifdef ONE
2
- #error ONE should not be defined
3
- #endif
@@ -1,527 +0,0 @@
1
- require 'fileutils'
2
-
3
- class Dir
4
- class << self
5
- alias_method :orig_bracket, :[]
6
- end
7
- def self.[](*args)
8
- orig_bracket(*args).sort
9
- end
10
- end
11
-
12
- describe Rscons do
13
- BUILD_TEST_RUN_DIR = "build_test_run"
14
-
15
- before(:all) do
16
- FileUtils.rm_rf(BUILD_TEST_RUN_DIR)
17
- @owd = Dir.pwd
18
- end
19
-
20
- before(:each) do
21
- @output = ""
22
- $stdout.stub(:write) do |content|
23
- @output += content
24
- end
25
- $stderr.stub(:write) do |content|
26
- @output += content
27
- end
28
- end
29
-
30
- after(:each) do
31
- Dir.chdir(@owd)
32
- FileUtils.rm_rf(BUILD_TEST_RUN_DIR)
33
- end
34
-
35
- def test_dir(build_test_directory)
36
- FileUtils.cp_r("build_tests/#{build_test_directory}", BUILD_TEST_RUN_DIR)
37
- Dir.chdir(BUILD_TEST_RUN_DIR)
38
- end
39
-
40
- def file_sub(fname)
41
- contents = File.read(fname)
42
- replaced = ''
43
- contents.each_line do |line|
44
- replaced += yield(line)
45
- end
46
- File.open(fname, 'w') do |fh|
47
- fh.write(replaced)
48
- end
49
- end
50
-
51
- def lines
52
- @output.lines.map(&:rstrip).tap do |v|
53
- @output = ""
54
- end
55
- end
56
-
57
- ###########################################################################
58
- # Tests
59
- ###########################################################################
60
-
61
- it 'builds a C program with one source file' do
62
- test_dir('simple')
63
- Rscons::Environment.new do |env|
64
- env.Program('simple', Dir['*.c'])
65
- end
66
- File.exists?('simple.o').should be_true
67
- `./simple`.should == "This is a simple C program\n"
68
- end
69
-
70
- it 'prints commands as they are executed' do
71
- test_dir('simple')
72
- Rscons::Environment.new(echo: :command) do |env|
73
- env["LD"] = "gcc"
74
- env.Program('simple', Dir['*.c'])
75
- end
76
- lines.should == [
77
- 'gcc -c -o simple.o -MMD -MF simple.mf simple.c',
78
- 'gcc -o simple simple.o',
79
- ]
80
- end
81
-
82
- it 'prints short representations of the commands being executed' do
83
- test_dir('header')
84
- Rscons::Environment.new do |env|
85
- env.Program('header', Dir['*.c'])
86
- end
87
- lines.should == [
88
- 'CC header.o',
89
- 'LD header',
90
- ]
91
- end
92
-
93
- it 'builds a C program with one source file and one header file' do
94
- test_dir('header')
95
- Rscons::Environment.new do |env|
96
- env.Program('header', Dir['*.c'])
97
- end
98
- File.exists?('header.o').should be_true
99
- `./header`.should == "The value is 2\n"
100
- end
101
-
102
- it 'rebuilds a C module when a header it depends on changes' do
103
- test_dir('header')
104
- env = Rscons::Environment.new do |env|
105
- env.Program('header', Dir['*.c'])
106
- end
107
- `./header`.should == "The value is 2\n"
108
- file_sub('header.h') {|line| line.sub(/2/, '5')}
109
- env.process
110
- `./header`.should == "The value is 5\n"
111
- end
112
-
113
- it 'does not rebuild a C module when its dependencies have not changed' do
114
- test_dir('header')
115
- env = Rscons::Environment.new do |env|
116
- env.Program('header', Dir['*.c'])
117
- end
118
- `./header`.should == "The value is 2\n"
119
- lines.should == [
120
- 'CC header.o',
121
- 'LD header',
122
- ]
123
- env.process
124
- lines.should == []
125
- end
126
-
127
- it "does not rebuild a C module when only the file's timestampe has changed" do
128
- test_dir('header')
129
- env = Rscons::Environment.new do |env|
130
- env.Program('header', Dir['*.c'])
131
- end
132
- `./header`.should == "The value is 2\n"
133
- lines.should == [
134
- 'CC header.o',
135
- 'LD header',
136
- ]
137
- file_sub('header.c') {|line| line}
138
- env.process
139
- lines.should == []
140
- end
141
-
142
- it 're-links a program when the link flags have changed' do
143
- test_dir('simple')
144
- Rscons::Environment.new(echo: :command) do |env|
145
- env.Program('simple', Dir['*.c'])
146
- end
147
- lines.should == [
148
- 'gcc -c -o simple.o -MMD -MF simple.mf simple.c',
149
- 'gcc -o simple simple.o',
150
- ]
151
- Rscons::Environment.new(echo: :command) do |env|
152
- env["LIBS"] += ["c"]
153
- env.Program('simple', Dir['*.c'])
154
- end
155
- lines.should == ['gcc -o simple simple.o -lc']
156
- end
157
-
158
- it 'builds object files in a different build directory' do
159
- test_dir('build_dir')
160
- Rscons::Environment.new do |env|
161
- env.append('CPPPATH' => Dir['src/**/*/'])
162
- env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/')
163
- env.Program('build_dir', Dir['src/**/*.c'])
164
- end
165
- `./build_dir`.should == "Hello from two()\n"
166
- File.exists?('build_one/one.o').should be_true
167
- File.exists?('build_two/two.o').should be_true
168
- end
169
-
170
- it 'uses build directories before build root' do
171
- test_dir('build_dir')
172
- Rscons::Environment.new do |env|
173
- env.append('CPPPATH' => Dir['src/**/*/'])
174
- env.build_dir("src", "build")
175
- env.build_root = "build_root"
176
- env.Program('build_dir', Dir['src/**/*.c'])
177
- end
178
- lines.should == ["CC build/one/one.o", "CC build/two/two.o", "LD build_dir"]
179
- end
180
-
181
- it 'uses build_root if no build directories match' do
182
- test_dir('build_dir')
183
- Rscons::Environment.new do |env|
184
- env.append('CPPPATH' => Dir['src/**/*/'])
185
- env.build_dir("src2", "build")
186
- env.build_root = "build_root"
187
- env.Program('build_dir', Dir['src/**/*.c'])
188
- end
189
- lines.should == ["CC build_root/src/one/one.o", "CC build_root/src/two/two.o", "LD build_dir"]
190
- end
191
-
192
- it "expands target and source paths starting with ^/ to be relative to the build root" do
193
- test_dir('build_dir')
194
- Rscons::Environment.new(echo: :command) do |env|
195
- env.append('CPPPATH' => Dir['src/**/*/'])
196
- env.build_root = "build_root"
197
- FileUtils.mkdir_p(env.build_root)
198
- FileUtils.mv("src/one/one.c", "build_root")
199
- env.Object("^/one.o", "^/one.c")
200
- env.Program('build_dir', Dir['src/**/*.c'] + ["^/one.o"])
201
- end
202
- lines.should == [
203
- %q{gcc -c -o build_root/one.o -MMD -MF build_root/one.mf -Isrc/one/ -Isrc/two/ build_root/one.c},
204
- %q{gcc -c -o build_root/src/two/two.o -MMD -MF build_root/src/two/two.mf -Isrc/one/ -Isrc/two/ src/two/two.c},
205
- %q{gcc -o build_dir build_root/src/two/two.o build_root/one.o},
206
- ]
207
- end
208
-
209
- it 'cleans built files' do
210
- test_dir('build_dir')
211
- Rscons::Environment.new do |env|
212
- env.append('CPPPATH' => Dir['src/**/*/'])
213
- env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/')
214
- env.Program('build_dir', Dir['src/**/*.c'])
215
- end
216
- `./build_dir`.should == "Hello from two()\n"
217
- File.exists?('build_one/one.o').should be_true
218
- File.exists?('build_two/two.o').should be_true
219
- Rscons.clean
220
- File.exists?('build_one/one.o').should be_false
221
- File.exists?('build_two/two.o').should be_false
222
- File.exists?('build_one').should be_false
223
- File.exists?('build_two').should be_false
224
- File.exists?('src/one/one.c').should be_true
225
- end
226
-
227
- it 'does not clean created directories if other non-rscons-generated files reside there' do
228
- test_dir('build_dir')
229
- Rscons::Environment.new do |env|
230
- env.append('CPPPATH' => Dir['src/**/*/'])
231
- env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/')
232
- env.Program('build_dir', Dir['src/**/*.c'])
233
- end
234
- `./build_dir`.should == "Hello from two()\n"
235
- File.exists?('build_one/one.o').should be_true
236
- File.exists?('build_two/two.o').should be_true
237
- File.open('build_two/tmp', 'w') { |fh| fh.puts "dum" }
238
- Rscons.clean
239
- File.exists?('build_one/one.o').should be_false
240
- File.exists?('build_two/two.o').should be_false
241
- File.exists?('build_one').should be_false
242
- File.exists?('build_two').should be_true
243
- File.exists?('src/one/one.c').should be_true
244
- end
245
-
246
- it 'allows Ruby classes as custom builders to be used to construct files' do
247
- test_dir('custom_builder')
248
- class MySource < Rscons::Builder
249
- def run(target, sources, cache, env, vars)
250
- File.open(target, 'w') do |fh|
251
- fh.puts <<EOF
252
- #define THE_VALUE 5678
253
- EOF
254
- end
255
- target
256
- end
257
- end
258
-
259
- Rscons::Environment.new do |env|
260
- env.add_builder(MySource.new)
261
- env.MySource('inc.h', [])
262
- env.Program('program', Dir['*.c'])
263
- end
264
-
265
- lines.should == ['CC program.o', 'LD program']
266
- File.exists?('inc.h').should be_true
267
- `./program`.should == "The value is 5678\n"
268
- end
269
-
270
- it 'supports custom builders with multiple targets' do
271
- test_dir('custom_builder')
272
- class CHGen < Rscons::Builder
273
- def run(target, sources, cache, env, vars)
274
- c_fname = target
275
- h_fname = target.sub(/\.c$/, ".h")
276
- unless cache.up_to_date?([c_fname, h_fname], "", sources, env)
277
- puts "CHGen #{c_fname}"
278
- File.open(c_fname, "w") {|fh| fh.puts "int THE_VALUE = 42;"}
279
- File.open(h_fname, "w") {|fh| fh.puts "extern int THE_VALUE;"}
280
- cache.register_build([c_fname, h_fname], "", sources, env)
281
- end
282
- target
283
- end
284
- end
285
-
286
- env = Rscons::Environment.new do |env|
287
- env.add_builder(CHGen.new)
288
- env.CHGen("inc.c", ["program.c"])
289
- env.Program("program", Dir["*.c"] + ["inc.c"])
290
- end
291
-
292
- lines.should == ["CHGen inc.c", "CC program.o", "CC inc.o", "LD program"]
293
- File.exists?("inc.c").should be_true
294
- File.exists?("inc.h").should be_true
295
- `./program`.should == "The value is 42\n"
296
-
297
- File.open("inc.c", "w") {|fh| fh.puts "int THE_VALUE = 33;"}
298
- env.process
299
- lines.should == ["CHGen inc.c"]
300
- `./program`.should == "The value is 42\n"
301
- end
302
-
303
- it 'allows cloning Environment objects' do
304
- test_dir('clone_env')
305
-
306
- debug = Rscons::Environment.new(echo: :command) do |env|
307
- env.build_dir('src', 'debug')
308
- env['CFLAGS'] = '-O2'
309
- env['CPPFLAGS'] = '-DSTRING="Debug Version"'
310
- env.Program('program-debug', Dir['src/*.c'])
311
- end
312
-
313
- release = debug.clone do |env|
314
- env["CPPFLAGS"] = '-DSTRING="Release Version"'
315
- env.build_dir('src', 'release')
316
- env.Program('program-release', Dir['src/*.c'])
317
- end
318
-
319
- lines.should == [
320
- %q{gcc -c -o debug/program.o -MMD -MF debug/program.mf '-DSTRING="Debug Version"' -O2 src/program.c},
321
- %q{gcc -o program-debug debug/program.o},
322
- %q{gcc -c -o release/program.o -MMD -MF release/program.mf '-DSTRING="Release Version"' -O2 src/program.c},
323
- %q{gcc -o program-release release/program.o},
324
- ]
325
- end
326
-
327
- it 'allows cloning all attributes of an Environment object' do
328
- test_dir('clone_env')
329
-
330
- env1 = Rscons::Environment.new(echo: :command) do |env|
331
- env.build_dir('src', 'build')
332
- env['CFLAGS'] = '-O2'
333
- env.add_build_hook do |build_op|
334
- build_op[:vars]['CPPFLAGS'] = '-DSTRING="Hello"'
335
- end
336
- env.Program('program', Dir['src/*.c'])
337
- end
338
-
339
- env2 = env1.clone(clone: :all) do |env|
340
- env.Program('program2', Dir['src/*.c'])
341
- end
342
-
343
- lines.should == [
344
- %q{gcc -c -o build/program.o -MMD -MF build/program.mf -DSTRING="Hello" -O2 src/program.c},
345
- %q{gcc -o program build/program.o},
346
- %q{gcc -o program2 build/program.o},
347
- ]
348
- end
349
-
350
- it 'builds a C++ program with one source file' do
351
- test_dir('simple_cc')
352
- Rscons::Environment.new do |env|
353
- env.Program('simple', Dir['*.cc'])
354
- end
355
- File.exists?('simple.o').should be_true
356
- `./simple`.should == "This is a simple C++ program\n"
357
- end
358
-
359
- it 'allows overriding construction variables for individual builder calls' do
360
- test_dir('two_sources')
361
- Rscons::Environment.new(echo: :command) do |env|
362
- env.Object("one.o", "one.c", 'CPPFLAGS' => ['-DONE'])
363
- env.Program('two_sources', ['one.o', 'two.c'])
364
- end
365
- lines.should == [
366
- 'gcc -c -o one.o -MMD -MF one.mf -DONE one.c',
367
- 'gcc -c -o two.o -MMD -MF two.mf two.c',
368
- 'gcc -o two_sources one.o two.o',
369
- ]
370
- File.exists?('two_sources').should be_true
371
- `./two_sources`.should == "This is a C program with two sources.\n"
372
- end
373
-
374
- it 'builds a static library archive' do
375
- test_dir('library')
376
- Rscons::Environment.new(echo: :command) do |env|
377
- env.Program('library', ['lib.a', 'three.c'])
378
- env.Library("lib.a", ['one.c', 'two.c'], 'CPPFLAGS' => ['-Dmake_lib'])
379
- end
380
- lines.should == [
381
- 'gcc -c -o one.o -MMD -MF one.mf -Dmake_lib one.c',
382
- 'gcc -c -o two.o -MMD -MF two.mf -Dmake_lib two.c',
383
- 'ar rcs lib.a one.o two.o',
384
- 'gcc -c -o three.o -MMD -MF three.mf three.c',
385
- 'gcc -o library lib.a three.o',
386
- ]
387
- File.exists?('library').should be_true
388
- `ar t lib.a`.should == "one.o\ntwo.o\n"
389
- end
390
-
391
- it 'supports build hooks to override construction variables' do
392
- test_dir("build_dir")
393
- Rscons::Environment.new(echo: :command) do |env|
394
- env.append('CPPPATH' => Dir['src/**/*/'])
395
- env.build_dir(%r{^src/([^/]+)/}, 'build_\\1/')
396
- env.add_build_hook do |build_op|
397
- if build_op[:target] =~ %r{build_one/.*\.o}
398
- build_op[:vars]["CFLAGS"] << "-O1"
399
- elsif build_op[:target] =~ %r{build_two/.*\.o}
400
- build_op[:vars]["CFLAGS"] << "-O2"
401
- end
402
- end
403
- env.Program('build_hook', Dir['src/**/*.c'])
404
- end
405
- `./build_hook`.should == "Hello from two()\n"
406
- lines.should =~ [
407
- 'gcc -c -o build_one/one.o -MMD -MF build_one/one.mf -Isrc/one/ -Isrc/two/ -O1 src/one/one.c',
408
- 'gcc -c -o build_two/two.o -MMD -MF build_two/two.mf -Isrc/one/ -Isrc/two/ -O2 src/two/two.c',
409
- 'gcc -o build_hook build_one/one.o build_two/two.o',
410
- ]
411
- end
412
-
413
- it 'rebuilds when user-specified dependencies change' do
414
- test_dir('simple')
415
- Rscons::Environment.new do |env|
416
- env.Program('simple', Dir['*.c'])
417
- File.open("file.ld", "w") do |fh|
418
- fh.puts("foo")
419
- end
420
- env.depends('simple', 'file.ld')
421
- end
422
- lines.should == ["CC simple.o", "LD simple"]
423
- File.exists?('simple.o').should be_true
424
- `./simple`.should == "This is a simple C program\n"
425
- Rscons::Environment.new do |env|
426
- env.Program('simple', Dir['*.c'])
427
- File.open("file.ld", "w") do |fh|
428
- fh.puts("bar")
429
- end
430
- env.depends('simple', 'file.ld')
431
- end
432
- lines.should == ["LD simple"]
433
- Rscons::Environment.new do |env|
434
- env.Program('simple', Dir['*.c'])
435
- File.unlink("file.ld")
436
- end
437
- lines.should == ["LD simple"]
438
- Rscons::Environment.new do |env|
439
- env.Program('simple', Dir['*.c'])
440
- end
441
- lines.should == []
442
- end
443
-
444
- unless ENV["omit_gdc_tests"]
445
- it "supports building D sources" do
446
- test_dir("d")
447
- Rscons::Environment.new(echo: :command) do |env|
448
- env.Program("hello-d", Dir["*.d"])
449
- end
450
- lines.should == [
451
- "gdc -c -o main.o main.d",
452
- "gdc -o hello-d main.o",
453
- ]
454
- `./hello-d`.rstrip.should == "Hello from D!"
455
- end
456
- end
457
-
458
- it "supports disassembling object files" do
459
- test_dir("simple")
460
- Rscons::Environment.new do |env|
461
- env.Object("simple.o", "simple.c")
462
- env.Disassemble("simple.txt", "simple.o")
463
- end
464
- File.exists?("simple.txt").should be_true
465
- File.read("simple.txt").should =~ /Disassembly of section .text:/
466
- end
467
-
468
- it "supports preprocessing C sources" do
469
- test_dir("simple")
470
- Rscons::Environment.new do |env|
471
- env.Preprocess("simplepp.c", "simple.c")
472
- env.Program("simple", "simplepp.c")
473
- end
474
- File.read("simplepp.c").should =~ /# \d+ "simple.c"/
475
- `./simple`.should == "This is a simple C program\n"
476
- end
477
-
478
- it "supports preprocessing C++ sources" do
479
- test_dir("simple_cc")
480
- Rscons::Environment.new do |env|
481
- env.Preprocess("simplepp.cc", "simple.cc")
482
- env.Program("simple", "simplepp.cc")
483
- end
484
- File.read("simplepp.cc").should =~ /# \d+ "simple.cc"/
485
- `./simple`.should == "This is a simple C++ program\n"
486
- end
487
-
488
- it "supports invoking builders with no sources and a build_root defined" do
489
- class TestBuilder < Rscons::Builder
490
- def run(target, sources, cache, env, vars)
491
- target
492
- end
493
- end
494
- test_dir("simple")
495
- Rscons::Environment.new do |env|
496
- env.build_root = "build"
497
- env.add_builder(TestBuilder.new)
498
- env.TestBuilder("file")
499
- end
500
- end
501
-
502
- it "expands construction variables in builder target and sources before invoking the builder" do
503
- test_dir('custom_builder')
504
- class MySource < Rscons::Builder
505
- def run(target, sources, cache, env, vars)
506
- File.open(target, 'w') do |fh|
507
- fh.puts <<EOF
508
- #define THE_VALUE 678
509
- EOF
510
- end
511
- target
512
- end
513
- end
514
-
515
- Rscons::Environment.new do |env|
516
- env["hdr"] = "inc.h"
517
- env["src"] = "program.c"
518
- env.add_builder(MySource.new)
519
- env.MySource('${hdr}')
520
- env.Program('program', "${src}")
521
- end
522
-
523
- lines.should == ['CC program.o', 'LD program']
524
- File.exists?('inc.h').should be_true
525
- `./program`.should == "The value is 678\n"
526
- end
527
- end