1. 介绍

开篇先介绍、先甩资料给大家看,之后再自己演示一下基本使用。Ninja 是Google的一名程序员推出的注重速度的构建工具,一般在Unix/Linux上的程序通过make/makefile来构建编译,而Ninja通过将编译任务并行组织,大大提高了构建速度。

官网:ninja-build.org

Github:github.com/ninja-build/ninja

2. 参考资料

《The Performance Of Open Source Application》第三章

使用Ninja代替make

零壹軒Ninja相关文章(推荐!)

Ninja编译过程分析

Ninja - chromium核心构建工具

3. 使用

3.1. cmake生成

一般是通过cmake来生成ninja的配置,进而进行编译。先从cmake-examples入门:github.com/ttroy50/cmake-examples

比如01-basic\B-hello-headers项目,运行指令:cmake -Bbuild -GNinja 即可生成ninja工程。

运行ninja编译:

3.2. 手动写ninja配置文件

本文重点演示一下手写ninja配置文件方法,Demo工程结构:

./build.ninja

./src/jfz.cpp

其中jfz.cpp:

  1. #include "Hello.h"
  2. int main(int argc, char *argv[])
  3. {
  4. printf("sandeepin poi!");
  5. return 0;
  6. }

build.ninja(注意结尾要有空行):

  1. # 指定ninja最小需要版本
  2. ninja_required_version = 1.5
  3. # 变量
  4. GCC = D:\Library\MinGW\bin\g++.exe
  5. cflags = -Wall
  6. # 编译规则,指定depfile,可以用于生成ninja_deps文件
  7. rule compile_jfz
  8. command = $GCC -c $cflags -MD -MF $out.d $in -o $out
  9. description = 编译 $in 成为 $out
  10. depfile = $out.d
  11. deps = gcc
  12. build jfz.o : compile_jfz src/jfz.c
  13. # 链接规则
  14. rule link_jfz
  15. command = $GCC $DEFINES $INCLUDES $cflags $in -o $out
  16. description = 链接 $in 成为 $out
  17. build jfz.exe : link_jfz jfz.o
  18. # 编译all,就是做任务build jfz.exe
  19. build all: phony jfz.exe
  20. # 默认编译什么(单独运行ninja)
  21. default all

运行效果:

第一次运行按任务先编译,再链接,最终产生了可执行文件,第二次运行由于没改文件,ninja不处理。ninja支持如下参数:

  1. --version # 打印版本信息
  2. -v # 显示构建中的所有命令行(这个对实际构建的命令核对非常有用)
  3. -C DIR # 在执行操作之前,切换到`DIR`目录
  4. -f FILE # 制定`FILE`为构建输入文件。默认文件为当前目录下的`build.ninja`。如 ./ninja -f demo.ninja
  5. -j N # 并行执行 N 个作业。默认N=3(需要对应的CPU支持)。如 ./ninja -j 2 all
  6. -k N # 持续构建直到N个作业失败为止。默认N=1
  7. -l N # 如果平均负载大于N,不启动新的作业
  8. -n # 排练(dry run)(不执行命令,视其成功执行。如 ./ninja -n -t clean)
  9. -d MODE # 开启调试模式 (用 -d list 罗列所有的模式)
  10. -t TOOL # 执行一个子工具(用 -t list 罗列所有子命令工具)。如 ./ninja -t query all
  11. -w FLAG # 控制告警级别

ninja -d list相关:

  1. debugging modes:
  2. stats print operation counts/timing info 打印统计信息
  3. explain explain what caused a command to execute 解释导致命令执行的原因
  4. keepdepfile don't delete depfiles after they're read by ninja 读取depfile后,不删除它
  5. keeprsp don't delete @response files on success 读取@response后,不删除它
  6. nostatcache don't batch stat() calls per directory and cache them 不对每个目录批量处理stat()调用和缓存它们
  7. multiple modes can be enabled via -d FOO -d BAR 多模式调用可以接着几个-d

ninja -w list相关,主要指定几种情况下告警级别是多少:

  1. warning flags:
  2. dupbuild={err,warn} multiple build lines for one target
  3. phonycycle={err,warn} phony build statement references itself
  4. depfilemulti={err,warn} depfile has multiple output paths on separate lines

