OpenHarmony下GN语法普法
引言
前面一直在折腾怎么移植,怎么编写,尼玛忘了搞最基本的GN语法了。这不必须给安排上!
一.GN表达式语言和GN作用域
GN 是简单的动态类型的命令式语言,其最终目的只是产生声明性的 Ninja 规则。一切都围绕作用域决定,它既是该语言的词法绑定(lexical binding,即静态绑定)结构,也是数据类型。
GN 值可以使用下列几种类型的任何一种:
- 布尔型(boolean),或 true 或 false
- 整型(integer),带符号,使用普通十进制语法;不常用
- 字符串(string),总是使用"双引号"引住(注意下面关于 $ 的扩展)
- 域(scope),使用花括号括住 { … };见下。
- 值列表(list of values),使用方括号括住:[ 1, true, “foo”, { x=1 y=2 } ]是一个四元素列表。
值是动态类型的,因而没有隐式类型的强迫,但也就没有这样的类型检查。不同类型的值比较结果永不相等,但是比较它们并不是错误。
字符串字面值在双引号中将简单的 $var 或 v a r 表达式扩展。这是一种立即扩展( i m m e d i a t e e x p a n s i o n ):当 v a r 为字符串时, x {var} 表达式扩展。这是一种立即扩展(immediate expansion):当 var 为字符串时,x var表达式扩展。这是一种立即扩展(immediateexpansion):当var为字符串时,x{var}y 与 x + var + y 相同。这样,任何值都可以表示为打印美观的字符串。
字母、数字和下划线组成的标志符可以通过赋值运算符填充一个域。GN 语言所做的实际上就是使用 = 进行命令式赋值,并通过 += 进行修改(也有一些特殊的方式来产生副作用,如 print(),用于调试;又如 write_file(),谨慎使用)。
1.1 整形
整形就比较简单了,形如:
x = 1
y = 2
关于这块有如下几点需要注意:
- GN语法是空白不敏感的
- GN语法不支持 ?= 这种
1.2 Strings 字符串
字符串括在双引号中,并使用反斜杠作为转义字符。仅仅支持如下转义序列是!
- \"(双引号)
- \$(美元符号$)
- \\(反斜杠)
反斜杠的任何其他用法都被视为反斜杠。因此,例如,\b不需要转义,大多数 Windows 路径如 “C:\foo\bar.h”)不需要转义。
通过符号 支持简单变量替换,其中美元符号 支持简单变量替换,其中美元符号 支持简单变量替换,其中美元符号后面的单词被替换为变量的值。如果没有非变量名称字符来终止变量名称,则可以选择${}将名称括起来。不支持更复杂的表达式,仅支持变量名称替换。
a = "mypath"
b = "$a/foo.cc" # b -> "mypath/foo.cc"
c = "foo${a}bar.cc" # c -> "foomypathbar.cc"
1.3 Lists列表
除了把非空列表赋值给空列表(a == [])之外,没有办法获得列表的长度。如果你发现自己想做这种事情,意味着在构建中做太多的工作。
ps:说的是,列表不提供获取长度,也不应该获取长度。
1.3.1 列表追加
列表支持追加,如下所示。将一个列表追加到另一个列表,会把每一个列表项追加为第二个列表中的项,而不是将该列表追加为嵌套成员。
a = [ "first" ]
a += [ "second" ] # [ "first", "second" ]
a += [ "third", "fourth" ] # [ "first", "second", "third", "fourth" ]
b = a + [ "fifth" ] # [ "first", "second", "third", "fourth", "fifth" ]
1.3.2 列表删除
还可以从列表中删除项目,如下。列表中的减号运算符“-”搜索匹配项并删除所有匹配项。从另一个列表中减去一个列表将删除第二个列表中的每个项目。如果未找到匹配的项目,则会引发错误,因此您需要在删除列表项之前,需要提前知道该列表项是否存在。
a = [ "first", "second", "third", "first" ]
b = a - [ "first" ] # [ "second", "third" ]
a -= [ "second" ] # [ "first", "third", "first" ]
鉴于无法测试列表项的添加引入,可以这样使用:设置一个文件或标志的主列表,然后根据各种条件删除不适用于当前版本的文件或标志。— 注:这算是推荐做法,维护一个主列表,然后只做减法,排除不适合的列表项。这个和下文的GYP提供的建议一样。这里读起来有些奇怪。
在风格上,更喜欢只添加到列表中,让每个源文件或依赖项出现一次。这与Chrome团队过去为GYP提供的建议相反(GYP更愿意列出所有文件,然后基于条件删除您不需要的文件)。
1.3.3 列表项获取
列表支持从零开始的下标来提取值:
a = [ "first", "second", "third" ]
b = a[1] # -> "second"
[] 运算符是只读的,不能用于改变列表。其主要使用场景是当外部脚本返回多个已知值,并且您想要提取它们时。
在某些情况下,覆盖一个列表比追加到一个列表更容易。为了帮助满足这种情况,将非空列表赋值给值为非空列表的变量,会产生错误。如果要绕过此限制,请首先将目标变量赋值给一个空列表。如下:
a = [ "one" ]
a = [ "two" ] # Error: overwriting nonempty list with a nonempty list.
a = [] # OK
a = [ "two" ] # OK
1.4 Conditionals条件表达式
条件语句类似于 C语言,如下。可以在大多数情况下,使用条件语句。甚至可以把整个target目标放在条件里,如果这些target只在特定的条件下才需要声明。
if (is_linux || (is_win && target_cpu == "x86")) {
sources -= [ "something.cc" ]
} else if (...) {
...
} else {
...
}
1.5 Looping循环
您可以使用foreach循环访问列表。这是不鼓励的。构建应该做的大多数事情通常都可以在不这样做的情况下来完成,如果你觉得有必要,这可能表明你在元构建中做了太多的工作。
foreach(i, mylist) {
print(i) # Note: i is a copy of each element, not a reference to it.
}
1.6 Function calls函数调用
简单的函数调用看起来像大多数其他语言:
print("hello, world")
assert(is_win, "This should only be executed on Windows")
这些函数是内置的,用户无法定义新的函数。一些函数采用以下代码块括起来:{ }
static_library("mylibrary") {
sources = [ "a.cc" ]
}
大多数函数定义了目标target。用户可以使用下面讨论的template模板机制定义这样的新功能。
准确地说,上面说的代码块{}作为函数参数来执行函数的。大多数块样式的函数执行代码块,并将生成的作用域做为供读取的变量字典。
1.7 Scoping and execution作用域与执行
文件和函数调用后面跟的{}块引入新的作用域。作用域是嵌套的。读取变量时,将按相反的顺序搜索包含作用域,直到找到匹配的名称。变量写入始终转到最内层的作用域。
除了最里面的作用域之外,无法修改任何封闭作用域。这意味着,例如,当您定义target目标时,您在块内执行的任何操作都不会“泄漏”到文件的其余部分。
每个文件在内部都表示为一个域,并且没有全局域。共享“全局域”可以定义在 .gni 文件中,并在它们被使用的地方导入(import(“//path/to/something.gni”))。每个 .gni 文件在每个工具链(toolchain)中处理一次(见下以获取关于工具链的信息),然后结果域被复制到导入文件的域中。
目标的声明引入了一个子域:
foo = true
executable("target") {
foo = 12
}
# 目标之外,foo == true
当一个变量在域中被定义而未被使用时,GN 对于错误的诊断非常严格。目标内部的作用域就像目标的关键字参数列表一样,它检查参数名称是否正确拼写。如果必需的参数被忽略,那么目标定义代码也可以使用“ assert()”来诊断错误。
一个值可以是一个域。那么当你使用它的时候,它就如同一个结构体:value.member。但是域总是一个 GN 代码块,它的执行用来产生其名称和值的集合:
foo = {
x = global_tuning + 42
If (some_global && other_thing == "foobar") {
y = 2
}
}
这总是会定义 foo.x ,但仅有时会定义 foo.y。
二. GN源路径和GN标签
GN 使用 POSIX 风格路径(path)(总以字符串表示),它们既用于文件,也用于提及 GN 定义的实体。路径可以是相对的,即路径的表示是相对于包含 BUILD.gn 文件目录的。他们也可以是“绝对于源的(source-absolute)”,即相对于源工作区。绝对于源的路径在 GN 中以 // 开头。
当最终在命令中使用源路径时,它们会转换为对应于操作系统的(OS-appropriate)路径,这些路径是绝对的或相对于构建目录(运行命令的位置)的路径。
GN源路径有三种可能形式:
- 相对名称:
"foo.cc"
"src/foo.cc"
"../src/foo.cc"
- 源树绝对名称:
"//net/foo.cc"
"//base/test/foo.cc"
- 系统绝对名称(罕见,通常用于包含目录):
"/usr/local/include/"
"/C:/Program Files/Windows Kits/Include"
2.1 GN标签
GN 标签是我们引用在 BUILD.gn 文件中定义的内容的方式。它们基于源路径,并且总是出现在 GN 字符串之内。GN 标签的完整语法是 “dir:name”,其中 dir 部分是命名了特定 BUILD.gn 文件的源路径。name 指在该文件中使用 target_type(“name”) { … } 定义的目标。简而言之,您可以定义一个名称与其所在目录名称相同的目标。无 : 部分的标签 “//path/to/dir” 是 “//path/to/dir:dir” 的略写。这是最常见的情况。常见形如:
import("//build/ohos.gni")
print("xxxx_group in")
group("xxxx_group") {
deps = [
"cfg:init_configs",
"distributedhardware:distributedhardware",
"kernel:build_kernel",
"//device/soc/xxxx/xxxx/hardware:hardware_group",
"//device/board/xxxx/xxxx/window_cfg:window_config",
]
}
三. GN Build configuration构建配置
GN的最初开发的目的是为了替换CMAKE,用来构建各种模块。而构建肯定离不来各种配置构建选项!下面让我一一道来!
3.1 Targets目标
一个目标target是构建图中的一个节点。它通常表示将生成的某种可执行文件或库文件。目标依赖于其他目标。内置目标类型如下所示。可以使用命令gn help 以获取更多帮助。可以使用模板创建自定义目标类型,来扩充内置的目标类型。
- action:运行脚本以生成文件。
- action_foreach:为每个源文件运行一次脚本。
- bundle_data:声明数据以进入 Mac/iOS 捆绑包。
- create_bundle:创建苹果/iOS 捆绑包。
- executable:生成可执行文件。
- group:引用一个或多个其他目标的虚拟依赖关系节点。
- shared_library:共享库.dll或 .so。
- loadable_module:仅在运行时可加载.dll或 .so。
- source_set:轻量级虚拟静态库(通常比真正的静态库更可取,因为它的构建速度更快)。
- static_library:.lib 或 .a 文件(通常可以使用一个source_set替代)。
写在最后
好了今天的博客OpenHarmony下GN语法普法就到这里了。总之,青山不改绿水长流先到这里了。如果本博客对你有所帮助,麻烦关注或者点个赞,如果觉得很烂也可以踩一脚!谢谢各位了!!文章来源:https://www.toymoban.com/news/detail-832642.html
1.GN 介绍
2.gn语法与操作学习文章来源地址https://www.toymoban.com/news/detail-832642.html
到了这里,关于OpenHarmony下GN语法普法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!