bp2build_bazel_test.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  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_bp2build_symlinks_files {
  191. setup
  192. mkdir -p foo
  193. touch foo/BLANK1
  194. touch foo/BLANK2
  195. touch foo/F2D
  196. touch foo/BUILD
  197. run_soong bp2build
  198. if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then
  199. fail "./out/soong/workspace/foo/BUILD should be omitted"
  200. fi
  201. for file in BLANK1 BLANK2 F2D
  202. do
  203. if [[ ! -L "./out/soong/workspace/foo/$file" ]]; then
  204. fail "./out/soong/workspace/foo/$file should exist"
  205. fi
  206. done
  207. local -r BLANK1_BEFORE=$(stat -c %y "./out/soong/workspace/foo/BLANK1")
  208. rm foo/BLANK2
  209. rm foo/F2D
  210. mkdir foo/F2D
  211. touch foo/F2D/BUILD
  212. run_soong bp2build
  213. if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then
  214. fail "./out/soong/workspace/foo/BUILD should be omitted"
  215. fi
  216. local -r BLANK1_AFTER=$(stat -c %y "./out/soong/workspace/foo/BLANK1")
  217. if [[ "$BLANK1_AFTER" != "$BLANK1_BEFORE" ]]; then
  218. fail "./out/soong/workspace/foo/BLANK1 should be untouched"
  219. fi
  220. if [[ -e "./out/soong/workspace/foo/BLANK2" ]]; then
  221. fail "./out/soong/workspace/foo/BLANK2 should be removed"
  222. fi
  223. if [[ -L "./out/soong/workspace/foo/F2D" ]] || [[ ! -d "./out/soong/workspace/foo/F2D" ]]; then
  224. fail "./out/soong/workspace/foo/F2D should be a dir"
  225. fi
  226. }
  227. function test_cc_correctness {
  228. setup
  229. mkdir -p a
  230. cat > a/Android.bp <<EOF
  231. cc_object {
  232. name: "qq",
  233. srcs: ["qq.cc"],
  234. bazel_module: {
  235. bp2build_available: true,
  236. },
  237. stl: "none",
  238. system_shared_libs: [],
  239. }
  240. EOF
  241. cat > a/qq.cc <<EOF
  242. #include "qq.h"
  243. int qq() {
  244. return QQ;
  245. }
  246. EOF
  247. cat > a/qq.h <<EOF
  248. #define QQ 1
  249. EOF
  250. run_soong bp2build
  251. run_bazel build --config=android --config=bp2build --config=ci //a:qq
  252. local -r output_mtime1=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
  253. run_bazel build --config=android --config=bp2build --config=ci //a:qq
  254. local -r output_mtime2=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
  255. if [[ "$output_mtime1" != "$output_mtime2" ]]; then
  256. fail "output changed on null build"
  257. fi
  258. cat > a/qq.h <<EOF
  259. #define QQ 2
  260. EOF
  261. run_bazel build --config=android --config=bp2build --config=ci //a:qq
  262. local -r output_mtime3=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
  263. if [[ "$output_mtime1" == "$output_mtime3" ]]; then
  264. fail "output not changed when included header changed"
  265. fi
  266. }
  267. # Regression test for the following failure during symlink forest creation:
  268. #
  269. # Cannot stat '/tmp/st.rr054/foo/bar/unresolved_symlink': stat /tmp/st.rr054/foo/bar/unresolved_symlink: no such file or directory
  270. #
  271. function test_bp2build_null_build_with_unresolved_symlink_in_source() {
  272. setup
  273. mkdir -p foo/bar
  274. ln -s /tmp/non-existent foo/bar/unresolved_symlink
  275. cat > foo/bar/Android.bp <<'EOF'
  276. filegroup {
  277. name: "fg",
  278. srcs: ["unresolved_symlink/non-existent-file.txt"],
  279. }
  280. EOF
  281. run_soong bp2build
  282. dest=$(readlink -f out/soong/workspace/foo/bar/unresolved_symlink)
  283. if [[ "$dest" != "/tmp/non-existent" ]]; then
  284. fail "expected to plant an unresolved symlink out/soong/workspace/foo/bar/unresolved_symlink that resolves to /tmp/non-existent"
  285. fi
  286. }
  287. # Smoke test to verify api_bp2build worksapce does not contain any errors
  288. function test_api_bp2build_empty_build() {
  289. setup
  290. run_soong api_bp2build
  291. run_bazel build --config=android --config=api_bp2build //:empty
  292. }
  293. # Verify that an *_api_contribution target can refer to an api file from
  294. # another Bazel package.
  295. function test_api_export_from_another_bazel_package() {
  296. setup
  297. # Parent dir Android.bp
  298. mkdir -p foo
  299. cat > foo/Android.bp << 'EOF'
  300. cc_library {
  301. name: "libfoo",
  302. stubs: {
  303. symbol_file: "api/libfoo.map.txt",
  304. },
  305. }
  306. EOF
  307. # Child dir Android.bp
  308. mkdir -p foo/api
  309. cat > foo/api/Android.bp << 'EOF'
  310. package{}
  311. EOF
  312. touch foo/api/libfoo.map.txt
  313. # Run test
  314. run_soong api_bp2build
  315. run_bazel build --config=android --config=api_bp2build //foo:libfoo.contribution
  316. }
  317. scan_and_run_tests