4. 开发环境搭建(下):下载鸿蒙源码、配置编译环境、安装交叉编译工具链(gcc_riscv32)
好,咱们接着上一章继续聊。环境搭建的上半部分我们把基础软件包和依赖库搞定了,现在要动真格的了——把鸿蒙源码拉下来,把编译环境配好,再把交叉编译工具链装上去。这三步走完,你的电脑才算真正具备了给开发板“造固件”的能力。
说实话,我刚开始移植鸿蒙的时候,最头疼的就是工具链版本不匹配。明明代码拉下来了,编译却报一堆莫名其妙的错误。后来才发现,是gcc版本和内核代码对不上。所以这一章,我会把每一步的坑都给你指出来。
4.1 下载鸿蒙源码
鸿蒙的源码托管在码云(Gitee)上,我们用repo工具来管理。repo是Google为Android开发的多仓库管理工具,鸿蒙也沿用了这套机制。你想想看,鸿蒙涉及的内核、驱动、框架、应用层,几十个仓库,一个个git clone得累死,repo一条命令全搞定。
4.1.1 安装repo工具
先确认你的系统里有没有repo:
which repo
如果没有,按下面步骤安装:
mkdir -p ~/bin
curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > ~/bin/repo
chmod a+x ~/bin/repo
echo 'export PATH=~/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
这里有个小细节——我建议你用repo-py3这个分支,因为它是Python3版本的。鸿蒙新版本的repo脚本已经全面转向Python3,如果你用老版本的repo,后面同步代码时可能会报UnicodeDecodeError。我在项目里就吃过这个亏,折腾了半天才发现是repo版本的问题。
4.1.2 配置git用户信息
repo在同步代码时会用到git,所以先配好你的身份:
git config --global user.name "你的名字"
git config --global user.email "你的邮箱"
嗯,这里邮箱最好用Gitee注册的邮箱,后面提交代码时能关联上你的账号。
4.1.3 初始化并同步源码
创建一个工作目录,比如ohos_workspace:
mkdir ohos_workspace && cd ohos_workspace
repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify
repo sync -c -j4
解释一下参数:
-u:指定manifest仓库地址,这个仓库里记录了所有子仓库的路径和版本-b master:选择master分支。如果你想移植稳定版,可以用-b OpenHarmony-3.2-Release-c:只同步当前分支,不下载其他分支的引用,能省不少带宽-j4:4个线程并行下载。如果你的网络好,可以改成-j8
repo sync -c -j4即可,它会断点续传。
同步完成后,你会看到ohos_workspace目录下有一堆文件夹,比如kernel、drivers、foundation等等。这就是鸿蒙的全量源码了。
4.2 配置编译环境
源码拉下来了,但还不能直接编译。鸿蒙的编译系统基于hb工具(HarmonyOS Builder),我们需要先把它装好。
4.2.1 安装hb工具
hb工具在源码的build/lite目录下,安装命令如下:
cd ohos_workspace
pip3 install build/lite
安装完成后,验证一下:
hb --version
如果输出版本号,说明安装成功。如果没有,可能是Python路径问题,检查一下~/.local/bin是否在PATH里。
hb的路径加到.bashrc里,这样每次打开终端都能直接用:echo 'export PATH=~/.local/bin:$PATH' >> ~/.bashrc
4.2.2 设置编译环境变量
鸿蒙的编译脚本依赖一些环境变量,比如产品名称、设备架构等。我们创建一个脚本来统一设置:
vim setenv.sh
写入以下内容:
#!/bin/bash
export OHOS_ROOT=$(pwd)
export PATH=$OHOS_ROOT/prebuilts/python/linux-x86/3.9.2/bin:$PATH
export PATH=$OHOS_ROOT/prebuilts/build-tools/linux-x86/bin:$PATH
然后执行:
source setenv.sh
为什么要这么做?因为鸿蒙的预编译工具链和Python解释器都在源码的prebuilts目录下。如果不加这些路径,编译时可能会找不到gn、ninja这些构建工具。我曾经见过有人直接拿系统的Python去编译,结果因为版本不对,卡在语法解析上,折腾了两天。
4.2.3 选择产品配置
鸿蒙支持多种开发板,每种开发板对应一个产品配置。我们以hispark_pegasus(海思Hi3861)为例:
hb set -p hispark_pegasus
这条命令会在当前目录生成一个ohos_config.json文件,里面记录了产品名、设备架构、内核类型等信息。你可以用cat查看:
cat ohos_config.json
输出大概长这样:
{
"product_name": "hispark_pegasus",
"device_company": "hisilicon",
"kernel_version": "liteos_m",
"board": "hispark_pegasus",
"target_os": "liteos_m"
}
看到kernel_version是liteos_m,说明这个产品用的是轻量级内核,适合资源受限的MCU开发板。
4.3 安装交叉编译工具链(gcc_riscv32)
终于到最关键的一步了。交叉编译工具链,说白了就是让你在x86的电脑上,编译出能在RISC-V架构上运行的代码。没有它,你写的C代码开发板根本看不懂。
4.3.1 下载gcc_riscv32工具链
鸿蒙官方提供了预编译好的工具链,放在prebuilts目录下。但如果你是从零搭建,需要手动下载:
cd ohos_workspace
wget https://gitee.com/openharmony/prebuilts_gcc_riscv32/releases/download/v1.0.0/gcc_riscv32-linux-7.3.0.tar.gz
tar -xzf gcc_riscv32-linux-7.3.0.tar.gz -C prebuilts/
解压后,工具链会放在prebuilts/gcc/riscv32目录下。你可以进去看看:
ls prebuilts/gcc/riscv32/bin/
里面应该有riscv32-unknown-elf-gcc、riscv32-unknown-elf-objcopy等可执行文件。
implicit declaration of function之类的错误。我踩过这个坑,后来老老实实换回7.3.0。
4.3.2 配置工具链路径
把工具链的bin目录加到PATH里,这样编译时才能找到riscv32-unknown-elf-gcc:
export PATH=$OHOS_ROOT/prebuilts/gcc/riscv32/bin:$PATH
验证一下:
riscv32-unknown-elf-gcc --version
如果输出类似riscv32-unknown-elf-gcc (GCC) 7.3.0,说明安装成功。
4.3.3 测试编译一个简单程序
写一个Hello World,测试工具链是否正常工作:
vim test.c
内容:
#include <stdio.h>
int main() {
printf("Hello, RISC-V!\n");
return 0;
}
编译:
riscv32-unknown-elf-gcc -o test.elf test.c
生成test.elf后,用file命令查看它的架构:
file test.elf
输出应该是:
test.elf: ELF 32-bit LSB executable, UCB RISC-V, version 1 (SYSV), statically linked, not stripped
看到RISC-V字样,说明编译出来的程序确实是RISC-V架构的。这个程序不能在x86电脑上直接运行,但可以烧录到开发板上跑。
4.4 知识体系总览
下面这张图把本章的核心逻辑串起来了,你可以对照着看:
这张图把三个模块的流程串起来了。你从左边开始,依次完成源码下载、环境配置、工具链安装,最后就能进入编译阶段。每一步都有对应的命令和验证方法,照着做就行。
4.5 常见问题与避坑指南
最后,分享几个我实际遇到过的问题,你遇到了可以直接对照解决:
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
repo sync时提示fatal: unable to access |
网络不通或Gitee被墙 | 检查网络,或使用代理:export http_proxy=http://你的代理地址 |
hb set找不到产品 |
没有在源码根目录执行 | cd到ohos_workspace根目录再执行 |
编译时报riscv32-unknown-elf-gcc: command not found |
工具链路径没加到PATH | 检查export PATH是否生效,用echo $PATH查看 |
编译报implicit declaration of function |
gcc版本不匹配 | 确认使用的是7.3.0版本,不要用高版本 |
我曾经在一次移植项目中,因为工具链路径配错了,编译出来的固件烧到板子上直接跑飞。后来用readelf -h查看ELF文件头,才发现入口地址不对。所以,每一步做完后,一定要用我上面提到的验证方法检查一下,别偷懒。
好了,环境搭建到这里就全部完成了。你的电脑现在具备了编译鸿蒙固件的能力。下一章,我们会真正开始编译第一个鸿蒙镜像,然后烧录到开发板上,看到LED灯闪烁的那一刻,你会觉得前面所有的折腾都值了。