ninja文件语法学习
ninja文件语法学习
ninja本质上是配置文件,没有分支,循环的流程控制。
语法
基本概念
- edge(边):build语句,可以指定目标(target)输出(output)、规则(rule)与输入(input)
- target(目标):编译过程需要差生的目标,由build语句指定
- output(输出):build语句的前半段,是target的另一种称呼
- input(输入):build语句的后半段,用于产生output的文件或目标,另一种称呼是依赖
- rule(规则):通过指定command与一些内置变量,决定如何从输入产生输出
- pool:一组rule或edge,通过指定其depth,可以控制并行上限
- scope(作用域):变量的作用范围,有rule与build语句的块级,也有文件级别。
关键字
- build:定义一个edge
- rule:定义一个rule
- pool:定义一个pool
- default:指定默认的一个或多个target
- include:添加一个ninja文件到当前scope
- subninja:添加一个ninja文件,其scope与当前文件不同。
- phony:一个内置的特殊规则,指定非文件的target
变量
变量分两种,内置变量与自定义变量。二者都可以通过var = str
的方式定义,通过$var
或${var}
的方式引用。变量类型只有字符串这一种。
内置变量只有两个:
- builddir : 指定一些文件的输出目录
- ninja_required_version : 指定ninja命令的最低版本
rule
rule namecommand = echo ${in} > ${out}var = str
一个rule就是通过${in}
输入的目标列表,生成${out}
的输出目标列表
目标一般都是文件。例如是,有一个内置的特殊规则phony
,可以指定非文件目标。
除了可以自定义变量以外,包括command
在内,rule
还有以下变量:
- command:定义一个规则必备的变量,指定实际执行的命令
- description:command的说明,会替代command在无-v时打印
- generator:指定后,这条rule生成的文件不会被默认清理
- in:空格分割的input列表
- in_newline:换行符分割的input列表。
- out:空格分割的output列表
- depfile:指定一个Makefile文件作为额外的显式依赖。
- deps:指定gcc或mscv方式的依赖处理
- msvc_deps_prefile:在deps = msvc情况下,指定需要去除的msvc输出前缀。
- restat:在command执行结束后,如果output时间戳不变,则当作未执行
- rspfile,rspfile_content:同时指定,在执行command前,把rspfile_content写入rspfile文件,执行成功后删除。
build edge
build foo : phony barvar = str
形如以上的,就是build代码块,也是编译过程中的一个edge。 其中,foo就是output,bar就是input,:
后面第一个位置的phony就是rule,var就是自定义变量。 在build块中,也可以对rule块的变量进行扩展(复写)。
build的复杂情况举例,代码如下:
Gcc = gcc # 全局变量# rule
rule name # name是rule名command = ${Gcc} ${in} > ${out} # 执行命令var = str # 局部变量
# Edge
# output0 output1 显示输出
# output2 output3 隐式输出
# rule_name 规则名称
build output0 output1 | output2 output3: rule_name $ input0 input1 $ # 显示依赖| input2 input3 $ # 隐式依赖|| input4 input5 # order-only依赖 可有可无var0 = str0 var1 = str1
其中,行末的$
是转义字符,并未真正换行; output0
和output1
是显示(explicit)输出,会出现在${out}
列表中; 出现在|
后面的output2
和output3
是隐式(implicit)输出,不会出现在${out}
列表中; rule_name
是规则名称; input0
和input1
是显示依赖(输入),会出现在${in}
列表中; 出现在|
后面的input2
和input3
是隐式依赖,不会出现在${in}
列表中; 出现在||
后面的input4
和input5
是隐式order-only依赖,不会出现在${in}
列表中。
所谓order-only依赖,如字面意思,就是指仅仅是顺序需要的依赖。 在首次编译时,和其它依赖的表现相同; 再次编译时,如果input4
或input5
有缺失,ninja 会更新它们,但不会执行这条edge,更新output0
和output1
。 order-only的依赖
,不是真的依赖,而是可有可无、只是需要在当前edge之前执行而已。
pool
pool的意义,在于限制一些非常消耗硬件资源的edge同时执行
pool exampledepth = 2rule echo_varcommand = echo ${var} >> ${out}pool = examplebuild a : echo_varvar = abuild b : echo_varvar = bbuild c : echo_varvar = c
以上代码,通过pool = example
,在rule或build代码块中指定对应的edge所属的pool为example
。 由于example的depth = 2,所以a、b、c三个target最多只有2个可以同时生成。
目前,ninja只有一个内置的pool,名为console
。 这个pool的depth等于1,只能同时执行1个edge。 它的特点是,可以直接访问stdin、stdout、stderr三个特殊stream。
一个简单的ninja实例
//test.h
#include<stdio.h>void print_ninja()
{printf("this is a ninja_test!\n");
}
//test.c
#include"test.h"int main(int argc, char *argv[])
{print_ninja();return 0;
}
build.ninja
ninja_required_version = 1.5GCC = gcc
cflags = -Wall rule rule1 command = $GCC -c $cflags -MD -MF $out.d $in -o $outdescription = 编译 $in 成为 $outdepfile = $out.ddeps = gccbuild test.o : rule1 test.crule linkcommand = $GCC $DEFINES $INCLUDES $cflags $in -o $outdescription = 链接 $in 成为 $out
build test : link test.o# 编译all,就是做任务build test
build all: phony test # 默认编译什么(单独运行ninja)
default all
终端打印执行ninja,在目录下出现了test.o,test,.ninja_deps,.ninja_log
执行./test,执行成功。
ninja的使用
ninja支持的参数,使用 ninja -help
可以查看:
--version # 打印版本信息
-v # 显示构建中的所有命令行(这个对实际构建的命令核对非常有用)-C DIR # 在执行操作之前,切换到`DIR`目录
-f FILE # 制定`FILE`为构建输入文件。默认文件为当前目录下的`build.ninja`。如 ./ninja -f demo.ninja-j N # 并行执行 N 个作业。默认N=3(需要对应的CPU支持)。如 ./ninja -j 2 all
-k N # 持续构建直到N个作业失败为止。默认N=1
-l N # 如果平均负载大于N,不启动新的作业
-n # 排练(dry run)(不执行命令,视其成功执行。如 ./ninja -n -t clean)-d MODE # 开启调试模式 (用 -d list 罗列所有的模式)
-t TOOL # 执行一个子工具(用 -t list 罗列所有子命令工具)。如 ./ninja -t query all
-w FLAG # 控制告警级别
ninja -d list:
debugging modes:stats print operation counts/timing info 打印统计信息explain explain what caused a command to execute 解释导致命令执行的原因keepdepfile don't delete depfiles after they're read by ninja 读取depfile后,不删除它keeprsp don't delete @response files on success 读取@response后,不删除它nostatcache don't batch stat() calls per directory and cache them 不对每个目录批量处理stat()调用和缓存它们
multiple modes can be enabled via -d FOO -d BAR 多模式调用可以接着几个-d
ninja -t list (集成graphviz等一些对开发有用的工具)
ninja subtools:browse # 在浏览器中浏览依赖关系图。(默认会在 8080 端口启动一个基于python的http服务)clean # 清除构建生成的文件commands # 罗列重新构建制定目标所需的所有命令deps # 显示存储在deps日志中的依赖关系graph # 为指定目标生成 graphviz dot 文件。如 ninja -t graph all |dot -Tpng -o graph.pnginputs # 显示目标的所有(递归)输入path # 查找两个目标之间的依赖关系路径paths # 查找两个目标之间的所有依赖项路径query # 显示一个路径的inputs/outputstargets # 通过DAG中rule或depth罗列targetcompdb # dump JSON兼容的数据库到标准输出recompact # 重新紧凑化ninja内部数据结构
工具使用举例:
- 显示依赖 : ninja -t deps
- 显示执行命令 : ninja -t commands test
- 显示目标 : ninja -t targets all
- 绘制依赖图 :ninja -t graph
- 转图片 : ninja -t graph | dot -Tpng -o test.png
ninja文件语法学习相关推荐
- Qt的.pro工程文件语法学习
我们编写Qt应用程序时,不管使用Qt Creator还是VS或者Eclipse,不管是Qt Widgets还是Qt Quick,总会发现有.pro文件,我们称.pro文件为Qt的工程管理文件,它存在的 ...
- Cadence物理库 LEF 文件语法学习【持续更新】
我是 雪天鱼,一名FPGA爱好者,研究方向是FPGA架构探索. 关注公众号,拉你进"IC设计交流群". 文章目录 一.LEF简介 1.1 通用规则 1.2 管理 LEF 文件 二. ...
- [转]verilog语法学习心得
verilog语法学习心得 1.数字电路基础知识: 布尔代数.门级电路的内部晶体管结构.组合逻辑电路分析与设计.触发器.时序逻辑电路分析与设计 2.数字系统的构成: 传感器 AD 数字处理器 D ...
- 【C++学习之路】第二章——C++基础语法学习(1)之黑客攻击系统
2 C++基础语法学习(1)之黑客攻击系统 遵循原则:从实战中学习知识 法律声明:本系统仅能攻击自己搭建的网站,作为学习使用,不会触犯法律 time:2020.01.20 author:姜海天 IDE ...
- chrome ninja 文件_ninja和gn
引言 官方文档: What is GN? GN快速入门指南 ninja 教程 1 构建系统简介 在探讨chromium的最新GN构建系统之前,回顾一下软件开发中的构建系统.构建系统的需求是随着软件规模 ...
- jsx 调用php,JavaScript_JavaScript的React框架中的JSX语法学习入门教程,什么是JSX?
在用React写组件的 - phpStudy...
JavaScript的React框架中的JSX语法学习入门教程 什么是JSX? 在用React写组件的时候,通常会用到JSX语法,粗看上去,像是在Javascript代码里直接写起了XML标签,实质上 ...
- P4 程序设计语法学习
P4语法学习 P4程序模板 #include<core.p4> #include<v1model.p4> /* HEADERS */ struct metadata { ... ...
- MySQL语法学习笔记
MySQL语法学习笔记 学习之道,非尽心竭力者不能进也!我是小七黛,欢迎查看我的笔记,有问题欢迎交流探讨. SQL是一种结构查询语言,用于查询关系数据库的标准语言,包括若干关键字和一致的语法,便于数据 ...
- Go基础语法学习总结
Go基础语法学习总结 一.基础语法 1.常见数据类型 数据类型包括有:布尔类型.字符串类型.数字类型(整型.浮点型.复数等).派生类型(数组类型.slice 切片类型.map 集合类型.struct ...
最新文章
- vue 时间插件_Vue3 插件开发详解尝鲜版「值得收藏」
- OpenCV F变换理论F-transform theory
- 设计模式C++实现(4)——原型模式、模板方法模式
- php公交查询系统源代码,基于Smarty公交查询系统的设计与实现(PHP,MySQL)
- 技术沟通者的自我修养
- oracle 添加外键,报“未找到父项关键字”
- Java 线程池 ThreadPoolExecutor源码简析
- 什么是qq文件服务器,qq 收到的文件 - 卡饭网
- 大学生竞赛管理系统项目
- 对自然数e的理解,推导(基础)
- 添加zabbix飞信报警
- 绝知此事要躬行|fatal: not in a git directoryError: Command failed with exit 128: git
- 制作你的专属BB8机器人
- 页面验证是否是真实有效的身份证号码
- 计算机软件著作权保护包括哪些
- 第15章_存储过程与函数(创建存储过程、调用存储过程、存储函数的使用、存储过程和函数的查看、修改、删除)
- SAP 如何把科目快速扩充到所有公司
- WiFi信号感知精度
- android运行activity时报 Unfortunately,TestLayout has stopped 问题
- 基恩士PLC KV8000+XH16EC总线控制,全ST程序实例 全程序无加密,公司级框架,功能齐全,提供项目源码框架FB源码
热门文章
- 大学生期末考试html,《大学英语(第二学期)》期末考试试卷(A卷)
- 回文数函数的粗浅理解
- [阮一峰]腾讯的历史.转帖
- 哈工大李治军老师操作系统笔记【29】:目录与文件系统(Learning OS Concepts By Coding Them !)
- 直流有刷电机调速原理及Matlab/Simulink仿真
- python描述符详解
- 关于python的英文参考文献_英文参考文献格式
- jsp中去掉超链接下划线吗,在JSP中,若要在JSP正确使用标签:
,在jsp中声称的taglib指令为:
下划线处应该是() 答案:x...
- 我为什么反对提“全栈工程师”?
- 期货开户亏损的一点原因