欢迎加入开源鸿蒙 PC 社区:https://harmonypc.csdn.net/

欢迎在 PC 社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper

适配开源地址(AtomGit):https://atomgit.com/OpenHarmonyPCDeveloper/ohos_typst


项目说明
适配软件typst(命令行排版引擎,CLI,无图形界面)
开源协议Apache-2.0
源码版本v0.15.1
目标平台鸿蒙 PC(x86_64)与 arm64 设备(鸿蒙 PC / 平板 / 开发板)
交叉目标x86_64-unknown-linux-ohos、aarch64-unknown-linux-ohos
构建宿主Linux x86_64(Ubuntu 24)
工具链rustup stable ≥ 1.92(实测 1.98.1)+ zig-patch 0.16.0(zig cc / zig c++ / zig ar)
上游改动源码零修改,仅修改 Cargo.lock 以使用更高版本依赖
产物out/x86_64/typst(strip 后约 52 MB)、out/aarch64/typst(strip 后约 48 MB)
验证方式静态检查与实机测试
上游地址https://github.com/typst/typst
适配仓库https://atomgit.com/OpenHarmonyPCDeveloper/ohos_typst

Typst 简介

Typst 是一个新兴的基于标记语言的开源排版系统。Typst 首个版本发布于 2023 年,允许使用一种类似于 Markdown 的标记语言对文档内容进行排版,并生成 PDF、SVG、PNG 和 HTML 等格式产物。

该领域过去长期使用 LaTeX,但其诸多问题已被诟病多年:报错信息可读性极差、工具链臃肿复杂、编译速度较慢、与现代编辑器集成度较差等等。Typst 极大改善了这些问题。

本次适配的目标与产物

本次适配基于 typst v0.15.1,面向 API 24~26 的鸿蒙 PC 设备,构建环境为 Linux x86_64。适配过程遵守一条约束:上游 typst 源码树保持零修改。适配内容全部放在仓库自己的脚本与配置里,升级上游版本时只需要重新走一遍构建,不需要重新合并改动。

产物路径说明
鸿蒙 PCout/x86_64/typstx86_64-unknown-linux-ohos,PIE,仅依赖 libc.so
arm64 设备out/aarch64/typstaarch64-unknown-linux-ohos,同上
宿主基线由宿主 cargo build 得到x86_64-linux-gnu,用于对拍
设备测试包out/typst-ohos-0.15.1-{x86_64,aarch64}-device-test.tar.gz产物 + 中英文样例 + 随包子集字体 + run.sh 自检脚本

不需要自己编译时,也可以直接下载预构建版:

预构建版下载页

移植路线:所有修改均在构建部分

Typst 主体使用 rust 编写,源码里没有对鸿蒙进行特别适配。编译工作完全由 rustc:Rust 官方为 aarch64-unknown-linux-ohos 与 x86_64-unknown-linux-ohos 提供 Tier 2 支持,同时提供这两个目标平台预编译的标准库,无需自行构建。C/C++ 编译和链接由 zig 提供的 zig cc / zig c++,编译产物的外部依赖只有 libc.so。

层次上游预期鸿蒙侧的处理方式
Rust 编译环境 rustcrustup 安装 ohos 目标平台的标准库
C/C++ 编译环境 ccCC_<triple> / AR_<triple> 指向 build/wrapper/<arch>/zig-cc 与 zig-ar
链接环境 ccCARGO_TARGET_<TRIPLE>_LINKER 指向 build/wrapper/<arch>/zig-c++
C 标准库glibc修改的 muslc,链接时附加 build/shim/shim-ohos-<arch>.o
依赖树Cargo.lock 中锁定的版本升级 cc 与 shlex 两个条目的版本

build.sh 按以下步骤进行一次构建:

  1. 下载解压 typst v0.15.1 源代码到 typst-0.15.1/,解压 zig-patch 到 build/zig-ohos/;
  2. 应用 patches/ 下的代码补丁文件;
  3. 用 zig cc 用于编译符号补齐的 shim 代码;
  4. 执行 cargo build --release --package typst-cli --features vendor-openssl --target <triple> 编译;
  5. 将产物复制到 out/<arch>/typst,调用 build/strip.sh 移除符号;
  6. 静态核查产出的可执行文件。