ninja -t list相关,主要集成了graphviz等一些对开发非常有用的工具。

  1. ninja subtools:
  2. browse # 在浏览器中浏览依赖关系图。(默认会在8080端口启动一个基于python的http服务)
  3. clean # 清除构建生成的文件
  4. commands # 罗列重新构建制定目标所需的所有命令
  5. deps # 显示存储在deps日志中的依赖关系
  6. graph # 为指定目标生成 graphviz dot 文件。如 ninja -t graph all |dot -Tpng -o graph.png
  7. query # 显示一个路径的inputs/outputs
  8. targets # 通过DAG中rule或depth罗列target
  9. compdb # dump JSON兼容的数据库到标准输出
  10. recompact # 重新紧凑化ninja内部数据结构

这里主要列举几种参数执行效果:

-n是假执行,实际未产生文件,由于假执行,keepdepfile没起到效果,这个受限于编译器分析依赖,下面的统计信息就是stats效果,explain解释了为什么执行这些任务。

这里-v打印每个任务执行了哪些指令,可见到keepdepfile生效了,保存了依赖.d文件。

ninja工具举例:

1、显示依赖

2、显示执行指令

3、显示目标

4、绘依赖图(要安装graphviz,直接打印出dot文本)

转图片(支持png、svg等,大图推荐svg渲染,相关dot参数见graphviz文档):

ninja -t graph | dot -Tpng -o jfz.png

这个demo比较简单,实际上依赖分析功能需要编译器提供,或者任务自己输出依赖文件,ninja只做一个任务编排和执行功能。

4. 信息补充

4.1. 环境变量

通过环境变量NINJA_STATUS可以控制ninja打印进度状态的样式,有几个占位符:

  1. %s 起始edges的数量。
  2. %t 完成构建必须运行的edges总数。
  3. %p 起始edges的百分比。
  4. %r 当前运行的edges数。
  5. %u 要开始的剩余edges数。
  6. %f 完成的edges数。
  7. %o 每秒完成edges的总速率
  8. %c 当前每秒完成edges的速率(由-j或其默认值指定的构建的平均值)
  9. %e 经过的时间(以秒为单位)。(自Ninja 1.2起可用。)
  10. %% 一个普通的%字符。
  11. 默认进度状态为"[%f/%t] "(请注意尾随空格以与构建规则分开)。可能的进度状态的另一个示例可能是"[%u/%r/%f] "

尝试改为export NINJA_STATUS="[%p/%f/%t %e] "(Windows下set NINJA_STATUS="[%p/%f/%t %e] ")的效果如下:

4.2. ninja_log每项含义

依次为:开始时间、结束时间、mtime、output文件路径名、命令行hash。

其中mtime是输入文件们的最后修改时间的时间戳算出来的值,经测试,开始时间、结束时间、命令行hash均不会影响增量的判定。

4.3. mtime检查文件测试

假设现在时间是2019-12-31 15:35:55,将输入.c文件修改时间改为之前的,不会触发重新编译;将输入.c文件修改时间改为未来的,每次都触发编译。

4.4. frontend_file参数

特别的,AOSP定制版的ninja有frontend_file参数,可以将控制台输出信息转为流存储,通过其它的工具如tail -f xxx查看信息。soong源码中就是这样读取ninja日志的,效率更高,之前应该是靠cat捕获日志的吧。见这个提交

4.5. ninja检测的是任务名的文件是否生成

如果我让输出文件和任务名不一样,ninja每次都会重新编译:

这点要注意,为了利用ninja的增量特性,除非迫不得已,不要让输出文件和任务名不同。

源码编译

本文仅尝试官方版的编译,AOSP版本可以依赖不同,GCC版本要求不同,需要注意。

