1. 安装 WSL2
通常情况下,我们在 Linux 环境中开发 OpenHarmony 代码。你可以在 Windows 子系统 Linux(WSL)上搭建开发环境。推荐使用运行在 WSL2 上的 Ubuntu 22.04 LTS 版本,使用其他 Ubuntu 版本可能会出现不可预见的问题。
参考文档:安装 WSL | Microsoft Learn
请确保满足以下条件:
WSL2 安装所在的磁盘分区需有足够的空间,至少170GB。这是因为不含 WSL 中其他文件的情况下,OpenHarmony 完整代码及编译产物就占用 161GB。
参考文档:查找 Linux 分发版的 .vhdx 文件和磁盘路径
安装 WSL2 而非 WSL1。你可以使用命令
wsl -l -v进行检查。两者的编译速度相差数十倍。配置 WSL2,避免编译代码时出现栈帧大小超限的问题。
在文件资源管理器的地址栏中输入%UserProfile%并按回车键,然后创建一个名为.wslconfig的文件。[wsl2] memory=14GB swap=8GB如果电脑内存不足,可以增大交换分区(swap)的大小。但需要注意,过大的交换空间可能会导致性能下降。
配置完成后,运行
wsl --shutdown关闭所有正在运行的分发版,等待 8 秒让 WSL2 重启并更新配置。也可参考以下链接:参考文档: WSL 中的高级设置配置 | Microsoft Learn
2. 安装依赖库和工具
在使用命令行界面(CLI)进行设备开发前,请执行以下步骤在 WSL2 中安装所需的依赖库和工具。
将 dash 替换为 bash
- 检查当前 shell:
ls -l /bin/sh - 替换 shell:
sudo dpkg-reconfigure dash # 选择 No
安装 python3 和 pip3
配置 python 命令别名
Ubuntu 22.04 系统默认安装了python3.10。执行以下命令:
sudoupdate-alternatives--install/usr/bin/python python /usr/bin/python3150150 是优先级数值,数值越大,优先级越高。
配置完成后,你可以输入python或python3来运行 Python 程序,而在此之前只能使用python3命令。
安装 pip3
sudoaptupdatesudoaptinstallpython3-setuptools python3-pip-y并将 pip3 的镜像源设置为华为云镜像源:
pip3 configsetglobal.index-url https://mirrors.huaweicloud.com/repository/pypi/simple安装依赖库
sudoaptupdate&&sudoaptinstall-yandroid-sdk-libsparse-utilsbcbinutils bison build-essential ccachecurldefault-jdk doxygen flex g++-multilib gcc-arm-none-eabi gcc-multilib genext2fsgitgit-lfs gnupg gnutls-bin gperf lib32ncurses-dev lib32ncurses-dev lib32z1-dev libc++1 libc6-dev-i386 libelf-dev libgl1-mesa-dev liblz4-tool libssl-dev libtinfo5 libx11-dev libxcursor-dev libxi-dev libxinerama-dev libxml2-utils libxrandr-dev m4 mtd-utilsmtoolsopenssl ruby scons u-boot-toolsunzipx11proto-core-dev xsltproczipzlib1g-dev libffi-dev gcc-arm-linux-gnueabi autoconf automake libtool cmake pkg-config check openssl libssl-dev libcurl4-openssl-dev我在测试过程中,该步骤安装依赖库的操作可以正常完成。
考虑到开发环境配置的复杂性,如果根据提示仍无法解决安装问题,建议重新安装 WSL2。
3. 获取源码
在 Ubuntu 环境中,执行以下步骤获取 OpenHarmony 源码。
准备工作
GitCode 配置
前往 GitCode 注册账号。
配置 SSH 密钥 - GitCode 以实现 gitcode 免密访问。
执行
ssh-keygen -t ed25519 -C "gitcode SSH Key",根据提示连续按 3 次回车键。-t:指定密钥类型-C:添加注释信息
Generating public/private ed25519 key pair. Enterfileinwhichto save the key(/home/git/.ssh/id_ed25519): Enter passphrase(emptyforno passphrase): Enter same passphrase again: Your identification has been savedin/home/git/.ssh/id_ed25519 Your public key has been savedin/home/git/.ssh/id_ed25519.pub The key fingerprint is: SHA256:ohDd0OK5WG2dx4gST/j35HjvlJlGHvihyY+Msl6IC8I gitcode SSH Key The key's randomart image is: +--[ED25519256]--+|.o||.+oo||...O.o +||.=*=+.||.o +..S*. +||....o o..+* *||.E. o...+.O||..... o=.||..oo. o.o|+----[SHA256]-----+获取并复制公钥
~/.ssh/id_ed25519.pub:cat~/.ssh/id_ed25519.pub示例输出:
ssh-ed25519 AAAA***5B gitcode SSH Key将公钥添加到 gitcode 账号中。SSH 密钥 - gitcode
验证配置是否成功:
zq@DESKTOP-RGE1MF4:~$ssh-Tgit@gitcode.com Hi zhangqiang(@inkuu)!You've successfully authenticated, but gitcode.COM does not provide shell access.
Git 配置
gitconfig--globaluser.name"你的用户名"gitconfig--globaluser.email"你的账号邮箱@xxx.com"gitconfig--globalcredential.helper store安装 Repo 工具
sudocurlhttps://gitee.com/oschina/repo/raw/fork_flow/repo-py3-o/usr/local/bin/reposudochmod777/usr/local/bin/reposudopip3install-ihttps://repo.huaweicloud.com/repository/pypi/simple requests拉取代码
我们基于master分支进行开发,请确保下载的代码完整且正确!
mkdir~/OpenHarmonycd~/OpenHarmony repo init-uhttps://gitcode.com/openharmony/manifest.git-bmaster --no-repo-verify reposync-c# -c 仅同步当前分支repo forall-c'git lfs pull'# 注意这步也很关键编译代码时可能会遇到一些意外问题,这些问题可能由网络异常或其他原因导致。可能需要多次尝试下载所需文件,直到无错误信息为止。
你可以重复执行命令repo sync -j1 --fail-fast && repo forall -c 'git lfs pull',该命令会以单线程方式下载文件,且遇到错误时立即停止,便于你逐个解决错误。
更新代码
repo init-uhttps://gitcode.com/openharmony/manifest.git-bmaster --no-repo-verify repo forall-c'git reset --hard';\repo forall-c'git clean -df';\reposync-cd--no-tags --force-sync&&repo forall-c'git lfs pull'查看每个仓库的节点
如果想查看每个仓库的git节点, 执行命令repo manifest -r > full_ohos_manifest.xml
常见问题
报错 “could not check out xxx”
重复执行命令repo sync -j1 --fail-fast和repo forall -c 'git lfs pull'。
报错 “unable to fully sync the tree”
按照提示重新执行repo sync -j1 --fail-fast,你会得到更具体的错误信息。
进入目录applications/standard/app_samples/,执行git status:
执行以下命令修复:
gitreset--hardgitclean-df重新执行repo sync -j1 --fail-fast和repo forall -c 'git lfs pull',问题即可解决。
切换用户账号导致的问题
下载代码过程中请勿切换 Linux 用户账号:
重新执行以下命令:
repo init-uhttps://gitcode.com/openharmony/manifest.git-bmaster --no-repo-verify reposync-c# -c 并发同步repo forall-c'git lfs pull'4. 预编译准备
安装预编译工具
正式编译代码前,在 OpenHarmony 代码目录中执行脚本,准备包含编译器等工具的预编译包:
cd~/Openharmony ./build/prebuilts_download.sh --skip-ssl安装 hb 工具(可选)
可选的编译辅助工具:
cd~/Openharmonysudopip3install--default-timeout=100build/hb若安装过程中出现问题,你可能需要执行以下命令:
pip3 uninstall-yprompt_toolkitsudopip3 uninstall-yprompt_toolkitsudopip3install-ihttps://mirrors.aliyun.com/pypi/simple/ prompt-toolkit==1.0.185. 编译 OpenHarmony
开发环境已准备就绪,现在可以开始编译!
如果存在 “out” 目录,请先清空:
cd~/Openharmony ./build.sh --product-name rk3568 --target-cpu arm64# 编译并构建所有代码# 比如graphic_2d图形仓./build.sh --product-name rk3568-Tgraphic_2d --gn-flags="--export-compile-commands"--target-cpu arm64若不是首次编译,可以使用 “–fast-rebuild” 参数加快编译速度。
你可以使用 “./build.sh -h” 查看帮助信息。也可以添加
--build-target BUILD_TARGET或者-T参数编译指定目标模块。比如graphic_2d图形仓--build-target graphic_2d添加参数
--gn-flags="--export-compile-commands"可生成out/rk3568/compile_commands.json文件(用于代码跳转/补全)。更多信息可参考 docs/zh-cn/device-dev/Readme-CN.md-代码预览-docs:基于OpenHarmony生态的开发者文档项目 - AtomGit | GitCode。
补充说明
确保所有依赖库安装正常
推荐使用全新的 WSL2 开发环境。
如果根据终端提示无法解决编译错误,此时重新安装 WSL2 可能是一个有效的解决办法。
确保下载的代码完整
可运行脚本章节代码sync-resumable.py
重新执行命令获取详细错误信息
例如,你执行的编译命令是./build.sh --product-name rk3568,则输出目录为out/rk3568。
在out/rk3568目录中,你可以按照图片红框中的提示执行/usr/bin/ccache xxx命令,查看更具体的错误信息以帮助定位问题。
你也可以在out/rk3568/error.log文件中查看详细错误日志。
脚本
sync-resumable.py
#!/usr/bin/env python3importosimportsysimporttimeimportsignalimportsubprocessfromdatetimeimportdatetime# ====================== 【可注册的Git全局配置项】 ======================# 想关闭某条,直接注释掉该行即可;应用/回滚/信号中断回滚全部复用此列表GIT_CONFIG_LIST=[("http.postBuffer","524288000"),("http.lowSpeedLimit","1000"),("http.lowSpeedTime","300"),("core.compression","0"),("filter.lfs.smudge","git-lfs smudge --skip -- %f"),("filter.lfs.process","git-lfs filter-process --skip"),("filter.lfs.required","false"),]# 文件路径配置COMPLETED_FILE="completed_repos.txt"LOG_FILE="sync-resumable.log"BACKUP_FILE=os.path.join(os.path.expanduser("~"),f"gitconfig.backup.{datetime.now().strftime('%Y%m%d_%H%M%S')}")# 全局标记:是否已经回滚git配置,防止信号多次触发重复unset_git_config_restored=False# ======================================================================defwrite_log(msg:str):"""同时打印控制台 + 写入日志文件,模拟tee -a"""print(msg)withopen(LOG_FILE,"a",encoding="utf-8")asf:f.write(msg+"\n")defrun_cmd(cmd_list,capture_output=False):"""执行命令,返回 (returncode, stdout, stderr)"""ifcapture_output:proc=subprocess.Popen(cmd_list,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)out,err=proc.communicate()returnproc.returncode,out,errelse:# 直接继承stdout/stderr,实时打印proc=subprocess.Popen(cmd_list)proc.wait()returnproc.returncode,"",""defgit_apply_config():"""应用GIT_CONFIG_LIST内所有全局配置"""forkey,valinGIT_CONFIG_LIST:run_cmd(["git","config","--global",key,val])defgit_rollback_config():"""回滚:unset注册列表里的所有key;防重复执行"""global_git_config_restoredif_git_config_restored:return_git_config_restored=Trueforkey,_inGIT_CONFIG_LIST:run_cmd(["git","config","--global","--unset",key])defsignal_handler(sig,frame):"""Ctrl+C SIGINT信号处理器,替代bash trap INT"""write_log("\n检测到中断,正在恢复配置...")git_rollback_config()write_log("✓ 已恢复默认配置")sys.exit(130)defget_completed_set():"""读取已完成仓库集合"""s=set()ifos.path.exists(COMPLETED_FILE):withopen(COMPLETED_FILE,"r",encoding="utf-8")asf:forlineinf:line=line.strip()ifline:s.add(line)returnsdefmain():# 注册Ctrl+C信号signal.signal(signal.SIGINT,signal_handler)write_log("="*42)write_log(" OpenHarmony 断点续传同步脚本")write_log("="*42)# 备份 .gitconfiggitconfig_path=os.path.join(os.path.expanduser("~"),".gitconfig")ifos.path.exists(gitconfig_path):importshutil shutil.copy2(gitconfig_path,BACKUP_FILE)write_log("✓ 已应用全局优化配置")write_log(f"✓ 配置备份:{BACKUP_FILE}")write_log("")git_apply_config()# 打印当前生效配置信息write_log("当前配置:")fork,vinGIT_CONFIG_LIST:write_log(f"{k}={v}")write_log("="*42)write_log("")# 初始化完成记录文件ifnotos.path.exists(COMPLETED_FILE):open(COMPLETED_FILE,"a").close()write_log(f"✓ 创建完成记录文件:{COMPLETED_FILE}")completed_set=get_completed_set()completed_count=len(completed_set)ifcompleted_count>0:write_log(f"✓ 发现已完成仓库:{completed_count}个")write_log("")# 获取repo list,解析出repo名称(原 awk -F' : ' '{print $2}')write_log("正在获取仓库列表...")ret,repo_list_out,_=run_cmd(["repo","list"],capture_output=True)ifret!=0:write_log("ERROR: repo list 执行失败,请确认当前是repo根目录")git_rollback_config()sys.exit(1)all_repos=[]forlineinrepo_list_out.splitlines():parts=line.split(" : ")iflen(parts)>=2:repo_name=parts[1].strip()all_repos.append(repo_name)total=len(all_repos)current=0success_count=0fail_count=0skip_count=0write_log("="*42)write_log(f"开始同步,共{total}个仓库")write_log("="*42)write_log("")forrepo_nameinall_repos:current+=1ifrepo_nameincompleted_set:skip_count+=1continuewrite_log("="*42)write_log(f"[{current}/{total}] 处理:{repo_name}")write_log(f"↓ 同步中:{repo_name}")# repo sync -j1 --no-tags --force-sync repo_namesync_cmd=["repo","sync","-j","1","--no-tags","--force-sync",repo_name]retcode,_,_=run_cmd(sync_cmd)ifretcode==0:# 写入完成记录withopen(COMPLETED_FILE,"a",encoding="utf-8")asf:f.write(repo_name+"\n")write_log(f"✅ 完成:{repo_name}")success_count+=1else:write_log(f"⚠️ 失败:{repo_name}(下次会重试)")fail_count+=1time.sleep(3)# 全部同步完执行 repo forall -c 'git lfs pull'write_log("\n执行 repo forall git lfs pull ...")run_cmd(["repo","forall","-c","git lfs pull"])write_log("")write_log("="*42)write_log("同步完成!")write_log("="*42)write_log(f"总计:{total}个")write_log(f"成功:{success_count}个")write_log(f"跳过:{skip_count}个")write_log(f"失败:{fail_count}个")write_log("")write_log(f"日志文件:{LOG_FILE}")write_log(f"完成记录:{COMPLETED_FILE}")write_log(f"配置备份:{BACKUP_FILE}")write_log("")iffail_count>0:write_log("提示: 再次运行此脚本将重试失败的仓库")write_log("="*42)write_log("恢复默认 Git 配置...")git_rollback_config()write_log("✓ 已恢复默认配置")write_log("="*42)if__name__=="__main__":main()