准备工具链

Rust

Typst 主要使用 Rust 语言开发,编译时需要使用 rustc 和 cargo 项目管理器。这里使用 rustup 简化安装。

# 配置镜像源,后续所有涉及 rustup 的命令均需要重复配置
export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static
export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup

# 安装 rustup 与 Rust
curl --proto '=https' --tlsv1.2 -sSf https://mirrors.ustc.edu.cn/misc/rustup-install.sh | sh

为了加快下载进度,这里使用中国科学技术大学 Linux 用户协会提供的镜像源,替换 Rust 官方的链接。

Typst v0.15.1 的 workspace 声明了 rust-version = "1.92",edition 为 2024,因此宿主的 rustc 需要 1.92 或更高(本次实测 1.98.1)。Rust 默认安装只包含本机的工具链,我们还需要单独安装鸿蒙目标平台标准库(可能需要新打开一个终端以使用更新后的环境变量):

rustup target add aarch64-unknown-linux-ohos # arm64,必须
rustup target add x86_64-unknown-linux-ohos  # x86_64,鸿蒙 PC 与虚拟机使用

检查本机 Rust 环境:

rustc --version
cargo --version

若输出版本号则环境正常。

此外需要从系统包管理器安装一些包:

# Ubuntu 24
sudo apt update && sudo apt install -y git patch curl tar xz-utils perl binutils llvm

# Arch Linux
sudo pacman -Syu --noconfirm git patch curl tar xz perl binutils llvm

其中 patch 用于应用 patches/,binutils 提供 readelf 与 nm,llvm 提供 llvm-objcopy(用于移除符号)。

HarmonyOS SDK

编译过程中需要使用 HarmonyOS SDK,可从华为开发者联盟官网下载:

下载 HarmonyOS SDK

下载完成后,自行解压到特定目录即可。本移植版本的编译流程不使用 HarmonyOS SDK 提供的 C/C++ 编译器。HarmonyOS SDK 只用于使用 llvm-objcopy 清理编译符号,和提供鸿蒙环境中的 libc.a 用于静态检查符号覆盖。

Zig

这里使用对鸿蒙专门进行适配的 zig-patch 发行版,版本为 0.16.0:

下载 zig-patch

build.sh 会自动下载到 downloads/zig-patch-0.16.0.tar.xz 并解压到 build/zig-ohos/,离线环境可以预先下载。

依赖与改动部分

Typst 主要使用 Rust ,仅少量依赖需要 C/C++ 或汇编编译器参与。具体来说(当指定 --package typst-cli --features vendor-openssl 时)只有 psm 与 openssl-src 两个依赖库需要,以及一个对编译器调用封装的 crate cc:

依赖版本使用到的非 rust 语言在本次构建里承担什么需要处理的事项
psm0.1.24汇编提供上下文切换能力CC_<triple> / AR_<triple> 需正确指向包装脚本
openssl-sys 和 openssl-src0.9.116 / 300.4.1+3.4.0C包系统的网络支持需要 perl
cc1.4.5无上面两项都通过它使用编译器能力上游默认版本较旧

其余用于压缩、字体、文件监控等等功能的依赖(flate2 + libz-rs-sys、fdeflate、fontdb、notify 等)均完全使用 Rust 实现,无需额外处理。

只做一处对上游提供的文件的改动,放在 patches/0001-cargo-lock-cc-bump.patch 里,内容是升级 Cargo.lock 中的两个依赖项版本:

cc     1.2.11  ->  1.4.5   (同时引入 find-msvc-tools 0.1.12)
shlex  1.3.0   ->  2.0.1

这个补丁只修改配置文件 Cargo.lock,不改上游任意源码,即「源码树零修改」。观察构建日志里确认指定的升级版本确实被采用:

Compiling shlex v2.0.1
Compiling cc v1.4.5
Compiling openssl-src v300.4.1+3.4.0
Compiling psm v0.1.24

适配中遇到的问题

宿主 rustc 版本低于 typst 的要求

现象。 编译环境默认提供的 rustc 版本为 1.88.0,直接执行 cargo build 会立即终止:

error: package requires rustc 1.92 or newer

原因。 typst v0.15.1 的 workspace Cargo.toml 声明了 rust-version = "1.92",同时在清单文件中指定的 edition 2024 也要求较新的工具链。

