Files
2026-07-13 13:33:03 +08:00

802 lines
27 KiB
Bash

#!/bin/bash
# MNN 统一构建脚本
# 支持构建 Android、iOS、鸿蒙和 Python 版本的 MNN
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 默认配置
BUILD_ANDROID=false
BUILD_IOS=false
BUILD_PYTHON=false
BUILD_IOS_SIMULATOR=false
BUILD_HARMONY=false
ANDROID_NDK=""
HARMONY_HOME=""
OUTPUT_DIR="mnn_builds"
CLEAN_BUILD=true
VERSION=""
PYTHON_CMD="python3"
DEPS_OPTIONS=""
# 获取项目根目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$SCRIPT_DIR"
print_usage() {
echo "MNN 统一构建脚本"
echo ""
echo "用法: $0 [选项]"
echo ""
echo "构建目标:"
echo " --android 构建 Android 版本 (需要 --ndk)"
echo " --ios 构建 iOS 真机版本 (arm64)"
echo " --ios-simulator 构建 iOS 模拟器版本 (x86_64 + arm64)"
echo " --harmony 构建鸿蒙版本 (需要 --harmony-home 或设置 HARMONY_HOME)"
echo " --python 构建 Python 版本"
echo ""
echo "Android 选项:"
echo " --ndk PATH Android NDK 路径 (例如: ~/Library/Android/sdk/ndk/29.0.13599879)"
echo ""
echo "鸿蒙选项:"
echo " --harmony-home PATH 鸿蒙工具链路径 (例如: ~/Library/OpenHarmony/Sdk/native)"
echo " 如果未指定,将优先查找 ~/Library/OpenHarmony/Sdk/native"
echo ""
echo "Python 选项:"
echo " --python-deps OPTIONS Python 依赖选项,多个用逗号分隔"
echo " 可用选项: llm,opencl,cuda,torch,render,vulkan,internal,no_sse,openmp"
echo " --python-cmd CMD Python 命令 (默认: python3)"
echo ""
echo "通用选项:"
echo " -o, --output DIR 输出目录 (默认: mnn_builds)"
echo " -v, --version VERSION 版本号 (默认: 自动从源码读取)"
echo " --no-clean 不清理之前的构建目录"
echo " -h, --help 显示帮助信息"
echo ""
echo "示例:"
echo " # 构建所有平台"
echo " $0 --android --ios --harmony --python --ndk ~/Library/Android/sdk/ndk/29.0.13599879"
echo ""
echo " # 仅构建 Android"
echo " $0 --android --ndk ~/Library/Android/sdk/ndk/29.0.13599879"
echo ""
echo " # 构建鸿蒙版本"
echo " $0 --harmony --harmony-home ~/Library/OpenHarmony/Sdk/native"
echo ""
echo " # 构建 iOS 真机和模拟器"
echo " $0 --ios --ios-simulator"
echo ""
echo " # 构建 Python (带 LLM 支持)"
echo " $0 --python --python-deps llm,opencl"
}
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
--android)
BUILD_ANDROID=true
shift
;;
--ios)
BUILD_IOS=true
shift
;;
--ios-simulator)
BUILD_IOS_SIMULATOR=true
shift
;;
--python)
BUILD_PYTHON=true
shift
;;
--harmony)
BUILD_HARMONY=true
shift
;;
--ndk)
ANDROID_NDK="$2"
shift 2
;;
--harmony-home)
HARMONY_HOME="$2"
shift 2
;;
--python-deps)
DEPS_OPTIONS="$2"
shift 2
;;
--python-cmd)
PYTHON_CMD="$2"
shift 2
;;
-o|--output)
OUTPUT_DIR="$2"
shift 2
;;
-v|--version)
VERSION="$2"
shift 2
;;
--no-clean)
CLEAN_BUILD=false
shift
;;
-h|--help)
print_usage
exit 0
;;
*)
echo -e "${RED}错误: 未知选项 $1${NC}"
print_usage
exit 1
;;
esac
done
# 检查是否至少选择了一个构建目标
if [ "$BUILD_ANDROID" = false ] && [ "$BUILD_IOS" = false ] && [ "$BUILD_IOS_SIMULATOR" = false ] && [ "$BUILD_HARMONY" = false ] && [ "$BUILD_PYTHON" = false ]; then
echo -e "${RED}错误: 请至少选择一个构建目标 (--android, --ios, --ios-simulator, --harmony, 或 --python)${NC}"
print_usage
exit 1
fi
# 检查 Android NDK
if [ "$BUILD_ANDROID" = true ]; then
if [ -z "$ANDROID_NDK" ]; then
echo -e "${RED}错误: 构建 Android 必须指定 NDK 路径 (使用 --ndk)${NC}"
echo -e "${RED}示例: $0 --android --ndk ~/Library/Android/sdk/ndk/29.0.13599879${NC}"
exit 1
fi
# 展开路径中的 ~
ANDROID_NDK="${ANDROID_NDK/#\~/$HOME}"
if [ ! -d "$ANDROID_NDK" ]; then
echo -e "${RED}错误: NDK 路径不存在: $ANDROID_NDK${NC}"
exit 1
fi
fi
# 查找鸿蒙工具链的函数
find_harmony_toolchain() {
# 如果环境变量已设置,优先使用
if [ -n "$HARMONY_HOME" ]; then
# 支持两种路径格式:直接指定或带 native 子目录
if [ -f "$HARMONY_HOME/build/cmake/ohos.toolchain.cmake" ]; then
echo "$HARMONY_HOME"
return 0
elif [ -f "$HARMONY_HOME/native/build/cmake/ohos.toolchain.cmake" ]; then
echo "$HARMONY_HOME"
return 0
fi
fi
# 优先查找 ~/Library/OpenHarmony/Sdk,支持版本号目录
local sdk_base="$HOME/Library/OpenHarmony/Sdk"
if [ -d "$sdk_base" ]; then
# 查找所有版本号目录下的 native 或 toolchains
# 按版本号倒序排列,优先使用最新版本
for version_dir in $(ls -d "$sdk_base"/* 2>/dev/null | sort -Vr); do
if [ -d "$version_dir" ]; then
# 尝试 native/build/cmake/ohos.toolchain.cmake
if [ -f "$version_dir/native/build/cmake/ohos.toolchain.cmake" ]; then
echo "$version_dir/native"
return 0
fi
# 尝试 build/cmake/ohos.toolchain.cmake
if [ -f "$version_dir/build/cmake/ohos.toolchain.cmake" ]; then
echo "$version_dir"
return 0
fi
fi
done
fi
# 其他可能的路径
local possible_paths=(
"$HOME/Library/OpenHarmony/Sdk/native"
"$HOME/HarmonyOS/Sdk/native"
"$HOME/.ohos/native"
"/opt/HarmonyOS/Sdk/native"
"/usr/local/HarmonyOS/Sdk/native"
"$HOME/Library/HarmonyOS/Sdk/native"
)
# 尝试查找
for path in "${possible_paths[@]}"; do
if [ -n "$path" ] && [ -f "$path/build/cmake/ohos.toolchain.cmake" ]; then
echo "$path"
return 0
fi
done
# 限制搜索范围,只在 OpenHarmony/Sdk 目录下快速查找
# 避免在整个 OpenHarmony 目录下递归查找,这可能会很慢
local found=$(find "$HOME/Library/OpenHarmony/Sdk" -maxdepth 4 -type f -name "ohos.toolchain.cmake" 2>/dev/null | head -1)
if [ -n "$found" ]; then
# 从 ohos.toolchain.cmake 向上查找 native 目录或 SDK 根目录
found=$(dirname "$found")
if [ "$(basename "$found")" = "cmake" ]; then
found=$(dirname "$found")
if [ "$(basename "$found")" = "build" ]; then
found=$(dirname "$found")
fi
fi
echo "$found"
return 0
fi
return 1
}
# 检查鸿蒙工具链
if [ "$BUILD_HARMONY" = true ]; then
# 展开路径中的 ~
if [ -n "$HARMONY_HOME" ]; then
HARMONY_HOME="${HARMONY_HOME/#\~/$HOME}"
fi
# 尝试查找工具链
if [ -z "$HARMONY_HOME" ] || [ ! -f "$HARMONY_HOME/build/cmake/ohos.toolchain.cmake" ]; then
# 检查是否在 native 子目录下
if [ -n "$HARMONY_HOME" ] && [ -f "$HARMONY_HOME/native/build/cmake/ohos.toolchain.cmake" ]; then
HARMONY_HOME="$HARMONY_HOME/native"
else
echo -e "${YELLOW}正在查找鸿蒙工具链...${NC}"
HARMONY_HOME=$(find_harmony_toolchain)
if [ -z "$HARMONY_HOME" ]; then
echo -e "${RED}错误: 找不到鸿蒙工具链${NC}"
echo -e "${RED}默认查找路径: ~/Library/OpenHarmony/Sdk/*/native${NC}"
echo -e "${RED}请使用 --harmony-home 指定路径,或设置 HARMONY_HOME 环境变量${NC}"
echo -e "${RED}工具链文件应位于: <HARMONY_HOME>/build/cmake/ohos.toolchain.cmake 或 <HARMONY_HOME>/native/build/cmake/ohos.toolchain.cmake${NC}"
exit 1
fi
# 如果找到的是带 native 的路径,需要调整
if [ -f "$HARMONY_HOME/native/build/cmake/ohos.toolchain.cmake" ]; then
HARMONY_HOME="$HARMONY_HOME/native"
fi
fi
echo -e "${GREEN}找到鸿蒙工具链: $HARMONY_HOME${NC}"
fi
# 验证工具链文件存在
if [ ! -f "$HARMONY_HOME/build/cmake/ohos.toolchain.cmake" ]; then
echo -e "${RED}错误: 鸿蒙工具链文件不存在: $HARMONY_HOME/build/cmake/ohos.toolchain.cmake${NC}"
exit 1
fi
fi
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}MNN 统一构建脚本${NC}"
echo -e "${GREEN}========================================${NC}"
echo "项目根目录: $PROJECT_ROOT"
echo "输出目录: $OUTPUT_DIR"
echo ""
echo -e "${BLUE}构建目标:${NC}"
[ "$BUILD_ANDROID" = true ] && echo " ✓ Android"
[ "$BUILD_IOS" = true ] && echo " ✓ iOS (真机 arm64)"
[ "$BUILD_IOS_SIMULATOR" = true ] && echo " ✓ iOS (模拟器 x86_64 + arm64)"
[ "$BUILD_HARMONY" = true ] && echo " ✓ 鸿蒙 (arm64-v8a)"
[ "$BUILD_PYTHON" = true ] && echo " ✓ Python"
echo ""
cd "$PROJECT_ROOT"
mkdir -p "$OUTPUT_DIR"
# ============================================================================
# 构建 Android 版本
# ============================================================================
if [ "$BUILD_ANDROID" = true ]; then
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}开始构建 Android 版本${NC}"
echo -e "${GREEN}========================================${NC}"
export ANDROID_NDK
ANDROID_BUILD_DIR="project/android"
ANDROID_OUTPUT_DIR="$OUTPUT_DIR/android"
cd "$ANDROID_BUILD_DIR"
# 清理
if [ "$CLEAN_BUILD" = true ]; then
echo -e "${YELLOW}清理之前的 Android 构建...${NC}"
rm -rf build_32 build_64 export
fi
# 在项目根目录创建输出目录
mkdir -p "$PROJECT_ROOT/$ANDROID_OUTPUT_DIR"
# 构建 armeabi-v7a
echo -e "${BLUE}构建 armeabi-v7a...${NC}"
mkdir -p build_32
cd build_32
cmake ../../../ \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI="armeabi-v7a" \
-DANDROID_STL=c++_static \
-DANDROID_NATIVE_API_LEVEL=android-14 \
-DANDROID_TOOLCHAIN=clang \
-DMNN_USE_LOGCAT=false \
-DMNN_USE_SSE=OFF \
-DMNN_BUILD_TEST=ON \
-DMNN_ARM82=OFF \
-DMNN_LOW_MEMORY=ON \
-DMNN_SUPPORT_TRANSFORMER_FUSE=ON \
-DMNN_BUILD_LLM=ON \
-DMNN_BUILD_DIFFUSION=ON \
-DMNN_OPENCL=OFF \
-DMNN_SEP_BUILD=OFF \
-DLLM_SUPPORT_AUDIO=ON \
-DMNN_BUILD_AUDIO=ON \
-DLLM_SUPPORT_VISION=ON \
-DMNN_BUILD_OPENCV=ON \
-DMNN_IMGCODECS=ON \
-DMNN_BUILD_FOR_ANDROID_COMMAND=true \
-DNATIVE_LIBRARY_OUTPUT=. \
-DNATIVE_INCLUDE_OUTPUT=. \
> /dev/null
make -j4 MNN > /dev/null
cd ..
# 构建 arm64-v8a
echo -e "${BLUE}构建 arm64-v8a...${NC}"
mkdir -p build_64
cd build_64
cmake ../../../ \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI="arm64-v8a" \
-DANDROID_STL=c++_static \
-DANDROID_NATIVE_API_LEVEL=android-21 \
-DANDROID_TOOLCHAIN=clang \
-DMNN_USE_LOGCAT=false \
-DMNN_BUILD_BENCHMARK=ON \
-DMNN_USE_SSE=OFF \
-DMNN_BUILD_TEST=ON \
-DMNN_ARM82=ON \
-DMNN_LOW_MEMORY=ON \
-DMNN_SUPPORT_TRANSFORMER_FUSE=ON \
-DMNN_BUILD_LLM=ON \
-DMNN_BUILD_DIFFUSION=ON \
-DMNN_OPENCL=OFF \
-DMNN_SEP_BUILD=OFF \
-DLLM_SUPPORT_AUDIO=ON \
-DMNN_BUILD_AUDIO=ON \
-DLLM_SUPPORT_VISION=ON \
-DMNN_BUILD_OPENCV=ON \
-DMNN_IMGCODECS=ON \
-DMNN_BUILD_FOR_ANDROID_COMMAND=true \
-DNATIVE_LIBRARY_OUTPUT=. \
-DNATIVE_INCLUDE_OUTPUT=. \
> /dev/null
make -j4 MNN > /dev/null
cd ..
# 导出文件
echo -e "${BLUE}导出 Android 库文件...${NC}"
mkdir -p export/android/{armeabi-v7a,arm64-v8a}/libs export/android/include/MNN
cp build_32/*.so export/android/armeabi-v7a/libs/ 2>/dev/null || true
cp build_64/*.so export/android/arm64-v8a/libs/ 2>/dev/null || true
cp -r ../../include/MNN/* export/android/include/MNN/
# 复制到统一输出目录
# 如果目标路径存在但不是目录,先删除
if [ -e "$PROJECT_ROOT/$ANDROID_OUTPUT_DIR" ] && [ ! -d "$PROJECT_ROOT/$ANDROID_OUTPUT_DIR" ]; then
rm -f "$PROJECT_ROOT/$ANDROID_OUTPUT_DIR"
fi
mkdir -p "$PROJECT_ROOT/$ANDROID_OUTPUT_DIR"
cp -r export/android/* "$PROJECT_ROOT/$ANDROID_OUTPUT_DIR/"
echo -e "${GREEN}Android 构建完成!${NC}"
echo "输出位置: $ANDROID_OUTPUT_DIR"
cd "$PROJECT_ROOT"
fi
# ============================================================================
# 构建 iOS 真机版本
# ============================================================================
if [ "$BUILD_IOS" = true ]; then
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}开始构建 iOS 真机版本${NC}"
echo -e "${GREEN}========================================${NC}"
# 检查是否在 macOS 上
if [[ "$OSTYPE" != "darwin"* ]]; then
echo -e "${RED}错误: iOS 构建只能在 macOS 上执行${NC}"
exit 1
fi
# 检查 Xcode
if ! command -v xcodebuild &> /dev/null; then
echo -e "${RED}错误: 找不到 Xcode,请先安装 Xcode${NC}"
exit 1
fi
IOS_BUILD_DIR="project/ios"
IOS_OUTPUT_DIR="$OUTPUT_DIR/ios/device"
cd "$IOS_BUILD_DIR"
# 清理
if [ "$CLEAN_BUILD" = true ]; then
echo -e "${YELLOW}清理之前的 iOS 真机构建...${NC}"
rm -rf MNN-iOS-CPU-GPU/Static/ios_64
find "$PROJECT_ROOT" -name "CMakeCache.txt" -path "*/ios_64/*" 2>/dev/null | xargs rm -f 2>/dev/null || true
fi
mkdir -p MNN-iOS-CPU-GPU/Static
cd MNN-iOS-CPU-GPU/Static
# 构建真机版本 (arm64)
echo -e "${BLUE}构建 iOS 真机版本 (arm64)...${NC}"
rm -rf ios_64
mkdir ios_64
cd ios_64
cmake "$PROJECT_ROOT" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=$PROJECT_ROOT/cmake/ios.toolchain.cmake \
-DENABLE_BITCODE=0 \
-DMNN_AAPL_FMWK=1 \
-DMNN_SEP_BUILD=OFF \
-DMNN_BUILD_SHARED_LIBS=false \
-DMNN_USE_THREAD_POOL=OFF \
-DPLATFORM=OS64 \
-DARCHS="arm64" \
-DMNN_ARM82=ON \
-DMNN_LOW_MEMORY=ON \
-DMNN_SUPPORT_TRANSFORMER_FUSE=ON \
-DMNN_BUILD_LLM=ON \
-DMNN_METAL=ON \
-DMNN_BUILD_DIFFUSION=ON \
-DMNN_OPENCL=OFF \
-DLLM_SUPPORT_AUDIO=ON \
-DMNN_BUILD_AUDIO=ON \
-DLLM_SUPPORT_VISION=ON \
-DMNN_BUILD_OPENCV=ON \
-DMNN_IMGCODECS=ON \
> /dev/null
make MNN -j8 > /dev/null
cd ..
# 输出真机版本
mkdir -p "$PROJECT_ROOT/$IOS_OUTPUT_DIR"
rm -rf "$PROJECT_ROOT/$IOS_OUTPUT_DIR/MNN.framework"
cp -R ios_64/MNN.framework "$PROJECT_ROOT/$IOS_OUTPUT_DIR/"
# 清理
rm -rf ios_64
echo -e "${GREEN}iOS 真机构建完成!${NC}"
echo "输出位置: $IOS_OUTPUT_DIR/MNN.framework"
cd "$PROJECT_ROOT"
fi
# ============================================================================
# 构建 iOS 模拟器版本
# ============================================================================
if [ "$BUILD_IOS_SIMULATOR" = true ]; then
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}开始构建 iOS 模拟器版本${NC}"
echo -e "${GREEN}========================================${NC}"
# 检查是否在 macOS 上
if [[ "$OSTYPE" != "darwin"* ]]; then
echo -e "${RED}错误: iOS 构建只能在 macOS 上执行${NC}"
exit 1
fi
# 检查 Xcode
if ! command -v xcodebuild &> /dev/null; then
echo -e "${RED}错误: 找不到 Xcode,请先安装 Xcode${NC}"
exit 1
fi
IOS_BUILD_DIR="project/ios"
IOS_OUTPUT_DIR="$OUTPUT_DIR/ios/simulator"
cd "$IOS_BUILD_DIR"
# 清理
if [ "$CLEAN_BUILD" = true ]; then
echo -e "${YELLOW}清理之前的 iOS 模拟器构建...${NC}"
rm -rf MNN-iOS-CPU-GPU/Static/ios_simulator*
find "$PROJECT_ROOT" -name "CMakeCache.txt" -path "*/ios_simulator*/*" 2>/dev/null | xargs rm -f 2>/dev/null || true
fi
mkdir -p MNN-iOS-CPU-GPU/Static
cd MNN-iOS-CPU-GPU/Static
# 构建 x86_64 模拟器版本(尝试构建,失败则跳过)
BUILD_X86_64=false
echo -e "${BLUE}构建 iOS 模拟器版本 (x86_64)...${NC}"
rm -rf ios_simulator_x86
mkdir ios_simulator_x86
cd ios_simulator_x86
if cmake "$PROJECT_ROOT" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=$PROJECT_ROOT/cmake/ios.toolchain.cmake \
-DENABLE_BITCODE=0 \
-DMNN_AAPL_FMWK=1 \
-DMNN_SEP_BUILD=OFF \
-DMNN_BUILD_SHARED_LIBS=false \
-DMNN_USE_THREAD_POOL=OFF \
-DPLATFORM=SIMULATOR64 \
-DARCHS="x86_64" \
-DMNN_ARM82=OFF \
-DMNN_LOW_MEMORY=ON \
-DMNN_SUPPORT_TRANSFORMER_FUSE=ON \
-DMNN_BUILD_LLM=ON \
-DMNN_METAL=OFF \
-DMNN_BUILD_DIFFUSION=ON \
-DMNN_OPENCL=OFF \
-DLLM_SUPPORT_AUDIO=ON \
-DMNN_BUILD_AUDIO=ON \
-DLLM_SUPPORT_VISION=ON \
-DMNN_BUILD_OPENCV=ON \
-DMNN_IMGCODECS=ON \
&& make MNN -j8; then
if [ -f "MNN.framework/MNN" ]; then
BUILD_X86_64=true
echo -e "${GREEN}x86_64 模拟器构建成功${NC}"
cd ..
else
echo -e "${YELLOW}警告: x86_64 模拟器构建产物不存在,跳过此架构${NC}"
cd ..
rm -rf ios_simulator_x86
fi
else
echo -e "${YELLOW}警告: x86_64 模拟器构建失败,跳过此架构(这在 Apple Silicon Mac 上是正常的)${NC}"
cd ..
rm -rf ios_simulator_x86
fi
# 构建 arm64 模拟器版本
echo -e "${BLUE}构建 iOS 模拟器版本 (arm64)...${NC}"
rm -rf ios_simulator_arm64
mkdir ios_simulator_arm64
cd ios_simulator_arm64
if ! cmake "$PROJECT_ROOT" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=$PROJECT_ROOT/cmake/ios.toolchain.cmake \
-DENABLE_BITCODE=0 \
-DMNN_AAPL_FMWK=1 \
-DMNN_SEP_BUILD=OFF \
-DMNN_BUILD_SHARED_LIBS=false \
-DMNN_USE_THREAD_POOL=OFF \
-DPLATFORM=SIMULATOR64 \
-DARCHS="arm64" \
-DMNN_ARM82=ON \
-DMNN_LOW_MEMORY=ON \
-DMNN_SUPPORT_TRANSFORMER_FUSE=ON \
-DMNN_BUILD_LLM=ON \
-DMNN_METAL=OFF \
-DMNN_BUILD_DIFFUSION=ON \
-DMNN_OPENCL=OFF \
-DLLM_SUPPORT_AUDIO=ON \
-DMNN_BUILD_AUDIO=ON \
-DLLM_SUPPORT_VISION=ON \
-DMNN_BUILD_OPENCV=ON \
-DMNN_IMGCODECS=ON; then
echo -e "${RED}错误: arm64 模拟器 cmake 配置失败${NC}"
cd "$PROJECT_ROOT"
exit 1
fi
if ! make MNN -j8; then
echo -e "${RED}错误: arm64 模拟器编译失败${NC}"
cd "$PROJECT_ROOT"
exit 1
fi
cd ..
# 验证构建产物
if [ ! -f "ios_simulator_arm64/MNN.framework/MNN" ]; then
echo -e "${RED}错误: 未找到 arm64 模拟器框架文件${NC}"
cd "$PROJECT_ROOT"
exit 1
fi
# 合并模拟器架构
echo -e "${BLUE}合并模拟器架构...${NC}"
rm -rf ios_simulator
mkdir ios_simulator
if [ "$BUILD_X86_64" = true ] && [ -f "ios_simulator_x86/MNN.framework/MNN" ]; then
# 合并 x86_64 + arm64
echo -e "${BLUE}合并 x86_64 + arm64 架构...${NC}"
cp -R ios_simulator_x86/MNN.framework ios_simulator/MNN.framework
mv ios_simulator/MNN.framework/MNN ios_simulator/MNN.framework/MNN_x86
if ! lipo -create ios_simulator/MNN.framework/MNN_x86 ios_simulator_arm64/MNN.framework/MNN -output ios_simulator/MNN.framework/MNN; then
echo -e "${RED}错误: 合并架构失败${NC}"
cd "$PROJECT_ROOT"
exit 1
fi
rm ios_simulator/MNN.framework/MNN_x86
else
# 仅使用 arm64
echo -e "${BLUE}仅使用 arm64 架构(x86_64 不可用)...${NC}"
cp -R ios_simulator_arm64/MNN.framework ios_simulator/MNN.framework
fi
# 输出模拟器版本
mkdir -p "$PROJECT_ROOT/$IOS_OUTPUT_DIR"
rm -rf "$PROJECT_ROOT/$IOS_OUTPUT_DIR/MNN.framework"
cp -R ios_simulator/MNN.framework "$PROJECT_ROOT/$IOS_OUTPUT_DIR/"
# 清理临时目录
rm -rf ios_simulator ios_simulator_x86 ios_simulator_arm64
echo -e "${GREEN}iOS 模拟器构建完成!${NC}"
echo "输出位置: $IOS_OUTPUT_DIR/MNN.framework"
cd "$PROJECT_ROOT"
fi
# ============================================================================
# 构建鸿蒙版本
# ============================================================================
if [ "$BUILD_HARMONY" = true ]; then
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}开始构建鸿蒙版本${NC}"
echo -e "${GREEN}========================================${NC}"
export HARMONY_HOME
HARMONY_BUILD_DIR="project/harmony"
HARMONY_OUTPUT_DIR="$OUTPUT_DIR/harmony"
cd "$HARMONY_BUILD_DIR"
# 清理
if [ "$CLEAN_BUILD" = true ]; then
echo -e "${YELLOW}清理之前的鸿蒙构建...${NC}"
rm -rf build_64 export
fi
# 在项目根目录创建输出目录
mkdir -p "$PROJECT_ROOT/$HARMONY_OUTPUT_DIR"
# 构建 arm64-v8a
echo -e "${BLUE}构建 arm64-v8a...${NC}"
mkdir -p build_64
cd build_64
cmake "$PROJECT_ROOT" \
-DCMAKE_TOOLCHAIN_FILE=$HARMONY_HOME/build/cmake/ohos.toolchain.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DOHOS_ARCH="arm64-v8a" \
-DOHOS_STL=c++_static \
-DMNN_USE_LOGCAT=true \
-DMNN_BUILD_BENCHMARK=ON \
-DMNN_USE_SSE=OFF \
-DMNN_SUPPORT_BF16=OFF \
-DMNN_BUILD_TEST=ON \
-DMNN_ARM82=ON \
-DMNN_LOW_MEMORY=ON \
-DMNN_SUPPORT_TRANSFORMER_FUSE=ON \
-DMNN_BUILD_LLM=ON \
-DMNN_BUILD_DIFFUSION=ON \
-DMNN_OPENCL=OFF \
-DMNN_SEP_BUILD=OFF \
-DLLM_SUPPORT_AUDIO=ON \
-DMNN_BUILD_AUDIO=ON \
-DLLM_SUPPORT_VISION=ON \
-DMNN_BUILD_OPENCV=ON \
-DMNN_IMGCODECS=ON \
-DOHOS_PLATFORM_LEVEL=9 \
-DNATIVE_LIBRARY_OUTPUT=. \
-DNATIVE_INCLUDE_OUTPUT=. \
> /dev/null
make -j4 MNN > /dev/null
cd ..
# 导出文件
echo -e "${BLUE}导出鸿蒙库文件...${NC}"
mkdir -p export/harmony/arm64-v8a/libs export/harmony/include/MNN
cp build_64/*.so export/harmony/arm64-v8a/libs/ 2>/dev/null || true
cp -r ../../include/MNN/* export/harmony/include/MNN/
# 复制到统一输出目录
# 如果目标路径存在但不是目录,先删除
if [ -e "$PROJECT_ROOT/$HARMONY_OUTPUT_DIR" ] && [ ! -d "$PROJECT_ROOT/$HARMONY_OUTPUT_DIR" ]; then
rm -f "$PROJECT_ROOT/$HARMONY_OUTPUT_DIR"
fi
mkdir -p "$PROJECT_ROOT/$HARMONY_OUTPUT_DIR"
cp -r export/harmony/* "$PROJECT_ROOT/$HARMONY_OUTPUT_DIR/"
echo -e "${GREEN}鸿蒙构建完成!${NC}"
echo "输出位置: $HARMONY_OUTPUT_DIR"
cd "$PROJECT_ROOT"
fi
# ============================================================================
# 构建 Python 版本
# ============================================================================
if [ "$BUILD_PYTHON" = true ]; then
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}开始构建 Python 版本${NC}"
echo -e "${GREEN}========================================${NC}"
# 检查 Python
if ! command -v $PYTHON_CMD &> /dev/null; then
echo -e "${RED}错误: 找不到 Python 命令 '$PYTHON_CMD'${NC}"
exit 1
fi
PYTHON_OUTPUT_DIR="$OUTPUT_DIR/python"
# 使用之前创建的 build_pymnn.sh 脚本
if [ -f "$PROJECT_ROOT/build_pymnn.sh" ]; then
PYTHON_BUILD_ARGS="-o $PYTHON_OUTPUT_DIR"
[ -n "$VERSION" ] && PYTHON_BUILD_ARGS="$PYTHON_BUILD_ARGS -v $VERSION"
[ -n "$DEPS_OPTIONS" ] && PYTHON_BUILD_ARGS="$PYTHON_BUILD_ARGS -d $DEPS_OPTIONS"
[ "$CLEAN_BUILD" = false ] && PYTHON_BUILD_ARGS="$PYTHON_BUILD_ARGS --no-clean"
PYTHON_BUILD_ARGS="$PYTHON_BUILD_ARGS --python $PYTHON_CMD"
bash "$PROJECT_ROOT/build_pymnn.sh" $PYTHON_BUILD_ARGS
else
echo -e "${YELLOW}警告: 未找到 build_pymnn.sh,使用基本构建方式...${NC}"
cd pymnn/pip_package
# 构建依赖
if [ -n "$DEPS_OPTIONS" ]; then
$PYTHON_CMD build_deps.py $DEPS_OPTIONS
else
$PYTHON_CMD build_deps.py
fi
# 构建 wheel
$PYTHON_CMD -m pip install -U numpy wheel setuptools --quiet
rm -rf build dist
BUILD_ARGS=""
[ -n "$VERSION" ] && BUILD_ARGS="--version $VERSION"
[ -n "$DEPS_OPTIONS" ] && BUILD_ARGS="$BUILD_ARGS --deps $DEPS_OPTIONS"
$PYTHON_CMD setup.py bdist_wheel $BUILD_ARGS
mkdir -p "$PROJECT_ROOT/$PYTHON_OUTPUT_DIR"
cp dist/*.whl "$PROJECT_ROOT/$PYTHON_OUTPUT_DIR/"
cd "$PROJECT_ROOT"
fi
echo -e "${GREEN}Python 构建完成!${NC}"
echo "输出位置: $PYTHON_OUTPUT_DIR"
fi
# ============================================================================
# 总结
# ============================================================================
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}所有构建完成!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo "输出目录: $PROJECT_ROOT/$OUTPUT_DIR"
echo ""
[ "$BUILD_ANDROID" = true ] && echo -e "${GREEN}Android:${NC} $OUTPUT_DIR/android"
[ "$BUILD_IOS" = true ] && echo -e "${GREEN}iOS (真机):${NC} $OUTPUT_DIR/ios/device"
[ "$BUILD_IOS_SIMULATOR" = true ] && echo -e "${GREEN}iOS (模拟器):${NC} $OUTPUT_DIR/ios/simulator"
[ "$BUILD_HARMONY" = true ] && echo -e "${GREEN}鸿蒙:${NC} $OUTPUT_DIR/harmony"
[ "$BUILD_PYTHON" = true ] && echo -e "${GREEN}Python:${NC} $OUTPUT_DIR/python"
echo ""