build.sh 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. #!/usr/bin/env bash
  2. # Copyright 2018 Google
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. # USAGE: build.sh product [platform] [method]
  16. #
  17. # Builds the given product for the given platform using the given build method
  18. function pod_gen() {
  19. # Call pod gen with a podspec and additional optional arguments.
  20. bundle exec pod gen --local-sources=./ --sources=https://github.com/firebase/SpecsDev.git,https://github.com/firebase/SpecsStaging.git,https://cdn.cocoapods.org/ "$@"
  21. }
  22. set -euo pipefail
  23. if [[ $# -lt 1 ]]; then
  24. cat 1>&2 <<EOF
  25. USAGE: $0 product [platform] [method]
  26. product can be one of:
  27. Firebase
  28. Firestore
  29. InAppMessaging
  30. Messaging
  31. MessagingSample
  32. MLModelDownloaderSample
  33. RemoteConfig
  34. RemoteConfigSample
  35. Storage
  36. StorageSwift
  37. SymbolCollision
  38. GoogleDataTransport
  39. Performance
  40. platform can be one of:
  41. iOS (default)
  42. iOS-device
  43. macOS
  44. tvOS
  45. watchOS
  46. catalyst
  47. method can be one of:
  48. xcodebuild (default)
  49. cmake
  50. unit
  51. integration
  52. spm
  53. Optionally, reads the environment variable SANITIZERS. If set, it is expected to
  54. be a string containing a space-separated list with some of the following
  55. elements:
  56. asan
  57. tsan
  58. ubsan
  59. EOF
  60. exit 1
  61. fi
  62. product="$1"
  63. platform="iOS"
  64. if [[ $# -gt 1 ]]; then
  65. platform="$2"
  66. fi
  67. method="xcodebuild"
  68. if [[ $# -gt 2 ]]; then
  69. method="$3"
  70. fi
  71. echo "Building $product for $platform using $method"
  72. if [[ -n "${SANITIZERS:-}" ]]; then
  73. echo "Using sanitizers: $SANITIZERS"
  74. fi
  75. scripts_dir=$(dirname "${BASH_SOURCE[0]}")
  76. firestore_emulator="${scripts_dir}/run_firestore_emulator.sh"
  77. database_emulator="${scripts_dir}/run_database_emulator.sh"
  78. system=$(uname -s)
  79. case "$system" in
  80. Darwin)
  81. xcode_version=$(xcodebuild -version | head -n 1)
  82. xcode_version="${xcode_version/Xcode /}"
  83. xcode_major="${xcode_version/.*/}"
  84. ;;
  85. *)
  86. xcode_major="0"
  87. ;;
  88. esac
  89. # Source function to check if CI secrets are available.
  90. source scripts/check_secrets.sh
  91. # Runs xcodebuild with the given flags, piping output to xcpretty
  92. # If xcodebuild fails with known error codes, retries once.
  93. function RunXcodebuild() {
  94. echo xcodebuild "$@"
  95. xcpretty_cmd=(xcpretty)
  96. if [[ -n "${TRAVIS:-}" ]]; then
  97. # The formatter argument takes a file location of a formatter.
  98. # The xcpretty-travis-formatter binary prints its location on stdout.
  99. xcpretty_cmd+=(-f $(xcpretty-travis-formatter))
  100. fi
  101. result=0
  102. xcodebuild "$@" | tee xcodebuild.log | "${xcpretty_cmd[@]}" || result=$?
  103. if [[ $result == 65 ]]; then
  104. ExportLogs "$@"
  105. echo "xcodebuild exited with 65, retrying" 1>&2
  106. sleep 5
  107. result=0
  108. xcodebuild "$@" | tee xcodebuild.log | "${xcpretty_cmd[@]}" || result=$?
  109. fi
  110. if [[ $result != 0 ]]; then
  111. echo "xcodebuild exited with $result" 1>&2
  112. ExportLogs "$@"
  113. return $result
  114. fi
  115. }
  116. # Exports any logs output captured in the xcresult
  117. function ExportLogs() {
  118. python "${scripts_dir}/xcresult_logs.py" "$@"
  119. }
  120. if [[ "$xcode_major" -lt 11 ]]; then
  121. ios_flags=(
  122. -sdk 'iphonesimulator'
  123. -destination 'platform=iOS Simulator,name=iPhone 7'
  124. )
  125. else
  126. ios_flags=(
  127. -sdk 'iphonesimulator'
  128. -destination 'platform=iOS Simulator,name=iPhone 11'
  129. )
  130. fi
  131. ios_device_flags=(
  132. -sdk 'iphoneos'
  133. )
  134. ipad_flags=(
  135. -sdk 'iphonesimulator'
  136. -destination 'platform=iOS Simulator,name=iPad Pro (9.7-inch)'
  137. )
  138. macos_flags=(
  139. -sdk 'macosx'
  140. -destination 'platform=OS X,arch=x86_64'
  141. )
  142. tvos_flags=(
  143. -sdk "appletvsimulator"
  144. -destination 'platform=tvOS Simulator,name=Apple TV'
  145. )
  146. watchos_flags=(
  147. -destination 'platform=iOS Simulator,name=iPhone 11 Pro'
  148. )
  149. catalyst_flags=(
  150. ARCHS=x86_64 VALID_ARCHS=x86_64 SUPPORTS_MACCATALYST=YES -sdk macosx
  151. -destination platform="macOS,variant=Mac Catalyst" TARGETED_DEVICE_FAMILY=2
  152. CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
  153. )
  154. # Compute standard flags for all platforms
  155. case "$platform" in
  156. iOS)
  157. xcb_flags=("${ios_flags[@]}")
  158. gen_platform=ios
  159. ;;
  160. iOS-device)
  161. xcb_flags=("${ios_device_flags[@]}")
  162. gen_platform=ios
  163. ;;
  164. iPad)
  165. xcb_flags=("${ipad_flags[@]}")
  166. ;;
  167. macOS)
  168. xcb_flags=("${macos_flags[@]}")
  169. gen_platform=macos
  170. ;;
  171. tvOS)
  172. xcb_flags=("${tvos_flags[@]}")
  173. gen_platform=tvos
  174. ;;
  175. watchOS)
  176. xcb_flags=("${watchos_flags[@]}")
  177. ;;
  178. catalyst)
  179. xcb_flags=("${catalyst_flags[@]}")
  180. ;;
  181. all)
  182. xcb_flags=()
  183. ;;
  184. Linux)
  185. xcb_flags=()
  186. ;;
  187. *)
  188. echo "Unknown platform '$platform'" 1>&2
  189. exit 1
  190. ;;
  191. esac
  192. xcb_flags+=(
  193. ONLY_ACTIVE_ARCH=YES
  194. CODE_SIGNING_REQUIRED=NO
  195. CODE_SIGNING_ALLOWED=YES
  196. COMPILER_INDEX_STORE_ENABLE=NO
  197. )
  198. # TODO(varconst): Add --warn-unused-vars and --warn-uninitialized.
  199. # Right now, it makes the log overflow on Travis because many of our
  200. # dependencies don't build cleanly this way.
  201. cmake_options=(
  202. -Wdeprecated
  203. -DCMAKE_BUILD_TYPE=Debug
  204. )
  205. if [[ -n "${SANITIZERS:-}" ]]; then
  206. for sanitizer in $SANITIZERS; do
  207. case "$sanitizer" in
  208. asan)
  209. xcb_flags+=(
  210. -enableAddressSanitizer YES
  211. )
  212. cmake_options+=(
  213. -DWITH_ASAN=ON
  214. )
  215. ;;
  216. tsan)
  217. xcb_flags+=(
  218. -enableThreadSanitizer YES
  219. )
  220. cmake_options+=(
  221. -DWITH_TSAN=ON
  222. )
  223. ;;
  224. ubsan)
  225. xcb_flags+=(
  226. -enableUndefinedBehaviorSanitizer YES
  227. )
  228. cmake_options+=(
  229. -DWITH_UBSAN=ON
  230. )
  231. ;;
  232. *)
  233. echo "Unknown sanitizer '$sanitizer'" 1>&2
  234. exit 1
  235. ;;
  236. esac
  237. done
  238. fi
  239. case "$product-$platform-$method" in
  240. FirebasePod-iOS-*)
  241. RunXcodebuild \
  242. -workspace 'CoreOnly/Tests/FirebasePodTest/FirebasePodTest.xcworkspace' \
  243. -scheme "FirebasePodTest" \
  244. "${xcb_flags[@]}" \
  245. build
  246. ;;
  247. Auth-*-xcodebuild)
  248. if check_secrets; then
  249. RunXcodebuild \
  250. -workspace 'FirebaseAuth/Tests/Sample/AuthSample.xcworkspace' \
  251. -scheme "Auth_ApiTests" \
  252. "${xcb_flags[@]}" \
  253. build \
  254. test
  255. RunXcodebuild \
  256. -workspace 'FirebaseAuth/Tests/Sample/AuthSample.xcworkspace' \
  257. -scheme "SwiftApiTests" \
  258. "${xcb_flags[@]}" \
  259. build \
  260. test
  261. fi
  262. ;;
  263. InAppMessaging-*-xcodebuild)
  264. RunXcodebuild \
  265. -workspace 'FirebaseInAppMessaging/Tests/Integration/DefaultUITestApp/InAppMessagingDisplay-Sample.xcworkspace' \
  266. -scheme 'FiamDisplaySwiftExample' \
  267. "${xcb_flags[@]}" \
  268. build \
  269. test
  270. ;;
  271. Firestore-*-xcodebuild)
  272. "${firestore_emulator}" start
  273. trap '"${firestore_emulator}" stop' ERR EXIT
  274. RunXcodebuild \
  275. -workspace 'Firestore/Example/Firestore.xcworkspace' \
  276. -scheme "Firestore_IntegrationTests_$platform" \
  277. -enableCodeCoverage YES \
  278. "${xcb_flags[@]}" \
  279. build \
  280. test
  281. ;;
  282. Firestore-macOS-cmake | Firestore-Linux-cmake)
  283. "${firestore_emulator}" start
  284. trap '"${firestore_emulator}" stop' ERR EXIT
  285. (
  286. test -d build || mkdir build
  287. cd build
  288. echo "Preparing cmake build ..."
  289. cmake -G Ninja "${cmake_options[@]}" ..
  290. echo "Building cmake build ..."
  291. ninja -k 10 all
  292. ctest --output-on-failure
  293. )
  294. ;;
  295. SymbolCollision-*-*)
  296. RunXcodebuild \
  297. -workspace 'SymbolCollisionTest/SymbolCollisionTest.xcworkspace' \
  298. -scheme "SymbolCollisionTest" \
  299. "${xcb_flags[@]}" \
  300. build
  301. ;;
  302. Messaging-*-xcodebuild)
  303. pod_gen FirebaseMessaging.podspec --platforms=ios
  304. RunXcodebuild \
  305. -workspace 'gen/FirebaseMessaging/FirebaseMessaging.xcworkspace' \
  306. -scheme "FirebaseMessaging-Unit-unit" \
  307. "${ios_flags[@]}" \
  308. "${xcb_flags[@]}" \
  309. build \
  310. test
  311. if check_secrets; then
  312. # Integration tests are only run on iOS to minimize flake failures.
  313. RunXcodebuild \
  314. -workspace 'gen/FirebaseMessaging/FirebaseMessaging.xcworkspace' \
  315. -scheme "FirebaseMessaging-Unit-integration" \
  316. "${ios_flags[@]}" \
  317. "${xcb_flags[@]}" \
  318. build \
  319. test
  320. fi
  321. pod_gen FirebaseMessaging.podspec --platforms=macos --clean
  322. RunXcodebuild \
  323. -workspace 'gen/FirebaseMessaging/FirebaseMessaging.xcworkspace' \
  324. -scheme "FirebaseMessaging-Unit-unit" \
  325. "${macos_flags[@]}" \
  326. "${xcb_flags[@]}" \
  327. build \
  328. test
  329. pod_gen FirebaseMessaging.podspec --platforms=tvos --clean
  330. RunXcodebuild \
  331. -workspace 'gen/FirebaseMessaging/FirebaseMessaging.xcworkspace' \
  332. -scheme "FirebaseMessaging-Unit-unit" \
  333. "${tvos_flags[@]}" \
  334. "${xcb_flags[@]}" \
  335. build \
  336. test
  337. ;;
  338. MessagingSample-*-*)
  339. if check_secrets; then
  340. RunXcodebuild \
  341. -workspace 'FirebaseMessaging/Apps/Sample/Sample.xcworkspace' \
  342. -scheme "Sample" \
  343. "${xcb_flags[@]}" \
  344. build
  345. fi
  346. ;;
  347. MLModelDownloaderSample-*-*)
  348. if check_secrets; then
  349. RunXcodebuild \
  350. -workspace 'FirebaseMLModelDownloader/Apps/Sample/MLDownloaderTestApp.xcworkspace' \
  351. -scheme "MLDownloaderTestApp" \
  352. "${xcb_flags[@]}" \
  353. build
  354. fi
  355. ;;
  356. SegmentationSample-*-*)
  357. RunXcodebuild \
  358. -workspace 'FirebaseSegmentation/Tests/Sample/SegmentationSampleApp.xcworkspace' \
  359. -scheme "SegmentationSampleApp" \
  360. "${xcb_flags[@]}" \
  361. build
  362. ;;
  363. WatchOSSample-*-*)
  364. RunXcodebuild \
  365. -workspace 'Example/watchOSSample/SampleWatchApp.xcworkspace' \
  366. -scheme "SampleWatchAppWatchKitApp" \
  367. "${xcb_flags[@]}" \
  368. build
  369. ;;
  370. Database-*-unit)
  371. pod_gen FirebaseDatabase.podspec --platforms="${gen_platform}"
  372. RunXcodebuild \
  373. -workspace 'gen/FirebaseDatabase/FirebaseDatabase.xcworkspace' \
  374. -scheme "FirebaseDatabase-Unit-unit" \
  375. "${xcb_flags[@]}" \
  376. build \
  377. test
  378. ;;
  379. Database-*-integration)
  380. "${database_emulator}" start
  381. trap '"${database_emulator}" stop' ERR EXIT
  382. pod_gen FirebaseDatabase.podspec --platforms="${gen_platform}"
  383. RunXcodebuild \
  384. -workspace 'gen/FirebaseDatabase/FirebaseDatabase.xcworkspace' \
  385. -scheme "FirebaseDatabase-Unit-integration" \
  386. "${xcb_flags[@]}" \
  387. build \
  388. test
  389. ;;
  390. RemoteConfig-*-unit)
  391. pod_gen FirebaseRemoteConfig.podspec --platforms="${gen_platform}"
  392. RunXcodebuild \
  393. -workspace 'gen/FirebaseRemoteConfig/FirebaseRemoteConfig.xcworkspace' \
  394. -scheme "FirebaseRemoteConfig-Unit-unit" \
  395. "${xcb_flags[@]}" \
  396. build \
  397. test
  398. ;;
  399. RemoteConfig-*-fakeconsole)
  400. pod_gen FirebaseRemoteConfig.podspec --platforms="${gen_platform}"
  401. RunXcodebuild \
  402. -workspace 'gen/FirebaseRemoteConfig/FirebaseRemoteConfig.xcworkspace' \
  403. -scheme "FirebaseRemoteConfig-Unit-fake-console-tests" \
  404. "${xcb_flags[@]}" \
  405. build \
  406. test
  407. ;;
  408. RemoteConfig-*-integration)
  409. pod_gen FirebaseRemoteConfig.podspec --platforms="${gen_platform}"
  410. RunXcodebuild \
  411. -workspace 'gen/FirebaseRemoteConfig/FirebaseRemoteConfig.xcworkspace' \
  412. -scheme "FirebaseRemoteConfig-Unit-swift-api-tests" \
  413. "${xcb_flags[@]}" \
  414. build \
  415. test
  416. ;;
  417. RemoteConfigSample-*-*)
  418. RunXcodebuild \
  419. -workspace 'FirebaseRemoteConfig/Tests/Sample/RemoteConfigSampleApp.xcworkspace' \
  420. -scheme "RemoteConfigSampleApp" \
  421. "${xcb_flags[@]}" \
  422. build
  423. ;;
  424. Storage-*-xcodebuild)
  425. pod_gen FirebaseStorage.podspec --platforms=ios
  426. # Add GoogleService-Info.plist to generated Test Wrapper App.
  427. ruby ./scripts/update_xcode_target.rb gen/FirebaseStorage/Pods/Pods.xcodeproj \
  428. AppHost-FirebaseStorage-Unit-Tests \
  429. ../../../FirebaseStorage/Tests/Integration/Resources/GoogleService-Info.plist
  430. if check_secrets; then
  431. # Integration tests are only run on iOS to minimize flake failures.
  432. RunXcodebuild \
  433. -workspace 'gen/FirebaseStorage/FirebaseStorage.xcworkspace' \
  434. -scheme "FirebaseStorage-Unit-integration" \
  435. "${ios_flags[@]}" \
  436. "${xcb_flags[@]}" \
  437. build \
  438. test
  439. RunXcodebuild \
  440. -workspace 'gen/FirebaseStorage/FirebaseStorage.xcworkspace' \
  441. -scheme "FirebaseStorage-Unit-swift-integration" \
  442. "${ios_flags[@]}" \
  443. "${xcb_flags[@]}" \
  444. build \
  445. test
  446. fi
  447. ;;
  448. StorageSwift-*-xcodebuild)
  449. pod_gen FirebaseStorageSwift.podspec --platforms=ios
  450. # Add GoogleService-Info.plist to generated Test Wrapper App.
  451. ruby ./scripts/update_xcode_target.rb gen/FirebaseStorageSwift/Pods/Pods.xcodeproj \
  452. AppHost-FirebaseStorageSwift-Unit-Tests \
  453. ../../../FirebaseStorage/Tests/Integration/Resources/GoogleService-Info.plist
  454. if check_secrets; then
  455. # Integration tests are only run on iOS to minimize flake failures.
  456. RunXcodebuild \
  457. -workspace 'gen/FirebaseStorageSwift/FirebaseStorageSwift.xcworkspace' \
  458. -scheme "FirebaseStorageSwift-Unit-integration" \
  459. "${ios_flags[@]}" \
  460. "${xcb_flags[@]}" \
  461. build \
  462. test
  463. fi
  464. ;;
  465. GoogleDataTransport-watchOS-xcodebuild)
  466. RunXcodebuild \
  467. -workspace 'GoogleDataTransport/GDTWatchOSTestApp/GDTWatchOSTestApp.xcworkspace' \
  468. -scheme "GDTWatchOSTestAppWatchKitApp" \
  469. "${xcb_flags[@]}" \
  470. build
  471. RunXcodebuild \
  472. -workspace 'GoogleDataTransport/GDTCCTWatchOSTestApp/GDTCCTWatchOSTestApp.xcworkspace' \
  473. -scheme "GDTCCTWatchOSIndependentTestAppWatchKitApp" \
  474. "${xcb_flags[@]}" \
  475. build
  476. RunXcodebuild \
  477. -workspace 'GoogleDataTransport/GDTCCTWatchOSTestApp/GDTCCTWatchOSTestApp.xcworkspace' \
  478. -scheme "GDTCCTWatchOSCompanionTestApp" \
  479. "${xcb_flags[@]}" \
  480. build
  481. ;;
  482. Performance-*-unit)
  483. # Run unit tests on prod environment with unswizzle capabilities.
  484. export FPR_UNSWIZZLE_AVAILABLE="1"
  485. export FPR_AUTOPUSH_ENV="0"
  486. pod_gen FirebasePerformance.podspec --platforms="${gen_platform}"
  487. RunXcodebuild \
  488. -workspace 'gen/FirebasePerformance/FirebasePerformance.xcworkspace' \
  489. -scheme "FirebasePerformance-Unit-unit" \
  490. "${xcb_flags[@]}" \
  491. build \
  492. test
  493. ;;
  494. Performance-*-proddev)
  495. # Build the prod dev test app.
  496. export FPR_UNSWIZZLE_AVAILABLE="0"
  497. export FPR_AUTOPUSH_ENV="0"
  498. pod_gen FirebasePerformance.podspec --platforms="${gen_platform}"
  499. RunXcodebuild \
  500. -workspace 'gen/FirebasePerformance/FirebasePerformance.xcworkspace' \
  501. -scheme "FirebasePerformance-TestApp" \
  502. "${xcb_flags[@]}" \
  503. build
  504. ;;
  505. Performance-*-integration)
  506. # Generate the workspace for the SDK to generate Protobuf files.
  507. export FPR_UNSWIZZLE_AVAILABLE="0"
  508. pod_gen FirebasePerformance.podspec --platforms=ios --clean
  509. # Perform "pod install" to install the relevant dependencies
  510. cd FirebasePerformance/Tests/FIRPerfE2E; pod install; cd -
  511. # Run E2E Integration Tests for Autopush.
  512. RunXcodebuild \
  513. -workspace 'FirebasePerformance/Tests/FIRPerfE2E/FIRPerfE2E.xcworkspace' \
  514. -scheme "FIRPerfE2EAutopush" \
  515. FPR_AUTOPUSH_ENV=1 \
  516. "${ios_flags[@]}" \
  517. "${xcb_flags[@]}" \
  518. build \
  519. test
  520. # Run E2E Integration Tests for Prod.
  521. RunXcodebuild \
  522. -workspace 'FirebasePerformance/Tests/FIRPerfE2E/FIRPerfE2E.xcworkspace' \
  523. -scheme "FIRPerfE2EProd" \
  524. "${ios_flags[@]}" \
  525. "${xcb_flags[@]}" \
  526. build \
  527. test
  528. ;;
  529. *-*-spm)
  530. RunXcodebuild \
  531. -scheme $product \
  532. "${xcb_flags[@]}" \
  533. test
  534. ;;
  535. *-*-spmbuildonly)
  536. RunXcodebuild \
  537. -scheme $product \
  538. "${xcb_flags[@]}" \
  539. build
  540. ;;
  541. *)
  542. echo "Don't know how to build this product-platform-method combination" 1>&2
  543. echo " product=$product" 1>&2
  544. echo " platform=$platform" 1>&2
  545. echo " method=$method" 1>&2
  546. exit 1
  547. ;;
  548. esac