bp2build_bazel_test.sh 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. #!/bin/bash -eu
  2. set -o pipefail
  3. # Test that bp2build and Bazel can play nicely together
  4. source "$(dirname "$0")/lib.sh"
  5. readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel"
  6. function test_bp2build_null_build {
  7. setup
  8. run_soong bp2build
  9. local -r output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
  10. run_soong bp2build
  11. local -r output_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
  12. if [[ "$output_mtime1" != "$output_mtime2" ]]; then
  13. fail "Output bp2build marker file changed on null build"
  14. fi
  15. }
  16. # Tests that, if bp2build reruns due to a blueprint file changing, that
  17. # BUILD files whose contents are unchanged are not regenerated.
  18. function test_bp2build_unchanged {
  19. setup
  20. mkdir -p pkg
  21. touch pkg/x.txt
  22. cat > pkg/Android.bp <<'EOF'
  23. filegroup {
  24. name: "x",
  25. srcs: ["x.txt"],
  26. bazel_module: {bp2build_available: true},
  27. }
  28. EOF
  29. run_soong bp2build
  30. local -r buildfile_mtime1=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel)
  31. local -r marker_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
  32. # Force bp2build to rerun by updating the timestamp of a blueprint file.
  33. touch pkg/Android.bp
  34. run_soong bp2build
  35. local -r buildfile_mtime2=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel)
  36. local -r marker_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
  37. if [[ "$marker_mtime1" == "$marker_mtime2" ]]; then
  38. fail "Expected bp2build marker file to change"
  39. fi
  40. if [[ "$buildfile_mtime1" != "$buildfile_mtime2" ]]; then
  41. fail "BUILD.bazel was updated even though contents are same"
  42. fi
  43. # Force bp2build to rerun by updating the timestamp of the constants_exported_to_soong.bzl file.
  44. touch build/bazel/constants_exported_to_soong.bzl
  45. run_soong bp2build
  46. local -r buildfile_mtime3=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel)
  47. local -r marker_mtime3=$(stat -c "%y" out/soong/bp2build_workspace_marker)
  48. if [[ "$marker_mtime2" == "$marker_mtime3" ]]; then
  49. fail "Expected bp2build marker file to change"
  50. fi
  51. if [[ "$buildfile_mtime2" != "$buildfile_mtime3" ]]; then
  52. fail "BUILD.bazel was updated even though contents are same"
  53. fi
  54. }
  55. # Tests that blueprint files that are deleted are not present when the
  56. # bp2build tree is regenerated.
  57. function test_bp2build_deleted_blueprint {
  58. setup
  59. mkdir -p pkg
  60. touch pkg/x.txt
  61. cat > pkg/Android.bp <<'EOF'
  62. filegroup {
  63. name: "x",
  64. srcs: ["x.txt"],
  65. bazel_module: {bp2build_available: true},
  66. }
  67. EOF
  68. run_soong bp2build
  69. if [[ ! -e "./out/soong/bp2build/pkg/BUILD.bazel" ]]; then
  70. fail "Expected pkg/BUILD.bazel to be generated"
  71. fi
  72. rm pkg/Android.bp
  73. run_soong bp2build
  74. if [[ -e "./out/soong/bp2build/pkg/BUILD.bazel" ]]; then
  75. fail "Expected pkg/BUILD.bazel to be deleted"
  76. fi
  77. }
  78. function test_bp2build_null_build_with_globs {
  79. setup
  80. mkdir -p foo/bar
  81. cat > foo/bar/Android.bp <<'EOF'
  82. filegroup {
  83. name: "globs",
  84. srcs: ["*.txt"],
  85. }
  86. EOF
  87. touch foo/bar/a.txt foo/bar/b.txt
  88. run_soong bp2build
  89. local -r output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
  90. run_soong bp2build
  91. local -r output_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
  92. if [[ "$output_mtime1" != "$output_mtime2" ]]; then
  93. fail "Output bp2build marker file changed on null build"
  94. fi
  95. }
  96. function test_different_relative_outdir {
  97. setup
  98. mkdir -p a
  99. touch a/g.txt
  100. cat > a/Android.bp <<'EOF'
  101. filegroup {
  102. name: "g",
  103. srcs: ["g.txt"],
  104. bazel_module: {bp2build_available: true},
  105. }
  106. EOF
  107. # A directory under $MOCK_TOP
  108. outdir=out2
  109. trap "rm -rf $outdir" EXIT
  110. # Modify OUT_DIR in a subshell so it doesn't affect the top level one.
  111. (export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g)
  112. }
  113. function test_different_absolute_outdir {
  114. setup
  115. mkdir -p a
  116. touch a/g.txt
  117. cat > a/Android.bp <<'EOF'
  118. filegroup {
  119. name: "g",
  120. srcs: ["g.txt"],
  121. bazel_module: {bp2build_available: true},
  122. }
  123. EOF
  124. # A directory under /tmp/...
  125. outdir=$(mktemp -t -d st.XXXXX)
  126. trap 'rm -rf $outdir' EXIT
  127. # Modify OUT_DIR in a subshell so it doesn't affect the top level one.
  128. (export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g)
  129. }
  130. function _bp2build_generates_all_buildfiles {
  131. setup
  132. mkdir -p foo/convertible_soong_module
  133. cat > foo/convertible_soong_module/Android.bp <<'EOF'
  134. genrule {
  135. name: "the_answer",
  136. cmd: "echo '42' > $(out)",
  137. out: [
  138. "the_answer.txt",
  139. ],
  140. bazel_module: {
  141. bp2build_available: true,
  142. },
  143. }
  144. EOF
  145. mkdir -p foo/unconvertible_soong_module
  146. cat > foo/unconvertible_soong_module/Android.bp <<'EOF'
  147. genrule {
  148. name: "not_the_answer",
  149. cmd: "echo '43' > $(out)",
  150. out: [
  151. "not_the_answer.txt",
  152. ],
  153. bazel_module: {
  154. bp2build_available: false,
  155. },
  156. }
  157. EOF
  158. run_soong bp2build
  159. if [[ ! -f "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then
  160. fail "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated"
  161. fi
  162. if [[ ! -f "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then
  163. fail "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated"
  164. fi
  165. if ! grep "the_answer" "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
  166. fail "missing BUILD target the_answer in convertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
  167. fi
  168. if grep "not_the_answer" "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
  169. fail "found unexpected BUILD target not_the_answer in unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
  170. fi
  171. if ! grep "filegroup" "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
  172. fail "missing filegroup in unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
  173. fi
  174. # NOTE: We don't actually use the extra BUILD file for anything here
  175. run_bazel build --config=android --config=bp2build --config=ci //foo/...
  176. local -r the_answer_file="$(find -L bazel-out -name the_answer.txt)"
  177. if [[ ! -f "${the_answer_file}" ]]; then
  178. fail "Expected the_answer.txt to be generated, but was missing"
  179. fi
  180. if ! grep 42 "${the_answer_file}"; then
  181. fail "Expected to find 42 in '${the_answer_file}'"
  182. fi
  183. }
  184. function test_bp2build_generates_all_buildfiles {
  185. _save_trap=$(trap -p EXIT)
  186. trap '[[ $? -ne 0 ]] && echo Are you running this locally? Try changing --sandbox_tmpfs_path to something other than /tmp/ in build/bazel/linux.bazelrc.' EXIT
  187. _bp2build_generates_all_buildfiles
  188. eval "${_save_trap}"
  189. }
  190. function test_build_files_take_precedence {
  191. _save_trap=$(trap -p EXIT)
  192. trap '[[ $? -ne 0 ]] && echo Are you running this locally? Try changing --sandbox_tmpfs_path to something other than /tmp/ in build/bazel/linux.bazelrc.' EXIT
  193. _build_files_take_precedence
  194. eval "${_save_trap}"
  195. }
  196. function _build_files_take_precedence {
  197. setup
  198. # This specific directory is hardcoded in bp2build as being one
  199. # where the BUILD file should be intentionally kept.
  200. mkdir -p testpkg/keep_build_file
  201. cat > testpkg/keep_build_file/Android.bp <<'EOF'
  202. genrule {
  203. name: "print_origin",
  204. cmd: "echo 'from_soong' > $(out)",
  205. out: [
  206. "origin.txt",
  207. ],
  208. bazel_module: {
  209. bp2build_available: true,
  210. },
  211. }
  212. EOF
  213. run_soong bp2build
  214. run_bazel build --config=android --config=bp2build --config=ci //testpkg/keep_build_file:print_origin
  215. local -r output_file="$(find -L bazel-out -name origin.txt)"
  216. if [[ ! -f "${output_file}" ]]; then
  217. fail "Expected origin.txt to be generated, but was missing"
  218. fi
  219. if ! grep from_soong "${output_file}"; then
  220. fail "Expected to find 'from_soong' in '${output_file}'"
  221. fi
  222. cat > testpkg/keep_build_file/BUILD.bazel <<'EOF'
  223. genrule(
  224. name = "print_origin",
  225. outs = ["origin.txt"],
  226. cmd = "echo 'from_bazel' > $@",
  227. )
  228. EOF
  229. # Clean the workspace. There is a test infrastructure bug where run_bazel
  230. # will symlink Android.bp files in the source directory again and thus
  231. # pollute the workspace.
  232. # TODO: b/286059878 - Remove this clean after the underlying bug is fixed.
  233. run_soong clean
  234. run_soong bp2build
  235. run_bazel build --config=android --config=bp2build --config=ci //testpkg/keep_build_file:print_origin
  236. if ! grep from_bazel "${output_file}"; then
  237. fail "Expected to find 'from_bazel' in '${output_file}'"
  238. fi
  239. }
  240. function test_bp2build_symlinks_files {
  241. setup
  242. mkdir -p foo
  243. touch foo/BLANK1
  244. touch foo/BLANK2
  245. touch foo/F2D
  246. touch foo/BUILD
  247. run_soong bp2build
  248. if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then
  249. fail "./out/soong/workspace/foo/BUILD should be omitted"
  250. fi
  251. for file in BLANK1 BLANK2 F2D
  252. do
  253. if [[ ! -L "./out/soong/workspace/foo/$file" ]]; then
  254. fail "./out/soong/workspace/foo/$file should exist"
  255. fi
  256. done
  257. local -r BLANK1_BEFORE=$(stat -c %y "./out/soong/workspace/foo/BLANK1")
  258. rm foo/BLANK2
  259. rm foo/F2D
  260. mkdir foo/F2D
  261. touch foo/F2D/BUILD
  262. run_soong bp2build
  263. if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then
  264. fail "./out/soong/workspace/foo/BUILD should be omitted"
  265. fi
  266. local -r BLANK1_AFTER=$(stat -c %y "./out/soong/workspace/foo/BLANK1")
  267. if [[ "$BLANK1_AFTER" != "$BLANK1_BEFORE" ]]; then
  268. fail "./out/soong/workspace/foo/BLANK1 should be untouched"
  269. fi
  270. if [[ -e "./out/soong/workspace/foo/BLANK2" ]]; then
  271. fail "./out/soong/workspace/foo/BLANK2 should be removed"
  272. fi
  273. if [[ -L "./out/soong/workspace/foo/F2D" ]] || [[ ! -d "./out/soong/workspace/foo/F2D" ]]; then
  274. fail "./out/soong/workspace/foo/F2D should be a dir"
  275. fi
  276. }
  277. function test_cc_correctness {
  278. setup
  279. mkdir -p a
  280. cat > a/Android.bp <<EOF
  281. cc_object {
  282. name: "qq",
  283. srcs: ["qq.cc"],
  284. bazel_module: {
  285. bp2build_available: true,
  286. },
  287. stl: "none",
  288. system_shared_libs: [],
  289. }
  290. EOF
  291. cat > a/qq.cc <<EOF
  292. #include "qq.h"
  293. int qq() {
  294. return QQ;
  295. }
  296. EOF
  297. cat > a/qq.h <<EOF
  298. #define QQ 1
  299. EOF
  300. run_soong bp2build
  301. run_bazel build --config=android --config=bp2build --config=ci //a:qq
  302. local -r output_mtime1=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
  303. run_bazel build --config=android --config=bp2build --config=ci //a:qq
  304. local -r output_mtime2=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
  305. if [[ "$output_mtime1" != "$output_mtime2" ]]; then
  306. fail "output changed on null build"
  307. fi
  308. cat > a/qq.h <<EOF
  309. #define QQ 2
  310. EOF
  311. run_bazel build --config=android --config=bp2build --config=ci //a:qq
  312. local -r output_mtime3=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
  313. if [[ "$output_mtime1" == "$output_mtime3" ]]; then
  314. fail "output not changed when included header changed"
  315. fi
  316. }
  317. # Regression test for the following failure during symlink forest creation:
  318. #
  319. # Cannot stat '/tmp/st.rr054/foo/bar/unresolved_symlink': stat /tmp/st.rr054/foo/bar/unresolved_symlink: no such file or directory
  320. #
  321. function test_bp2build_null_build_with_unresolved_symlink_in_source() {
  322. setup
  323. mkdir -p foo/bar
  324. ln -s /tmp/non-existent foo/bar/unresolved_symlink
  325. cat > foo/bar/Android.bp <<'EOF'
  326. filegroup {
  327. name: "fg",
  328. srcs: ["unresolved_symlink/non-existent-file.txt"],
  329. }
  330. EOF
  331. run_soong bp2build
  332. dest=$(readlink -f out/soong/workspace/foo/bar/unresolved_symlink)
  333. if [[ "$dest" != "/tmp/non-existent" ]]; then
  334. fail "expected to plant an unresolved symlink out/soong/workspace/foo/bar/unresolved_symlink that resolves to /tmp/non-existent"
  335. fi
  336. }
  337. # Smoke test to verify api_bp2build worksapce does not contain any errors
  338. function test_api_bp2build_empty_build() {
  339. setup
  340. run_soong api_bp2build
  341. run_bazel build --config=android --config=api_bp2build //:empty
  342. }
  343. # Verify that an *_api_contribution target can refer to an api file from
  344. # another Bazel package.
  345. function test_api_export_from_another_bazel_package() {
  346. setup
  347. # Parent dir Android.bp
  348. mkdir -p foo
  349. cat > foo/Android.bp << 'EOF'
  350. cc_library {
  351. name: "libfoo",
  352. stubs: {
  353. symbol_file: "api/libfoo.map.txt",
  354. },
  355. }
  356. EOF
  357. # Child dir Android.bp
  358. mkdir -p foo/api
  359. cat > foo/api/Android.bp << 'EOF'
  360. package{}
  361. EOF
  362. touch foo/api/libfoo.map.txt
  363. # Run test
  364. run_soong api_bp2build
  365. run_bazel build --config=android --config=api_bp2build //foo:libfoo.contribution
  366. }
  367. function test_bazel_standalone_output_paths_contain_product_name {
  368. setup
  369. mkdir -p a
  370. cat > a/Android.bp <<EOF
  371. cc_object {
  372. name: "qq",
  373. srcs: ["qq.cc"],
  374. bazel_module: {
  375. bp2build_available: true,
  376. },
  377. stl: "none",
  378. system_shared_libs: [],
  379. }
  380. EOF
  381. cat > a/qq.cc <<EOF
  382. #include "qq.h"
  383. int qq() {
  384. return QQ;
  385. }
  386. EOF
  387. cat > a/qq.h <<EOF
  388. #define QQ 1
  389. EOF
  390. export TARGET_PRODUCT=aosp_arm; run_soong bp2build
  391. local -r output=$(run_bazel cquery //a:qq --output=files --config=android --config=bp2build --config=ci)
  392. if [[ ! $(echo ${output} | grep "bazel-out/aosp_arm") ]]; then
  393. fail "Did not find the product name '${TARGET_PRODUCT}' in the output path. This can cause " \
  394. "unnecessary rebuilds when toggling between products as bazel outputs for different products will " \
  395. "clobber each other. Output paths are: \n${output}"
  396. fi
  397. }
  398. scan_and_run_tests