diff --git a/README.md b/README.md index 5d41834..6379f1d 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,27 @@ flutter pub run build_runner watch 例如: flutter pub run build_runner build --delete-conflicting-outputs + +## Flutter 打包脚本 + +为方便快速构建安装包,项目在 `scripts/` 目录下提供了 iOS 与 Android 自动化脚本,均支持通过 `--output` 指定安装包输出位置,并透传额外的 `flutter build` 参数。 + +### iOS 打包 + +```bash +./scripts/build_ios.sh --output /绝对路径/输出目录 [其它 flutter build 参数] +``` + +- 默认输出目录:`build/ios_release` +- 若 `--output` 省略,产物会放到默认目录 +- 可追加 `--no-tree-shake-icons` 等 Flutter 构建参数 + +### Android 打包 + +```bash +./scripts/build_android.sh --output /绝对路径/目标目录或apk文件 [其它 flutter build 参数] +``` + +- 默认保存路径:`build/android_release/app-release.apk` +- 传入目录时会把生成的 APK 拷贝到该目录;传入以 `.apk` 结尾的路径则会重命名后保存 +- 同样可附带任何 Flutter 构建参数(如 `--no-tree-shake-icons`、`--split-per-abi`) diff --git a/scripts/build_android.sh b/scripts/build_android.sh new file mode 100755 index 0000000..b700f41 --- /dev/null +++ b/scripts/build_android.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# usage: +# ./scripts/build_android.sh --output /absolute/path/to/dir_or_apk [extra flutter build args...] + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +DEFAULT_OUTPUT_DIR="$PROJECT_ROOT/build/android_release" +DEFAULT_OUTPUT_PATH="$DEFAULT_OUTPUT_DIR/app-release.apk" + +OUTPUT_PATH="$DEFAULT_OUTPUT_PATH" +EXTRA_ARGS=() + +while [[ $# -gt 0 ]]; do + case "$1" in + --output=*) + OUTPUT_PATH="${1#*=}" + shift + ;; + --output) + if [[ $# -lt 2 ]]; then + echo "参数错误: --output 需要一个路径" >&2 + exit 1 + fi + OUTPUT_PATH="$2" + shift 2 + ;; + *) + EXTRA_ARGS+=("$1") + shift + ;; + esac +done + +pushd "$PROJECT_ROOT" >/dev/null +echo "📦 清理旧构建..." +flutter clean + +echo "📚 获取依赖..." +flutter pub get + +echo "🤖 开始构建 Android APK..." +flutter build apk --release "${EXTRA_ARGS[@]}" +popd >/dev/null + +ARTIFACT_DIR="$PROJECT_ROOT/build/app/outputs/flutter-apk" +if [[ ! -d "$ARTIFACT_DIR" ]]; then + echo "未找到 APK 输出目录:$ARTIFACT_DIR" >&2 + exit 1 +fi + +BUILT_APK="$(find "$ARTIFACT_DIR" -maxdepth 1 -name '*.apk' -print | head -n 1)" +if [[ -z "$BUILT_APK" || ! -f "$BUILT_APK" ]]; then + echo "未找到构建出的 APK 文件" >&2 + exit 1 +fi + +if [[ "$OUTPUT_PATH" == *.apk ]]; then + TARGET_PATH="$OUTPUT_PATH" + mkdir -p "$(dirname "$TARGET_PATH")" +else + mkdir -p "$OUTPUT_PATH" + TARGET_PATH="$OUTPUT_PATH/$(basename "$BUILT_APK")" +fi + +cp "$BUILT_APK" "$TARGET_PATH" +echo "✅ 构建完成,APK 已保存到:$TARGET_PATH" + diff --git a/scripts/build_ios.sh b/scripts/build_ios.sh new file mode 100755 index 0000000..f4b1192 --- /dev/null +++ b/scripts/build_ios.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# usage: +# ./scripts/build_ios.sh --output /absolute/path/to/output [extra flutter build args...] + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +DEFAULT_BUILD_DIR="$PROJECT_ROOT/build/ios_release" +OUTPUT_DIR="$DEFAULT_BUILD_DIR" +EXTRA_ARGS=() + +while [[ $# -gt 0 ]]; do + case "$1" in + --output=*) + OUTPUT_DIR="${1#*=}" + shift + ;; + --output) + if [[ $# -lt 2 ]]; then + echo "参数错误: --output 需要一个路径" >&2 + exit 1 + fi + OUTPUT_DIR="$2" + shift 2 + ;; + *) + EXTRA_ARGS+=("$1") + shift + ;; + esac +done + +mkdir -p "$OUTPUT_DIR" + +pushd "$PROJECT_ROOT" >/dev/null +echo "📦 清理旧构建..." +flutter clean + +echo "📚 获取依赖..." +flutter pub get + +echo "🚀 开始构建 iOS 安装包..." +flutter build ios --release --build-dir "$OUTPUT_DIR" "${EXTRA_ARGS[@]}" +popd >/dev/null + +echo "✅ 构建完成,产物目录:$OUTPUT_DIR" +