android-ndk开发(2): macOS 安装 ndk

android-ndk开发(2): macOS 安装 ndk

2025/05/05

1. 概要

对于 android-ndk 在 r23 之前的版本,官方提供了 .zip 文件, 解压即安装。

对于 android-ndk 在 r23 以及之后的版本, 官方只提供了 .dmg 文件, 不能简单的解压完成安装。

2. ndk >= r23, macOS 怎么安装 ?

android ndk 从 r23 开始, 不再提供 macOS 平台的 .zip 安装包(如android-ndk-r22b-darwin-x86_64.zip), 只提供 .dmg 格式的安装包。链接 [1] 可以确认。这导致无法像 Windows 和 Linux 一样, 解压 .zip 就完成 ndk 的安装。

以 android-ndk-r27c-darwin.dmg 为例, 双击后显示两个文件: AndroidNDK12479018.app 和 source.properties。 双击 AndroidNDK12479018.app 后感觉完成了安装, 但在 /Application, /Library, ~/Application, ~/Library 4个目录找不到安装的内容。

手动解压 AndroidNDK12479018.app,里面的 NDK 目录是工具链, CodeSign 这玩意儿暂时不知道用处,感觉就是故意使绊子。

为了一劳永逸解决 macOS 上 ndk >= r23 版本的安装, 上述过程写为 Python 脚本。基本思路是:挂载 .dmg -> 找到 .app 文件 -> 找 NDK 目录 -> 拷贝到目标目录。

import subprocess
import shutil
import os
import time

def mount_and_copy(dmg_path, target_dir):
    target_dir = os.path.expanduser(target_dir)

    try:
        print(f"⏳ 正在挂载 {dmg_path}...")
        mount_result = subprocess.run(
            ["hdiutil", "attach", "-nobrowse", dmg_path],
            capture_output=True,
            text=True,
            check=True
        )

        # 解析挂载路径
        mount_path = None
        for line in mount_result.stdout.splitlines():
            if "/Volumes" in line:
                mount_path = line.split("\t")[-1].strip()
                break

        if not mount_path:
            raise FileNotFoundError("无法定位挂载点")

        time.sleep(2)  # 等待文件系统稳定

        # 动态查找AndroidNDK*.app
        app_files = [f for f in os.listdir(mount_path)
                   if f.startswith("AndroidNDK") and f.endswith(".app")]
        # e.g. AndroidNDK12479018.app for android-ndk-r27c

        if not app_files:
            available = "\n".join(os.listdir(mount_path))
            raise FileNotFoundError(
                f"未找到AndroidNDK*.app文件,当前卷内容:\n{available}"
            )

        app_path = os.path.join(mount_path, app_files[0])
        print(f"  定位到应用包:{app_path}")

        # 验证NDK路径
        ndk_source = os.path.join(app_path, "Contents", "NDK")
        if not os.path.exists(ndk_source):
            raise FileNotFoundError(f"NDK目录不存在:{ndk_source}")

        # 准备目标目录
        os.makedirs(target_dir, exist_ok=True)
        print(f"  目标目录:{target_dir}")

        # 执行复制(保留元数据)
        print("⚙️ 开始复制NDK文件...")
        shutil.copytree(
            ndk_source,
            target_dir,
            dirs_exist_ok=True,
            copy_function=shutil.copy2
        )

        # 卸载镜像
        print("⏳ 正在卸载...")
        subprocess.run(["hdiutil", "detach", mount_path], check=True)
        print(f"  安装完成!路径:{target_dir}")

    except subprocess.CalledProcessError as e:
        print(f"❌ 命令执行失败:{e.stderr}")
        if 'mount_path' in locals() and os.path.exists(mount_path):
            print(f"⚠️ 尝试手动卸载:hdiutil detach {mount_path}")
    except Exception as e:
        print(f"❌ 错误:{str(e)}")

if __name__ == "__main__":
    dmg_path = os.path.join(os.getcwd(), "android-ndk-r27c-darwin.dmg")
    mount_and_copy(dmg_path, "/Users/zz/soft/toolchains/android-ndk-r27c")

References

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值