处理。 使用 rustup 更新环境 rustc 等组件:执行 rustup toolchain install stable 升级到 1.98.1,再重新 rustup target add 两个 ohos 目标平台。Rust 官方的 ohos target 都是 2 级支持,可直接下载对应平台标准库。

验证。 rustc --version 输出 1.98.1,cargo build 不再出现相关错误报告。

zig cc 的接线:三元组改写与两套环境变量

现象。 把 CC 直接指向 zig cc 之后,psm 的汇编文件仍然由宿主 cc 编译,报 error occurred in cc-rs: command did not execute successfully ... "cc";vendored OpenSSL 的 Configure 也从环境里拿到了宿主的编译器。

原因有两个。

  1. 目标平台的写法差异。rustc 与 cc-rs 传给 C 编译器的是 Rust 三元组 --target=aarch64-unknown-linux-ohos,而 zig 则要求 --target=aarch64-linux-ohos。使用一个 shell 包装脚本给 zig cc 传递其预期的参数:
# build/wrapper/aarch64/zig-cc 部分内容
for a in "$@"; do
  case "$a" in
  --target=*-unknown-linux-ohos) args+=("--target=aarch64-linux-ohos") ;;
  *) args+=("$a") ;;
  esac
done
exec "$ZIG" cc -target aarch64-linux-ohos "${args[@]}"
  1. 具体选择使用 C/C++ 编译器的流程不同。调用 C 编译器不由 Cargo 直接调用,而是在对应依赖库的构建脚本中调用构建(这里通过 cc-rs);Cargo 仅负责将链接器与归档器参数传递给 rustc。于是需要指定两部分变量:
  • Cargo 侧:CARGO_TARGET_<TRIPLE 大写>_LINKER、CARGO_TARGET_<TRIPLE 大写>_AR;
  • cc-rs 侧:CC_<triple>、AR_<triple>,其中三元组里的 - 换成 _。

处理。 build.sh 导出所有需要的变量, cc-rs 部分同时提供小写与全大写两个版本,以适应不同库的差异查找规则:

export "CC_$TRIPLE_LOWER=$CC" "CC_$TRIPLE_UPPER=$CC"
export "CXX_$TRIPLE_LOWER=$CXX" "CXX_$TRIPLE_UPPER=$CXX"
export "AR_$TRIPLE_LOWER=$AR" "AR_$TRIPLE_UPPER=$AR"
export "CARGO_TARGET_${TRIPLE_UPPER}_LINKER=$CC"
export "CARGO_TARGET_${TRIPLE_UPPER}_AR=$AR"

其中 LINKER 指向的是 zig-c++,这一点在后面还会提到。

验证。 构建日志显示 psm 与 openssl-src 正确编译完成,且 psm 相关的编译产物使用目标平台架构。

依赖库引用了 musl 不导出的 mmap64

现象。 链接阶段报错,找不到 mmap64 的定义。

原因。 Typst 间接依赖了 memmap2 库 的 v0.9.5 版本。在 src/unix.rs 里,其使用下面判定决定具体调用符号:

#[cfg(any(
    target_os = "android",
    all(target_os = "linux", not(target_env = "musl"))
))]
use libc::{mmap64 as mmap, off64_t as off_t};

Rust 的 ohos 目标平台的编译信息为 target_os = "linux"、target_env = "ohos",没有被条件编译选项排除,于是 memmap2 把鸿蒙视为 glibc 环境,使用 libc::mmap64。而鸿蒙实际使用 musl ,其只导出 mmap,mmap64 没有提供。参考 alpine 的 muslc 信息:

$ readelf -Ws downloads/alpine-x64-root/lib/ld-musl-x86_64.so.1 | grep -w mmap
   471: 00000000000564e7   197 FUNC    WEAK   DEFAULT   11 mmap

处理。 编译一个 C shim 把 mmap64 转发到 mmap:

#include <sys/mman.h>

void *mmap64(void *addr, size_t length, int prot, int flags, int fd, long long offset) {
    return mmap(addr, length, prot, flags, fd, (off_t)offset);
}

关键细节:这个 shim 通过封装脚本参与链接。 build/wrapper/<arch>/zig-c++ 把编译好的 shim 目标文件追加进链接参数,zig-cc 则没有:

