GN以及Ninja基本语法
GN用于编译文件作配置定义
语法
GN使用简单动态类型语言,涉及的变量类型为:
- Boolean (true, false)
- 64-bit signed integers
- Strings
- Lists
- Scopes (sort of like a dictionary, only for built-in stuff)
完整的语法参考gn help grammar
字符串
字符串有双引号包裹,使用反斜杠\转义,支持的反斜杠转义包括\"
, \$
,\\
。
其他使用都不会进行转义
$可以用于变量替换,可以用{}包裹。
1 | a = "mypath" |
可以使用$0xFF
语法表示8bit的数值。
列表
列表支持append操作:
1 | a = ["first"] |
还可以作减法:
1 | a = ["first", "second", "third", "first"] |
如果被减列表没有该元素的话,会报错。
列表支持索引:
1 | a = ["first", "second", "third"] |
当列表为空时,可以覆写为新的带元素列表。
条件语句
比较像C
1 | if (is_linux || (is_win && target_cpu == "x86")) { |
循环
使用foreach迭代列表,但是不推荐。
1 | foreach(i, mylist) { |
函数调用
简单的函数调用,例如print,assert
1 | print("hello, world") |
一些函数需要使用{}跟随
1 | static_libary("mylibrary") { |
该语句表示sources为该函数执行的参数,大多数的block_style函数都是执行block(eg: sources)然后将剩余的scope作为字典变量读取。
执行作用域
文件和函数调用{}块会引入新的作用域。
命名
文件和目录名
文件和目录名字是字符串并且是相对于当前编译文件目录的相对路径
1 | "foo.cc" |
相对于源码的绝对路径:
1 | "//net/foo.cc" |
系统绝对路径:
1 | "/usr/local/include/" |
编译配置
编译目标
目标是编译图中的一个节点。它一般代表要编译生成的可执行程序或者库文件。目标依赖于其他目标。定义的目标类型如下:
action
:执行脚本生成文件action_foreach
:循环执行多个脚本,一个脚本对应一个文件bundle_data
:声明数据为Mac/iOS bundlecreate_bundle
:创建 Mac/iOS bundleexecutable
:生成可执行文件group
:虚拟依赖节点,指向一个或多个其他的目标shared_library
:生成一个dll文件,或者so文件loadable_module
:运行时dll或so文件source_set
:轻量级虚拟静态库(效率更高)static_library
:.lib或.a文件,source_set是更优选择
你可以扩展其去定义目标类型,使用如下模版。component
:source_set / shared_library,基于其build类型test
:test可执行程序。在mobile环境中其会创建适合的native app类型来作为测试app
:Mac/iOS可执行程序android_apk
:制作APK。
设置
定义了flag,include directories和defines。这些可以应用于目标以及相依赖的目标
config定义:
1 | config("myconfig") { |
应用config到目标:
1 | executable("doom_melon") { |
常见情况是设置一个默认列表。目标可以根据列表做添加或删除。因此在实际中通常会使用configs += ":myconfig"
来添加配置。gn help config
来查阅更多的config相关配置
Public configs
目标可以将配置应用于依赖其的其他目标。最常见的情况是第三方目标需要一些定义或者导入库目录来正常编译。一般需要这些配置不仅应用于第三方库,还要应用于引用这些第三方库的目标上。
实现方式如下
1 | config("my_external_library_config") { |
然后该配置会加入到目标中作为”public” config,可以同时设置该config
1 | shared_library("my_external_library") { |
依赖的目标需要加入其依赖
1 | static_library("intermediate_library") { |
目标可以将config转发到所有依赖项直到触及边界值,通过设置all_dependent_config
实现。不推荐,因为会造成冗余以及错误。推荐使用public_deps
来实现。
模版
模版是GN重用代码的方式。模版会包括一到多个目标类型:
1 | # Declares a script that compiles IDL files to source, and then compiles those source files. |
该模版定义需要在.gni头文件中声明,用户可以使用该文件来查看定义
1 | import("//tools/idl_compiler.gni") |
声明模版后也引入了新的作用域。可以使用invoker来引用外部的变量。
1 | template("idl"){ |
其他
Imports
可以导入.gni文件。
Path processing
创建文件名或者列表。特别是运行脚本时,以编译输出目录作为当前目录。
可以使用rebase_path
来转换目录。
Patterns
用于生成输出文件的名字,并且自动化删除列表的元素gn help label_pattern
Executing scripts
脚本为python语言。使用action来执行。
第二种方案是在编译时同步进行,使用exec_script
。