当前位置: 首页 > news >正文

OpenHarmony下GN语法普法

    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 + 42If (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语法普法就到这里了。总之,青山不改绿水长流先到这里了。如果本博客对你有所帮助,麻烦关注或者点个赞,如果觉得很烂也可以踩一脚!谢谢各位了!!

1.GN 介绍
2.gn语法与操作学习

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • easyx 枪声模拟器
  • h5网页和 Android APP联调,webview嵌入网页,网页中window.open打开新页面,网页只在webview中打开,没有重开一个app窗口
  • html的列表标签
  • 入门【网络安全/黑客】启蒙教程
  • Hypervisor是什么
  • 利用ChatGPT提升工作效率
  • 说一下 JVM 有哪些垃圾回收算法?
  • 关于深度学习和大模型的基础认知
  • MySQL-基本使用,数据类型,简单操作
  • 机器人内部传感器阅读笔记及心得-位置传感器-光电编码器
  • 2024.2.19 模拟实现 RabbitMQ —— 虚拟主机设计
  • 小清新卡通人物404错误页面源码
  • msvcp140.dll丢失的解决方法,msvcp140.dll丢失的原因和
  • 【Pytorch 基础教程2】10分钟掌握Tensor基础 VSCode +Pytorch配置
  • 【Python】OpenCV-图片添加水印处理
  • Google 是如何开发 Web 框架的
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 2018一半小结一波
  • android 一些 utils
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • ES6 ...操作符
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • Java超时控制的实现
  • js面向对象
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • Transformer-XL: Unleashing the Potential of Attention Models
  • 欢迎参加第二届中国游戏开发者大会
  • ------- 计算机网络基础
  • 配置 PM2 实现代码自动发布
  • 前端面试总结(at, md)
  • 浅谈web中前端模板引擎的使用
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 携程小程序初体验
  • 一起参Ember.js讨论、问答社区。
  • 一天一个设计模式之JS实现——适配器模式
  • mysql面试题分组并合并列
  • puppet连载22:define用法
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • ​字​节​一​面​
  • #pragma预处理命令
  • #控制台大学课堂点名问题_课堂随机点名
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (C语言)字符分类函数
  • (day 12)JavaScript学习笔记(数组3)
  • (算法)Game
  • (一)为什么要选择C++
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • **《Linux/Unix系统编程手册》读书笔记24章**
  • .NET BackgroundWorker
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .net 获取某一天 在当月是 第几周 函数