# build/wrapper/aarch64/zig-c++(节选)
SHIM="$SELF/../../shim/shim-ohos-aarch64.o"
extra=()
[ -f "$SHIM" ] && extra+=("$SHIM")
exec "$ZIG" c++ -target aarch64-linux-ohos "${extra[@]}" "${args[@]}"

之所以只在 zig-c++ 封装脚本中参与,原因是 build.sh 把 CARGO_TARGET_<TRIPLE>_LINKER 指向了这个脚本,整个程序的链接通过该脚本完成,缺失符号也会在这步导致链接失败。

验证。 链接完成后,产物里 mmap64 不再是未定义符号,只剩 musl 提供的 mmap:

$ readelf -Ws out/aarch64/typst | grep -wE "mmap64|mmap"
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND mmap

这条经验可以推广。 依赖中所有 not(target_env = "musl") 形式的平台判定,在鸿蒙上都会判别为 glibc 分支,因为 ohos 的 target_env 取值是 ohos,与 gnu、musl 都不相同。遇到链接阶段缺符号时,先尝试检索存不存在相同问题。

Zig SDK 不提供 objcopy,转为使用 HarmonyOS SDK 提供的 strip 能力

现象。 zig-patch 的发行目录内有 zig、lib 与文档,没有 llvm-objcopy,缺失移除符号的能力。

处理。 build/strip.sh 按顺序尝试搜索:HarmonyOS SDK 自带的 llvm-objcopy、宿主 PATH 里的 llvm-objcopy、objcopy,若存在任一可用项就执行 --strip-all。

验证。 strip 之后 file 检查输出含 stripped 标记,产物体积(48 MB / 52 MB)极大减小。

Cargo.lock 里 cc 与 shlex 的版本

现象。 上游 v0.15.1 锁定的 cc 版本是 1.2.11,shlex 版本是 1.3.0。

处理。 补丁把 cc 升为 1.4.5(同时引入 find-msvc-tools 0.1.12)、shlex 升到 2.0.1,只改 Cargo.lock。

验证。 构建日志中出现 Compiling shlex v2.0.1 与 Compiling cc v1.4.5 说明确实使用升级后的版本。

产物的静态核查

交叉编译产物真的在鸿蒙平台上可以运行吗?在编译环境通过几个方法快速检查:build.sh 在结束处打印架构、NEEDED 与 interpreter,同时 build/check-symbols.sh 提供完整的完全静态的符号检查。

核查项aarch64 产物x86_64 产物
file 命令输出ELF 64-bit LSB pie executable, ARM aarch64, strippedELF 64-bit LSB pie executable, x86-64, stripped
interpreter/lib/ld-musl-aarch64.so.1/lib/ld-musl-x86_64.so.1
NEEDED仅 libc.so仅 libc.so
RUNPATH / RPATH无无
ELF 标志BIND_NOW、NOW PIE同
首个 LOAD 段的页边界0x100000x1000
动态未定义符号总数234229
其中 HarmonyOS SDK libc.a 不存在的00
其中 Alpine musl 不存在的00
弱引用外部符号44

符号覆盖检查的具体方法:获取产物符号表里所有 UND 符号,检查在 OHOS SDK sysroot 里的 libc.a、 Alpine musl 1.2.5 中是否存在。所有符号均存在,说明产物需要的外部符号,设备端与验证环境两端都具备。四个弱引用未定义符号是 copy_file_range、getentropy、getrandom、gettid,装载器找不到时按可选处理:

$ OHOS_SDK=/opt/ohos-sdk/sdk/default/openharmony ./build/check-symbols.sh out/aarch64/typst
UND 符号数: 234
== 缺失于 OHOS SDK libc.a: 0 ==
== 缺失于 Alpine musl 1.2.5(qemu 运行环境): 0 ==
== WEAK UND 符号数: 4 ==
copy_file_range
getentropy
getrandom
gettid

NEEDED 只有 libc.so,说明 libc++、compiler-rt 与 OpenSSL 都是静态链接的,不依赖设备上预装其它运行库。两个架构的首个 LOAD 段页边界不同(aarch64 是 0x10000,x86_64 是 0x1000),为指令集各自的默认页大小,均为 4096 的整数倍。

