rscons 1.4.3 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rscons.rb +75 -5
- data/lib/rscons/build_target.rb +36 -0
- data/lib/rscons/builder.rb +41 -3
- data/lib/rscons/builders/cfile.rb +15 -0
- data/lib/rscons/builders/disassemble.rb +15 -0
- data/lib/rscons/builders/library.rb +17 -2
- data/lib/rscons/builders/object.rb +37 -5
- data/lib/rscons/builders/preprocess.rb +15 -0
- data/lib/rscons/builders/program.rb +42 -2
- data/lib/rscons/cache.rb +26 -6
- data/lib/rscons/environment.rb +259 -19
- data/lib/rscons/varset.rb +33 -10
- data/lib/rscons/version.rb +1 -1
- data/rscons.gemspec +8 -10
- metadata +38 -103
- checksums.yaml +0 -15
- data/.gitignore +0 -18
- data/.rspec +0 -2
- data/Gemfile +0 -4
- data/README.md +0 -384
- data/Rakefile.rb +0 -26
- data/build_tests/build_dir/src/one/one.c +0 -6
- data/build_tests/build_dir/src/two/two.c +0 -7
- data/build_tests/build_dir/src/two/two.h +0 -6
- data/build_tests/clone_env/src/program.c +0 -6
- data/build_tests/custom_builder/program.c +0 -7
- data/build_tests/d/main.d +0 -6
- data/build_tests/header/header.c +0 -7
- data/build_tests/header/header.h +0 -6
- data/build_tests/library/one.c +0 -8
- data/build_tests/library/three.c +0 -0
- data/build_tests/library/two.c +0 -0
- data/build_tests/simple/simple.c +0 -6
- data/build_tests/simple_cc/simple.cc +0 -8
- data/build_tests/two_sources/one.c +0 -8
- data/build_tests/two_sources/two.c +0 -3
- data/spec/build_tests_spec.rb +0 -527
- data/spec/rscons/builders/cfile_spec.rb +0 -28
- data/spec/rscons/builders/disassemble_spec.rb +0 -17
- data/spec/rscons/builders/library_spec.rb +0 -18
- data/spec/rscons/builders/object_spec.rb +0 -23
- data/spec/rscons/builders/preprocess_spec.rb +0 -18
- data/spec/rscons/builders/program_spec.rb +0 -18
- data/spec/rscons/cache_spec.rb +0 -271
- data/spec/rscons/environment_spec.rb +0 -361
- data/spec/rscons/varset_spec.rb +0 -163
- data/spec/rscons_spec.rb +0 -26
- data/spec/spec_helper.rb +0 -7
@@ -1,28 +0,0 @@
|
|
1
|
-
module Rscons
|
2
|
-
module Builders
|
3
|
-
describe CFile do
|
4
|
-
let(:env) {Environment.new}
|
5
|
-
subject {CFile.new}
|
6
|
-
|
7
|
-
it "invokes bison to create a .c file from a .y file" do
|
8
|
-
subject.should_receive(:standard_build).with("YACC parser.c", "parser.c", ["bison", "-d", "-o", "parser.c", "parser.y"], ["parser.y"], env, :cache)
|
9
|
-
subject.run("parser.c", ["parser.y"], :cache, env, {})
|
10
|
-
end
|
11
|
-
|
12
|
-
it "invokes a custom lexer to create a .cc file from a .ll file" do
|
13
|
-
env["LEX"] = "custom_lex"
|
14
|
-
subject.should_receive(:standard_build).with("LEX lexer.cc", "lexer.cc", ["custom_lex", "-o", "lexer.cc", "parser.ll"], ["parser.ll"], env, :cache)
|
15
|
-
subject.run("lexer.cc", ["parser.ll"], :cache, env, {})
|
16
|
-
end
|
17
|
-
|
18
|
-
it "supports overriding construction variables" do
|
19
|
-
subject.should_receive(:standard_build).with("LEX lexer.c", "lexer.c", ["hi", "parser.l"], ["parser.l"], env, :cache)
|
20
|
-
subject.run("lexer.c", ["parser.l"], :cache, env, "LEX_CMD" => ["hi", "${_SOURCES}"])
|
21
|
-
end
|
22
|
-
|
23
|
-
it "raises an error when an unknown source file is specified" do
|
24
|
-
expect {subject.run("file.c", ["foo.bar"], :cache, env, {})}.to raise_error /Unknown source file .foo.bar. for CFile builder/
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Rscons
|
2
|
-
module Builders
|
3
|
-
describe Disassemble do
|
4
|
-
let(:env) {Environment.new}
|
5
|
-
subject {Disassemble.new}
|
6
|
-
|
7
|
-
it "supports overriding DISASM_CMD construction variable" do
|
8
|
-
cache = "cache"
|
9
|
-
cache.stub(:up_to_date?) { false }
|
10
|
-
cache.stub(:mkdir_p) { }
|
11
|
-
cache.stub(:register_build) { }
|
12
|
-
env.should_receive(:execute).with("Disassemble a_file.txt", ["my_disasm", "a_file.exe"], anything).and_return(true)
|
13
|
-
subject.run("a_file.txt", ["a_file.exe"], cache, env, "DISASM_CMD" => ["my_disasm", "${_SOURCES}"])
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Rscons
|
2
|
-
module Builders
|
3
|
-
describe Library do
|
4
|
-
let(:env) {Environment.new}
|
5
|
-
subject {Library.new}
|
6
|
-
|
7
|
-
it "supports overriding AR construction variable" do
|
8
|
-
subject.should_receive(:standard_build).with("AR prog.a", "prog.a", ["sp-ar", "rcs", "prog.a", "prog.o"], ["prog.o"], env, :cache)
|
9
|
-
subject.run("prog.a", ["prog.o"], :cache, env, "AR" => "sp-ar")
|
10
|
-
end
|
11
|
-
|
12
|
-
it "supports overriding ARCMD construction variable" do
|
13
|
-
subject.should_receive(:standard_build).with("AR prog.a", "prog.a", ["special", "AR!", "prog.o"], ["prog.o"], env, :cache)
|
14
|
-
subject.run("prog.a", ["prog.o"], :cache, env, "ARCMD" => ["special", "AR!", "${_SOURCES}"])
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Rscons
|
2
|
-
module Builders
|
3
|
-
describe Object do
|
4
|
-
let(:env) {Environment.new}
|
5
|
-
subject {Object.new}
|
6
|
-
|
7
|
-
it "supports overriding CCCMD construction variable" do
|
8
|
-
cache = "cache"
|
9
|
-
cache.stub(:up_to_date?) { false }
|
10
|
-
cache.stub(:mkdir_p) { }
|
11
|
-
cache.stub(:register_build) { }
|
12
|
-
FileUtils.stub(:rm_f) { }
|
13
|
-
File.stub(:exists?) { false }
|
14
|
-
env.should_receive(:execute).with("CC mod.o", ["llc", "mod.c"]).and_return(true)
|
15
|
-
subject.run("mod.o", ["mod.c"], cache, env, "CCCMD" => ["llc", "${_SOURCES}"])
|
16
|
-
end
|
17
|
-
|
18
|
-
it "raises an error when given a source file with an unknown suffix" do
|
19
|
-
expect { subject.run("mod.o", ["mod.xyz"], :cache, env, {}) }.to raise_error /unknown input file type: "mod.xyz"/
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Rscons
|
2
|
-
module Builders
|
3
|
-
describe Preprocess do
|
4
|
-
let(:env) {Environment.new}
|
5
|
-
subject {Preprocess.new}
|
6
|
-
|
7
|
-
it "supports overriding CC construction variable" do
|
8
|
-
subject.should_receive(:standard_build).with("Preprocess module.pp", "module.pp", ["my_cpp", "-E", "-o", "module.pp", "module.c"], ["module.c"], env, :cache)
|
9
|
-
subject.run("module.pp", ["module.c"], :cache, env, "CC" => "my_cpp")
|
10
|
-
end
|
11
|
-
|
12
|
-
it "supports overriding CPP_CMD construction variable" do
|
13
|
-
subject.should_receive(:standard_build).with("Preprocess module.pp", "module.pp", ["my_cpp", "module.c"], ["module.c"], env, :cache)
|
14
|
-
subject.run("module.pp", ["module.c"], :cache, env, "CPP_CMD" => ["my_cpp", "${_SOURCES}"])
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Rscons
|
2
|
-
module Builders
|
3
|
-
describe Program do
|
4
|
-
let(:env) {Environment.new}
|
5
|
-
subject {Program.new}
|
6
|
-
|
7
|
-
it "supports overriding CC construction variable" do
|
8
|
-
subject.should_receive(:standard_build).with("LD prog", "prog", ["sp-c++", "-o", "prog", "prog.o"], ["prog.o"], env, :cache)
|
9
|
-
subject.run("prog", ["prog.o"], :cache, env, "CC" => "sp-c++")
|
10
|
-
end
|
11
|
-
|
12
|
-
it "supports overriding LDCMD construction variable" do
|
13
|
-
subject.should_receive(:standard_build).with("LD prog", "prog", ["special", "LD!", "prog.o"], ["prog.o"], env, :cache)
|
14
|
-
subject.run("prog", ["prog.o"], :cache, env, "LDCMD" => ["special", "LD!", "${_SOURCES}"])
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/spec/rscons/cache_spec.rb
DELETED
@@ -1,271 +0,0 @@
|
|
1
|
-
module Rscons
|
2
|
-
describe Cache do
|
3
|
-
before do
|
4
|
-
File.stub(:read) { nil }
|
5
|
-
end
|
6
|
-
|
7
|
-
def build_from(cache)
|
8
|
-
JSON.stub(:load) do
|
9
|
-
cache
|
10
|
-
end
|
11
|
-
Cache.instance.tap do |cache|
|
12
|
-
cache.send(:initialize!)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe "#initialize" do
|
17
|
-
context "when corrupt" do
|
18
|
-
it "prints a warning and defaults to an empty hash" do
|
19
|
-
JSON.should_receive(:load).and_return("string")
|
20
|
-
$stderr.should_receive(:puts).with(/Warning:.*was.corrupt/)
|
21
|
-
c = Cache.instance
|
22
|
-
c.send(:initialize!)
|
23
|
-
c.instance_variable_get(:@cache).is_a?(Hash).should be_true
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "#clear" do
|
29
|
-
it "removes the cache file" do
|
30
|
-
FileUtils.should_receive(:rm_f).with(Cache::CACHE_FILE)
|
31
|
-
JSON.stub(:load) {{}}
|
32
|
-
Cache.instance.clear
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "#write" do
|
37
|
-
it "should fill in 'version' and write to file" do
|
38
|
-
cache = {}
|
39
|
-
fh = $stdout
|
40
|
-
fh.should_receive(:puts)
|
41
|
-
File.should_receive(:open).and_yield(fh)
|
42
|
-
build_from(cache).write
|
43
|
-
cache["version"].should == Rscons::VERSION
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe "#up_to_date?" do
|
48
|
-
empty_env = "env"
|
49
|
-
before do
|
50
|
-
empty_env.stub(:get_user_deps) { nil }
|
51
|
-
end
|
52
|
-
|
53
|
-
it "returns false when target file does not exist" do
|
54
|
-
File.should_receive(:exists?).with("target").and_return(false)
|
55
|
-
build_from({}).up_to_date?("target", "command", [], empty_env).should be_false
|
56
|
-
end
|
57
|
-
|
58
|
-
it "returns false when target is not registered in the cache" do
|
59
|
-
File.should_receive(:exists?).with("target").and_return(true)
|
60
|
-
build_from({}).up_to_date?("target", "command", [], empty_env).should be_false
|
61
|
-
end
|
62
|
-
|
63
|
-
it "returns false when the target's checksum does not match" do
|
64
|
-
_cache = {"targets" => {"target" => {"checksum" => "abc"}}}
|
65
|
-
cache = build_from(_cache)
|
66
|
-
File.should_receive(:exists?).with("target").and_return(true)
|
67
|
-
cache.should_receive(:calculate_checksum).with("target").and_return("def")
|
68
|
-
cache.up_to_date?("target", "command", [], empty_env).should be_false
|
69
|
-
end
|
70
|
-
|
71
|
-
it "returns false when the build command has changed" do
|
72
|
-
_cache = {"targets" => {"target" => {"checksum" => "abc", "command" => Digest::MD5.hexdigest("old command".inspect)}}}
|
73
|
-
cache = build_from(_cache)
|
74
|
-
File.should_receive(:exists?).with("target").and_return(true)
|
75
|
-
cache.should_receive(:calculate_checksum).with("target").and_return("abc")
|
76
|
-
cache.up_to_date?("target", "command", [], empty_env).should be_false
|
77
|
-
end
|
78
|
-
|
79
|
-
it "returns false when there is a new dependency" do
|
80
|
-
_cache = {"targets" => {"target" => {"checksum" => "abc",
|
81
|
-
"command" => Digest::MD5.hexdigest("command".inspect),
|
82
|
-
"deps" => [{"fname" => "dep.1"}]}}}
|
83
|
-
cache = build_from(_cache)
|
84
|
-
File.should_receive(:exists?).with("target").and_return(true)
|
85
|
-
cache.should_receive(:calculate_checksum).with("target").and_return("abc")
|
86
|
-
cache.up_to_date?("target", "command", ["dep.1", "dep.2"], empty_env).should be_false
|
87
|
-
end
|
88
|
-
|
89
|
-
it "returns false when a dependency's checksum has changed" do
|
90
|
-
_cache = {"targets" => {"target" => {"checksum" => "abc",
|
91
|
-
"command" => Digest::MD5.hexdigest("command".inspect),
|
92
|
-
"deps" => [{"fname" => "dep.1",
|
93
|
-
"checksum" => "dep.1.chk"},
|
94
|
-
{"fname" => "dep.2",
|
95
|
-
"checksum" => "dep.2.chk"},
|
96
|
-
{"fname" => "extra.dep",
|
97
|
-
"checksum" => "extra.dep.chk"}],
|
98
|
-
"user_deps" => []}}}
|
99
|
-
cache = build_from(_cache)
|
100
|
-
File.should_receive(:exists?).with("target").and_return(true)
|
101
|
-
cache.should_receive(:calculate_checksum).with("target").and_return("abc")
|
102
|
-
cache.should_receive(:calculate_checksum).with("dep.1").and_return("dep.1.chk")
|
103
|
-
cache.should_receive(:calculate_checksum).with("dep.2").and_return("dep.2.changed")
|
104
|
-
cache.up_to_date?("target", "command", ["dep.1", "dep.2"], empty_env).should be_false
|
105
|
-
end
|
106
|
-
|
107
|
-
it "returns false with strict_deps=true when cache has an extra dependency" do
|
108
|
-
_cache = {"targets" => {"target" => {"checksum" => "abc",
|
109
|
-
"command" => Digest::MD5.hexdigest("command".inspect),
|
110
|
-
"deps" => [{"fname" => "dep.1",
|
111
|
-
"checksum" => "dep.1.chk"},
|
112
|
-
{"fname" => "dep.2",
|
113
|
-
"checksum" => "dep.2.chk"},
|
114
|
-
{"fname" => "extra.dep",
|
115
|
-
"checksum" => "extra.dep.chk"}],
|
116
|
-
"user_deps" => []}}}
|
117
|
-
cache = build_from(_cache)
|
118
|
-
File.should_receive(:exists?).with("target").and_return(true)
|
119
|
-
cache.should_receive(:calculate_checksum).with("target").and_return("abc")
|
120
|
-
cache.up_to_date?("target", "command", ["dep.1", "dep.2"], empty_env, strict_deps: true).should be_false
|
121
|
-
end
|
122
|
-
|
123
|
-
it "returns false when there is a new user dependency" do
|
124
|
-
_cache = {"targets" => {"target" => {"checksum" => "abc",
|
125
|
-
"command" => Digest::MD5.hexdigest("command".inspect),
|
126
|
-
"deps" => [{"fname" => "dep.1"}],
|
127
|
-
"user_deps" => []}}}
|
128
|
-
cache = build_from(_cache)
|
129
|
-
env = "env"
|
130
|
-
env.should_receive(:get_user_deps).with("target").and_return(["file.ld"])
|
131
|
-
File.should_receive(:exists?).with("target").and_return(true)
|
132
|
-
cache.should_receive(:calculate_checksum).with("target").and_return("abc")
|
133
|
-
cache.up_to_date?("target", "command", ["dep.1"], env).should be_false
|
134
|
-
end
|
135
|
-
|
136
|
-
it "returns false when a user dependency checksum has changed" do
|
137
|
-
_cache = {"targets" => {"target" => {"checksum" => "abc",
|
138
|
-
"command" => Digest::MD5.hexdigest("command".inspect),
|
139
|
-
"deps" => [{"fname" => "dep.1",
|
140
|
-
"checksum" => "dep.1.chk"},
|
141
|
-
{"fname" => "dep.2",
|
142
|
-
"checksum" => "dep.2.chk"},
|
143
|
-
{"fname" => "extra.dep",
|
144
|
-
"checksum" => "extra.dep.chk"}],
|
145
|
-
"user_deps" => [{"fname" => "user.dep",
|
146
|
-
"checksum" => "user.dep.chk"}]}}}
|
147
|
-
cache = build_from(_cache)
|
148
|
-
env = "env"
|
149
|
-
env.should_receive(:get_user_deps).with("target").and_return(["user.dep"])
|
150
|
-
File.should_receive(:exists?).with("target").and_return(true)
|
151
|
-
cache.should_receive(:calculate_checksum).with("target").and_return("abc")
|
152
|
-
cache.should_receive(:calculate_checksum).with("dep.1").and_return("dep.1.chk")
|
153
|
-
cache.should_receive(:calculate_checksum).with("dep.2").and_return("dep.2.chk")
|
154
|
-
cache.should_receive(:calculate_checksum).with("extra.dep").and_return("extra.dep.chk")
|
155
|
-
cache.should_receive(:calculate_checksum).with("user.dep").and_return("INCORRECT")
|
156
|
-
cache.up_to_date?("target", "command", ["dep.1", "dep.2"], env).should be_false
|
157
|
-
end
|
158
|
-
|
159
|
-
it "returns true when no condition for false is met" do
|
160
|
-
_cache = {"targets" => {"target" => {"checksum" => "abc",
|
161
|
-
"command" => Digest::MD5.hexdigest("command".inspect),
|
162
|
-
"deps" => [{"fname" => "dep.1",
|
163
|
-
"checksum" => "dep.1.chk"},
|
164
|
-
{"fname" => "dep.2",
|
165
|
-
"checksum" => "dep.2.chk"},
|
166
|
-
{"fname" => "extra.dep",
|
167
|
-
"checksum" => "extra.dep.chk"}],
|
168
|
-
"user_deps" => []}}}
|
169
|
-
cache = build_from(_cache)
|
170
|
-
File.should_receive(:exists?).with("target").and_return(true)
|
171
|
-
cache.should_receive(:calculate_checksum).with("target").and_return("abc")
|
172
|
-
cache.should_receive(:calculate_checksum).with("dep.1").and_return("dep.1.chk")
|
173
|
-
cache.should_receive(:calculate_checksum).with("dep.2").and_return("dep.2.chk")
|
174
|
-
cache.should_receive(:calculate_checksum).with("extra.dep").and_return("extra.dep.chk")
|
175
|
-
cache.up_to_date?("target", "command", ["dep.1", "dep.2"], empty_env).should be_true
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
describe "#register_build" do
|
180
|
-
it "stores the given information in the cache" do
|
181
|
-
_cache = {}
|
182
|
-
cache = build_from(_cache)
|
183
|
-
env = "env"
|
184
|
-
env.should_receive(:get_user_deps).with("the target").and_return(["user.dep"])
|
185
|
-
cache.should_receive(:calculate_checksum).with("the target").and_return("the checksum")
|
186
|
-
cache.should_receive(:calculate_checksum).with("dep 1").and_return("dep 1 checksum")
|
187
|
-
cache.should_receive(:calculate_checksum).with("dep 2").and_return("dep 2 checksum")
|
188
|
-
cache.should_receive(:calculate_checksum).with("user.dep").and_return("user.dep checksum")
|
189
|
-
cache.register_build("the target", "the command", ["dep 1", "dep 2"], env)
|
190
|
-
cached_target = cache.instance_variable_get(:@cache)["targets"]["the target"]
|
191
|
-
cached_target.should_not be_nil
|
192
|
-
cached_target["command"].should == Digest::MD5.hexdigest("the command".inspect)
|
193
|
-
cached_target["checksum"].should == "the checksum"
|
194
|
-
cached_target["deps"].should == [
|
195
|
-
{"fname" => "dep 1", "checksum" => "dep 1 checksum"},
|
196
|
-
{"fname" => "dep 2", "checksum" => "dep 2 checksum"},
|
197
|
-
]
|
198
|
-
cached_target["user_deps"].should == [
|
199
|
-
{"fname" => "user.dep", "checksum" => "user.dep checksum"},
|
200
|
-
]
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
describe "#targets" do
|
205
|
-
it "returns a list of targets that are cached" do
|
206
|
-
cache = {"targets" => {"t1" => {}, "t2" => {}, "t3" => {}}}
|
207
|
-
build_from(cache).targets.should == ["t1", "t2", "t3"]
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
describe "#mkdir_p" do
|
212
|
-
it "makes directories and records any created in the cache" do
|
213
|
-
_cache = {}
|
214
|
-
cache = build_from(_cache)
|
215
|
-
File.should_receive(:exists?).with("one").and_return(true)
|
216
|
-
File.should_receive(:exists?).with("one/two").and_return(false)
|
217
|
-
FileUtils.should_receive(:mkdir).with("one/two")
|
218
|
-
File.should_receive(:exists?).with("one/two/three").and_return(false)
|
219
|
-
FileUtils.should_receive(:mkdir).with("one/two/three")
|
220
|
-
File.should_receive(:exists?).with("one").and_return(true)
|
221
|
-
File.should_receive(:exists?).with("one/two").and_return(true)
|
222
|
-
File.should_receive(:exists?).with("one/two/four").and_return(false)
|
223
|
-
FileUtils.should_receive(:mkdir).with("one/two/four")
|
224
|
-
cache.mkdir_p("one/two/three")
|
225
|
-
cache.mkdir_p("one\\two\\four")
|
226
|
-
cache.directories.should == ["one/two", "one/two/three", "one/two/four"]
|
227
|
-
end
|
228
|
-
|
229
|
-
it "handles absolute paths" do
|
230
|
-
_cache = {}
|
231
|
-
cache = build_from(_cache)
|
232
|
-
File.should_receive(:exists?).with("/one").and_return(true)
|
233
|
-
File.should_receive(:exists?).with("/one/two").and_return(false)
|
234
|
-
FileUtils.should_receive(:mkdir).with("/one/two")
|
235
|
-
cache.mkdir_p("/one/two")
|
236
|
-
cache.directories.should == ["/one/two"]
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
describe "#directories" do
|
241
|
-
it "returns a list of directories that are cached" do
|
242
|
-
_cache = {"directories" => {"dir1" => true, "dir2" => true}}
|
243
|
-
build_from(_cache).directories.should == ["dir1", "dir2"]
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
describe "#lookup_checksum" do
|
248
|
-
it "does not re-calculate the checksum when it is already cached" do
|
249
|
-
cache = build_from({})
|
250
|
-
cache.instance_variable_set(:@lookup_checksums, {"f1" => "f1.chk"})
|
251
|
-
cache.should_not_receive(:calculate_checksum)
|
252
|
-
cache.send(:lookup_checksum, "f1").should == "f1.chk"
|
253
|
-
end
|
254
|
-
|
255
|
-
it "calls calculate_checksum when the checksum is not cached" do
|
256
|
-
cache = build_from({})
|
257
|
-
cache.should_receive(:calculate_checksum).with("f1").and_return("ck")
|
258
|
-
cache.send(:lookup_checksum, "f1").should == "ck"
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
describe "#calculate_checksum" do
|
263
|
-
it "calculates the MD5 of the file contents" do
|
264
|
-
contents = "contents"
|
265
|
-
File.should_receive(:read).with("fname", mode: "rb").and_return(contents)
|
266
|
-
Digest::MD5.should_receive(:hexdigest).with(contents).and_return("the_checksum")
|
267
|
-
build_from({}).send(:calculate_checksum, "fname").should == "the_checksum"
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
@@ -1,361 +0,0 @@
|
|
1
|
-
module Rscons
|
2
|
-
describe Environment do
|
3
|
-
describe "#initialize" do
|
4
|
-
it "adds the default builders when they are not excluded" do
|
5
|
-
env = Environment.new
|
6
|
-
env.builders.size.should be > 0
|
7
|
-
env.builders.map {|name, builder| builder.is_a?(Builder)}.all?.should be_true
|
8
|
-
env.builders.find {|name, builder| name == "Object"}.should_not be_nil
|
9
|
-
env.builders.find {|name, builder| name == "Program"}.should_not be_nil
|
10
|
-
env.builders.find {|name, builder| name == "Library"}.should_not be_nil
|
11
|
-
end
|
12
|
-
|
13
|
-
it "excludes the default builders with exclude_builders: :all" do
|
14
|
-
env = Environment.new(exclude_builders: true)
|
15
|
-
env.builders.size.should == 0
|
16
|
-
end
|
17
|
-
|
18
|
-
context "when a block is given" do
|
19
|
-
it "yields self and invokes #process()" do
|
20
|
-
env = Environment.new do |env|
|
21
|
-
env.should_receive(:process)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe "#clone" do
|
28
|
-
it 'should create unique copies of each construction variable' do
|
29
|
-
env = Environment.new
|
30
|
-
env["CPPPATH"] << "path1"
|
31
|
-
env2 = env.clone
|
32
|
-
env2["CPPPATH"] << "path2"
|
33
|
-
env["CPPPATH"].should == ["path1"]
|
34
|
-
env2["CPPPATH"].should == ["path1", "path2"]
|
35
|
-
end
|
36
|
-
|
37
|
-
context "when a block is given" do
|
38
|
-
it "yields self and invokes #process()" do
|
39
|
-
env = Environment.new
|
40
|
-
env.clone do |env2|
|
41
|
-
env2.should_receive(:process)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe "#add_builder" do
|
48
|
-
it "adds the builder to the list of builders" do
|
49
|
-
env = Environment.new(exclude_builders: true)
|
50
|
-
env.builders.keys.should == []
|
51
|
-
env.add_builder(Rscons::Builders::Object.new)
|
52
|
-
env.builders.keys.should == ["Object"]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
describe "#get_build_fname" do
|
57
|
-
context "with no build directories" do
|
58
|
-
it "returns the name of the source file with suffix changed" do
|
59
|
-
env = Environment.new
|
60
|
-
env.get_build_fname("src/dir/file.c", ".o").should == "src/dir/file.o"
|
61
|
-
env.get_build_fname("src\\dir\\other.d", ".a").should == "src/dir/other.a"
|
62
|
-
env.get_build_fname("source.cc", ".o").should == "source.o"
|
63
|
-
end
|
64
|
-
|
65
|
-
context "with a build_root" do
|
66
|
-
it "uses the build_root unless the path is absolute" do
|
67
|
-
env = Environment.new
|
68
|
-
env.build_root = "build/proj"
|
69
|
-
env.get_build_fname("src/dir/file.c", ".o").should == "build/proj/src/dir/file.o"
|
70
|
-
env.get_build_fname("/some/lib.c", ".a").should == "/some/lib.a"
|
71
|
-
env.get_build_fname("C:\\abspath\\mod.cc", ".o").should == "C:/abspath/mod.o"
|
72
|
-
env.get_build_fname("build\\proj\\generated.c", ".o").should == "build/proj/generated.o"
|
73
|
-
env.get_build_fname("build/proj.XX", ".yy").should == "build/proj/build/proj.yy"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
context "with build directories" do
|
79
|
-
it "uses the build directories to create the output file name" do
|
80
|
-
env = Environment.new
|
81
|
-
env.build_dir("src", "bld")
|
82
|
-
env.build_dir(%r{^libs/([^/]+)}, 'build/libs/\1')
|
83
|
-
env.get_build_fname("src/input.cc", ".o").should == "bld/input.o"
|
84
|
-
env.get_build_fname("libs/lib1/some/file.c", ".o").should == "build/libs/lib1/some/file.o"
|
85
|
-
env.get_build_fname("libs/otherlib/otherlib.cc", ".o").should == "build/libs/otherlib/otherlib.o"
|
86
|
-
env.get_build_fname("other_directory/o.d", ".a").should == "other_directory/o.a"
|
87
|
-
end
|
88
|
-
|
89
|
-
context "with a build_root" do
|
90
|
-
it "uses the build_root unless a build directory matches or the path is absolute" do
|
91
|
-
env = Environment.new
|
92
|
-
env.build_dir("src", "bld")
|
93
|
-
env.build_dir(%r{^libs/([^/]+)}, 'build/libs/\1')
|
94
|
-
env.build_root = "bldit"
|
95
|
-
|
96
|
-
env.get_build_fname("src/input.cc", ".o").should == "bld/input.o"
|
97
|
-
env.get_build_fname("libs/lib1/some/file.c", ".o").should == "build/libs/lib1/some/file.o"
|
98
|
-
env.get_build_fname("libs/otherlib/otherlib.cc", ".o").should == "build/libs/otherlib/otherlib.o"
|
99
|
-
env.get_build_fname("other_directory/o.d", ".a").should == "bldit/other_directory/o.a"
|
100
|
-
env.get_build_fname("bldit/some/mod.d", ".a").should == "bldit/some/mod.a"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
describe "#[]" do
|
107
|
-
it "allows reading construction variables" do
|
108
|
-
env = Environment.new
|
109
|
-
env["CFLAGS"] = ["-g", "-Wall"]
|
110
|
-
env["CFLAGS"].should == ["-g", "-Wall"]
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
describe "#[]=" do
|
115
|
-
it "allows writing construction variables" do
|
116
|
-
env = Environment.new
|
117
|
-
env["CFLAGS"] = ["-g", "-Wall"]
|
118
|
-
env["CFLAGS"] -= ["-g"]
|
119
|
-
env["CFLAGS"] += ["-O3"]
|
120
|
-
env["CFLAGS"].should == ["-Wall", "-O3"]
|
121
|
-
env["other_var"] = "val33"
|
122
|
-
env["other_var"].should == "val33"
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
describe "#append" do
|
127
|
-
it "allows adding many construction variables at once" do
|
128
|
-
env = Environment.new
|
129
|
-
env["CFLAGS"] = ["-g"]
|
130
|
-
env["CPPPATH"] = ["inc"]
|
131
|
-
env.append("CFLAGS" => ["-Wall"], "CPPPATH" => ["include"])
|
132
|
-
env["CFLAGS"].should == ["-Wall"]
|
133
|
-
env["CPPPATH"].should == ["include"]
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
describe "#process" do
|
138
|
-
it "runs builders for all of the targets specified" do
|
139
|
-
env = Environment.new
|
140
|
-
env.Program("a.out", "main.c")
|
141
|
-
|
142
|
-
cache = "cache"
|
143
|
-
Cache.should_receive(:instance).and_return(cache)
|
144
|
-
cache.should_receive(:clear_checksum_cache!)
|
145
|
-
env.should_receive(:run_builder).with(anything, "a.out", ["main.c"], cache, {}).and_return(true)
|
146
|
-
cache.should_receive(:write)
|
147
|
-
|
148
|
-
env.process
|
149
|
-
end
|
150
|
-
|
151
|
-
it "builds dependent targets first" do
|
152
|
-
env = Environment.new
|
153
|
-
env.Program("a.out", "main.o")
|
154
|
-
env.Object("main.o", "other.cc")
|
155
|
-
|
156
|
-
cache = "cache"
|
157
|
-
Cache.should_receive(:instance).and_return(cache)
|
158
|
-
cache.should_receive(:clear_checksum_cache!)
|
159
|
-
env.should_receive(:run_builder).with(anything, "main.o", ["other.cc"], cache, {}).and_return("main.o")
|
160
|
-
env.should_receive(:run_builder).with(anything, "a.out", ["main.o"], cache, {}).and_return("a.out")
|
161
|
-
cache.should_receive(:write)
|
162
|
-
|
163
|
-
env.process
|
164
|
-
end
|
165
|
-
|
166
|
-
it "raises a BuildError when building fails" do
|
167
|
-
env = Environment.new
|
168
|
-
env.Program("a.out", "main.o")
|
169
|
-
env.Object("main.o", "other.cc")
|
170
|
-
|
171
|
-
cache = "cache"
|
172
|
-
Cache.should_receive(:instance).and_return(cache)
|
173
|
-
cache.should_receive(:clear_checksum_cache!)
|
174
|
-
env.should_receive(:run_builder).with(anything, "main.o", ["other.cc"], cache, {}).and_return(false)
|
175
|
-
cache.should_receive(:write)
|
176
|
-
|
177
|
-
expect { env.process }.to raise_error BuildError, /Failed.to.build.main.o/
|
178
|
-
end
|
179
|
-
|
180
|
-
it "writes the cache when the Builder raises an exception" do
|
181
|
-
env = Environment.new
|
182
|
-
env.Object("module.o", "module.c")
|
183
|
-
|
184
|
-
cache = "cache"
|
185
|
-
Cache.should_receive(:instance).and_return(cache)
|
186
|
-
cache.should_receive(:clear_checksum_cache!)
|
187
|
-
env.stub(:run_builder) do |builder, target, sources, cache, vars|
|
188
|
-
raise "Ruby exception thrown by builder"
|
189
|
-
end
|
190
|
-
cache.should_receive(:write)
|
191
|
-
|
192
|
-
expect { env.process }.to raise_error RuntimeError, /Ruby exception thrown by builder/
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
describe "#clear_targets" do
|
197
|
-
it "resets @targets to an empty hash" do
|
198
|
-
env = Environment.new
|
199
|
-
env.Program("a.out", "main.o")
|
200
|
-
expect(env.instance_variable_get(:@targets).keys).to eq(["a.out"])
|
201
|
-
|
202
|
-
env.clear_targets
|
203
|
-
|
204
|
-
expect(env.instance_variable_get(:@targets).keys).to eq([])
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
describe "#build_command" do
|
209
|
-
it "returns a command based on the variables in the Environment" do
|
210
|
-
env = Environment.new
|
211
|
-
env["path"] = ["dir1", "dir2"]
|
212
|
-
env["flags"] = ["-x", "-y", "${specialflag}"]
|
213
|
-
env["specialflag"] = "-z"
|
214
|
-
template = ["cmd", "-I${path}", "${flags}", "${_source}", "${_dest}"]
|
215
|
-
cmd = env.build_command(template, "_source" => "infile", "_dest" => "outfile")
|
216
|
-
cmd.should == ["cmd", "-Idir1", "-Idir2", "-x", "-y", "-z", "infile", "outfile"]
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
describe "#expand_varref" do
|
221
|
-
it "returns the fully expanded variable reference" do
|
222
|
-
env = Environment.new
|
223
|
-
env["path"] = ["dir1", "dir2"]
|
224
|
-
env["flags"] = ["-x", "-y", "${specialflag}"]
|
225
|
-
env["specialflag"] = "-z"
|
226
|
-
env["foo"] = {}
|
227
|
-
env.expand_varref(["-p${path}", "${flags}"]).should == ["-pdir1", "-pdir2", "-x", "-y", "-z"]
|
228
|
-
env.expand_varref("foo").should == "foo"
|
229
|
-
expect {env.expand_varref("${foo}")}.to raise_error /expand.a.variable.reference/
|
230
|
-
env.expand_varref("${specialflag}").should == "-z"
|
231
|
-
env.expand_varref("${path}").should == ["dir1", "dir2"]
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
describe "#execute" do
|
236
|
-
context "with echo: :short" do
|
237
|
-
context "with no errors" do
|
238
|
-
it "prints the short description and executes the command" do
|
239
|
-
env = Environment.new(echo: :short)
|
240
|
-
env.should_receive(:puts).with("short desc")
|
241
|
-
env.should_receive(:system).with("a", "command").and_return(true)
|
242
|
-
env.execute("short desc", ["a", "command"])
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
context "with errors" do
|
247
|
-
it "prints the short description, executes the command, and prints the failed command line" do
|
248
|
-
env = Environment.new(echo: :short)
|
249
|
-
env.should_receive(:puts).with("short desc")
|
250
|
-
env.should_receive(:system).with("a", "command").and_return(false)
|
251
|
-
$stdout.should_receive(:write).with("Failed command was: ")
|
252
|
-
env.should_receive(:puts).with("a command")
|
253
|
-
env.execute("short desc", ["a", "command"])
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
context "with echo: :command" do
|
259
|
-
it "prints the command executed and executes the command" do
|
260
|
-
env = Environment.new(echo: :command)
|
261
|
-
env.should_receive(:puts).with("a command '--arg=val with spaces'")
|
262
|
-
env.should_receive(:system).with({modified: :environment}, "a", "command", "--arg=val with spaces", {opt: :val}).and_return(false)
|
263
|
-
env.execute("short desc", ["a", "command", "--arg=val with spaces"], env: {modified: :environment}, options: {opt: :val})
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
describe "#method_missing" do
|
269
|
-
it "calls the original method missing when the target method is not a known builder" do
|
270
|
-
env = Environment.new
|
271
|
-
expect {env.foobar}.to raise_error /undefined method .foobar./
|
272
|
-
end
|
273
|
-
|
274
|
-
it "records the target when the target method is a known builder" do
|
275
|
-
env = Environment.new
|
276
|
-
env.instance_variable_get(:@targets).should == {}
|
277
|
-
env.Program("target", ["src1", "src2"], var: "val")
|
278
|
-
target = env.instance_variable_get(:@targets)["target"]
|
279
|
-
target.should_not be_nil
|
280
|
-
target[:builder].is_a?(Builder).should be_true
|
281
|
-
target[:sources].should == ["src1", "src2"]
|
282
|
-
target[:vars].should == {var: "val"}
|
283
|
-
target[:args].should == []
|
284
|
-
end
|
285
|
-
|
286
|
-
it "raises an error when vars is not a Hash" do
|
287
|
-
env = Environment.new
|
288
|
-
expect { env.Program("a.out", "main.c", "other") }.to raise_error /Unexpected construction variable set/
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
describe "#depends" do
|
293
|
-
it "records the given dependencies in @user_deps" do
|
294
|
-
env = Environment.new
|
295
|
-
env.depends("foo", "bar", "baz")
|
296
|
-
env.instance_variable_get(:@user_deps).should == {"foo" => ["bar", "baz"]}
|
297
|
-
end
|
298
|
-
it "records user dependencies only once" do
|
299
|
-
env = Environment.new
|
300
|
-
env.instance_variable_set(:@user_deps, {"foo" => ["bar"]})
|
301
|
-
env.depends("foo", "bar", "baz")
|
302
|
-
env.instance_variable_get(:@user_deps).should == {"foo" => ["bar", "baz"]}
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
|
-
describe "#build_sources" do
|
307
|
-
class ABuilder < Builder
|
308
|
-
def produces?(target, source, env)
|
309
|
-
target =~ /\.ab_out$/ and source =~ /\.ab_in$/
|
310
|
-
end
|
311
|
-
end
|
312
|
-
|
313
|
-
it "finds and invokes a builder to produce output files with the requested suffixes" do
|
314
|
-
cache = "cache"
|
315
|
-
env = Environment.new
|
316
|
-
env.add_builder(ABuilder.new)
|
317
|
-
env.builders["Object"].should_receive(:run).with("mod.o", ["mod.c"], cache, env, anything).and_return("mod.o")
|
318
|
-
env.builders["ABuilder"].should_receive(:run).with("mod2.ab_out", ["mod2.ab_in"], cache, env, anything).and_return("mod2.ab_out")
|
319
|
-
env.build_sources(["precompiled.o", "mod.c", "mod2.ab_in"], [".o", ".ab_out"], cache, {}).should == ["precompiled.o", "mod.o", "mod2.ab_out"]
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
describe "#run_builder" do
|
324
|
-
it "modifies the construction variables using given build hooks and invokes the builder" do
|
325
|
-
env = Environment.new
|
326
|
-
env.add_build_hook do |build_op|
|
327
|
-
if build_op[:sources].first =~ %r{src/special}
|
328
|
-
build_op[:vars]["CFLAGS"] += ["-O3", "-DSPECIAL"]
|
329
|
-
end
|
330
|
-
end
|
331
|
-
env.builders["Object"].stub(:run) do |target, sources, cache, env, vars|
|
332
|
-
vars["CFLAGS"].should == []
|
333
|
-
end
|
334
|
-
env.run_builder(env.builders["Object"], "build/normal/module.o", ["src/normal/module.c"], "cache", {})
|
335
|
-
env.builders["Object"].stub(:run) do |target, sources, cache, env, vars|
|
336
|
-
vars["CFLAGS"].should == ["-O3", "-DSPECIAL"]
|
337
|
-
end
|
338
|
-
env.run_builder(env.builders["Object"], "build/special/module.o", ["src/special/module.c"], "cache", {})
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
describe ".parse_makefile_deps" do
|
343
|
-
it 'handles dependencies on one line' do
|
344
|
-
File.should_receive(:read).with('makefile').and_return(<<EOS)
|
345
|
-
module.o: source.cc
|
346
|
-
EOS
|
347
|
-
Environment.parse_makefile_deps('makefile', 'module.o').should == ['source.cc']
|
348
|
-
end
|
349
|
-
|
350
|
-
it 'handles dependencies split across many lines' do
|
351
|
-
File.should_receive(:read).with('makefile').and_return(<<EOS)
|
352
|
-
module.o: module.c \\
|
353
|
-
module.h \\
|
354
|
-
other.h
|
355
|
-
EOS
|
356
|
-
Environment.parse_makefile_deps('makefile', 'module.o').should == [
|
357
|
-
'module.c', 'module.h', 'other.h']
|
358
|
-
end
|
359
|
-
end
|
360
|
-
end
|
361
|
-
end
|