docker-build.sh 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #!/bin/bash
  2. # This is intended to be run within a opengisch/qfield-sdk docker container.
  3. #
  4. # docker run -v $(pwd):/usr/src/qfield opengisch/qfield-sdk /usr/src/qfield/scripts/docker-build.sh
  5. #
  6. # The result will be put into `build-docker/android-build/build/outputs/apk/out-debug.apk`
  7. #
  8. #
  9. # ANDROID_NDK_PLATFORM and QT_VERSION are defined in docker-qt-crystax
  10. #
  11. # APK_VERSION_CODE (MMmmFFNNA: major,minor,fix,number,architecture_index, e.g. 010203040 from v1.2.3-rc4 arm7) is required.
  12. # APP_VERSION (e.g. v1.2.3, v1.2.3-rc4) is needed when a new version is published.
  13. # APP_VERSION_STR ("v1.2.3 - Release Name", v1.2.3-rc4, PR1234, master-dev) is required. Human readable name.
  14. DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
  15. source ${DIR}/version_number.sh
  16. set -e
  17. if [[ -z $APK_VERSION_CODE ]]; then
  18. echo "*** ERROR MISSING APK_VERSION_CODE ENVIRONMENT VARIABLE"
  19. exit 2
  20. fi
  21. if [[ -z $APP_VERSION_STR ]]; then
  22. echo "*** ERROR MISSING APP_VERSION_STR"
  23. exit 2
  24. fi
  25. if [[ $( echo "${APK_VERSION_CODE} > 030000000" | bc ) == 1 ]]; then
  26. echo "*** ERROR TOO BIG VERSION CODE ${APK_VERSION_CODE}"
  27. echo "Remove this check if QField is now 2.x"
  28. exit 1
  29. fi
  30. SOURCE_DIR=/usr/src/qfield
  31. if [[ -z ${BUILD_FOLDER+x} ]]; then
  32. BUILD_DIR=${SOURCE_DIR}/build-docker
  33. else
  34. BUILD_DIR=${SOURCE_DIR}/${BUILD_FOLDER}
  35. fi
  36. # Set default values if missing
  37. [[ -z ${ARCH} ]] && ARCH=armv7
  38. [[ -z ${APP_NAME} ]] && APP_NAME="QField"
  39. [[ -z ${APP_PACKAGE_NAME} ]] && APP_PACKAGE_NAME="qfield"
  40. INSTALL_DIR=${BUILD_DIR}/out
  41. QT_ANDROID=${QT_ANDROID_BASE}/android
  42. echo "Package name ${APP_PACKAGE_NAME}"
  43. echo "ANDROID_MINIMUM_PLATFORM: ${ANDROID_MINIMUM_PLATFORM}"
  44. echo "ANDROID_TARGET_PLATFORM: ${ANDROID_TARGET_PLATFORM}"
  45. if [[ -n ${APP_ICON} ]]; then
  46. # replace icon
  47. echo "Replacing icon with ${APP_ICON}"
  48. sed -i "s|<file alias=\"qfield_logo.svg\">icons/qfield_logo.svg</file>|<file alias=\"qfield_logo.svg\">icons/${APP_ICON}.svg</file>|" ${SOURCE_DIR}/images/images.qrc
  49. sed -i "s|@drawable/qfield_logo|@drawable/${APP_ICON}|g" ${SOURCE_DIR}/android/res/layout/unpacking_dialog.xml
  50. sed -i "s|@drawable/qfield_logo|@drawable/${APP_ICON}|g" ${SOURCE_DIR}/cmake/AndroidManifest.xml.in
  51. sed -i "s|@drawable/qfield_logo|@drawable/${APP_ICON}|g" ${SOURCE_DIR}/android/src/ch/opengis/qfield/QFieldProjectActivity.java
  52. fi
  53. if [[ "X${APP_PACKAGE_NAME}" != "Xqfield" ]]; then
  54. grep "ch.opengis.qfield" -l -r ${SOURCE_DIR}/android/ | xargs sed -i "s/ch.opengis.qfield/ch.opengis.${APP_PACKAGE_NAME}/g"
  55. grep "ch\.opengis\.qfield" -l -r ${SOURCE_DIR}/src/ | xargs sed -i "s/ch\.opengis\.qfield/ch.opengis.${APP_PACKAGE_NAME}/g"
  56. sed -i "s/ch_opengis_qfield/ch_opengis_${APP_PACKAGE_NAME//_/_1}/g" ${SOURCE_DIR}/src/core/platforms/android/androidplatformutilities.cpp
  57. mv ${SOURCE_DIR}/android/src/ch/opengis/qfield ${SOURCE_DIR}/android/src/ch/opengis/${APP_PACKAGE_NAME}
  58. sed -i "s|<string name=\"app_name\" translatable=\"false\">QField</string>|<string name=\"app_name\" translatable=\"false\">${APP_NAME}</string>|" ${SOURCE_DIR}/android/res/values/strings.xml
  59. fi
  60. mkdir -p ${BUILD_DIR}/.gradle
  61. # androiddeployqt needs gradle and downloads it to /root/.gradle. By linking it to the build folder, this will be cached between builds.
  62. ln -sfn ${BUILD_DIR}/.gradle $HOME/.gradle
  63. pushd ${BUILD_DIR}
  64. if [ "X${ARCH}" == "Xx86" ]; then
  65. export ANDROID_ARCH=x86
  66. export SHORTARCH=x86
  67. elif [ "X${ARCH}" == "Xarmv7" ]; then
  68. export ANDROID_ARCH=armeabi-v7a
  69. export SHORTARCH=arm
  70. elif [ "X${ARCH}" == "Xarm64_v8a" ]; then
  71. export ANDROID_ARCH=arm64-v8a
  72. export SHORTARCH=arm64
  73. elif [ "X${ARCH}" == "Xx86_64" ]; then
  74. export ANDROID_ARCH=x86_64
  75. export SHORTARCH=x86_64
  76. else
  77. echo "Error: Please report issue to enable support for arch (${ARCH})."
  78. exit 1
  79. fi
  80. export STAGE_PATH=/home/osgeo4a/${ANDROID_ARCH}
  81. export ANDROID_CMAKE_LINKER_FLAGS="-fuse-ld=lld"
  82. cmake \
  83. -G Ninja \
  84. -DAPK_VERSION_CODE=${APK_VERSION_CODE} \
  85. -DAPP_VERSION=${APP_VERSION} \
  86. -DAPP_VERSION_STR=${APP_VERSION_STR} \
  87. -DAPP_PACKAGE_NAME=${APP_PACKAGE_NAME} \
  88. -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake \
  89. -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \
  90. -DQt5_DIR:PATH=${QT_ANDROID_BASE}/android/lib/cmake/Qt5 \
  91. -DANDROID_DEPLOY_QT=${QT_ANDROID_BASE}/android/bin/androiddeployqt \
  92. -DCMAKE_FIND_ROOT_PATH:PATH=${ANDROID_NDK_ROOT}\;${QT_ANDROID_BASE}/android/\;/home/osgeo4a/${ANDROID_ARCH} \
  93. -DANDROID_LINKER_FLAGS="${ANDROID_CMAKE_LINKER_FLAGS}" \
  94. -DANDROID_ABI=${ANDROID_ARCH} \
  95. -DANDROID_BUILD_ABI_${ANDROID_ARCH}=ON \
  96. -DQGIS_CORE_LIBRARY=/home/osgeo4a/${ANDROID_ARCH}/lib/libqgis_core_${ANDROID_ARCH}.so \
  97. -DQGIS_ANALYSIS_LIBRARY=/home/osgeo4a/${ANDROID_ARCH}/lib/libqgis_analysis_${ANDROID_ARCH}.so \
  98. -DQGIS_INCLUDE_DIR=/home/osgeo4a/${ANDROID_ARCH}/include/qgis/ \
  99. -DSQLITE3_INCLUDE_DIR:PATH=/home/osgeo4a/${ANDROID_ARCH}/include/ \
  100. -DOSGEO4A_STAGE_DIR:PATH=/home/osgeo4a/ \
  101. -DANDROID_SDK=${ANDROID_SDK_ROOT}/ \
  102. -DANDROID_NDK=${ANDROID_NDK_ROOT}/ \
  103. -DANDROID_STL:STRING=c++_shared \
  104. -DANDROID_PLATFORM=${ANDROID_MINIMUM_PLATFORM} \ `# This one is for NDK -> we need to link against the minimum supported version` \
  105. -DANDROID_TARGET_PLATFORM=${ANDROID_TARGET_PLATFORM} \ `# This one is for the APK, it ends up in the AndroidManifest.xml` \
  106. -DENABLE_TESTS=OFF \
  107. ..
  108. ninja
  109. # Patch the input file for androiddeployqt with the build tools revision
  110. # See https://forum.qt.io/topic/112578/unable-to-sign-android-app-wrong-path-for-zipalign
  111. # Temporary workaround (fingers crossed)
  112. cat <<< "$(jq ". += { \"sdkBuildToolsRevision\" : \"29.0.2\" }" < android_deployment_settings.json)" > android_deployment_settings_patched.json
  113. if [ -n "${KEYNAME}" ] && [ -n "${KEYPASS}" ] && [ -n "${STOREPASS}" ]; then
  114. ${QT_ANDROID}/bin/androiddeployqt \
  115. --sign ${SOURCE_DIR}/keystore.p12 "${KEYNAME}" \
  116. --storepass "${STOREPASS}" \
  117. --keypass "${KEYPASS}" \
  118. --input ${BUILD_DIR}/android_deployment_settings_patched.json \
  119. --output ${BUILD_DIR}/android-build \
  120. --deployment bundled \
  121. --android-platform android-${ANDROID_TARGET_PLATFORM} \
  122. --gradle
  123. else
  124. echo "-- Not signing the apk, KEYNAME, KEYPASS or STOREPASS is not set"
  125. ${QT_ANDROID}/bin/androiddeployqt \
  126. --input ${BUILD_DIR}/android_deployment_settings_patched.json \
  127. --output ${BUILD_DIR}/android-build \
  128. --deployment bundled \
  129. --android-platform android-${ANDROID_TARGET_PLATFORM} \
  130. --gradle
  131. fi
  132. popd