Files
phs_v1.0.1.0/build/docs/cmake转gn指导文档.md
2024-09-27 19:16:49 +08:00

331 lines
9.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# cmake转gn指导
## 概述
本文档介绍GN构建工具在OpenHarmony中的常见使用方法指导三方库由cmake构建到GN构建的转换。
## GN常用的内置变量
| 名称 | 描述 |
|-------------------|---------------|
| current_cpu | 当前工具链的处理器架构 |
| current_os | 当前工具链的操作系统类型 |
| current_toolchain | 表示当前使用的工具链 |
| default_toolchain | 表示默认使用的工具链 |
| target_cpu | 表示目标平台的CPU类型 |
| target_os | 表示目标平台的操作系统类型 |
| root_build_dir | 表示根目录的构建目录 |
| root_gen_dir | 表示根目录的生成目录 |
| root_out_dir | 表示根目录的输出目录 |
| target_out_dir | 表示目标文件的输出目录 |
| target_gen_dir | 表示中间文件的生成目录 |
| defines | 表示当前目标的预定义宏列表 |
| include_dirs | 表示当前目标的头文件搜索路径列表 |
| cflags | 表示当前目标的C语言编译选项列表 |
| cxxflags | 表示当前目标的C++语言编译选项列表 |
| ldflags | 表示当前目标的链接选项列表 |
| asmflags | 表示当前目标的汇编语言编译选项列表 |
| libs | 表示当前目标依赖的库文件列表 |
## GN常用的内置函数
| 名称 | 描述 |
|------|-----|
| assert() | 断言函数,如果条件不成立,则会抛出一个异常 |
| defined() | 判断变量是否已经定义 |
| exec_script() | 执行一个Python脚本 |
| get_label_info() | 获取标签信息,例如标签的名称、路径、类型等等 |
| get_path_info() | 获取路径信息,例如路径是否存在、是否是目录、是否是文件等等 |
| group() | 将一组目标文件组合成一个库文件 |
| import() | 导入其他GN构建文件 |
| read_file() | 读取文件内容 |
| read_json() | 读取JSON格式的文件 |
| read_path() | 读取路径中的内容,返回一个字符串列表 |
| rebase_path() | 重新定位路径,将路径中的某个部分替换为新的值 |
| write_file() | 写入文件内容 |
| template() | 处理字符串模板,将模板中的变量替换为实际的值,其功能类似与函数 |
| action() | 定义一个自定义的构建动作通过action调用python脚本完成期望动作 |
| action_foreach() | 针对每个元素执行一个自定义的构建动作 |
| executable() | 定义一个可执行文件 |
| shared_library() | 定义一个动态库 |
| static_library() | 定义一个静态库 |
## 如何使用GN进行构建
当将一个基于CMake的项目转换为使用GN进行构建时需要了解如何指定动态库、静态库和可执行文件的构建规则。以下是一个简单的指南介绍如何在GN中指定这些构建规则
- **动态库**
在CMake中可以使用add_library命令来指定动态库的构建规则。例如
```
add_library(mylib SHARED
src/foo.cpp
src/bar.cpp
)
```
在GN中可以使用shared_library模板来指定动态库的构建规则创建BUILD.gn文件内容如下
```
# 指定动态库名称
mylib_name = "mylib"
# 指定动态库源文件
mylib_sources = [
"src/foo.cpp",
"src/bar.cpp",
]
# 指定动态库编译选项和链接选项
mylib_cflags = [
"-Wall",
]
mylib_ldflags = [
"-L/usr/local/lib",
]
# 指定动态库构建规则
shared_library(mylib_name) {
sources = mylib_sources
cflags = mylib_cflags
ldflags = mylib_ldflags
}
```
- **静态库**
在CMake中可以使用add_library命令来指定静态库的构建规则。例如
```
add_library(mylib STATIC
src/foo.cpp
src/bar.cpp
)
```
在GN中可以使用static_library模板来指定静态库的构建规则创建BUILD.gn文件内容如下
```
# 指定静态库名称
mylib_name = "mylib"
# 指定静态库源文件
mylib_sources = [
"src/foo.cpp",
"src/bar.cpp",
]
# 指定静态库编译选项
mylib_cflags = [
"-Wall",
]
# 指定静态库构建规则
static_library(mylib_name) {
sources = mylib_sources
cflags = mylib_cflags
}
```
- **可执行文件**
在CMake中可以使用add_executable命令来指定可执行文件的构建规则。例如
```
add_executable(myapp
src/main.cpp
)
```
在GN中可以使用executable模板来指定可执行文件的构建规则。例如
```
# 指定可执行文件名称
myapp_name = "myapp"
# 指定可执行文件源文件
myapp_sources = [
"src/main.cpp",
]
# 指定可执行文件编译选项和链接选项
myapp_cflags = [
"-Wall",
]
myapp_ldflags = [
"-L/usr/local/lib",
]
# 指定可执行文件构建规则
executable(myapp_name) {
sources = myapp_sources
cflags = myapp_cflags
ldflags = myapp_ldflags
}
```
OpenHarmony在GN原生模板的基础上进行了功能扩展提供了ohos_shared_library、ohos_static_library、ohos_executable模板在BUILD.gn中import("//build/ohos.gni")即可使用ohos_shared_library示例如下
```
import("//build/ohos.gni")
ohos_shared_library("helloworld") {
sources = []
include_dirs = []
cflags = []
cflags_c = []
cflags_cc = []
ldflags = []
configs = []
deps = [] # 部件内模块依赖
# 跨部件模块依赖定义,
# 定义格式为 "部件名:模块名称"
# 这里依赖的模块必须是依赖的部件声明在inner_kits中的模块
external_deps = [
"part_name:module_name",
]
output_name = "" # 可选,模块输出名
output_extension = "" # 可选,模块名后缀
module_install_dir = "" # 可选,缺省在/system/lib64或/system/lib下 模块安装路径模块安装路径从system/vendor/后开始指定
relative_install_dir = "" # 可选,模块安装相对路径,相对于/system/lib64或/system/lib如果有module_install_dir配置时该配置不生效
install_images = [] # 可选缺省值system指定模块安装到那个分区镜像中可以指定多个
part_name = "" # 必选,所属部件名称
}
```
## 简单示例
假设我们有一个简单的CMake项目包含两个源文件main.cpp和hello.cpp以及一个头文件hello.h。CMakeLists.txt文件内容如下
```
cmake_minimum_required(VERSION 3.10)
project(hello)
add_executable(hello main.cpp hello.cpp hello.h)
```
目录结构如下:
```
hello/
├── include
│ └── hello.h
└── src
├── hello.cpp
└── main.cpp
```
以下介绍如何在OpenHarmony编译框架中使用GN编译上述示例
1. 在OpenHarmony代码中增加example目录将hello示例放在example目录下在hello目录下新建BUILD.gn文件示例如下
```
import("//build/ohos.gni")
config("hello_config") {
include_dirs = [ "./include" ]
}
ohos_shared_library("hello_so") {
configs = [ ":hello_config" ]
sources = [ "./src/hello.cpp" ]
part_name = "hello"
subsystem_name = "example"
}
ohos_executable("hello") {
deps = [ ":hello_so" ]
configs = [ ":hello_config" ]
sources = [ "./src/main.cpp" ]
part_name = "hello"
subsystem_name = "example"
}
```
2. 在example目录下新建bundle.json文件示例如下
```
{
"name": "@ohos/example",
"description": "",
"version": "3.1",
"license": "MIT",
"publishAs": "code-segment",
"segment": {
"destPath": ""
},
"dirs": {},
"scripts": {},
"licensePath": "COPYING",
"readmePath": {
"en": "README.rst"
},
"component": {
"name": "hello", # 部件名称
"subsystem": "example", # 部件所属子系统
"syscap": [],
"features": [],
"adapted_system_type": [],
"rom": "",
"ram": "",
"deps": {
"components": [],
"third_party": []
},
"build": {
"group_type": { # 部件编译入口,新增模块在此处配置
"base_group": [ "//example/hello:hello" ],
"fwk_group": [],
"service_group": []
},
"inner_kits": [],
"test": []
}
}
}
```
3.`vendor\产品厂商\产品名\config.json`中配置新增的example子系统和hello组件以rk3568为例示例如下
```
# 以rk3568为例
{
"product_name": "rk3568",
"device_company": "rockchip",
"device_build_path": "device/board/hihope/rk3568",
"target_cpu": "arm",
"type": "standard",
"version": "3.0",
"board": "rk3568",
"api_version": 8,
"enable_ramdisk": true,
"enable_absystem": false,
"build_selinux": true,
"build_seccomp": true,
"inherit": [ "productdefine/common/inherit/rich.json", "productdefine/common/inherit/chipset_common.json" ],
"subsystems": [
{
"subsystem": "example",
"components": [
{
"component": "hello",
"features": []
}
]
},
......
]
}
```
4. 在build/subsystem_config.json中增加新增的example子系统路径示例如下
```
{
"example": {
"path": "example",
"name": "example"
}
......
}
```
5. 执行编译命令以rk3568为例
```
./build.sh --product-name rk3568 -T hello
# build.sh是OpenHarmony编译入口脚本
# --product-name用于指定产品名
# -T指定编译目标单独编译
```
6. 编译产物生成在out/rk3568/example/hello目录下
```
out/rk3568/example/hello/
├── hello
└── libhello_so.z.so
```