功能验证:与上游版本 9 项比对

Typst 的行为是否与其它平台一致,靠逐项比较验证来判定。做法是在编译环境上额外构建一份 x86_64-linux-gnu 产物作为参照版,OHOS 产物放在 qemu-user + Alpine musl 1.2.5 的运行环境里执行,两者跑同一批样例,比对输出。

鸿蒙设备环境模拟使用 qemu-user 9.2.1 与 Alpine musl 1.2.5 的 rootfs,本次复用自同机的前置适配项目,放在 downloads/ 下,不纳入版本管理;换到别的机器上需要比照时,准备同样的 qemu-aarch64 / qemu-x86_64 与 Alpine rootfs 即可。

对拍前做了两处修改,避免把无关的随机量算成差异:

  • 样例文档里加 #set document(date: none),消除编译时间戳;
  • PDF 的 XMP InstanceID / DocumentID 每次编译都会重新生成,比对前替换成占位符。

SVG、PNG 与文本输出不做归一化,逐字节比对。验证脚本与样例文档(baseline/run-alignment.sh 与 test-project/ 里的拉丁样例、中文样例、查询样例与随包子集字体)随适配工作目录提供,本节列出的输出都由它产生。

序号比对项比对方式aarch64x86_64
1--version逐字节PASSPASS
2--help逐字节PASSPASS
3fonts --ignore-system-fonts逐字节PASSPASS
4拉丁样例导出 PDF / SVG / PNGSVG、PNG 逐字节;PDF 归一化随机 IDPASSPASS
5中文样例导出 PDF(随包子集字体)归一化随机 IDPASSPASS
6eval 查询(heading / figure)逐字节PASSPASS
7错误路径(即编译不存在的文件)退出码 + 报错文本PASSPASS
8无 HOME 环境下的行为退出码 + 输出PASSPASS
9包系统实际工作:真实下载 @preview 包日志 + 缓存落位 + 编译结果PASSPASS

第 4、5 项:产物完全一致。 拉丁样例两页的 SVG 与 PNG 在两个平台上的摘要完全一致:

$ cd baseline/align-out
$ md5sum host/latin-1.png aarch64/latin-1.png
6a85352873d5944047220ca0be15e390  host/latin-1.png
6a85352873d5944047220ca0be15e390  aarch64/latin-1.png

$ md5sum host/latin-2.svg aarch64/latin-2.svg
f3f2e103325d3e1dc4ec0de1b845a0d5  host/latin-2.svg
f3f2e103325d3e1dc4ec0de1b845a0d5  aarch64/latin-2.svg

PDF 在去除随机 ID 影响后同样一致,说明字体子集、坐标与结构树都是逐项相同的。

第 9 项:包系统实际运行测试。 样例引用 @preview/a2c-nums:0.0.1,编译时 Typst 会发起请求请求下载该包:

typst compile pkg-test.typ pkg.pdf

这一项同时验证了 typst 网络部分模块能正常工作,输出:

downloading @preview/a2c-nums:0.0.1

  0 B /   2.5 KiB (  0 %),  24.7 KiB/s, ETA: 0 s
  2.5 KiB /   2.5 KiB (100 %),  24.7 KiB/s, ETA: 0 s

下载完成后包被写入 ~/.cache/typst/packages/preview/a2c-nums/0.0.1/,文档里 int-to-cn-num(123456789) 渲染出 一亿二千三百四十五万六千七百八十九。两个架构在这一项上都是通过。

功能划分

状态依据适配仓库里的功能核查记录与上面测试结果填写。

T0 基础

功能状态备注
CLI 参数解析与子命令分发支持
源码解析与求值(typst-syntax / typst-eval)支持
排版引擎(typst-layout)支持
内嵌字体(typst-assets)支持随二进制分发,无需外部字体文件
PDF / SVG / PNG 导出支持SVG 与 PNG 与宿主位级一致
错误诊断输出支持退出码与报错文本与宿主一致
标准输入与标准输出(-)支持stdin → stdout 导出 PDF 正常

T1 核心

