• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# cmake转gn指导
2
3## 概述
4本文档介绍GN构建工具在OpenHarmony中的常见使用方法,指导三方库由cmake构建到GN构建的转换。
5
6## GN常用的内置变量
7| 名称                | 描述            |
8|-------------------|---------------|
9| current_cpu       | 当前工具链的处理器架构   |
10| current_os        | 当前工具链的操作系统类型 |
11| current_toolchain | 表示当前使用的工具链    |
12| default_toolchain | 表示默认使用的工具链    |
13| target_cpu        | 表示目标平台的CPU类型  |
14| target_os         | 表示目标平台的操作系统类型 |
15| root_build_dir    | 表示根目录的构建目录    |
16| root_gen_dir      | 表示根目录的生成目录    |
17| root_out_dir      | 表示根目录的输出目录    |
18| target_out_dir    | 表示目标文件的输出目录 |
19| target_gen_dir    | 表示中间文件的生成目录 |
20| defines | 表示当前目标的预定义宏列表 |
21| include_dirs | 表示当前目标的头文件搜索路径列表 |
22| cflags | 表示当前目标的C语言编译选项列表 |
23| cxxflags | 表示当前目标的C++语言编译选项列表 |
24| ldflags | 表示当前目标的链接选项列表 |
25| asmflags | 表示当前目标的汇编语言编译选项列表 |
26| libs | 表示当前目标依赖的库文件列表 |
27
28## GN常用的内置函数
29| 名称 | 描述 |
30|------|-----|
31| assert() | 断言函数,如果条件不成立,则会抛出一个异常 |
32| defined() | 判断变量是否已经定义 |
33| exec_script() | 执行一个Python脚本 |
34| get_label_info() | 获取标签信息,例如标签的名称、路径、类型等等 |
35| get_path_info() | 获取路径信息,例如路径是否存在、是否是目录、是否是文件等等 |
36| group() | 将一组目标文件组合成一个库文件 |
37| import() | 导入其他GN构建文件 |
38| read_file() | 读取文件内容 |
39| read_json() | 读取JSON格式的文件 |
40| read_path() | 读取路径中的内容,返回一个字符串列表 |
41| rebase_path() | 重新定位路径,将路径中的某个部分替换为新的值 |
42| write_file() | 写入文件内容 |
43| template() | 处理字符串模板,将模板中的变量替换为实际的值,其功能类似与函数 |
44| action() | 定义一个自定义的构建动作,通过action调用python脚本完成期望动作 |
45| action_foreach() | 针对每个元素执行一个自定义的构建动作 |
46| executable() | 定义一个可执行文件 |
47| shared_library() | 定义一个动态库 |
48| static_library() | 定义一个静态库 |
49
50
51## 如何使用GN进行构建
52当将一个基于CMake的项目转换为使用GN进行构建时,需要了解如何指定动态库、静态库和可执行文件的构建规则。以下是一个简单的指南,介绍如何在GN中指定这些构建规则:
53- **动态库**
54
55在CMake中,可以使用add_library命令来指定动态库的构建规则。例如:
56```
57add_library(mylib SHARED
58  src/foo.cpp
59  src/bar.cpp
60)
61```
62在GN中,可以使用shared_library模板来指定动态库的构建规则,创建BUILD.gn文件,内容如下:
63```
64# 指定动态库名称
65mylib_name = "mylib"
66
67# 指定动态库源文件
68mylib_sources = [
69  "src/foo.cpp",
70  "src/bar.cpp",
71]
72
73# 指定动态库编译选项和链接选项
74mylib_cflags = [
75  "-Wall",
76]
77mylib_ldflags = [
78  "-L/usr/local/lib",
79]
80
81# 指定动态库构建规则
82shared_library(mylib_name) {
83  sources = mylib_sources
84  cflags = mylib_cflags
85  ldflags = mylib_ldflags
86}
87```
88
89- **静态库**
90
91在CMake中,可以使用add_library命令来指定静态库的构建规则。例如:
92```
93add_library(mylib STATIC
94  src/foo.cpp
95  src/bar.cpp
96)
97
98```
99
100在GN中,可以使用static_library模板来指定静态库的构建规则,创建BUILD.gn文件,内容如下:
101```
102# 指定静态库名称
103mylib_name = "mylib"
104
105# 指定静态库源文件
106mylib_sources = [
107  "src/foo.cpp",
108  "src/bar.cpp",
109]
110
111# 指定静态库编译选项
112mylib_cflags = [
113  "-Wall",
114]
115
116# 指定静态库构建规则
117static_library(mylib_name) {
118  sources = mylib_sources
119  cflags = mylib_cflags
120}
121```
122
123- **可执行文件**
124
125在CMake中,可以使用add_executable命令来指定可执行文件的构建规则。例如:
126```
127add_executable(myapp
128  src/main.cpp
129)
130```
131在GN中,可以使用executable模板来指定可执行文件的构建规则。例如:
132```
133# 指定可执行文件名称
134myapp_name = "myapp"
135
136# 指定可执行文件源文件
137myapp_sources = [
138  "src/main.cpp",
139]
140
141# 指定可执行文件编译选项和链接选项
142myapp_cflags = [
143  "-Wall",
144]
145myapp_ldflags = [
146  "-L/usr/local/lib",
147]
148
149# 指定可执行文件构建规则
150executable(myapp_name) {
151  sources = myapp_sources
152  cflags = myapp_cflags
153  ldflags = myapp_ldflags
154}
155```
156
157OpenHarmony在GN原生模板的基础上进行了功能扩展,提供了ohos_shared_library、ohos_static_library、ohos_executable模板,在BUILD.gn中import("//build/ohos.gni")即可使用,ohos_shared_library示例如下:
158```
159import("//build/ohos.gni")
160ohos_shared_library("helloworld") {
161  sources = []
162  include_dirs = []
163  cflags = []
164  cflags_c = []
165  cflags_cc = []
166  ldflags = []
167  configs = []
168  deps = []                  # 部件内模块依赖
169
170  # 跨部件模块依赖定义,
171  # 定义格式为 "部件名:模块名称"
172  # 这里依赖的模块必须是依赖的部件声明在inner_kits中的模块
173  external_deps = [
174    "part_name:module_name",
175  ]
176
177  output_name = ""           # 可选,模块输出名
178  output_extension = ""      # 可选,模块名后缀
179  module_install_dir = ""    # 可选,缺省在/system/lib64/system/lib下, 模块安装路径,模块安装路径,从system/,vendor/后开始指定
180  relative_install_dir = ""  # 可选,模块安装相对路径,相对于/system/lib64/system/lib;如果有module_install_dir配置时,该配置不生效
181  install_images = []        # 可选,缺省值system,指定模块安装到那个分区镜像中,可以指定多个
182
183  part_name = ""             # 必选,所属部件名称
184}
185```
186
187## 简单示例
188假设我们有一个简单的CMake项目,包含两个源文件:main.cpphello.cpp,以及一个头文件hello.hCMakeLists.txt文件内容如下:
189```
190cmake_minimum_required(VERSION 3.10)
191
192project(hello)
193
194add_executable(hello main.cpp hello.cpp hello.h)
195```
196
197目录结构如下:
198```
199hello/
200├── include
201│   └── hello.h
202└── src
203    ├── hello.cpp
204    └── main.cpp
205```
206
207以下介绍如何在OpenHarmony编译框架中使用GN编译上述示例:
2081. 在OpenHarmony代码中,增加example目录,将hello示例放在example目录下,在hello目录下新建BUILD.gn文件,示例如下:
209```
210import("//build/ohos.gni")
211
212config("hello_config") {
213    include_dirs = [ "./include" ]
214}
215
216ohos_shared_library("hello_so") {
217    configs = [ ":hello_config" ]
218    sources = [ "./src/hello.cpp" ]
219    part_name = "hello"
220    subsystem_name = "example"
221}
222
223ohos_executable("hello") {
224    deps = [ ":hello_so" ]
225    configs = [ ":hello_config" ]
226    sources = [ "./src/main.cpp" ]
227    part_name = "hello"
228    subsystem_name = "example"
229}
230```
231
2322. 在example目录下新建bundle.json文件,示例如下:
233```
234{
235   "name": "@ohos/example",
236   "description": "",
237   "version": "3.1",
238   "license": "MIT",
239   "publishAs": "code-segment",
240   "segment": {
241       "destPath": ""
242   },
243   "dirs": {},
244   "scripts": {},
245   "licensePath": "COPYING",
246   "readmePath": {
247       "en": "README.rst"
248   },
249   "component": {
250       "name": "hello",                                       # 部件名称
251       "subsystem": "example",                                # 部件所属子系统
252       "syscap": [],
253       "features": [],
254       "adapted_system_type": [],
255       "rom": "",
256       "ram": "",
257       "deps": {
258           "components": [],
259           "third_party": []
260       },
261       "build": {
262           "group_type": {                                    # 部件编译入口,新增模块在此处配置
263               "base_group": [ "//example/hello:hello" ],
264               "fwk_group": [],
265               "service_group": []
266           },
267           "inner_kits": [],
268           "test": []
269       }
270   }
271}
272```
273
2743. 在`vendor\产品厂商\产品名\config.json`中配置新增的example子系统和hello组件,以rk3568为例,示例如下:
275```
276# 以rk3568为例
277{
278  "product_name": "rk3568",
279  "device_company": "rockchip",
280  "device_build_path": "device/board/hihope/rk3568",
281  "target_cpu": "arm",
282  "type": "standard",
283  "version": "3.0",
284  "board": "rk3568",
285  "api_version": 8,
286  "enable_ramdisk": true,
287  "enable_absystem": false,
288  "build_selinux": true,
289  "build_seccomp": true,
290  "inherit": [ "productdefine/common/inherit/rich.json", "productdefine/common/inherit/chipset_common.json" ],
291  "subsystems": [
292    {
293      "subsystem": "example",
294      "components": [
295        {
296          "component": "hello",
297          "features": []
298        }
299      ]
300    },
301    ......
302  ]
303}
304```
305
3064. 在build/subsystem_config.json中增加新增的example子系统路径,示例如下:
307```
308{
309  "example": {
310    "path": "example",
311    "name": "example"
312  }
313  ......
314}
315```
316
3175. 执行编译命令,以rk3568为例:
318```
319./build.sh --product-name rk3568 -T hello
320
321# build.sh是OpenHarmony编译入口脚本
322# --product-name用于指定产品名
323# -T指定编译目标,单独编译
324```
325
3266. 编译产物生成在out/rk3568/example/hello目录下:
327```
328out/rk3568/example/hello/
329├── hello
330└── libhello_so.z.so
331```