HarmonyOS 鸿蒙Next使用rust+仓颉混合编程方案分享
HarmonyOS 鸿蒙Next使用rust+仓颉混合编程方案分享
- 参考链接:https://doc.rust-lang.org/rustc/platform-support/openharmony.html
- 参考链接2:HarmonyOS RUST 应用开发指导
- 参考链接3
- 需要Linux系统
准备工作
获取本机的openharmony sdk版本,可以通过打开DevEco Studio,帮助,关于Dev Eco Studio获取。从这段貌似来看,我的本地sdk版本是
5.0.0.68
,它的储存地址是:C:\Program Files\HuaWei\DevEco Studio\sdk\default\openharmony
,我们也可以通过浏览C:\Program Files\HuaWei\DevEco Studio\sdk\default\openharmony\native\docs\index.html
查看sdk文档,里面也有它的版本号。HarmonyOS NEXT Beta1 SDK,基于OpenHarmony SDK Ohos_sdk_public 5.0.0.68 (API Version 12 Release)
获取openharmony sdk,链接,项目选择openharmony, 分支选择master或者
OpenHarmony-5.0-Release
,时间先选择本月,或者更长周期。点击
ohos-sdk-full
,可以看到所有构建的版本信息。目前比较接近的版本号应该是OpenHarmony_5.0.0.60
,没有看到OpenHarmony_5.0.0.68
版本,所以先下载这个用着咯。将sdk上传到linux系统中,因为后面的ohos(openharmony OS)跨平台编译时,rust那边目前给出的方案只能在linux跨平台编译ohos。
解压sdk,放到某个路径下,我一般习惯放/usr/local下面。
# 解压tar.gz包 tar -zxvf ./version-Master_Version-OpenHarmony_5.0.0.60-20240806_020315-ohos-sdk-full.tar.gz
cd linux # 再批量解压zip包 ls *.zip | xargs -n1 unzip
# 删除.zip rm *.zip
# 将解压后的文件移动到/usr/loca/下面 sudo mkdir -p /usr/local/ohos-sdk/linux sudo mv ./* /usr/local/ohos-sdk/linux/
配置rust
安装rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
安装nightly版rust,并添加标准库源码支持。
rustup toolchain install nightly rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
添加ohos支持。
rustup target add aarch64-unknown-linux-ohos rustup target add x86_64-unknown-linux-ohos
配置一些脚本文件,可以放任意目录,我这里放~/.ohos/scipt目录下。
mkdir ~/.ohos/script/ -p
第一个文件
vim ~/.ohos/script/aarch64-unknown-linux-ohos-clang.sh
填入下面的内容。
#!/bin/sh exec /usr/local/ohos-sdk/linux/native/llvm/bin/clang \ -target aarch64-linux-ohos \ --sysroot=/usr/local/ohos-sdk/linux/native/sysroot \ -D__MUSL__ \ "$@"
第二个文件。
vim ~/.ohos/script/aarch64-unknown-linux-ohos-clang++.sh
填入下面的内容。
#!/bin/sh exec /usr/local/ohos-sdk/linux/native/llvm/bin/clang++ \ -target aarch64-linux-ohos \ --sysroot=/usr/local/ohos-sdk/linux/native/sysroot \ -D__MUSL__ \ "$@"
第三个文件
vim ~/.ohos/script/x86_64-unknown-linux-ohos-clang.sh
填入下面的内容。
#!/bin/sh exec /usr/local/ohos-sdk/linux/native/llvm/bin/clang \ -target x86_64-linux-ohos \ --sysroot=/usr/local/ohos-sdk/linux/native/sysroot \ -D__MUSL__ \ "$@"
第四个文件
vim ~/.ohos/script/x86_64-unknown-linux-ohos-clang++.sh
填入下面的内容。
#!/bin/sh exec /usr/local/ohos-sdk/linux/native/llvm/bin/clang++ \ -target x86_64-linux-ohos \ --sysroot=/usr/local/ohos-sdk/linux/native/sysroot \ -D__MUSL__ \ "$@"
给上面4个文件添加可执行权限。
chmod +x ~/.ohos/script/*.sh
第五个文件
vim ~/.cargo/config.toml
填入或者添加下面的内容,这样交叉编译的时候就可以调用ohos的可执行文件了,这也算是一个默认配置。
[target.aarch64-unknown-linux-ohos] ar = "/usr/local/ohos-sdk/linux/native/llvm/bin/llvm-ar" linker = ".ohos/script/aarch64-unknown-linux-ohos-clang.sh"
[target.x86_64-unknown-linux-ohos] ar = “/usr/local/ohos-sdk/linux/native/llvm/bin/llvm-ar” linker = “.ohos/script/x86_64-unknown-linux-ohos-clang.sh”
编译动态库
先用rust新建一个库函数
cargo new rslib --lib
进入该库函数所在文件夹。
cd rslib
默认里面有一个add函数,大概长这样,为了容易区分,我们可以将add函数改名为my_add函数,并添加c支持。
- 修改前
pub fn add(left: u64, right: u64) -> u64 { left + right }
- 修改后
#[no_mangle] pub extern "C" fn my_add(left: u64, right: u64) -> u64 { left + right }
- 修改前
修改cargo.toml 指定目标类型为C动态库
[lib] crate-type=["cdylib"]
先编译一个Linux版的so库测试一下,编译结果在
target/release/librslib.so
路径cargo build --release
我们可以通过strings工具来搜索一下这个so库,看看是否能看到我们刚刚定义的函数,能搜到说明正常。
strings librslib.so | grep my_add
在仓颉程序中测试动态库
新建仓颉程序。
mkdir rs_test cd rs_test cjpm init --name rs_test
将刚刚编译好的so库放到仓颉项目目录,和cjpm.toml同级。然后修改src/main.cj文件
package rs_test foreign func my_add(a: UInt64, b: UInt64): UInt64;
main(): Int64 { println(“hello world”) let res = unsafe{my_add(3, 5)}; println(“my_add(3, 5) = ${res}”); return 0 }
再修改cjpm.toml文件。添加一个
compile-option = "-L . -l rslib"
编译仓颉项目。
cjpm build
运行仓颉项目。
LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:. ./target/release/bin/main
输出结果。
hello world my_add(3, 5) = 8
交叉编译动态库,用于鸿蒙Next APP
项目还是刚刚
编译动态库
的rust项目。编译(aarch64),一般用于手机真机(下面编译方法随便选一个都行,如果用到了rust的标准库,则只能用最后一种)
- 标准版编译
cargo build --target aarch64-unknown-linux-ohos
- 标准版release版本编译,目标会出现在
target/aarch64-unknown-linux-ohos/release
目录中。文件名为:librslib.so
cargo build --target aarch64-unknown-linux-ohos --release
- nightly版编译(支持std标准库)。
cargo +nightly build -Z build-std --target aarch64-unknown-linux-ohos
- 标准版编译
编译(x86-64),一般用于模拟器。(下面编译方法随便选一个都行,如果用到了rust的标准库,则只能用最后一种)
- 标准版编译
cargo build --target x86_64-unknown-linux-ohos
- 标准版release版本编译,目标会出现在
target/x86_64-unknown-linux-ohos/release
目录中。文件名为:librslib.so
cargo build --target x86_64-unknown-linux-ohos --release
- nightly版编译(支持std标准库)。
cargo +nightly build -Z build-std --target x86_64-unknown-linux-ohos
- 标准版编译
我们先执行第三步得到一个x86-64的so库。然后将这个库下载下来。然后用DevEco Studio新建一个Cangjie项目。将so放到
entry/sc/main/cangjie
目录。在
entry/src/main/cangjie/index.cj
中加入一行导入外部c函数的代码,代码如下:... import ohos.hilog.Hilog foreign func my_add(a: UInt64, b: UInt64): UInt64;
@Entry @Component class EntryView { @State var message: String = “Hello Cangjie” func build() { Row { Column { Button(message).onClick { let res = unsafe {my_add(5, 10)}; Hilog.info(0, “res”, “my_add(5, 10) = ${res}”); }.fontSize(40).height(80) }.width(100.percent) }.height(100.percent) } }
在
entry/src/main/cangjie/cjpm.toml
文件中,[target.x86_64-linux-ohos]
的compile-option
加上-L . -l rslib
,如下面所示:[target.x86_64-linux-ohos] compile-option = "-B \"${DEVECO_CANGJIE_HOME}/compiler/third_party/llvm/bin\" -B \"${DEVECO_CANGJIE_HOME}/musl/usr/lib/x86_64-linux-ohos\" -L \"${DEVECO_CANGJIE_HOME}/musl/usr/lib/x86_64-linux-ohos\" -L \"${DEVECO_CANGJIE_HOME}/build/linux_ohos_x86_64_llvm/openssl\" --sysroot \"${DEVECO_CANGJIE_HOME}/musl\" -L . -lrslib"
运行项目,可以看到app正常打开,点击按钮,可以看到对应的日志。