Ninja构建系统入门的更多相关文章

  1. C/C++ 构建系统,我用 xmake

    XMake 是什么 XMake 是一个基于 Lua 的 现代化 C/C++ 构建系统. 它的语法简洁易上手,对新手友好,即使完全不会 lua 也能够快速入门,并且完全无任何依赖,轻量,跨平台. 同时, ...

  2. GYP构建系统总结

    GYP,Generate Your Project,一个Google开源的构建系统,最开始用于Chromium项目,现在一些其他的开源项目也开始使用GYP,如v8和node-gyp.不管怎样,这仅仅是 ...

  3. (一)ROS系统入门 Getting Started with ROS 以Kinetic为主更新 附课件PPT

    ROS机器人程序设计(原书第2版)补充资料 教案1 ROS Kinetic系统入门 ROS Kinetic在Ubuntu 16.04.01 安装可参考:http://blog.csdn.net/zha ...

  4. Skia构建系统与编译脚本分析

    分析下Skia的构建系统,详细编译过程參看Windows下从源代码编译Skia.这里以ninja为例来分析.运行以下三条命令就能够完毕编译: SET "GYP_GENERATORS=ninj ...

  5. xmake v2.3.1 发布, 无缝对接其他构建系统

    最近对xmake内部做了不少的重构来改进,并且新增了不少实用的新特性,欢迎来体验. 项目源码 官方文档 一些新特性: 一键编译其他构建系统维护的项目,实现无缝对接,并且支持交叉编译(比如autotoo ...

  6. Spring Boot2(004):关于 Build Systems (构建系统)

    Spring Boot Ref 建议使用 maven 或者 gradle 来进行依赖管理和应用构建. 一.Dependency Management(依赖管理) Spring Boot 的每个版本都会 ...

  7. ESP32构建系统(CMake版)

    ESP32 芯片是一款 2.4 GHz Wi-Fi 和蓝牙双模芯片,内置 1 或 2 个 32 位处理器,运算能力最高可达 600 DMIPS. ESP-IDF 即乐鑫物联网开发框架,可为在 Wind ...

  8. Google分布式构建软件之二:构建系统如何工作

    分布式软件构建第二部分:构建系统如何工作 注:本文英文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但请尊重作者版权,注名原文地址. 上篇文章中提到了在Google,所 ...

  9. IT技术学习指导之Linux系统入门的4个阶段(纯干货带图)

    IT技术学习指导之Linux系统入门的4个阶段(纯干货带图) 全世界60%的人都在使用Linux.几乎没有人没有受到Linux系统的"恩惠",我们享受的大量服务(包括网页服务.聊天 ...

随机推荐

  1. CentOS 7防火墙

    CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙步骤. 1.关闭firewall: systemctl stop firewalld.service #停止f ...

  2. 中小型企业级 IPS 部署

    <构建基于Snort+Guardian+Iptables的IPS> 2020年的第三天,依旧如往常写文章,分享最近做的项目继<中小型企业级防火墙部署>之后的另一部分<构建 ...

  3. 【学习笔鸡】快速沃尔什变换FWT

    [学习笔鸡]快速沃尔什变换FWT OR的FWT 快速解决: \[ C[i]=\sum_{j|k=i} A[j]B[k] \] FWT使得我们 \[ FWT(C)=FWT(A)*FWT(B) \] 其中 ...

  4. Linux 学习笔记 2 Centos 安装与网络的配置以及VI编辑器的使用

    前言 当然,还是觉得Centos 在众多的Linux 发行版中,还是很有地位的,好多的服务器大多沿用的都是一代的Centos 因为它开源(这是废话)而且稳定,这才是服务器沿用的最重要的一项指标. 镜像 ...

  5. MySQL基础篇(04):存储过程和视图,用法和特性详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.存储过程 1.概念简介 存储程序是被存储在服务器中的组合SQL语句,经编译创建并保存在数据库中,用户可通过存储过程的名字调用执行.存储过程 ...

  6. 「Luogu P1435」回文字串 解题报告

    题面 主要大衣大意: 给定一个字符串,求至少加入多少个字符才能使字符串变成回文字符串 下面就是我一本正经的胡说八道题解 思路: 很显然,这应该是一道典型的最长公共子序列的题目 因此,主要思想就是DP ...

  7. 1044 火星数字 (20 分)C语言

    火星人是以 13 进制计数的: 地球人的 0 被火星人称为 tret. 地球人数字 1 到 12 的火星文分别为:jan, feb, mar, apr, may, jun, jly, aug, sep ...

  8. 物理ceph集群+K8s

    前提条件 在Ceph为k8s创建一个pool ceph osd pool create k8s 128 创建admin用户 ceph auth get-or-create client.admin m ...

  9. 记第一个javaweb网页

      <%@ page language="java" contentType="text/html; charset=utf-8" pageEncodin ...

  10. 深入理解协程(二):yield from实现异步协程

    原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的第二篇. yield from ...