rscons 1.4.3 → 1.5.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.
- 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
|