1# 产品 2### 产品配置规则 3 4产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、部件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为:**vendor/{产品解决方案厂商}/{产品名称}**_。 5 6产品解决方案的目录树规则如下: 7 8```shell 9vendor 10└── company # 产品解决方案厂商 11 ├── product # 产品名称 12 │ ├── init_configs 13 │ │ ├── etc # init进程启动配置(可选,仅linux内核需要) 14 │ │ └── init.cfg # 系统服务启动配置 15 │ ├── hals # 产品解决方案OS适配 16 │ ├── BUILD.gn # 产品编译脚本 17 │ └── config.json # 产品配置文件 18 │ └── fs.yml # 文件系统打包配置 19 └── ...... 20``` 21 22> ![icon-note.gif](public_sys-resources/icon-note.gif)**注意**:新增产品须按如上的规则创建目录和文件,编译构建系统将按该规则扫描已配置的产品。 23 24关键的目录和文件详细介绍如下: 25 261. **vendor/company/product/init_configs/etc** 该文件夹中包含rcS脚本,Sxxx脚本和fstab脚本。init进程在启动系统服务之前执行这些脚本。执行的流程为“rcS->fstab->S00-xxx“。Sxxx脚本中的内容与开发板和产品需要有关,主要包括设备节点的创建、创建目录、扫描设备节点、修改文件权限等等。这些文件在产品编译的BUILD.gn中按需拷贝到产品out目录中,最终打包到rootfs镜像中。 27 282. **vendor/company/product/init_configs/init.cfg** init进程启动服务的配置文件,当前支持解析的命令有: 29 30 - start: 启动某个服务 31 32 - mkdir: 创建文件夹 33 34 - chmod: 修改指定路径/文件的权限 35 36 - chown: 修改指定路径/文件的属组 37 38 - mount: 挂载命令 39 40 该文件中的各个字段的解释如下: 41 42 ```shell 43 { 44 "jobs" : [{ # job数组,一个job对应一个命令集合。job的执行顺序:pre-init -> init -> post-init。 45 "name" : "pre-init", 46 "cmds" : [ 47 "mkdir /storage/data", # 创建目录 48 "chmod 0755 /storage/data", # 修改权限,权限值的格式为0xxx, 如0755 49 "mkdir /storage/data/log", 50 "chmod 0755 /storage/data/log", 51 "chown 4 4 /storage/data/log", # 修改属组,第一个数字为uid, 第二个数字为gid 52 ...... 53 "mount vfat /dev/mmcblock0 /sdcard rw,umask=000" # 挂载,格式为: mount [文件系统类型] [source] [target] [flags] [data] 54 # 其中flags仅支持:nodev、noexec、nosuid和rdonly 55 ] 56 }, { 57 "name" : "init", 58 "cmds" : [ # 按cmds数组顺序启动启动服务 59 "start shell", # 注意:start与服务名称之间有且只有一个空格 60 ...... 61 "start service1" 62 ] 63 }, { 64 "name" : "post-init", # 最后执行的job, init进程启动完成后的处理(如驱动初始化后再mount设备) 65 "cmds" : [] 66 } 67 ], 68 "services" : [{ # service数组,一个service对应一个进程 69 "name" : "shell", # 服务名称 70 "path" : ["/sbin/getty", "-n", "-l", "/bin/sh", "-L", "115200", "ttyS000", "vt100"], # 可执行文件全路径,path必须为第一个元素 71 "uid" : 0, # 进程的uid,须与二进制文件的uid保持一致 72 "gid" : 0, # 进程的gid,须与二进制文件的gid保持一致 73 "once" : 0, # 是否为一次性进程,1:进程退出后,init不在重新拉起。0:常驻进程,进程若退出,init将重新拉起 74 "importance" : 0, # 是否为关键进程,1:是关键进程,若进程退出,init将会重启单板。0:非关键进程,若进程退出,init不会重启单板 75 "caps" : [4294967295] 76 }, 77 ...... 78 ] 79 } 80 ``` 81 823. **vendor/company/product/init_configs/hals** 解决方案厂商对OS的适配,需要实现的接口请见各个部件的readme说明文档。 83 844. **vendor/company/product/config.json** config.json为编译构建的主入口,包含了开发板、OS部件和内核等配置信息。 85 86 以基于hispark_taurus开发板的ipcamera产品为例,配置文件如下: 87 88 ```shell 89 { 90 "product_name": "ipcamera", # 产品名称 91 "version": "3.0", # config.json的版本号, 固定"3.0" 92 "type": "small", # 系统类型, 可选[mini, small, standard] 93 "ohos_version": "OpenHarmony 1.0", # 选择的OS版本 94 "device_company": "hisilicon", # 芯片厂商 95 "board": "hispark_taurus", # 开发板名称 96 "kernel_type": "liteos_a", # 选择的内核类型 97 "kernel_version": "3.0.0", # 选择的内核版本 98 "subsystems": [ 99 { 100 "subsystem": "aafwk", # 选择的子系统 101 "components": [ 102 { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # 选择的部件和部件特性配置 103 ] 104 }, 105 { 106 ...... 107 } 108 ...... 109 更多子系统和部件 110 } 111 } 112 ``` 113 1145. **vendor/company/product/fs.yml** 该文件用于配置文件系统镜像制作过程,将编译产物打包成文件系统镜像,比如用户态根文件系统rootfs.img和可读写的userfs.img。它由多个列表组成,每个列表对应一个文件系统。字段说明如下: 115 116 ```shell 117 fs_dir_name: 必填,声明文件系统文件名, 如rootfs、userfs 118 fs_dirs: 选填,配置out下文件目录与文件系统文件目录的映射关系,每个文件目录对应一个列表 119 source_dir: 选填,out下目标文件目录,若缺失则将根据target_dir在文件系统下创建空目录 120 target_dir: 必填,文件系统下对应文件目录 121 ignore_files:选填,声明拷贝忽略文件 122 dir_mode: 选填,文件目录权限,默认755 123 file_mode: 选填,该文件目录下所有文件的权限,默认555 124 fs_filemode: 选填,配置需要特殊声明权限的文件,每个文件对应一个列表 125 file_dir: 必填,文件系统下具体文件路径 126 file_mode: 必填,文件权限声明 127 fs_symlink: 选填,配置文件系统软连接 128 fs_make_cmd: 必填,配置需要制作文件系统脚本,OS提供的脚本在build/lite/make_rootfs下, 支持linux,liteos内核和ext4、jffs2、vfat格式。也支持芯片解决方案厂商自定义。 129 fs_attr: 选填,根据配置项动态调整文件系统 130 ``` 131 132 其中fs_symlink、fs_make_cmd字段支持以下变量: 133 134 - rootpath代码根目录,对应gn的{ohos_root_path} 135 - outpath产品out目录,对应gn的{root_out_dir} 136 - ${fs_dir} 文件系统目录,由以下变量拼接而成 137 - ${root_path} 138 - ${fs_dir_name} 139 140> ![icon-note.gif](public_sys-resources/icon-note.gif)**注意**:fs.yml是可选的,对于没有文件系统的设备可不配置。 141 1426. **vendor/company/product/BUILD.gn** 产品编译的入口,主要用于编译解决方案厂商源码和拷贝启动配置文件。如果某个产品被选择为要编译的产品,那么对应产品目录下的BUILD.gn会默认编译。一个典型的产品编译BUILD.gn应该如下: 143 144 ```shell 145 group("product") { # target名称需与product名称即三级目录名称一致 146 deps = [] 147 deps += [ "init_configs" ] # 拷贝init配置 148 ...... # 其他 149 } 150 ``` 151 152### 新增并编译产品 153 154编译构建支持芯片解决方案和部件的灵活拼装,形成定制化的产品解决方案。具体步骤如下: 155 1561. 创建产品目录 按照产品配置规则创建产品目录,以基于“rtl8720“开发板的wifiiot模组为例,在代码根目录执行: 157 158 ```shell 159 mkdir -p vendor/my_company/wifiiot 160 ``` 161 1622. 拼装产品 在新建的产品目录下新建config.json文件,以步骤1中的wifiiot为例,vendor/my_company/wifiiot/config.json可以是: 163 164 ```shell 165 { 166 "product_name": "wifiiot", # 产品名称 167 "version": "3.0", # config.json的版本号, 固定"3.0" 168 "type": "small", # 系统类型, 可选[mini, small, standard] 169 "ohos_version": "OpenHarmony 1.0", # 使用的OS版本 170 "device_company": "realtek", # 芯片解决方案厂商名称 171 "board": "rtl8720", # 开发板名称 172 "kernel_type": "liteos_m", # 选择的内核类型 173 "kernel_version": "3.0.0", # 选择的内核版本 174 "subsystems": [ 175 { 176 "subsystem": "kernel", # 选择的子系统 177 "components": [ 178 { "component": "liteos_m", "features":[] } # 选择的部件和部件特性 179 ] 180 }, 181 ... 182 { 183 更多子系统和部件 184 } 185 ] 186 } 187 ``` 188 189 ![icon-note.gif](public_sys-resources/icon-note.gif)**注意**:编译构建系统编译前会对device_company,board,kernel_type,kernel_version、subsystem、component字段进行有效性检查,其中device_company,board,kernel_type,kernel_version应与已知的芯片解决方案匹配,subsystem、component应与build/lite/components下的部件描述匹配。 190 1913. 适配OS接口 在产品目录下创建hals目录,并将产品解决方案对OS适配的源码和编译脚本放入该目录下。 192 1934. 配置系统服务 在产品目录下创建init_configs目录,并在init_configs目录下创建init.cfg文件,按需配置要启动的系统服务。 194 1955. 配置init进程(仅linux内核需要) 在init_configs目录下创建etc目录,然后在etc下创建init.d文件夹和fstab文件。最后按产品需求在init.d文件下创建并编辑rcS文件和Sxxx文件。 196 1976. 配置文件系统镜像(可选,仅支持文件系统的开发板需要) 在产品目录下创建fs.yml文件。fs.yml需按产品实际情况配置,一个典型的fs.yml文件如下: 198 199 ```shell 200 - 201 fs_dir_name: rootfs # 镜像的名称 202 fs_dirs: 203 - 204 # 将编译生成的out/my_board/my_product/bin目录下的文件拷贝到rootfs/bin中,并忽略测试bin 205 source_dir: bin 206 target_dir: bin 207 ignore_files: 208 - Test.bin 209 - TestSuite.bin 210 - 211 # 将编译生成的out/my_board/my_product/libs目录下的文件拷贝到rootfs/lib中,忽略所有.a文件,并设置文件和文件夹的权限为644和755 212 source_dir: libs 213 target_dir: lib 214 ignore_files: 215 - .a 216 dir_mode: 755 217 file_mode: 644 218 - 219 source_dir: usr/lib 220 target_dir: usr/lib 221 ignore_files: 222 - .a 223 dir_mode: 755 224 file_mode: 644 225 - 226 source_dir: config 227 target_dir: etc 228 - 229 source_dir: system 230 target_dir: system 231 - 232 source_dir: sbin 233 target_dir: sbin 234 - 235 source_dir: usr/bin 236 target_dir: usr/bin 237 - 238 source_dir: usr/sbin 239 target_dir: usr/sbin 240 - 241 # 创建一个proc空目录 242 target_dir: proc 243 - 244 target_dir: mnt 245 - 246 target_dir: opt 247 - 248 target_dir: tmp 249 - 250 target_dir: var 251 - 252 target_dir: sys 253 - 254 source_dir: etc 255 target_dir: etc 256 - 257 source_dir: vendor 258 target_dir: vendor 259 - 260 target_dir: storage 261 262 fs_filemode: 263 - 264 file_dir: lib/ld-uClibc-0.9.33.2.so 265 file_mode: 555 266 - 267 file_dir: lib/ld-2.24.so 268 file_mode: 555 269 - 270 file_dir: etc/init.cfg 271 file_mode: 400 272 fs_symlink: 273 - 274 # 在rootfs/lib下创建软连接ld-musl-arm.so.1 -> libc.so 275 source: libc.so 276 link_name: ${fs_dir}/lib/ld-musl-arm.so.1 277 - 278 source: mksh 279 link_name: ${fs_dir}/bin/sh 280 - 281 source: mksh 282 link_name: ${fs_dir}/bin/shell 283 fs_make_cmd: 284 # 使用脚本将rootfs制作为ext4格式的image 285 - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 286 - 287 fs_dir_name: userfs 288 fs_dirs: 289 - 290 source_dir: storage/etc 291 target_dir: etc 292 - 293 source_dir: data 294 target_dir: data 295 fs_make_cmd: 296 - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 297 ``` 298 2997. 配置产品Patch(可选,视产品涉及部件是否需要打补丁而定) 在产品目录下创建patch.yml文件。patch.yml需按产品实际情况配置,一个典型的patch.yml文件如下: 300 301 ```shell 302 # 需要打patch的路径 303 foundation/communication/dsoftbus: 304 # 该路径下需要打的patch存放路径 305 - foundation/communication/dsoftbus/1.patch 306 - foundation/communication/dsoftbus/2.patch 307 third_party/wpa_supplicant: 308 - third_party/wpa_supplicant/1.patch 309 - third_party/wpa_supplicant/2.patch 310 - third_party/wpa_supplicant/3.patch 311 ... 312 ``` 313 314 配置完成后,编译时增加--patch参数,即可在产品编译前将配置的Patch文件打到对应目录中,再进行编译: 315 316 ```shell 317 hb build -f --patch 318 ``` 319 3208. 编写编译脚本 在产品目录下创建BUILD.gn文件,按产品实际情况编写脚本。以步骤1中的wifiiot为例,BUILD.gn示例如下: 321 322 ```shell 323 group("wifiiot") { # target名称与产品名一致 324 deps = [] 325 deps += [ "init_configs" ] # 拷贝init配置 326 deps += [ "hals" ] # 将hals加入编译 327 ...... # 其他 328 } 329 ``` 330 3319. 编译产品。 主要有两种编译方式,[命令行方式和hb方式](subsys-build-all.md#编译命令),这里以命令行方式为例,假设编译的产品名是hispark_taurus_standard,则编译命令是: 332 333 ``` 334 ./build.sh --product-name hispark_taurus_standard --ccache 335 ``` 336 337 338