功能状态备注
中文(CJK)排版支持需要 --font-path 或 TYPST_FONT_PATHS 指定中文字体
数学排版、表格、图形、交叉引用、脚注支持
eval 子命令与查询支持
包系统(@preview 下载)支持依赖 HOME 或 TYPST_PACKAGE_CACHE_PATH
包缓存与数据目录支持无 HOME 时的行为与其它平台一致
watch 模式支持inotify 后端
自定义字体路径支持--font-path / TYPST_FONT_PATHS
模板初始化(init)支持与包系统共用下载与缓存路径

T2 其它与边界

功能状态备注
系统字体自动扫描不支持fontdb 扫描的是标准 Linux 字体目录,鸿蒙的系统字体位于 /system/fonts,需要用 --font-path /system/fonts 或 TYPST_FONT_PATHS 显式指定
--open 打开外部查看器不支持鸿蒙系统不支持
shell 补全(completions)支持bash 补全脚本生成正常
info 子命令支持输出正常,含特性开关状态
PDF 标准与 tagged PDF支持
HTML 与 bundle 导出支持
编译性能参数(-j / --timings / --deps)支持
自定义 CA 证书(--cert)支持

在鸿蒙 PC 上验证

以下内容在鸿蒙 PC 真机上执行(设备型号、分辨率与系统版本待填)。

准备

在系统设置应用「隐私和安全 > 高级」中开启「运行外部来源的扩展程序」开关,并从应用商店安装【BiShengJDK17-OH】与【DevBox】。

执行文件签名

鸿蒙 PC 要求所有可执行文件在执行前都必须签名,这里使用调试签名。把可执行文件传输到设备后:

# 假设传输的可执行文件名为 typst_unsign
binary-sign-tool sign -inFile typst_unsign -outFile typst -selfSign "1"
chmod 755 ./typst
# typst 为签名后的可运行的可执行文件

真机快速核查

设备测试目录里提供测试脚本 run.sh,运行该脚本即可进行完全测试:

tar xzf typst-ohos-0.15.1-x86_64-device-test.tar.gz
cd typst-ohos-device-test
sh run.sh ./typst

脚本覆盖:产物版本、内嵌字体列表、拉丁样例导出 PDF/SVG/PNG、中文样例导出 PDF、eval 查询、产物目录清单。

在鸿蒙PC中运行 Typst 测试脚本

图中终端窗口顶部是设备桌面与任务栏,可以看到签名命令与自检脚本从 --version 一路执行到 DEVICE TEST DONE,out/ 目录下生成了 sample-cjk.pdf、sample-latin-1.svg、sample-latin-1.png、sample-latin-2.svg、sample-latin-2.png 与 sample-latin.pdf。

签名完成之后,即可参考官网文档开始排版工作。

常见问题(FAQ)

Q1:产物拷到设备上执行报权限错误(Operation not permitted)。

鸿蒙 PC 要求可执行文件先签名。用 binary-sign-tool sign -selfSign "1" 做一次调试签名,并对文件执行 chmod 755。

Q2: 产物在第三方终端中签名后运行仍报错权限错误。

鸿蒙 PC 对自签类型可执行文件的限制,建议使用系统内置终端应用。

Q3:含中文项目编译出来汉字不显示。

默认只使用内嵌字体,内嵌字体不含中文字形。加 --font-path fonts 指定随包子集字体,或 TYPST_FONT_PATHS=/system/fonts 使用设备系统字体。

Q4:包里引用的 @preview 包下载失败。

确认正确设置 HOME环境变量。需要网络代理时设置 http_proxy / https_proxy,包系统会读取这两个环境变量。

Q5:产物在本机 qemu 里运行失败。

产物动态链接的是 musl 的 libc.so,用 qemu-user 执行时需要提供对应的 musl 运行环境,靠 -L 指定根目录:

./downloads/qemu-u92-root/usr/bin/qemu-aarch64 -L ./downloads/alpine-root out/aarch64/typst --version

未准备好 Alpine rootfs 时,运行会失败,这与产物本身无关;按上面的命令准备好 rootfs,或者直接到真机上验证。

后续

后续拟继续推进的方向:

  • 系统字体自动扫描:目前中文排版要显式给出字体路径。fontdb 扫描的是标准 Linux 字体目录,拟推动支持 /system/fonts。
  • --open 的外部查看器:鸿蒙设备目前不向终端应用开放类似 xdg-open 的权限。

参考资料:

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