forked from feedc0de/evcharger-app
First try with CI
This commit is contained in:
1 parent
4f1a91fd3e
commit
0384137c85
16 files changed
+528
-558
No files matched your search
@@ -0,0 +1,114 @@
|
||||
name: Build Linux and Android
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
tags:
|
||||
- "**"
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
QT_VERSION: "6.11.1"
|
||||
ANDROID_NDK_VERSION: "27.2.12479018"
|
||||
BUILD_IMAGE: "evcharger-ci:qt-6.11.1-${{ gitea.sha }}"
|
||||
BUILD_CACHE_IMAGE: "evcharger-ci:qt-6.11.1-cache"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# Register a trusted host-mode runner with this label. It only needs
|
||||
# Docker, Bash, Git, and Node.js for the actions used below.
|
||||
runs-on: linux_amd64
|
||||
timeout-minutes: 180
|
||||
|
||||
steps:
|
||||
- name: Check out source and submodules
|
||||
uses: https://gitea.com/actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Restore compiler and Gradle caches
|
||||
uses: https://gitea.com/actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
.ccache
|
||||
.gradle/caches
|
||||
.gradle/wrapper
|
||||
key: evcharger-${{ runner.os }}-qt-6.11.1-${{ gitea.ref_name }}
|
||||
restore-keys: |
|
||||
evcharger-${{ runner.os }}-qt-6.11.1-
|
||||
|
||||
- name: Build the pinned Qt toolchain image
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
docker image inspect "$BUILD_CACHE_IMAGE" >/dev/null 2>&1 || true
|
||||
docker build --pull \
|
||||
--cache-from "$BUILD_CACHE_IMAGE" \
|
||||
--tag "$BUILD_IMAGE" \
|
||||
.
|
||||
docker tag "$BUILD_IMAGE" "$BUILD_CACHE_IMAGE"
|
||||
|
||||
- name: Build Linux development executable
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
docker run --rm \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
--env HOME=/tmp/ci-home \
|
||||
--env CI_WORKSPACE=/workspace \
|
||||
--env CCACHE_DIR=/workspace/.ccache \
|
||||
--volume "$GITHUB_WORKSPACE:/workspace" \
|
||||
--workdir /workspace \
|
||||
"$BUILD_IMAGE" \
|
||||
bash ci/build-linux.sh
|
||||
|
||||
- name: Build Android APK and Play bundle
|
||||
env:
|
||||
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
|
||||
ANDROID_KEYSTORE_ALIAS: ${{ secrets.ANDROID_KEYSTORE_ALIAS }}
|
||||
ANDROID_KEYSTORE_STORE_PASS: ${{ secrets.ANDROID_KEYSTORE_STORE_PASS }}
|
||||
ANDROID_KEYSTORE_KEY_PASS: ${{ secrets.ANDROID_KEYSTORE_KEY_PASS }}
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
docker run --rm \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
--env HOME=/tmp/ci-home \
|
||||
--env CI_WORKSPACE=/workspace \
|
||||
--env CI_RUN_NUMBER="$GITHUB_RUN_NUMBER" \
|
||||
--env CI_REF_NAME="$GITHUB_REF_NAME" \
|
||||
--env CI_REF_TYPE="$GITHUB_REF_TYPE" \
|
||||
--env CCACHE_DIR=/workspace/.ccache \
|
||||
--env GRADLE_USER_HOME=/workspace/.gradle \
|
||||
--env ANDROID_KEYSTORE_BASE64 \
|
||||
--env ANDROID_KEYSTORE_ALIAS \
|
||||
--env ANDROID_KEYSTORE_STORE_PASS \
|
||||
--env ANDROID_KEYSTORE_KEY_PASS \
|
||||
--volume "$GITHUB_WORKSPACE:/workspace" \
|
||||
--workdir /workspace \
|
||||
"$BUILD_IMAGE" \
|
||||
bash ci/build-android.sh
|
||||
|
||||
- name: Upload Linux build
|
||||
uses: https://gitea.com/actions/upload-artifact@v4
|
||||
with:
|
||||
name: evcharger-linux
|
||||
path: dist/linux/
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload Android APK and AAB
|
||||
uses: https://gitea.com/actions/upload-artifact@v4
|
||||
with:
|
||||
name: evcharger-android
|
||||
path: dist/android/
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
|
||||
- name: Remove the commit-specific image tag
|
||||
if: always()
|
||||
run: docker image rm "$BUILD_IMAGE" >/dev/null 2>&1 || true
|
||||
+15
-1
@@ -52,4 +52,18 @@ compile_commands.json
|
||||
*creator.user*
|
||||
|
||||
*_qmlcache.qrc
|
||||
build/
|
||||
build/
|
||||
/build-ci/
|
||||
/dist/
|
||||
/.ccache/
|
||||
/.gradle/
|
||||
|
||||
# The generic *build-* rule above would otherwise hide these CI entrypoints.
|
||||
!/ci/
|
||||
!/ci/build-linux.sh
|
||||
!/ci/build-android.sh
|
||||
|
||||
# Android release signing material must only live in CI/CD secrets.
|
||||
/android_release.keystore
|
||||
/*.keystore
|
||||
/*.jks
|
||||
+92
-67
@@ -1,76 +1,101 @@
|
||||
FROM archlinux
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN pacman -Syu --noconfirm sudo git jdk11-openjdk base-devel ninja \
|
||||
&& rm -R /var/cache/pacman \
|
||||
&& git clone https://github.com/KDAB/android_openssl /opt/android-sdk/android_openssl \
|
||||
&& echo '%sudo ALL=(ALL:ALL) NOPASSWD: ALL' >> /etc/sudoers \
|
||||
&& useradd -m feedc0de \
|
||||
&& groupadd sudo \
|
||||
&& usermod -a -G sudo feedc0de \
|
||||
&& sed -i 's/ debug / !debug /g' /etc/makepkg.conf
|
||||
ARG QT_VERSION=6.11.1
|
||||
ARG AQTINSTALL_VERSION=3.3.0
|
||||
ARG ANDROID_COMMAND_LINE_TOOLS_VERSION=15859902
|
||||
ARG ANDROID_COMMAND_LINE_TOOLS_SHA256=4e4c464f145a7512b57d088ac6c278c03c9eea610886b35a5e0804e74eedf583
|
||||
ARG ANDROID_NDK_VERSION=27.2.12479018
|
||||
ARG ANDROID_OPENSSL_COMMIT=32ebe304ff064a9affb699b2185af78e3494f49a
|
||||
|
||||
USER feedc0de
|
||||
ENV DEBIAN_FRONTEND=noninteractive \
|
||||
QT_ROOT=/opt/Qt \
|
||||
ANDROID_SDK_ROOT=/opt/android-sdk \
|
||||
ANDROID_HOME=/opt/android-sdk \
|
||||
ANDROID_NDK_ROOT=/opt/android-sdk/ndk/${ANDROID_NDK_VERSION} \
|
||||
JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 \
|
||||
PATH=/opt/aqt/bin:/opt/android-sdk/cmdline-tools/latest/bin:/opt/android-sdk/platform-tools:${PATH}
|
||||
|
||||
RUN cd \
|
||||
&& git clone https://aur.archlinux.org/trizen.git \
|
||||
&& cd trizen \
|
||||
&& makepkg -si --noconfirm \
|
||||
&& cd .. \
|
||||
&& sudo rm -R trizen /var/cache/pacman
|
||||
RUN apt-get update \
|
||||
&& apt-get install --yes --no-install-recommends \
|
||||
ca-certificates \
|
||||
ccache \
|
||||
cmake \
|
||||
curl \
|
||||
file \
|
||||
git \
|
||||
libavahi-client-dev \
|
||||
libdbus-1-3 \
|
||||
libegl1 \
|
||||
libfontconfig1 \
|
||||
libgl1 \
|
||||
libx11-6 \
|
||||
libx11-xcb1 \
|
||||
libxcb-cursor0 \
|
||||
libxcb-glx0 \
|
||||
libxcb-icccm4 \
|
||||
libxcb-image0 \
|
||||
libxcb-keysyms1 \
|
||||
libxcb-randr0 \
|
||||
libxcb-render-util0 \
|
||||
libxcb-shape0 \
|
||||
libxcb-shm0 \
|
||||
libxcb-sync1 \
|
||||
libxcb-util1 \
|
||||
libxcb-xfixes0 \
|
||||
libxcb-xinerama0 \
|
||||
libxcb-xkb1 \
|
||||
libxcb1 \
|
||||
libxkbcommon-x11-0 \
|
||||
ninja-build \
|
||||
openjdk-21-jdk-headless \
|
||||
p7zip-full \
|
||||
pkg-config \
|
||||
python3 \
|
||||
python3-venv \
|
||||
unzip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN trizen -S --noconfirm android-environment \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
RUN python3 -m venv /opt/aqt \
|
||||
&& /opt/aqt/bin/pip install --no-cache-dir "aqtinstall==${AQTINSTALL_VERSION}" \
|
||||
&& aqt install-qt linux desktop "${QT_VERSION}" linux_gcc_64 \
|
||||
-m qtcharts qtwebsockets -O "${QT_ROOT}" \
|
||||
&& aqt install-qt linux android "${QT_VERSION}" android_arm64_v8a \
|
||||
-m qtcharts qtwebsockets -O "${QT_ROOT}" \
|
||||
&& aqt install-qt linux android "${QT_VERSION}" android_armv7 \
|
||||
-m qtcharts qtwebsockets -O "${QT_ROOT}"
|
||||
|
||||
RUN trizen -S --noconfirm android-sdk-build-tools \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
RUN mkdir -p "${ANDROID_SDK_ROOT}/cmdline-tools" \
|
||||
&& curl --fail --location --retry 5 \
|
||||
--output /tmp/android-command-line-tools.zip \
|
||||
"https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_COMMAND_LINE_TOOLS_VERSION}_latest.zip" \
|
||||
&& echo "${ANDROID_COMMAND_LINE_TOOLS_SHA256} /tmp/android-command-line-tools.zip" | sha256sum --check \
|
||||
&& unzip -q /tmp/android-command-line-tools.zip -d "${ANDROID_SDK_ROOT}/cmdline-tools" \
|
||||
&& mv "${ANDROID_SDK_ROOT}/cmdline-tools/cmdline-tools" "${ANDROID_SDK_ROOT}/cmdline-tools/latest" \
|
||||
&& rm /tmp/android-command-line-tools.zip \
|
||||
&& yes | sdkmanager --licenses >/dev/null \
|
||||
&& sdkmanager \
|
||||
"platform-tools" \
|
||||
"platforms;android-36" \
|
||||
"build-tools;36.0.0" \
|
||||
"ndk;${ANDROID_NDK_VERSION}"
|
||||
|
||||
RUN trizen -S --noconfirm android-sdk \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
RUN git init "${ANDROID_SDK_ROOT}/android_openssl" \
|
||||
&& git -C "${ANDROID_SDK_ROOT}/android_openssl" remote add origin https://github.com/KDAB/android_openssl.git \
|
||||
&& git -C "${ANDROID_SDK_ROOT}/android_openssl" fetch --depth 1 origin "${ANDROID_OPENSSL_COMMIT}" \
|
||||
&& git -C "${ANDROID_SDK_ROOT}/android_openssl" checkout --detach FETCH_HEAD \
|
||||
&& rm -rf "${ANDROID_SDK_ROOT}/android_openssl/.git"
|
||||
|
||||
RUN trizen -S --noconfirm android-ndk \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
# Build dependencies needed by applications using the prebuilt desktop Qt.
|
||||
# Keep these in a separate layer so changes here do not invalidate the large
|
||||
# Qt and Android SDK downloads above.
|
||||
RUN apt-get update \
|
||||
&& apt-get install --yes --no-install-recommends \
|
||||
build-essential \
|
||||
libgl1-mesa-dev \
|
||||
libglib2.0-0t64 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV ANDROID_NDK_ROOT=/opt/android-ndk
|
||||
ENV LANG=C.UTF-8 \
|
||||
LC_ALL=C.UTF-8
|
||||
|
||||
RUN trizen -S --noconfirm android-pkg-config \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-cmake \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-sdk-platform-tools \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-platform \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-aarch64-libjpeg-turbo \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-configure \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-aarch64-zlib \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-aarch64-libpng \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN gpg2 --recv-keys D894E2CE8B3D79F5 \
|
||||
&& trizen -S --noconfirm android-aarch64-openssl \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-aarch64-qt6-base \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-aarch64-qt6-shadertools \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-aarch64-qt6-declarative \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-aarch64-qt6-websockets \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
|
||||
RUN trizen -S --noconfirm android-aarch64-qt6-tools \
|
||||
&& sudo rm -R ~/.cache /var/cache/pacman
|
||||
WORKDIR /workspace
|
||||
@@ -14,3 +14,15 @@ This app aims to be functional first and pretty second.
|
||||
* You can also select any color you like in all color pickers
|
||||
* Has an actual start / stop button that doesnt interfere with any other settings
|
||||
* Has an actual helpful cellular information and settings page
|
||||
|
||||
## Building
|
||||
|
||||
The application is built with CMake and Qt 6.11.1. A reproducible build
|
||||
container and Gitea Actions workflow are included. The workflow compiles a Linux
|
||||
development build and produces an Android APK plus an Android App Bundle for
|
||||
Google Play. Release credentials make both Android artifacts signed; pipelines
|
||||
without credentials produce unsigned validation packages.
|
||||
|
||||
See [docs/gitea-actions.md](docs/gitea-actions.md) for runner requirements, signing
|
||||
secret setup, artifact downloads, local container builds, and release
|
||||
versioning.
|
||||
Executable
+99
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
readonly project_dir="${CI_WORKSPACE:-${GITHUB_WORKSPACE:-$(pwd)}}"
|
||||
readonly build_dir="${project_dir}/build-ci/android"
|
||||
readonly output_dir="${project_dir}/dist/android"
|
||||
readonly qt_root="${QT_ROOT:-/opt/Qt}"
|
||||
readonly qt_version="${QT_VERSION:-6.11.1}"
|
||||
readonly android_ndk_version="${ANDROID_NDK_VERSION:-27.2.12479018}"
|
||||
readonly run_number="${CI_RUN_NUMBER:-${GITHUB_RUN_NUMBER:-1}}"
|
||||
readonly ref_name="${CI_REF_NAME:-${GITHUB_REF_NAME:-}}"
|
||||
readonly ref_type="${CI_REF_TYPE:-${GITHUB_REF_TYPE:-}}"
|
||||
readonly version_code="${ANDROID_VERSION_CODE:-${run_number}}"
|
||||
|
||||
if [[ -n "${ANDROID_VERSION_NAME:-}" ]]; then
|
||||
version_name="${ANDROID_VERSION_NAME}"
|
||||
elif [[ "${ref_type}" == tag && -n "${ref_name}" ]]; then
|
||||
version_name="${ref_name#v}"
|
||||
else
|
||||
version_name="${PROJECT_VERSION:-0.1.0}-ci.${run_number}"
|
||||
fi
|
||||
readonly version_name
|
||||
|
||||
sign_android=OFF
|
||||
keystore_path=""
|
||||
if [[ -n "${ANDROID_KEYSTORE_BASE64:-}" ]]; then
|
||||
keystore_path="${build_dir}/release.keystore"
|
||||
mkdir -p "${build_dir}"
|
||||
printf '%s' "${ANDROID_KEYSTORE_BASE64}" | base64 --decode > "${keystore_path}"
|
||||
trap 'rm -f -- "${keystore_path}"' EXIT
|
||||
elif [[ -n "${ANDROID_KEYSTORE_FILE:-}" ]]; then
|
||||
keystore_path="${ANDROID_KEYSTORE_FILE}"
|
||||
fi
|
||||
|
||||
if [[ -n "${keystore_path}" ]]; then
|
||||
: "${ANDROID_KEYSTORE_ALIAS:?ANDROID_KEYSTORE_ALIAS is required when a keystore is provided}"
|
||||
: "${ANDROID_KEYSTORE_STORE_PASS:?ANDROID_KEYSTORE_STORE_PASS is required when a keystore is provided}"
|
||||
: "${ANDROID_KEYSTORE_KEY_PASS:?ANDROID_KEYSTORE_KEY_PASS is required when a keystore is provided}"
|
||||
export QT_ANDROID_KEYSTORE_PATH="${keystore_path}"
|
||||
export QT_ANDROID_KEYSTORE_ALIAS="${ANDROID_KEYSTORE_ALIAS}"
|
||||
export QT_ANDROID_KEYSTORE_STORE_PASS="${ANDROID_KEYSTORE_STORE_PASS}"
|
||||
export QT_ANDROID_KEYSTORE_KEY_PASS="${ANDROID_KEYSTORE_KEY_PASS}"
|
||||
sign_android=ON
|
||||
else
|
||||
echo "No Android keystore configured; producing unsigned CI packages."
|
||||
fi
|
||||
|
||||
"${qt_root}/${qt_version}/android_arm64_v8a/bin/qt-cmake" \
|
||||
--fresh \
|
||||
-S "${project_dir}" \
|
||||
-B "${build_dir}" \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DQT_HOST_PATH="${qt_root}/${qt_version}/gcc_64" \
|
||||
-DANDROID_SDK_ROOT="${ANDROID_SDK_ROOT}" \
|
||||
-DANDROID_NDK_ROOT="${ANDROID_SDK_ROOT}/ndk/${android_ndk_version}" \
|
||||
-DQT_ANDROID_ABIS="arm64-v8a;armeabi-v7a" \
|
||||
-DEVCHARGER_ANDROID_VERSION_CODE="${version_code}" \
|
||||
-DEVCHARGER_ANDROID_VERSION_NAME="${version_name}" \
|
||||
-DQT_ANDROID_SIGN_APK="${sign_android}" \
|
||||
-DQT_ANDROID_SIGN_AAB="${sign_android}"
|
||||
|
||||
# Both package targets use the same android-build staging directory. Running
|
||||
# them in one parallel Ninja invocation makes androiddeployqt race with itself.
|
||||
cmake --build "${build_dir}" --parallel
|
||||
cmake --build "${build_dir}" --parallel --target apk
|
||||
cmake --build "${build_dir}" --parallel --target aab
|
||||
|
||||
mkdir -p "${output_dir}"
|
||||
|
||||
if [[ "${sign_android}" == ON ]]; then
|
||||
apk_path="$(find "${build_dir}" -type f -path '*/outputs/apk/release/*.apk' ! -name '*unsigned*' -print -quit)"
|
||||
else
|
||||
apk_path="$(find "${build_dir}" -type f -path '*/outputs/apk/release/*.apk' -print -quit)"
|
||||
fi
|
||||
aab_path="$(find "${build_dir}" -type f -path '*/outputs/bundle/release/*.aab' -print -quit)"
|
||||
|
||||
: "${apk_path:?The Android build did not produce an APK}"
|
||||
: "${aab_path:?The Android build did not produce an AAB}"
|
||||
|
||||
cp "${apk_path}" "${output_dir}/evcharger-${version_name}-universal.apk"
|
||||
cp "${aab_path}" "${output_dir}/evcharger-${version_name}.aab"
|
||||
|
||||
readonly output_apk="evcharger-${version_name}-universal.apk"
|
||||
readonly output_aab="evcharger-${version_name}.aab"
|
||||
|
||||
for abi in arm64-v8a armeabi-v7a; do
|
||||
unzip -Z1 "${output_dir}/${output_apk}" "lib/${abi}/*" >/dev/null
|
||||
done
|
||||
|
||||
if [[ "${sign_android}" == ON ]]; then
|
||||
"${ANDROID_SDK_ROOT}/build-tools/36.0.0/apksigner" verify --verbose --print-certs "${output_dir}/${output_apk}"
|
||||
jarsigner -verify "${output_dir}/${output_aab}"
|
||||
fi
|
||||
|
||||
(
|
||||
cd "${output_dir}"
|
||||
sha256sum "${output_apk}" "${output_aab}" > SHA256SUMS
|
||||
)
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
readonly project_dir="${CI_WORKSPACE:-${GITHUB_WORKSPACE:-$(pwd)}}"
|
||||
readonly build_dir="${project_dir}/build-ci/linux"
|
||||
readonly output_dir="${project_dir}/dist/linux"
|
||||
readonly qt_root="${QT_ROOT:-/opt/Qt}"
|
||||
readonly qt_version="${QT_VERSION:-6.11.1}"
|
||||
|
||||
"${qt_root}/${qt_version}/gcc_64/bin/qt-cmake" \
|
||||
--fresh \
|
||||
-S "${project_dir}" \
|
||||
-B "${build_dir}" \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_COMPILE_WARNING_AS_ERROR=OFF
|
||||
|
||||
cmake --build "${build_dir}" --parallel
|
||||
|
||||
mkdir -p "${output_dir}"
|
||||
cp "${build_dir}/evcharger-app/evcharger-app" "${output_dir}/evcharger-app"
|
||||
file "${output_dir}/evcharger-app"
|
||||
@@ -0,0 +1,152 @@
|
||||
# Gitea Actions builds
|
||||
|
||||
The workflow in `.gitea/workflows/build.yml` builds the pinned toolchain image,
|
||||
then compiles the Linux and Android packages. Its toolchain is:
|
||||
|
||||
- Qt 6.11.1 from Qt's public binary repository, installed with `aqtinstall`;
|
||||
- Ubuntu 24.04 and JDK 21;
|
||||
- Android API and Build Tools 36;
|
||||
- Android NDK 27.2.12479018;
|
||||
- a pinned KDAB Android OpenSSL revision;
|
||||
- `arm64-v8a` and `armeabi-v7a` device ABIs.
|
||||
|
||||
The runner's Docker daemon retains the large image layers. The first run must
|
||||
download Qt and the Android SDK, but ordinary later runs reuse that local cache.
|
||||
No Gitea Container Registry credentials are required. A runner replacement or
|
||||
Docker cache cleanup causes the toolchain to be downloaded again.
|
||||
|
||||
Qt's current Gradle template is intentionally not copied into the source tree.
|
||||
`androiddeployqt` overlays the custom manifest and resources from
|
||||
`evcharger-app/android` onto the template supplied by Qt 6.11.1. This keeps Qt,
|
||||
Gradle, and the Android Gradle Plugin in sync.
|
||||
|
||||
## Runner requirements
|
||||
|
||||
Enable Actions in the repository settings and register a trusted Gitea Runner
|
||||
with the workflow label `linux_amd64`. Use host mode because the workflow itself
|
||||
starts build containers:
|
||||
|
||||
```yaml
|
||||
runner:
|
||||
labels:
|
||||
- "linux_amd64:host"
|
||||
```
|
||||
|
||||
The runner host needs Docker, Bash, Git, and Node.js. Its user must be allowed
|
||||
to access the Docker daemon. Keep this runner restricted to repositories you
|
||||
trust: Docker daemon access is effectively host-level access.
|
||||
|
||||
For example, after downloading `act_runner`, obtain a repository runner token
|
||||
from **Settings > Actions > Runners**, then run:
|
||||
|
||||
```sh
|
||||
./act_runner register --no-interactive \
|
||||
--instance https://your-gitea.example \
|
||||
--token YOUR_REGISTRATION_TOKEN \
|
||||
--name evcharger-builder \
|
||||
--labels linux_amd64:host
|
||||
|
||||
./act_runner daemon
|
||||
```
|
||||
|
||||
The workflow timeout is three hours because the uncached first image build is
|
||||
large. The toolchain image is cached independently from the ccache and Gradle
|
||||
caches stored by Gitea Actions.
|
||||
|
||||
## Signing secrets
|
||||
|
||||
Without a keystore, the workflow deliberately produces unsigned validation
|
||||
packages. This allows pull requests to test Android compilation without release
|
||||
credentials.
|
||||
|
||||
In **Settings > Actions > Secrets**, add these repository secrets:
|
||||
|
||||
| Secret | Value |
|
||||
| --- | --- |
|
||||
| `ANDROID_KEYSTORE_BASE64` | Release keystore encoded as one base64 line |
|
||||
| `ANDROID_KEYSTORE_ALIAS` | Private-key alias in the keystore |
|
||||
| `ANDROID_KEYSTORE_STORE_PASS` | Keystore password |
|
||||
| `ANDROID_KEYSTORE_KEY_PASS` | Private-key password |
|
||||
|
||||
Encode the keystore locally with:
|
||||
|
||||
```sh
|
||||
base64 -w0 android_release.keystore
|
||||
```
|
||||
|
||||
Never commit the keystore. Root-level `.keystore` and `.jks` files are ignored.
|
||||
The workflow's decoded temporary copy is deleted when the Android script exits.
|
||||
|
||||
### Check an uncertain password and alias safely
|
||||
|
||||
`keytool` is included in a JDK. This command prompts for the store password and
|
||||
lists all aliases; the password is not placed in shell history or the process
|
||||
list:
|
||||
|
||||
```sh
|
||||
keytool -list -v -keystore android_release.keystore
|
||||
```
|
||||
|
||||
That only proves the store password. To verify the selected alias and its
|
||||
private-key password without modifying the keystore, sign a disposable JAR:
|
||||
|
||||
```sh
|
||||
probe_dir="$(mktemp -d)"
|
||||
trap 'rm -rf -- "$probe_dir"' EXIT
|
||||
printf 'keystore test\n' > "$probe_dir/probe.txt"
|
||||
jar --create --file "$probe_dir/probe.jar" -C "$probe_dir" probe.txt
|
||||
jarsigner -keystore android_release.keystore "$probe_dir/probe.jar" YOUR_ALIAS
|
||||
jarsigner -verify "$probe_dir/probe.jar"
|
||||
```
|
||||
|
||||
`jarsigner` prompts first for the store password and, when different, for the
|
||||
private-key password. A successful signing followed by `jar verified` confirms
|
||||
all three values. Do not use `-storepass` or `-keypass` on an interactive shell,
|
||||
because command-line arguments can leak through history and process listings.
|
||||
|
||||
## Artifacts and Android versions
|
||||
|
||||
Each successful workflow exposes two downloads in the Gitea Actions run:
|
||||
|
||||
```text
|
||||
evcharger-linux/
|
||||
evcharger-app
|
||||
|
||||
evcharger-android/
|
||||
evcharger-<version>-universal.apk
|
||||
evcharger-<version>.aab
|
||||
SHA256SUMS
|
||||
```
|
||||
|
||||
Artifacts are retained for 30 days. A signed universal APK is suitable for
|
||||
direct download and sideloading; an unsigned one is only a validation artifact.
|
||||
Upload the signed AAB to Google Play, which produces device-specific APKs.
|
||||
|
||||
The Android `versionCode` defaults to the monotonically increasing Gitea Actions
|
||||
run number. Tags become the `versionName` after an optional leading `v` is
|
||||
removed; other builds use `0.1.0-ci.<run number>`. Override these with workflow
|
||||
environment values `ANDROID_VERSION_CODE` and `ANDROID_VERSION_NAME` if needed.
|
||||
|
||||
## Local container builds
|
||||
|
||||
```sh
|
||||
docker build -t evcharger-build:qt-6.11.1 .
|
||||
|
||||
docker run --rm -v "$PWD:/workspace" -w /workspace \
|
||||
evcharger-build:qt-6.11.1 bash ci/build-linux.sh
|
||||
|
||||
docker run --rm -v "$PWD:/workspace" -w /workspace \
|
||||
evcharger-build:qt-6.11.1 bash ci/build-android.sh
|
||||
```
|
||||
|
||||
Pass the signing variables through `--env` or an environment file for a signed
|
||||
local Android build. Do not add secrets to the Dockerfile or image.
|
||||
|
||||
## Qt open-source licensing note
|
||||
|
||||
The public Qt binaries do not require a commercial account. Distribution must
|
||||
still follow every linked module's license. Qt Charts is GPLv3-only for
|
||||
open-source users (or commercially licensed), so distributing this application
|
||||
with Qt Charts requires GPLv3-compatible distribution of the combined program
|
||||
and corresponding source. Review and document that licensing choice before
|
||||
publishing the APK/AAB, or use a commercial Qt license.
|
||||
@@ -23,9 +23,29 @@ qt6_add_translations(evcharger-app
|
||||
)
|
||||
|
||||
if (ANDROID)
|
||||
set_property(TARGET evcharger-app APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android)
|
||||
set(EVCHARGER_ANDROID_VERSION_CODE "1" CACHE STRING "Monotonically increasing Android version code")
|
||||
set(EVCHARGER_ANDROID_VERSION_NAME "0.1.0" CACHE STRING "Human-readable Android version")
|
||||
|
||||
set_property(TARGET evcharger-app APPEND PROPERTY
|
||||
QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android
|
||||
)
|
||||
include(${ANDROID_SDK_ROOT}/android_openssl/CMakeLists.txt)
|
||||
set_target_properties(evcharger-app PROPERTIES QT_ANDROID_EXTRA_LIBS "${ANDROID_EXTRA_LIBS}")
|
||||
set_target_properties(evcharger-app PROPERTIES
|
||||
QT_ANDROID_EXTRA_LIBS "${ANDROID_EXTRA_LIBS}"
|
||||
QT_ANDROID_PACKAGE_NAME "ninja.brunner.evcharger"
|
||||
QT_ANDROID_MIN_SDK_VERSION 28
|
||||
QT_ANDROID_COMPILE_SDK_VERSION 36
|
||||
QT_ANDROID_TARGET_SDK_VERSION 36
|
||||
QT_ANDROID_VERSION_CODE "${EVCHARGER_ANDROID_VERSION_CODE}"
|
||||
QT_ANDROID_VERSION_NAME "${EVCHARGER_ANDROID_VERSION_NAME}"
|
||||
)
|
||||
|
||||
# Custom cache variables are not automatically inherited by Qt's
|
||||
# secondary ABI builds.
|
||||
list(APPEND QT_ANDROID_MULTI_ABI_FORWARD_VARS
|
||||
EVCHARGER_ANDROID_VERSION_CODE
|
||||
EVCHARGER_ANDROID_VERSION_NAME
|
||||
)
|
||||
endif()
|
||||
|
||||
qt_add_qml_module(evcharger-app
|
||||
|
||||
@@ -14,23 +14,6 @@
|
||||
<meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/splashscreen_port"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/splashscreen_land"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splashscreen"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/splashscreen_port"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/splashscreen_land"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splashscreen"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/splashscreen_port"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/splashscreen_land"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splashscreen"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/splashscreen_port"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/splashscreen_land"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splashscreen"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/splashscreen_port"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/splashscreen_land"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splashscreen"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/splashscreen_port"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/splashscreen_land"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splashscreen"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/splashscreen_port"/>
|
||||
<meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/splashscreen_land"/>
|
||||
</activity>
|
||||
|
||||
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.qtprovider" android:exported="false" android:grantUriPermissions="true">
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.4.0'
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
apply plugin: qtGradlePluginType
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
||||
implementation 'androidx.core:core:1.13.1'
|
||||
}
|
||||
|
||||
android {
|
||||
/*******************************************************
|
||||
* The following variables:
|
||||
* - androidBuildToolsVersion,
|
||||
* - androidCompileSdkVersion
|
||||
* - qtAndroidDir - holds the path to qt android files
|
||||
* needed to build any Qt application
|
||||
* on Android.
|
||||
* - qtGradlePluginType - whether to build an app or a library
|
||||
*
|
||||
* are defined in gradle.properties file. This file is
|
||||
* updated by QtCreator and androiddeployqt tools.
|
||||
* Changing them manually might break the compilation!
|
||||
*******************************************************/
|
||||
|
||||
namespace androidPackageName
|
||||
compileSdkVersion androidCompileSdkVersion
|
||||
buildToolsVersion androidBuildToolsVersion
|
||||
ndkVersion androidNdkVersion
|
||||
|
||||
// Extract native libraries from the APK
|
||||
packagingOptions.jniLibs.useLegacyPackaging true
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = [qtAndroidDir + '/src', 'src', 'java']
|
||||
aidl.srcDirs = [qtAndroidDir + '/src', 'src', 'aidl']
|
||||
res.srcDirs = [qtAndroidDir + '/res', 'res']
|
||||
resources.srcDirs = ['resources']
|
||||
renderscript.srcDirs = ['src']
|
||||
assets.srcDirs = ['assets']
|
||||
jniLibs.srcDirs = ['libs']
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.incremental = true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
// Do not compress Qt binary resources file
|
||||
aaptOptions {
|
||||
noCompress 'rcc'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
resConfig "en"
|
||||
minSdkVersion qtMinSdkVersion
|
||||
targetSdkVersion qtTargetSdkVersion
|
||||
ndk.abiFilters = qtTargetAbiList.split(",")
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
# Project-wide Gradle settings.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2500m -XX:MaxMetaspaceSize=768m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
# Enable building projects in parallel
|
||||
org.gradle.parallel=true
|
||||
|
||||
# Gradle caching allows reusing the build artifacts from a previous
|
||||
# build with the same inputs. However, over time, the cache size will
|
||||
# grow. Uncomment the following line to enable it.
|
||||
#org.gradle.caching=true
|
||||
#org.gradle.configuration-cache=true
|
||||
|
||||
# Allow AndroidX usage
|
||||
android.useAndroidX=true
|
||||
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
Vendored
-249
@@ -1,249 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
-92
@@ -1,92 +0,0 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<!-- DO NOT EDIT THIS: This file is populated automatically by the deployment tool. -->
|
||||
|
||||
<array name="bundled_libs">
|
||||
<!-- %%INSERT_EXTRA_LIBS%% -->
|
||||
</array>
|
||||
|
||||
<array name="qt_libs">
|
||||
<!-- %%INSERT_QT_LIBS%% -->
|
||||
</array>
|
||||
|
||||
<array name="load_local_libs">
|
||||
<!-- %%INSERT_LOCAL_LIBS%% -->
|
||||
</array>
|
||||
|
||||
<string name="static_init_classes"><!-- %%INSERT_INIT_CLASSES%% --></string>
|
||||
<string name="use_local_qt_libs"><!-- %%USE_LOCAL_QT_LIBS%% --></string>
|
||||
<string name="bundle_local_qt_libs"><!-- %%BUNDLE_LOCAL_QT_LIBS%% --></string>
|
||||
<string name="system_libs_prefix"><!-- %%SYSTEM_LIBS_PREFIX%% --></string>
|
||||
</resources>
|
||||
Reference in new issue
Block a user