blob: 08d4dcfea93562381dfd1b3b4540ebfa52cd45b9 [file] [log] [blame]
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01001#!/bin/bash -eu
2
3# This test exercises the bootstrapping process of the build system
4# in a source tree that only contains enough files for Bazel and Soong to work.
5
Lukacs T. Berki3b730c42021-04-08 13:21:13 +02006source "$(dirname "$0")/lib.sh"
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01007
8function test_smoke {
9 setup
10 run_soong
11}
12
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +010013function test_null_build() {
14 setup
15 run_soong
16 local bootstrap_mtime1=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
17 local output_mtime1=$(stat -c "%y" out/soong/build.ninja)
18 run_soong
19 local bootstrap_mtime2=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
20 local output_mtime2=$(stat -c "%y" out/soong/build.ninja)
21
22 if [[ "$bootstrap_mtime1" == "$bootstrap_mtime2" ]]; then
23 # Bootstrapping is always done. It doesn't take a measurable amount of time.
24 fail "Bootstrap Ninja file did not change on null build"
25 fi
26
27 if [[ "$output_mtime1" != "$output_mtime2" ]]; then
28 fail "Output Ninja file changed on null build"
29 fi
30}
31
32function test_soong_build_rebuilt_if_blueprint_changes() {
33 setup
34 run_soong
35 local mtime1=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
36
37 sed -i 's/pluginGenSrcCmd/pluginGenSrcCmd2/g' build/blueprint/bootstrap/bootstrap.go
38
39 run_soong
40 local mtime2=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
41
42 if [[ "$mtime1" == "$mtime2" ]]; then
43 fail "Bootstrap Ninja file did not change"
44 fi
45}
46
47function test_change_android_bp() {
48 setup
49 mkdir -p a
50 cat > a/Android.bp <<'EOF'
51python_binary_host {
52 name: "my_little_binary_host",
53 srcs: ["my_little_binary_host.py"]
54}
55EOF
56 touch a/my_little_binary_host.py
57 run_soong
58
59 grep -q "^# Module:.*my_little_binary_host" out/soong/build.ninja || fail "module not found"
60
61 cat > a/Android.bp <<'EOF'
62python_binary_host {
63 name: "my_great_binary_host",
64 srcs: ["my_great_binary_host.py"]
65}
66EOF
67 touch a/my_great_binary_host.py
68 run_soong
69
70 grep -q "^# Module:.*my_little_binary_host" out/soong/build.ninja && fail "old module found"
71 grep -q "^# Module:.*my_great_binary_host" out/soong/build.ninja || fail "new module not found"
72}
73
74
75function test_add_android_bp() {
76 setup
77 run_soong
78 local mtime1=$(stat -c "%y" out/soong/build.ninja)
79
80 mkdir -p a
81 cat > a/Android.bp <<'EOF'
82python_binary_host {
83 name: "my_little_binary_host",
84 srcs: ["my_little_binary_host.py"]
85}
86EOF
87 touch a/my_little_binary_host.py
88 run_soong
89
90 local mtime2=$(stat -c "%y" out/soong/build.ninja)
91 if [[ "$mtime1" == "$mtime2" ]]; then
92 fail "Output Ninja file did not change"
93 fi
94
95 grep -q "^# Module:.*my_little_binary_host$" out/soong/build.ninja || fail "New module not in output"
96
97 run_soong
98}
99
100function test_delete_android_bp() {
101 setup
102 mkdir -p a
103 cat > a/Android.bp <<'EOF'
104python_binary_host {
105 name: "my_little_binary_host",
106 srcs: ["my_little_binary_host.py"]
107}
108EOF
109 touch a/my_little_binary_host.py
110 run_soong
111
112 grep -q "^# Module:.*my_little_binary_host$" out/soong/build.ninja || fail "Module not in output"
113
114 rm a/Android.bp
115 run_soong
116
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200117 if grep -q "^# Module:.*my_little_binary_host$" out/soong/build.ninja; then
118 fail "Old module in output"
119 fi
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100120}
121
Colin Cross10425952021-04-12 18:59:18 -0700122# Test that an incremental build with a glob doesn't rerun soong_build, and
123# only regenerates the globs on the first but not the second incremental build.
124function test_glob_noop_incremental() {
125 setup
126
127 mkdir -p a
128 cat > a/Android.bp <<'EOF'
129python_binary_host {
130 name: "my_little_binary_host",
131 srcs: ["*.py"],
132}
133EOF
134 touch a/my_little_binary_host.py
135 run_soong
136 local ninja_mtime1=$(stat -c "%y" out/soong/build.ninja)
137
Colin Crosscb33a002021-04-12 22:25:17 -0700138 local glob_deps_file=out/soong/.primary/globs/0.d
Colin Cross10425952021-04-12 18:59:18 -0700139
140 if [ -e "$glob_deps_file" ]; then
141 fail "Glob deps file unexpectedly written on first build"
142 fi
143
144 run_soong
145 local ninja_mtime2=$(stat -c "%y" out/soong/build.ninja)
146
147 # There is an ineffiencency in glob that requires bpglob to rerun once for each glob to update
148 # the entry in the .ninja_log. It doesn't update the output file, but we can detect the rerun
149 # by checking if the deps file was created.
150 if [ ! -e "$glob_deps_file" ]; then
151 fail "Glob deps file missing after second build"
152 fi
153
154 local glob_deps_mtime2=$(stat -c "%y" "$glob_deps_file")
155
156 if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then
157 fail "Ninja file rewritten on null incremental build"
158 fi
159
160 run_soong
161 local ninja_mtime3=$(stat -c "%y" out/soong/build.ninja)
162 local glob_deps_mtime3=$(stat -c "%y" "$glob_deps_file")
163
164 if [[ "$ninja_mtime2" != "$ninja_mtime3" ]]; then
165 fail "Ninja file rewritten on null incremental build"
166 fi
167
168 # The bpglob commands should not rerun after the first incremental build.
169 if [[ "$glob_deps_mtime2" != "$glob_deps_mtime3" ]]; then
170 fail "Glob deps file rewritten on second null incremental build"
171 fi
172}
173
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100174function test_add_file_to_glob() {
175 setup
176
177 mkdir -p a
178 cat > a/Android.bp <<'EOF'
179python_binary_host {
180 name: "my_little_binary_host",
181 srcs: ["*.py"],
182}
183EOF
184 touch a/my_little_binary_host.py
185 run_soong
186 local mtime1=$(stat -c "%y" out/soong/build.ninja)
187
188 touch a/my_little_library.py
189 run_soong
190
191 local mtime2=$(stat -c "%y" out/soong/build.ninja)
192 if [[ "$mtime1" == "$mtime2" ]]; then
193 fail "Output Ninja file did not change"
194 fi
195
196 grep -q my_little_library.py out/soong/build.ninja || fail "new file is not in output"
197}
198
Lukacs T. Berkif0b3b942021-03-23 11:46:47 +0100199function test_soong_build_rerun_iff_environment_changes() {
200 setup
201
202 mkdir -p cherry
203 cat > cherry/Android.bp <<'EOF'
204bootstrap_go_package {
205 name: "cherry",
206 pkgPath: "android/soong/cherry",
207 deps: [
208 "blueprint",
209 "soong",
210 "soong-android",
211 ],
212 srcs: [
213 "cherry.go",
214 ],
215 pluginFor: ["soong_build"],
216}
217EOF
218
219 cat > cherry/cherry.go <<'EOF'
220package cherry
221
222import (
223 "android/soong/android"
224 "github.com/google/blueprint"
225)
226
227var (
228 pctx = android.NewPackageContext("cherry")
229)
230
231func init() {
232 android.RegisterSingletonType("cherry", CherrySingleton)
233}
234
235func CherrySingleton() android.Singleton {
236 return &cherrySingleton{}
237}
238
239type cherrySingleton struct{}
240
241func (p *cherrySingleton) GenerateBuildActions(ctx android.SingletonContext) {
242 cherryRule := ctx.Rule(pctx, "cherry",
243 blueprint.RuleParams{
244 Command: "echo CHERRY IS " + ctx.Config().Getenv("CHERRY") + " > ${out}",
245 CommandDeps: []string{},
246 Description: "Cherry",
247 })
248
249 outputFile := android.PathForOutput(ctx, "cherry", "cherry.txt")
250 var deps android.Paths
251
252 ctx.Build(pctx, android.BuildParams{
253 Rule: cherryRule,
254 Output: outputFile,
255 Inputs: deps,
256 })
257}
258EOF
259
260 export CHERRY=TASTY
261 run_soong
262 grep -q "CHERRY IS TASTY" out/soong/build.ninja \
263 || fail "first value of environment variable is not used"
264
265 export CHERRY=RED
266 run_soong
267 grep -q "CHERRY IS RED" out/soong/build.ninja \
268 || fail "second value of environment variable not used"
269 local mtime1=$(stat -c "%y" out/soong/build.ninja)
270
271 run_soong
272 local mtime2=$(stat -c "%y" out/soong/build.ninja)
273 if [[ "$mtime1" != "$mtime2" ]]; then
274 fail "Output Ninja file changed when environment variable did not"
275 fi
276
277}
278
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100279function test_add_file_to_soong_build() {
280 setup
281 run_soong
282 local mtime1=$(stat -c "%y" out/soong/build.ninja)
283
284 mkdir -p a
285 cat > a/Android.bp <<'EOF'
286bootstrap_go_package {
287 name: "picard-soong-rules",
288 pkgPath: "android/soong/picard",
289 deps: [
290 "blueprint",
291 "soong",
292 "soong-android",
293 ],
294 srcs: [
295 "picard.go",
296 ],
297 pluginFor: ["soong_build"],
298}
299EOF
300
301 cat > a/picard.go <<'EOF'
302package picard
303
304import (
305 "android/soong/android"
306 "github.com/google/blueprint"
307)
308
309var (
310 pctx = android.NewPackageContext("picard")
311)
312
313func init() {
314 android.RegisterSingletonType("picard", PicardSingleton)
315}
316
317func PicardSingleton() android.Singleton {
318 return &picardSingleton{}
319}
320
321type picardSingleton struct{}
322
323func (p *picardSingleton) GenerateBuildActions(ctx android.SingletonContext) {
324 picardRule := ctx.Rule(pctx, "picard",
325 blueprint.RuleParams{
326 Command: "echo Make it so. > ${out}",
327 CommandDeps: []string{},
328 Description: "Something quotable",
329 })
330
331 outputFile := android.PathForOutput(ctx, "picard", "picard.txt")
332 var deps android.Paths
333
334 ctx.Build(pctx, android.BuildParams{
335 Rule: picardRule,
336 Output: outputFile,
337 Inputs: deps,
338 })
339}
340
341EOF
342
343 run_soong
344 local mtime2=$(stat -c "%y" out/soong/build.ninja)
345 if [[ "$mtime1" == "$mtime2" ]]; then
346 fail "Output Ninja file did not change"
347 fi
348
349 grep -q "Make it so" out/soong/build.ninja || fail "New action not present"
350}
351
Colin Crossc02504e2021-04-08 10:34:16 -0700352# Tests a glob in a build= statement in an Android.bp file, which is interpreted
353# during bootstrapping.
354function test_glob_during_bootstrapping() {
355 setup
356
357 mkdir -p a
358 cat > a/Android.bp <<'EOF'
359build=["foo*.bp"]
360EOF
361 cat > a/fooa.bp <<'EOF'
362bootstrap_go_package {
363 name: "picard-soong-rules",
364 pkgPath: "android/soong/picard",
365 deps: [
366 "blueprint",
367 "soong",
368 "soong-android",
369 ],
370 srcs: [
371 "picard.go",
372 ],
373 pluginFor: ["soong_build"],
374}
375EOF
376
377 cat > a/picard.go <<'EOF'
378package picard
379
380import (
381 "android/soong/android"
382 "github.com/google/blueprint"
383)
384
385var (
386 pctx = android.NewPackageContext("picard")
387)
388
389func init() {
390 android.RegisterSingletonType("picard", PicardSingleton)
391}
392
393func PicardSingleton() android.Singleton {
394 return &picardSingleton{}
395}
396
397type picardSingleton struct{}
398
399var Message = "Make it so."
400
401func (p *picardSingleton) GenerateBuildActions(ctx android.SingletonContext) {
402 picardRule := ctx.Rule(pctx, "picard",
403 blueprint.RuleParams{
404 Command: "echo " + Message + " > ${out}",
405 CommandDeps: []string{},
406 Description: "Something quotable",
407 })
408
409 outputFile := android.PathForOutput(ctx, "picard", "picard.txt")
410 var deps android.Paths
411
412 ctx.Build(pctx, android.BuildParams{
413 Rule: picardRule,
414 Output: outputFile,
415 Inputs: deps,
416 })
417}
418
419EOF
420
421 run_soong
422 local mtime1=$(stat -c "%y" out/soong/build.ninja)
423
424 grep -q "Make it so" out/soong/build.ninja || fail "Original action not present"
425
426 cat > a/foob.bp <<'EOF'
427bootstrap_go_package {
428 name: "worf-soong-rules",
429 pkgPath: "android/soong/worf",
430 deps: [
431 "blueprint",
432 "soong",
433 "soong-android",
434 "picard-soong-rules",
435 ],
436 srcs: [
437 "worf.go",
438 ],
439 pluginFor: ["soong_build"],
440}
441EOF
442
443 cat > a/worf.go <<'EOF'
444package worf
445
446import "android/soong/picard"
447
448func init() {
449 picard.Message = "Engage."
450}
451EOF
452
453 run_soong
454 local mtime2=$(stat -c "%y" out/soong/build.ninja)
455 if [[ "$mtime1" == "$mtime2" ]]; then
456 fail "Output Ninja file did not change"
457 fi
458
459 grep -q "Engage" out/soong/build.ninja || fail "New action not present"
460
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200461 if grep -q "Make it so" out/soong/build.ninja; then
462 fail "Original action still present"
463 fi
Colin Crossc02504e2021-04-08 10:34:16 -0700464}
465
Lukacs T. Berkif0b3b942021-03-23 11:46:47 +0100466function test_null_build_after_docs {
467 setup
468 run_soong
469 local mtime1=$(stat -c "%y" out/soong/build.ninja)
470
471 prebuilts/build-tools/linux-x86/bin/ninja -f out/soong/build.ninja soong_docs
472 run_soong
473 local mtime2=$(stat -c "%y" out/soong/build.ninja)
474
475 if [[ "$mtime1" != "$mtime2" ]]; then
476 fail "Output Ninja file changed on null build"
477 fi
478}
479
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200480function test_integrated_bp2build_smoke {
481 setup
482 INTEGRATED_BP2BUILD=1 run_soong
483 if [[ ! -e out/soong/.bootstrap/bp2build_workspace_marker ]]; then
Lukacs T. Berkid518e1a2021-04-14 13:49:50 +0200484 fail "bp2build marker file not created"
485 fi
486}
487
488function test_integrated_bp2build_add_android_bp {
489 setup
490
491 mkdir -p a
492 touch a/a.txt
493 cat > a/Android.bp <<'EOF'
494filegroup {
495 name: "a",
496 srcs: ["a.txt"],
497 bazel_module: { bp2build_available: true },
498}
499EOF
500
501 INTEGRATED_BP2BUILD=1 run_soong
502 if [[ ! -e out/soong/bp2build/a/BUILD ]]; then
503 fail "a/BUILD not created";
504 fi
505
506 mkdir -p b
507 touch b/b.txt
508 cat > b/Android.bp <<'EOF'
509filegroup {
510 name: "b",
511 srcs: ["b.txt"],
512 bazel_module: { bp2build_available: true },
513}
514EOF
515
516 INTEGRATED_BP2BUILD=1 run_soong
517 if [[ ! -e out/soong/bp2build/b/BUILD ]]; then
518 fail "b/BUILD not created";
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200519 fi
520}
521
522function test_integrated_bp2build_null_build {
523 setup
Lukacs T. Berkid518e1a2021-04-14 13:49:50 +0200524
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200525 INTEGRATED_BP2BUILD=1 run_soong
526 local mtime1=$(stat -c "%y" out/soong/build.ninja)
527
528 INTEGRATED_BP2BUILD=1 run_soong
529 local mtime2=$(stat -c "%y" out/soong/build.ninja)
530
531 if [[ "$mtime1" != "$mtime2" ]]; then
532 fail "Output Ninja file changed on null build"
533 fi
534}
535
Lukacs T. Berkid518e1a2021-04-14 13:49:50 +0200536function test_integrated_bp2build_add_to_glob {
537 setup
538
539 mkdir -p a
540 touch a/a1.txt
541 cat > a/Android.bp <<'EOF'
542filegroup {
543 name: "a",
544 srcs: ["*.txt"],
545 bazel_module: { bp2build_available: true },
546}
547EOF
548
549 INTEGRATED_BP2BUILD=1 run_soong
550 grep -q a1.txt out/soong/bp2build/a/BUILD || fail "a1.txt not in BUILD file"
551
552 touch a/a2.txt
553 INTEGRATED_BP2BUILD=1 run_soong
554 grep -q a2.txt out/soong/bp2build/a/BUILD || fail "a2.txt not in BUILD file"
555}
556
Lukacs T. Berki97bb9f12021-04-01 18:28:45 +0200557function test_dump_json_module_graph() {
558 setup
559 SOONG_DUMP_JSON_MODULE_GRAPH="$MOCK_TOP/modules.json" run_soong
560 if [[ ! -r "$MOCK_TOP/modules.json" ]]; then
561 fail "JSON file was not created"
562 fi
563}
564
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100565test_smoke
566test_null_build
Lukacs T. Berkif0b3b942021-03-23 11:46:47 +0100567test_null_build_after_docs
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100568test_soong_build_rebuilt_if_blueprint_changes
Colin Cross10425952021-04-12 18:59:18 -0700569test_glob_noop_incremental
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100570test_add_file_to_glob
571test_add_android_bp
572test_change_android_bp
573test_delete_android_bp
574test_add_file_to_soong_build
Colin Crossc02504e2021-04-08 10:34:16 -0700575test_glob_during_bootstrapping
Lukacs T. Berkif0b3b942021-03-23 11:46:47 +0100576test_soong_build_rerun_iff_environment_changes
Lukacs T. Berki97bb9f12021-04-01 18:28:45 +0200577test_dump_json_module_graph
Lukacs T. Berkif8e24282021-04-14 10:31:00 +0200578test_integrated_bp2build_smoke
579test_integrated_bp2build_null_build
Lukacs T. Berkid518e1a2021-04-14 13:49:50 +0200580test_integrated_bp2build_add_to_glob