概述
一个基于gn和ninja的构建系统,以支持OpenHarmony组件化开发为目标,提供以下基本功能:
- 支持按组件拼装产品并编译。
- 独立构建芯片解决方案厂商源码。
- 独立构建单个组件。
基本概念
在使用编译构建子系统前,应了解如下基本概念:
- 子系统
子系统是一个逻辑概念,它由一个或多个具体的组件组成。OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。 - 组件
系统最小的可复用、可配置、可裁剪的功能单元。组件具备目录独立可并行开发、可独立编译、可独立测试的特征。 - gn
Generate ninja的缩写,用于产生ninja文件。 - ninja
ninja是一个专注于速度的小型构建系统。 - hb
OpenHarmony的命令行工具,用来执行编译命令。
目录结构- ├── components # 组件描述文件
- ├── figure # readme中的图片
- ├── hb # hb pip安装包源码
- ├── make_rootfs # 文件系统镜像制作脚本
- ├── config # 编译配置项
- │ ├── component # 组件相关的模板定义
- │ ├── kernel # 内核相关的编译配置
- │ └── subsystem # 子系统编译配置
- ├── platform # ld脚本
- ├── testfwk # 测试编译框架
- └── toolchain # 编译工具链配置,包括:编译器路径、编译选项、链接选项等
复制代码
构建流程
编译构建流程如图1 所示,主要分设置和编译两步:
图 1 编译构建流程
- hb set: 设置OpenHarmony源码目录和要编译的产品。
- hb build: 编译产品、开发板或者组件。编译主要过程如下:
- 读取编译配置:根据产品选择的开发板,读取开发板config.gni文件内容,主要包括编译工具链、编译链接命令和选项等。
- 调用gn:调用gn gen命令,读取产品配置生成产品解决方案out目录和ninja文件。
- 调用ninja:调用ninja -C out/board/product启动编译。
- 系统镜像打包:将组件编译产物打包,设置文件属性和权限,制作文件系统镜像。
配置规则
为了实现芯片解决方案、产品解决方案与OpenHarmony是解耦的、可插拔的,组件、芯片解决方案和产品解决方案的路径、目录树和配置需遵循一定的规则,具体如下:
组件
组件源码路径命名规则为:
{领域}/{子系统}/{组件},组件目录树规则如下:
注意:组件的名称、源码路径、功能简介、是否必选、编译目标、RAM、ROM、编译输出、已适配的内核、可配置的特性和依赖等属性定义在build/lite/components目录下对应子系统的json文件中,新增组件时需要在对应子系统json文件中添加相应的组件定义。产品所配置的组件必须在某个子系统中被定义过,否则会校验失败。
- component
- ├── interfaces
- │ ├── innerkits # 系统内接口,组件间使用
- │ └── kits # 应用接口,应用开发者使用
- ├── frameworks # framework实现
- ├── services # service实现
- └── BUILD.gn # 组件编译脚本
复制代码以泛sensor子系统的sensor服务组件为例,组件属性定义描述文件字段说明如下:
- {
- "components": [
- {
- "component": "sensor_lite", # 组件名称
- "description": "Sensor services", # 组件一句话功能描述
- "optional": "true", # 组件是否为最小系统必选
- "dirs": [ # 组件源码路径
- "base/sensors/sensor_lite"
- ],
- "targets": [ # 组件编译入口
- "//base/sensors/sensor_lite/services:sensor_service"
- ],
- "rom": "92KB", # 组件ROM值
- "ram": "~200KB", # 组件RAM估值
- "output": [ "libsensor_frameworks.so" ], # 组件编译输出
- "adapted_kernel": [ "liteos_a" ], # 组件已适配的内核
- "features": [], # 组件可配置的特性
- "deps": {
- "components": [ # 组件依赖的其他组件
- "samgr_lite",
- "ipc_lite"
- ],
- "third_party": [ # 组件依赖的三方开源软件
- "bounds_checking_function"
- ]
- }
- }
- ]
- }
复制代码
组件BUILD.gn的编写建议如下:
- 编译目标名称与组件一致。
- 组件对外可配置的特性变量需声明在该组件BUILD.gn中,特性变量命名规则:ohos_{subsystem}_{component}_{feature}。特性在组件描述中也需要同步定义,在产品配置文件config.json中按需配置。
- 宏定义规则:OHOS_{SUBSYSTEM}_{COMPONENT}_{FEATURE}
说明:组件的编译脚本语言为gn,gn的基本用法请见https://gn.googlesource.com/gn/+/master/docs/quick_start.md。 组件即为gn定义的编译目标,可以为静态库、动态库、可执行文件或group。
以图形的UI组件为例,foundation/graphic/ui/BUILD.gn文件如下:
- # 声明组件可配置的特性
- declare_args() {
- enable_ohos_graphic_ui_animator = false # 动效特性开关
- ohos_ohos_graphic_ui_font = "vector" # 可配置的字体类型,vector或者bitmap
- }
-
- # 组件基础功能
- shared_library("base") {
- sources = [
- ......
- ]
- include_dirs = [
- ......
- ]
- }
-
- # 仅在animator开启时编译
- if(enable_ohos_graphic_ui_animator ) {
- shared_library("animator") {
- sources = [
- ......
- ]
- include_dirs = [
- ......
- ]
- deps = [ :base ]
- }
- }
- ......
- # target名称建议与组件名称一致, 组件target类型可以是executable(bin文件),shared_library(动态库.so),static_library(静态库.a),group等等
- executable("ui") {
- deps = [
- ":base"
- ]
- # animator特性由产品配置
- if(enable_ohos_graphic_ui_animator ) {
- deps += [
- "animator"
- ]
- }
- }
复制代码
芯片解决方案- 芯片解决方案是指基于某款开发板的完整解决方案,包含驱动、设备侧接口适配、开发板sdk等。
- 芯片解决方案是一个特殊的组件,源码路径规则为:device/{芯片解决方案厂商}/{开发板}。
- 芯片解决方案组件会随产品选择的开发板默认编译。
芯片解决方案目录树规则如下:
- device
- └── company # 芯片解决方案厂商
- └── board # 开发板名称
- ├── BUILD.gn # 编译脚本
- ├── hals # OS南向接口适配
- ├── linux # 可选,linux内核版本
- │ └── config.gni # linux版本编译配置
- └── liteos_a # 可选,liteos内核版本
- └── config.gni # liteos_a版本编译配置
复制代码
说明:config.gni为开发板编译相关的配置,编译时会采用该配置文件中的参数编译所有OS组件,编译阶段系统全局可见。
config.gni的关键字段介绍如下:
- kernel_type: 开发板使用的内核类型,例如:“liteos_a”, “liteos_m”, “linux”。
- kernel_version: 开发使用的内核版本,例如:“4.19”。
- board_cpu: 开发板CPU类型,例如:“cortex-a7”, “riscv32”。
- board_arch: 开发芯片arch, 例如: “armv7-a”, “rv32imac”。
- board_toolchain: 开发板自定义的编译工具链名称,例如:“gcc-arm-none-eabi”。若为空,则使用默认为ohos-clang。
- board_toolchain_prefix:编译工具链前缀,例如:“gcc-arm-none-eabi”。
- board_toolchain_type: 编译工具链类型,目前支持gcc和clang。例如:“gcc” ,“clang”。
- board_cflags: 开发板配置的c文件编译选项。
- board_cxx_flags: 开发板配置的cpp文件编译选项。
- board_ld_flags: 开发板配置的链接选项。
复制代码
产品解决方案产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、组件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为:
vendor/{产品解决方案厂商}/{产品名称}_。_产品解决方案也是一个特殊的组件。
产品解决方案的目录树规则如下:
- vendor
- └── company # 产品解决方案厂商
- ├── product # 产品名称
- │ ├── init_configs
- │ │ ├── etc # init进程启动配置(可选,仅linux内核需要)
- │ │ └── init.cfg # 系统服务启动配置
- │ ├── hals # 产品解决方案OS适配
- │ ├── BUILD.gn # 产品编译脚本
- │ └── config.json # 产品配置文件
- │ └── fs.yml # 文件系统打包配置
- └── ......
复制代码
注意:新增产品须按如上的规则创建目录和文件,编译构建系统将按该规则扫描已配置的产品。
关键的目录和文件详细介绍如下:
- vendor/company/product/init_configs/etc
该文件夹中包含rcS脚本,Sxxx脚本和fstab脚本。init进程在启动系统服务之前执行这些脚本。执行的流程为“rcS->fstab->S00-xxx“。Sxxx脚本中的内容与开发板和产品需要有关,主要包括设备节点的创建、创建目录、扫描设备节点、修改文件权限等等。这些文件在产品编译的BUILD.gn中按需拷贝到产品out目录中,最终打包到rootfs镜像中。 - vendor/company/product/init_configs/init.cfg
init进程启动服务的配置文件,当前支持解析的命令有:
- start: 启动某个服务
- mkdir: 创建文件夹
- chmod: 修改指定路径/文件的权限
- chown: 修改指定路径/文件的属组
- mount: 挂载命令
该文件中的各个字段的解释如下:
- {
- "jobs" : [{ # job数组,一个job对应一个命令集合。job的执行顺序:pre-init -> init -> post-init。
- "name" : "pre-init",
- "cmds" : [
- "mkdir /storage/data", # 创建目录
- "chmod 0755 /storage/data", # 修改权限,权限值的格式为0xxx, 如0755
- "mkdir /storage/data/log",
- "chmod 0755 /storage/data/log",
- "chown 4 4 /storage/data/log", # 修改属组,第一个数字为uid, 第二个数字为gid
- ......
- "mount vfat /dev/mmcblock0 /sdcard rw,umask=000" # 挂载,格式为: mount [文件系统类型] [source] [target] [flags] [data]
- # 其中flags仅支持:nodev、noexec、nosuid和rdonly
- ]
- }, {
- "name" : "init",
- "cmds" : [ # 按cmds数组顺序启动启动服务
- "start shell", # 注意:start与服务名称之间有且只有一个空格
- ......
- "start service1"
- ]
- }, {
- "name" : "post-init", # 最后执行的job, init进程启动完成后的处理(如驱动初始化后再mount设备)
- "cmds" : []
- }
- ],
- "services" : [{ # service数组,一个service对应一个进程
- "name" : "shell", # 服务名称
- "path" : ["/sbin/getty", "-n", "-l", "/bin/sh", "-L", "115200", "ttyS000", "vt100"], # 可执行文件全路径,path必须为第一个元素
- "uid" : 0, # 进程的uid,须与二进制文件的uid保持一致
- "gid" : 0, # 进程的gid,须与二进制文件的gid保持一致
- "once" : 0, # 是否为一次性进程,1:进程退出后,init不在重新拉起。0:常驻进程,进程若退出,init将重新拉起
- "importance" : 0, # 是否为关键进程,1:是关键进程,若进程退出,init将会重启单板。0:非关键进程,若进程退出,init不会重启单板
- "caps" : [4294967295]
- },
- ......
- ]
- }
- {
- "product_name": "ipcamera", # 产品名称
- "version": "3.0", # config.json的版本号, 固定"3.0"
- "type": "small", # 系统类型, 可选[mini, small, standard]
- "ohos_version": "OpenHarmony 1.0", # 选择的OS版本
- "device_company": "hisilicon", # 芯片厂商
- "board": "hispark_taurus", # 开发板名称
- "kernel_type": "liteos_a", # 选择的内核类型
- "kernel_version": "3.0.0", # 选择的内核版本
- "subsystems": [
- {
- "subsystem": "aafwk", # 选择的子系统
- "components": [
- { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # 选择的组件和组件特性配置
- ]
- },
- {
- ......
- }
- ......
- 更多子系统和组件
- }
- }
- fs_dir_name: 必填,声明文件系统文件名, 如rootfs、userfs
- fs_dirs: 选填,配置out下文件目录与文件系统文件目录的映射关系,每个文件目录对应一个列表
- source_dir: 选填,out下目标文件目录,若缺失则将根据target_dir在文件系统下创建空目录
- target_dir: 必填,文件系统下对应文件目录
- ignore_files:选填,声明拷贝忽略文件
- dir_mode: 选填,文件目录权限,默认755
- file_mode: 选填,该文件目录下所有文件的权限,默认555
- fs_filemode: 选填,配置需要特殊声明权限的文件,每个文件对应一个列表
- file_dir: 必填,文件系统下具体文件路径
- file_mode: 必填,文件权限声明
- fs_symlink: 选填,配置文件系统软连接
- fs_make_cmd: 必填,配置需要制作文件系统脚本,OS提供的脚本在build/lite/make_rootfs下, 支持linux,liteos内核和ext4、jffs2、vfat格式。也支持芯片解决方案厂商自定义。
- fs_attr: 选填,根据配置项动态调整文件系统
- group("product") { # target名称需与product名称即三级目录名称一致
- deps = []
- # 拷贝init配置
- deps += [ "init_configs" ]
- # 其他
- ......
- }
复制代码
使用指导前提条件开发环境需安装gn、ninja构建工具、python 3.7.4及以上和hb。安装方法请见搭建系统基础环境。
hb工具使用说明hb是OpenHarmony的命令行工具,用来执行编译命令。以下对hb的常用命令进行说明。
hb set
- hb set -h
- usage: hb set [-h] [-root [ROOT_PATH]] [-p]
- optional arguments:
- -h, --help show this help message and exit
- -root [ROOT_PATH], --root_path [ROOT_PATH]
- Set OHOS root path
- -p, --product Set OHOS board and kernel
复制代码
- hb set 后无参数,进入默认设置流程
- hb set -root dir可直接设置代码根目录
- hb set -p设置要编译的产品
hb env
查看当前设置信息
- hb env
- [OHOS INFO] root path: xxx
- [OHOS INFO] board: hispark_taurus
- [OHOS INFO] kernel: liteos
- [OHOS INFO] product: ipcamera
- [OHOS INFO] product path: xxx/vendor/hisilicon/ipcamera
- [OHOS INFO] device path: xxx/device/hisilicon/hispark_taurus/sdk_linux_4.19
复制代码
hb build
- hb build -h
- usage: hb build [-h] [-b BUILD_TYPE] [-c COMPILER] [-t [TEST [TEST ...]]]
- [--dmverity] [--tee] [-p PRODUCT] [-f] [-n]
- [-T [TARGET [TARGET ...]]] [-v] [-shs] [--patch]
- [component [component ...]]
- positional arguments:
- component name of the component
- optional arguments:
- -h, --help show this help message and exit
- -b BUILD_TYPE, --build_type BUILD_TYPE
- release or debug version
- -c COMPILER, --compiler COMPILER
- specify compiler
- -t [TEST [TEST ...]], --test [TEST [TEST ...]]
- compile test suit
- --dmverity Enable dmverity
- --tee Enable tee
- -p PRODUCT, --product PRODUCT
- build a specified product with
- {product_name}@{company}, eg: camera@huawei
- -f, --full full code compilation
- -n, --ndk compile ndk
- -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]]
- Compile single target
- -v, --verbose show all command lines while building
- -shs, --sign_haps_by_server
- sign haps by server
- --patch apply product patch before compiling
- --dmverity Enable dmverity
- -p PRODUCT, --product PRODUCT
- build a specified product with
- {product_name}@{company}, eg: ipcamera@hisilcon
- -f, --full full code compilation
- -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]]
- Compile single target
复制代码
- hb build后无参数,会按照设置好的代码路径、产品进行编译,编译选项使用与之前保持一致。-f 选项将删除当前产品所有编译产品,等同于hb clean + hb build.
- hb build {component_name}:基于设置好的产品对应的单板、内核,单独编译组件(e.g.:hb build kv_store)。
- hb build -p ipcamera@hisilicon:免set编译产品,该命令可以跳过set步骤,直接编译产品。
- 在device/device_company/board下单独执行hb build会进入内核选择界面,选择完成后会根据当前路径的单板、选择的内核编译出仅包含内核、驱动的镜像。
hb clean
清除out目录对应产品的编译产物,仅保留args.gn、build.log。清除指定路径可输入路径参数:hb clean out/board/product,默认将清除当前hb set的产品对应out路径。
- hb clean
- usage: hb clean [-h] [out_path]
- positional arguments:
- out_path clean a specified path.
- optional arguments:
- -h, --help show this help message and exit
复制代码
新增组件
本小节介绍如何新增一个组件,首先确定组件归属的子系统和组件名称,然后按如下步骤新增:
- 源码开发完成后,添加组件编译脚本。
以编译组件hello_world可执行文件为例,applications/sample/hello_world/BUILD.gn可以写为:
- executable("hello_world") {
- include_dirs = [
- "include",
- ]
- sources = [
- "src/hello_world.c"
- ]
- }
复制代码
如上编译脚本,可编译出一个可在OpenHarmony上运行的名为hello_world的可执行文件。
单独编译该组件,hb set任意选择一款产品,然后使用-T选项单独编译组件:
- hb build -f -T //applications/sample/hello_world
- {
- "components": [
- {
- "component": "hello_world",
- "description": "Hello world.",
- "optional": "true",
- "dirs": [
- "applications/sample/hello_world"
- ],
- "targets": [
- "//applications/sample/hello_world"
- ]
- },
- ...
- ]
- }
- {
- "product_name": "hello_world_test",
- "ohos_version": "OpenHarmony 1.0",
- "device_company": "hisilicon",
- "board": "hispark_taurus",
- "kernel_type": "liteos_a",
- "kernel_version": "1.0.0",
- "subsystems": [
- {
- "subsystem": "applications",
- "components": [
- { "component": "hello_world", "features":[] }
- ]
- },
- ...
- ]
- }
复制代码
- 编译产品。
- 代码根目录输入hb set选择对应产品。
- 执行hb build。
新增芯片解决方案
编译构建支持添加新的芯片解决方案厂商,具体步骤如下:
- 创建芯片解决方案目录。
按照芯片解决方案配置规则创建目录,以芯片厂商realtek的“rtl8720“开发板为例, 在代码根目录执行:
- mkdir -p device/realtek/rtl8720
- # Kernel type, e.g. "linux", "liteos_a", "liteos_m".
- kernel_type = "liteos_a"
- # Kernel version.
- kernel_version = "3.0.0"
- # Board CPU type, e.g. "cortex-a7", "riscv32".
- board_cpu = "real-m300"
- # Board arch, e.g. "armv7-a", "rv32imac".
- board_arch = ""
- # Toolchain name used for system compiling.
- # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf.
- # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain.
- board_toolchain = "gcc-arm-none-eabi"
- # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc.
- board_toolchain_path =
- rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin",
- root_build_dir)
- # Compiler prefix.
- board_toolchain_prefix = "gcc-arm-none-eabi-"
- # Compiler type, "gcc" or "clang".
- board_toolchain_type = "gcc"
- # Board related common compile flags.
- board_cflags = []
- board_cxx_flags = []
- board_ld_flags = []
- group("rtl8720") { # target类型也可以shared_library, static_library, executable
- # 具体内容
- ......
- }
复制代码
- 编译芯片解决方案。
在开发板目录下执行hb build,即可启动芯片解决方案的编译。
新增产品解决方案
编译构建支持芯片解决方案和组件的灵活拼装,形成定制化的产品解决方案。具体步骤如下:
- 创建产品目录
按照产品解决方案配置规则创建产品目录,以基于“rtl8720“开发板的wifiiot模组为例,在代码根目录执行:
- mkdir -p vendor/my_company/wifiiot
- {
- "product_name": "wifiiot", # 产品名称
- "version": "3.0", # config.json的版本号, 固定"3.0"
- "type": "small", # 系统类型, 可选[mini, small, standard]
- "ohos_version": "OpenHarmony 1.0", # 使用的OS版本
- "device_company": "realtek", # 芯片解决方案厂商名称
- "board": "rtl8720", # 开发板名称
- "kernel_type": "liteos_m", # 选择的内核类型
- "kernel_version": "3.0.0", # 选择的内核版本
- "subsystems": [
- {
- "subsystem": "kernel", # 选择的子系统
- "components": [
- { "component": "liteos_m", "features":[] } # 选择的组件和组件特性
- ]
- },
- ...
- {
- 更多子系统和组件
- }
- ]
- }
- -
- fs_dir_name: rootfs # 镜像的名称
- fs_dirs:
- -
- # 将编译生成的out/my_board/my_product/bin目录下的文件拷贝到rootfs/bin中,并忽略测试bin
- source_dir: bin
- target_dir: bin
- ignore_files:
- - Test.bin
- - TestSuite.bin
- -
- # 将编译生成的out/my_board/my_product/libs目录下的文件拷贝到rootfs/lib中,忽略所有.a文件,并设置文件和文件夹的权限为644和755
- source_dir: libs
- target_dir: lib
- ignore_files:
- - .a
- dir_mode: 755
- file_mode: 644
- -
- source_dir: usr/lib
- target_dir: usr/lib
- ignore_files:
- - .a
- dir_mode: 755
- file_mode: 644
- -
- source_dir: config
- target_dir: etc
- -
- source_dir: system
- target_dir: system
- -
- source_dir: sbin
- target_dir: sbin
- -
- source_dir: usr/bin
- target_dir: usr/bin
- -
- source_dir: usr/sbin
- target_dir: usr/sbin
- -
- # 创建一个proc空目录
- target_dir: proc
- -
- target_dir: mnt
- -
- target_dir: opt
- -
- target_dir: tmp
- -
- target_dir: var
- -
- target_dir: sys
- -
- source_dir: etc
- target_dir: etc
- -
- source_dir: vendor
- target_dir: vendor
- -
- target_dir: storage
- fs_filemode:
- -
- file_dir: lib/ld-uClibc-0.9.33.2.so
- file_mode: 555
- -
- file_dir: lib/ld-2.24.so
- file_mode: 555
- -
- file_dir: etc/init.cfg
- file_mode: 400
- fs_symlink:
- -
- # 在rootfs/lib下创建软连接ld-musl-arm.so.1 -> libc.so
- source: libc.so
- link_name: ${fs_dir}/lib/ld-musl-arm.so.1
- -
- source: mksh
- link_name: ${fs_dir}/bin/sh
- -
- source: mksh
- link_name: ${fs_dir}/bin/shell
- fs_make_cmd:
- # 使用脚本将rootfs制作为ext4格式的image
- - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4
- -
- fs_dir_name: userfs
- fs_dirs:
- -
- source_dir: storage/etc
- target_dir: etc
- -
- source_dir: data
- target_dir: data
- fs_make_cmd:
- - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4
- # 需要打patch的路径
- foundation/communication/dsoftbus:
- # 该路径下需要打的patch存放路径
- - foundation/communication/dsoftbus/1.patch
- - foundation/communication/dsoftbus/2.patch
- third_party/wpa_supplicant:
- - third_party/wpa_supplicant/1.patch
- - third_party/wpa_supplicant/2.patch
- - third_party/wpa_supplicant/3.patch
- ...
复制代码
配置完成后,编译时增加–patch参数,即可在产品编译前将配置的Patch文件打到对应目录中,再进行编译:
- hb build -f --patch
- group("wifiiot") { # target名称与产品名一致
- deps = []
- # 拷贝init配置
- deps += [ "init_configs" ]
- # 将hals加入编译
- deps += [ "hals" ]
- # 其他
- ......
- }
复制代码
- 编译产品。
在代码根目录执行hb set按提示选择新增的产品,然后执行hb build即可启动编译。
常见问题编译构建过程中,提示“usr/sbin/ninja: invalid option – w”- 现象描述:
编译失败,提示“usr/sbin/ninja: invalid option – w”。 - 可能原因:
编译环境中ninja版本太低,不支持–w选项。 - 解决办法:
卸载环境中ninja和gn,按照获取工具。
编译构建过程中,提示“/usr/bin/ld: cannot find -lncurses”- 现象描述:
编译失败,提示“/usr/bin/ld: cannot find -lncurses”。 - 可能原因:
编译环境ncurses库缺失。 - 解决办法:
- sudo apt-get install lib32ncurses5-dev
复制代码 编译构建过程中,提示“line 77: mcopy: command not found”- 现象描述:
编译失败,提示“line 77: mcopy: command not found”。 - 可能原因:
编译环境未安装mcopy。 - 解决办法:
- sudo apt-get install dosfstools mtools
复制代码 编译构建过程中,提示“riscv32-unknown-elf-gcc: error trying to exec ‘cc1’: execvp: No such file or directory”- 现象描述:
编译失败,提示“riscv32-unknown-elf-gcc: error trying to exec ‘cc1’: execvp: No such file or directory”。 - 可能原因:
当前用户对riscv编译器路径下的文件访问权限不够。 - 解决办法:
查询gcc_riscv32所在目录。
- which riscv32-unknown-elf-gcc
复制代码 编译构建过程中,提示“No module named ‘Crypto’”- 现象描述:
编译失败,提示“No module named ‘Crypto’”。 - 可能原因:
python3未安装Crypto。 - 解决办法:
python3 --versionsudo pip3 install pycryptodome
- sudo pip3 install pycryptodome
编译构建过程中,提示“xx.sh : xx unexpected operator”- 现象描述:
编译失败:“xx.sh [: xx unexpected operator”。 - 可能原因:
编译环境shell不是bash。 - 解决办法:
- sudo rm -rf /bin/sh
- sudo ln -s /bin/bash /bin/sh
复制代码