Commit fe1df623 authored by dsq's avatar dsq

一键打包脚本

parent 40d7b1cc
#!/bin/bash
#
# Eazytec is pleased to support the open source community by making CPF-KMP-CMP available.
# Copyright (C) 2026 Eazytec. All rights reserved.
#
# 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
#
# http://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.
#
#
set -e
# Record script start time
START_TIME=$(date +%s)
# ====================== [1. Default Configuration and Parameter Parsing] ======================
DEFAULT_PLATFORM="ohosArm64"
DEFAULT_TARGET_ID="127.0.0.1:5555"
DEFAULT_BUNDLE_NAME="com.example.harmonyapp"
DEFAULT_ABILITY_NAME="EntryAbility"
LOCAL_OHOS_PATH=""
usage() {
echo "Usage: $0 [options] [PLATFORM] [TARGET_ID]"
echo ""
echo "Parameters:"
echo " PLATFORM Build platform (default: $DEFAULT_PLATFORM)"
echo " TARGET_ID Device ID (default: $DEFAULT_TARGET_ID)"
echo ""
echo "Options:"
echo " -M MODES 打包类型: debug | release | all (default: 交互选择)"
echo " -m MODE Build mode: debug or release (default: debug)"
echo " -b BUNDLE Set bundle name (current: $DEFAULT_BUNDLE_NAME)"
echo " -a ABILITY Set Ability name (current: $DEFAULT_ABILITY_NAME)"
echo " -d MODE Debug mode: debug or attach (default: attach)"
echo " -p PATH Set external OHOS project path (localOhosPath)"
echo " -h Show this help message"
echo ""
echo "Examples:"
echo " $0 ohosArm64 127.0.0.1:5555"
echo " $0 -M debug # 仅打 debug 包"
echo " $0 -M release # 仅打 release 包"
echo " $0 -M all # debug+release(默认可交互选择)"
echo " $0 -b com.test.app -a MainAbility"
echo " $0 -p /path/to/external/ohos/project"
exit 0
}
# Preset variables
BUNDLE_NAME=$DEFAULT_BUNDLE_NAME
ABILITY_NAME=$DEFAULT_ABILITY_NAME
BUILD_MODE="debug"
BUILD_MODES_SELECT="" # 空表示打包前交互选择;可选 debug | release | all
DEBUG_MODE="attach"
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
# Parse options (supports options in any position, e.g. ohosArm64 62Q0226107024702 -m release)
POSITIONALS=()
while [[ $# -gt 0 ]]; do
case $1 in
-M) BUILD_MODES_SELECT="$2"; shift 2 ;;
-m) BUILD_MODE="$2"; shift 2 ;;
-b) BUNDLE_NAME="$2"; shift 2 ;;
-a) ABILITY_NAME="$2"; shift 2 ;;
-d) DEBUG_MODE="$2"; shift 2 ;;
-p) LOCAL_OHOS_PATH="$2"; shift 2 ;;
-h) usage ;;
-*)
echo "Unknown option: $1"
usage
;;
*)
POSITIONALS+=("$1")
shift
;;
esac
done
PLATFORM=${POSITIONALS[0]:-$DEFAULT_PLATFORM}
TARGET_ID=${POSITIONALS[1]:-$DEFAULT_TARGET_ID}
echo -e "\033[32m▶ Run environment configuration:\033[0m"
echo " - Platform: $PLATFORM"
echo " - Devices: from hdc list targets (see below)"
echo " - Build modes: 由 -M 或打包前选择 (debug / release / debug+release)"
echo " - Debug mode: $DEBUG_MODE"
echo " - Bundle: $BUNDLE_NAME"
echo " - Ability: $ABILITY_NAME"
if [ -n "$LOCAL_OHOS_PATH" ]; then
echo " - External OHOS path: $LOCAL_OHOS_PATH"
fi
echo "------------------------------------------------------------"
# --- Configuration ---
DEVECO_PATH="${DEVECO_PATH:-/Applications/DevEco-Studio.app}"
MIN_VERSION="6.0.0"
echo " DevEco Studio Path ${DEVECO_PATH}"
echo "🔍 Checking environment configuration..."
# 1. Check if DevEco exists
if [ ! -d "$DEVECO_PATH" ]; then
echo "❌ Error: DevEco Studio not found at $DEVECO_PATH."
exit 1
fi
# 2. Get version (from Info.plist CFBundleShortVersionString)
# Output example: 5.0.3.406
CURRENT_VERSION=$(defaults read "$DEVECO_PATH/Contents/Info.plist" CFBundleShortVersionString)
echo "Current DevEco version: $CURRENT_VERSION"
echo "Minimum required version: $MIN_VERSION"
CUR_MAJOR=$(echo "$CURRENT_VERSION" | cut -d. -f1)
CUR_MINOR=$(echo "$CURRENT_VERSION" | cut -d. -f2)
REQ_MAJOR=$(echo "$MIN_VERSION" | cut -d. -f1)
REQ_MINOR=$(echo "$MIN_VERSION" | cut -d. -f2)
if [ "$CUR_MAJOR" -lt "$REQ_MAJOR" ] 2>/dev/null || \
{ [ "$CUR_MAJOR" -eq "$REQ_MAJOR" ] && [ "$CUR_MINOR" -lt "$REQ_MINOR" ]; }; then
echo "-------------------------------------------------------"
echo -e "${RED}⛔️ Error: DevEco version is too low!${NC}"
echo -e "${RED}Current version: $CURRENT_VERSION${NC}"
echo -e "${RED}Minimum required: $MIN_VERSION+${NC}"
echo -e "${RED}Please upgrade DevEco Studio and run this script again.${NC}"
echo "-------------------------------------------------------"
exit 5
fi
echo "✅ DevEco version meets requirements ($CURRENT_VERSION)"
# ====================== [2. Environment Path and SDK Configuration] ======================
DEVECO_HOME="${DEVECO_HOME:-$DEVECO_PATH/Contents}"
echo "✅ ($DEVECO_HOME)"
HDC_BIN="$DEVECO_HOME/sdk/default/openharmony/toolchains/hdc"
export DEVECO_SDK_HOME="$DEVECO_HOME/sdk"
export PATH="$DEVECO_SDK_HOME:$DEVECO_HOME/jbr/Contents/Home/bin:$DEVECO_HOME/tools/node/bin:$DEVECO_HOME/tools/ohpm/bin:$DEVECO_HOME/tools/hvigor/bin:$PATH"
# ====================== [2.5 Device List and Build Mode List] ======================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEVICE_IDS=()
while IFS= read -r line; do
line=$(echo "$line" | tr -d '\r' | xargs)
[ -n "$line" ] && DEVICE_IDS+=("$line")
done < <("$HDC_BIN" list targets 2>/dev/null | awk '{if (NF>=1) print $1}')
# 打包类型:未指定 -M 时交互选择
if [ -z "$BUILD_MODES_SELECT" ]; then
echo ""
echo "请选择打包类型:"
echo " 1) 仅 debug"
echo " 2) 仅 release"
echo " 3) debug+release"
printf "请输入 [1/2/3,默认 3]: "
read -r BUILD_CHOICE
BUILD_CHOICE=${BUILD_CHOICE:-3}
case "$BUILD_CHOICE" in
1) BUILD_MODES_SELECT="debug" ;;
2) BUILD_MODES_SELECT="release" ;;
3|*) BUILD_MODES_SELECT="all" ;;
esac
fi
case "$(echo "$BUILD_MODES_SELECT" | tr '[:upper:]' '[:lower:]')" in
debug) BUILD_MODES=(debug) ;;
release) BUILD_MODES=(release) ;;
all|*) BUILD_MODES=(debug release) ;;
esac
if [ ${#DEVICE_IDS[@]} -eq 0 ]; then
echo -e "\033[31mError: No device found. Run 'hdc list targets' to check connected devices.\033[0m"
exit 5
fi
echo "Devices: ${DEVICE_IDS[*]}"
echo "Build modes: ${BUILD_MODES[*]}"
echo "------------------------------------------------------------"
TOTAL_COUNT=0
SUCCESS_COUNT=0
set +e
for TARGET_ID in "${DEVICE_IDS[@]}"; do
for BUILD_MODE in "${BUILD_MODES[@]}"; do
((TOTAL_COUNT++))
echo ""
echo "$TARGET_ID 设备 $BUILD_MODE 模式 进行打包"
# 每次打包前:先删除 entry/builds、entry/libs/arm64_v8a、entry/libs/x86_64,删除后检测,确认无 HAP 与 libs 中间产物后再进行打包(含第一次)
ENTRY_BASE="$SCRIPT_DIR/harmonyApp/entry"
CHECK_BASE="$SCRIPT_DIR/harmonyApp"
HAP_PATH="$CHECK_BASE/entry/build/default/outputs/default/entry-default-signed.hap"
LIBS_ARM="$CHECK_BASE/entry/libs/arm64_v8a"
LIBS_X86="$CHECK_BASE/entry/libs/x86_64"
DEL_RETRY=0
while true; do
rm -rf "$ENTRY_BASE/builds"
rm -rf "$ENTRY_BASE/libs/arm64_v8a"
rm -rf "$ENTRY_BASE/libs/x86_64"
HAP_EXISTS="无"; [ -f "$HAP_PATH" ] && HAP_EXISTS="有"
LIBS_EXISTS="无"; [ -d "$LIBS_ARM" ] || [ -d "$LIBS_X86" ] && LIBS_EXISTS="有"
if [ "$HAP_EXISTS" = "无" ] && [ "$LIBS_EXISTS" = "无" ]; then
echo -e "\033[35m删除后检测: HAP包=无, libs中间产物=无,已确认清理完成\033[0m"
break
fi
DEL_RETRY=$((DEL_RETRY + 1))
if [ $DEL_RETRY -ge 5 ]; then
echo -e "\033[35m删除后检测: HAP包=${HAP_EXISTS}, libs中间产物=${LIBS_EXISTS},清理未完全,继续打包\033[0m"
break
fi
sleep 1
done
# 当前设备先卸载应用,再打包安装
"$HDC_BIN" -t "$TARGET_ID" shell bm uninstall -n "$BUNDLE_NAME" >/dev/null 2>&1 || true
"$HDC_BIN" -t "$TARGET_ID" shell aa force-stop "$BUNDLE_NAME" >/dev/null 2>&1 || true
# ====================== [3. Gradle Build] ======================
if [ "$PLATFORM" = "ohosArm64" ]; then
if [ "$BUILD_MODE" = "release" ]; then
if [ -n "$LOCAL_OHOS_PATH" ]; then
./gradlew :composeApp:publishReleaseBinariesToHarmonyApp -PharmonyAppPath="$LOCAL_OHOS_PATH"
else
./gradlew :composeApp:publishReleaseBinariesToHarmonyApp
fi
else
if [ -n "$LOCAL_OHOS_PATH" ]; then
./gradlew :composeApp:publishDebugBinariesToHarmonyApp -PharmonyAppPath="$LOCAL_OHOS_PATH"
else
./gradlew :composeApp:publishDebugBinariesToHarmonyApp
fi
fi
elif [ "$PLATFORM" = "iosSimulatorArm64" ]; then
./gradlew :composeApp:linkDebugFrameworkIosSimulatorArm64
else
echo "错误的 $TARGET_ID 设备 $BUILD_MODE 模式"
continue
fi
# SO packaging end time
HAP_START_TIME=$(date +%s)
# --- Subsequent install logic (hdc install etc.) ---
# ====================== [4. HAP Package Build] ======================
# Switch to harmonyApp directory for subsequent OHOS commands
# Use external path if specified, otherwise use default harmonyApp directory
if [ -n "$LOCAL_OHOS_PATH" ]; then
HARMONY_APP_DIR="$LOCAL_OHOS_PATH"
else
HARMONY_APP_DIR="harmonyApp"
fi
if [ ! -d "$HARMONY_APP_DIR" ]; then
echo "错误的 $TARGET_ID 设备 $BUILD_MODE 模式"
continue
fi
cd "$HARMONY_APP_DIR"
ohpm install --all
node "$DEVECO_HOME/tools/hvigor/bin/hvigorw.js" --sync -p product=default -p buildMode="$BUILD_MODE" --analyze=normal --parallel --incremental --daemon
if [ "$BUILD_MODE" = "release" ]; then
node "$DEVECO_HOME/tools/hvigor/bin/hvigorw.js" --mode module -p module=entry -p product=default -p buildMode=release -p requiredDeviceType=phone assembleHap compileNative --analyze=normal --parallel --incremental --daemon
else
node "$DEVECO_HOME/tools/hvigor/bin/hvigorw.js" --mode module -p module=entry@default -p product=default -p buildMode=debug -p requiredDeviceType=phone assembleHap --analyze=normal --parallel --incremental --daemon
fi
# ====================== [5. Install and Push Debug Components] ======================
AVAILABLE_TARGETS=$("$HDC_BIN" list targets)
HAP_DIR="./entry/build/default/outputs/default"
SIGNED_HAP="entry-default-signed.hap"
HAP_FILE="$HAP_DIR/$SIGNED_HAP"
# Check if signed HAP package exists
if [ ! -f "$HAP_FILE" ]; then
echo "错误的 $TARGET_ID 设备 $BUILD_MODE 模式"
cd "$SCRIPT_DIR"
continue
fi
if ! echo "$AVAILABLE_TARGETS" | grep -q "$TARGET_ID"; then
echo "错误的 $TARGET_ID 设备 $BUILD_MODE 模式"
cd "$SCRIPT_DIR"
continue
fi
# Install HAP (using temp directory)
REMOTE_HAP_DIR="/data/local/tmp/debug_install"
"$HDC_BIN" -t "$TARGET_ID" shell mkdir -p "$REMOTE_HAP_DIR" >/dev/null 2>&1
"$HDC_BIN" -t "$TARGET_ID" file send "$HAP_FILE" "$REMOTE_HAP_DIR" >/dev/null 2>&1
INSTALL_OUTPUT=$("$HDC_BIN" -t "$TARGET_ID" shell bm install -p "$REMOTE_HAP_DIR/$SIGNED_HAP" 2>&1)
sleep 1
INSTALL_RESULT=$?
if echo "$INSTALL_OUTPUT" | grep -qE "failed"; then
"$HDC_BIN" -t "$TARGET_ID" shell bm uninstall -n "$BUNDLE_NAME" >/dev/null 2>&1 || true
sleep 5
INSTALL_OUTPUT=$("$HDC_BIN" -t "$TARGET_ID" shell bm install -p "$REMOTE_HAP_DIR/$SIGNED_HAP" 2>&1)
sleep 5
fi
# ====================== [6. App Launch and Debug Mount] ======================
"$HDC_BIN" -t "$TARGET_ID" shell rm -rf "$REMOTE_HAP_DIR" >/dev/null 2>&1
sleep 1
# Step 1: Start app (with -D if debug mode enabled)
if [ "$DEBUG_MODE" = "debug" ]; then
AA_START_OUTPUT=$("$HDC_BIN" -t "$TARGET_ID" shell aa start -a "$ABILITY_NAME" -b "$BUNDLE_NAME" -D 2>&1)
else
AA_START_OUTPUT=$("$HDC_BIN" -t "$TARGET_ID" shell aa start -a "$ABILITY_NAME" -b "$BUNDLE_NAME" 2>&1)
fi
# Package push complete time
END_TIME=$(date +%s)
AA_START_RESULT=$?
# Check if screen lock error
if echo "$AA_START_OUTPUT" | grep -q "10106102\|screen is locked"; then
echo "错误的 $TARGET_ID 设备 $BUILD_MODE 模式"
cd "$SCRIPT_DIR"
continue
fi
# Step 2: Get app PID
get_pid_func() {
"$HDC_BIN" -t "$TARGET_ID" shell "pidof $BUNDLE_NAME" 2>/dev/null | tr -d '\r' | tr -d '\n' | awk '{print $1}'
}
MAX_WAIT=20
COUNT=0
APP_PID=""
while [ $COUNT -lt $MAX_WAIT ]; do
APP_PID=$(get_pid_func)
if [[ "$APP_PID" =~ ^[0-9]+$ ]]; then
break
fi
sleep 1
let COUNT=COUNT+1
done
if [ -z "$APP_PID" ]; then
echo "错误的 $TARGET_ID 设备 $BUILD_MODE 模式"
cd "$SCRIPT_DIR"
continue
fi
echo "$TARGET_ID 设备 $BUILD_MODE 模式 打包成功"
((SUCCESS_COUNT++))
# Return to project root for next iteration (Gradle runs from project root)
cd "$SCRIPT_DIR"
done
done
set -e
# ====================== [7. Packing Result Statistics] ======================
echo ""
echo "=============================================="
echo -e "\033[32m▶ 打包结果统计 / Packing Result Summary\033[0m"
echo "=============================================="
echo " 总次数 Total: $TOTAL_COUNT"
echo " 推包成功 Success: $SUCCESS_COUNT"
if [ "$TOTAL_COUNT" -gt 0 ]; then
RATE_PCT=$((SUCCESS_COUNT * 100 / TOTAL_COUNT))
echo " 通过率 Rate: ${SUCCESS_COUNT}/${TOTAL_COUNT} = ${RATE_PCT}%"
else
echo " 通过率 Rate: N/A"
fi
echo "=============================================="
echo ""
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment