使用 Ninja 代替 make_ninja和make-程序员宅基地

技术标签: webrtc  

转自:https://www.jianshu.com/p/d118615c1943

前言

在传统的 C/C++ 等项目构建时,通常会采用 make 系统使用 Makefile 文件来进行整个项目的编译构建,通过 Makefile 中指定的编译所依赖的规则使得程序的构建非常简单,并且在复杂项目中可以避免由于少部分源码修改而造成的很多不必要的重编译。但是它仍然不够好,因为其大而且复杂,有时候我们并不需要 make 那么强大的功能,相反我们需要更灵活,速度更快的编译工具。Ninja 作为一个新型的编译工具,小巧而又高效,它就是为此而生。

这篇文章介绍 Ninja 的安装以及如何使用 Ninja 来构建项目

首先,我们需要安装 Ninja,只需要去官网下载一个 release 的二进制版本,放在系统目录(比如 /usr/bin)中就可以了,非常的简单。另外,现在大多数 Linux 发行版都有自己的包管理工具,直接使用包管理工具来下载也很简单。

下面简单介绍下通过编译 Ninja 源码的方式来安装
首先,确保已经安装了这些依赖:g++,graphviz,gtest,git,re2c 和 python2.7+。

获取源码
$ git clone git://github.com/ninja-build/ninja.git && cd ninja
$ git checkout release
$ cat README

$ ls
COPYING  HACKING.md  README  RELEASING  bootstrap.py  configure.py  doc/  misc/  src/

我们可以去 HACKING.md 中查看更多信息。

编译

一切就绪之后,执行下列命令来编译 ninja

$ ./configure.py --bootstrap

上述命令会在当前目录下生成一个叫 ninja (Windows 下是 ninja.exe)的可执行文件,然后我们把这个文件拷到系统目录(比如 /usr/bin)就完成安装了。

编译过程解析

实际上 ninja 本身也是通过 ninja 系统来编译完成的。
具体过程就是:执行 ./configure.py --bootstrap 之后先编译源码(生成一个 a.out),然后在当前目录生成一个 ninja.build(这个文件类似于 make 工具的 Makefile,语法和规则非常类似)。然后再根据这个 ninja.build 来重新编译生成可执行文件 ninja,在 ninja 根据 ninja.build 来编译时会自动创建一个 build 目录用于存放编译过程中的临时文件,比如 *.o 等。

执行./configure.py 时还可以指定其他选项:

--bootstrap    bootstrap a ninja binary from nothing
--verbose    enable verbose build
--platform     choose known platforms
--host       choose host known_platforms
--debug      enable debugging extras
--profile      enable profiling
--with-gtest
--with-python
  use EXE as the Python interpreter
--force-pselect   ppoll() is used by default where available

可以通过 ./configure.py -h 可以查看更多帮助。
如果我们想要开启 Ninja 的其他特性(比如:Bash completion, Emacs 和 Vim 编辑模式等),编译完成之后,我们需要把 /misc 目录中的文件拷贝到合适的位置。

测试

现在,我们可以测试一下 ninja 是否成功安装并且可以使用。

当直接执行 ninja 命令是,它会在当前目录下默认寻找 build.ninja 文件来进行编译。
ninja 的语法格式是:

$ ninja [options] TARGETs

上述 options 如果没有则可以省略。比如,直接执行 ./ninja ninja_test 将会生成可执行文件 ninja_test,然后再执行 ninja_test 就可以看到测试结果。

如下:

$ ./ninja ninja_test
$ ./ninja_test
[214/226] SubprocessTest.SetWithLotsRaise [ulimit -n] above 1025 (currently 1024) to make this test go
[226/226] ElideMiddle.ElideInTheMiddle
passed

或者,我们还可以直接执行 ./ninja all,这样,ninja 就会执行 ninja.build 中指定的所有目标了。

$ ./ninja all
[10/10] LINK canon_perftest

上述 ninja_test 和 all 都是 ninja.build 中的 build rule,概念类似于 Makefile 中的 target recipe。

测试完成之后,我们就把 ninja 拷贝到一个系统目录中 /usr/bin 来完成整个的安装。

提示: build.ninja 文件类似于 Makefile,熟悉它的语法规则之后我们也可以手动编写。另外,可以通过 ninja -f NINJA_FILE 的方式来指定 .ninja 文件

更多选项

实际上, ninja 还提供了一个 Python based generator ,它实际上是一个 Python 模块 misc/ninja_syntax.py,通过它我们可以较方便的生成 build.ninja 文件。比如,在我们的 Python 文件中引入该模块之后,就可以直接通过调用 ninja.rule(name='foo', command='bar', depfile='$out.d') 来生成符合 ninja 语法的内容。下面是一个简单例子:

from ninja_syntax import Writer

with open("build.ninja", "w") as buildfile:
    n = Writer(buildfile)

    if platform.is_msvc():
        n.rule("link",
                command="$cxx $in $libs /nologo /link $ldflags /out:$out",
                description="LINK $out")
    else:
        n.rule("link",
                command="$cxx $ldflags -o $out $in $libs",
                description="LINK $out")

另外,我们还可以在执行 cmake 时通过 -G 选项指定生成器为 ninja 来生成 build.ninja。
比如:

$ cd build 
$ cmake -GNinja ../proj_src_dir
Ninja 工具集

Ninja 还集成了 graphviz 等一些对开发非常有用的工具,通过执行 ./ninja -t list 可以查看 ninja 中集成了哪些工具。

下面是一个常见的工具集列表:

ninja subtools:

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

.ninja 的语法规则跟 Makefile 类似,虽然有许多 generator 工具 可以用来自动生成 .ninja 文件,但是在某些场合可能需要手动编写或修改 .ninja 文件,下面做个简单介绍:

# VARIABLE: (referenced like $name or alternate ${name})
cflag = -g -Wall -Werror

# RULE:
rule RULE_NAME
    command = gcc $cflags -c $in -o $out
    description = ${out} will be treat as "$out"

# BUILD statement:
build TARGET_NAME: RULE_NAME INPUTS

# PHONE rule:(creating alias)
build ALIAS: phony INPUTS ...

# DEFAULT target statement(cumulative):
default TARGET1 TARGET2
default TARGET3

    $ ninja
    build TARGET1 TARGET2 TARGET3

例子: build.ninja

ninja_required_version = 1.3

#variable
cc = g++
cflags = -Wall

# rule
rule cc
    command = gcc $cflags -c $in -o $out
    description = compile .cc

# build
build foo.o: cc foo.c

.ninja_log 可以用来指定保存 build 时产生的 log。

子模块 和 include 指令

subninja 指令可以用来引入其他 .ninja 文件,从而引入一个新的 scope。这意味着,子模块中可以引用父模块中的变量。
比如:

subninja obj/content/content_resources.ninja
subninja obj/extensions/extensions_strings.ninja
subninja obj/third_party/expat/expat_nacl.ninja

include 指令也是用来引入其他 .ninja 文件,但是不同的是,引入的其他 .ninja 文件会被引入当前 scope,子模块中不可以访问父模块中的变量。

include obj/content/content_resource.ninja
include obj/extensions/extensions_strings.ninja
include obj/third_party/expat/expat_nacl.ninja

参考
https://github.com/ninja-build/ninja
https://ninja-build.org/manual.html



作者:juniway
链接:https://www.jianshu.com/p/d118615c1943
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/rankun1/article/details/80420301

智能推荐

UML类图及其关系_uml类图的关系-程序员宅基地

文章浏览阅读1.6k次。在UML类图中, 常见的关系有一下几种: 泛化(Generalization), 实现(Realization), 关联(Association), 聚合(Aggregation), 组合(Composition), 依赖(Dependency).示例类图请看下面的类图车的类图结构为abstract,表示车是一个抽象类;它有两个继承类:汽车和自行车;它们之间的关系为实现关系,使用带空心箭头的虚线表示;通常用来表示接口的实现;汽车为与SUV之间也是继承关系,它们之间的关系为泛化关系,使用带空_uml类图的关系

css选择器包含内容,CSS 包含选择器-程序员宅基地

文章浏览阅读1.2k次。包含选择器包含选择器也叫派生选择器,顾名思义,是一种具有包含关系的选择。多个选择器以空格分开,组合成包含关系,且右边的选择器从属于左边(即右边的选择器只能在左边的选择器范围内选择)。一个包含选择器的应用示例:#nav a{text-decoration: none;}这个例子表示对“id="nav"”的元素里面的超链接应用该样式(超链接取消下划线),而其他网页元素的超链接不受影响。包含选择器是常用..._包含选择器

西科大c语言题库,科大C语言每章节上机习题-程序员宅基地

文章浏览阅读128次。该楼层疑似违规已被系统折叠隐藏此楼查看此楼1.输入4个不同的数,将它们从大到小排序。(使用循环语句)#include"stdio.h"voidswap(int&a,int&b){intt;t=a;a=b;b=t;}voidmain(){intnum[4];printf("输入四个整数(以空格分隔):");scanf("%d%d%d%d",&num[0],&a..._西南科技大学c语言机考

VC6.0 error LNK2001: unresolved external symbol __imp__ntohl@4-程序员宅基地

文章浏览阅读282次。--------------------Configuration: oxToint1 - Win32 Debug--------------------Linking...main.obj : error LNK2001: unresolved external symbol __imp__ntohl@4Debug/oxToint1.exe : fatal error LNK1120: 1 ..._unresolved external symbol __imp__ntohl@4

解决redhat忘记root密码的问题_虚拟机redhat密码忘了咋办-程序员宅基地

文章浏览阅读1.8w次,点赞7次,收藏35次。redhat密码忘记了怎么办,不要谎,看接下来的解决办法可以轻松解决1.首先需要进去到登陆界面,然后点击右上角的Restart 2.重启后进入开机界面选择内核的时候按e然后进入下图这个界面3.用键盘上的下键移动到最底部删除如图fi下两行 ro 后的所有内容,然后添加rw rd.break ,然后按ctrl +x4.后进入到以下的界面5.输入以下命令..._虚拟机redhat密码忘了咋办

SpringMVC 的工作原理_springmvc的工作原理-程序员宅基地

文章浏览阅读100次。SpringMVC 的工作原理a. 用户向服务器发送请求,请求被 springMVC 前端控制器 DispatchServlet 捕获;b. DispatcherServle 对请求 URL 进行解析,得到请求资源标识符(URL),然后根据该 URL 调用 HandlerMapping将请求映射到处理器 HandlerExcutionChain;c. DispatchServlet 根据获得..._springmvc的工作原理

随便推点

mybatis中if判断的坑_mybaties中if-程序员宅基地

文章浏览阅读3.1k次。最近在项目使用mybatis中碰到个问题Xml代码 if test="type=='y'"> and status = 0 if> 当传入的type的值为y的时候,if判断内的sql也不会执行,抱着这个疑问就去看了mybatis是怎么解析sql的。下面我们一起来看一下mybatis 的执行过程。DefaultSqlSession.c_mybaties中if

Java 基础系列(十六) --- Java中模板引擎的使用_java模板引擎-程序员宅基地

文章浏览阅读6.4k次,点赞4次,收藏6次。Java 中的模板引擎的使用_java模板引擎

【算法】快速排序与归并排序对比_快速排序和归并排序区别-程序员宅基地

文章浏览阅读5.3k次,点赞12次,收藏29次。算法 系列博客、一、时间复杂度、二、空间复杂度、三、排序稳定性、三、局部有序与整体有序、_快速排序和归并排序区别

Android开发初级00_1有关Toast和Menu的知识点-程序员宅基地

文章浏览阅读398次。Toast和Menu的使用 Toast的使用.java文件<(直接在java文件中就可以使用)/b> /*按钮一的作用*///提示一个个点击事件 Button button1 = (Button) findViewById(R.id.button_1); button1.setOnClickListener(new View.OnClickListe_menu的知识点

react radar_RADAR的完整形式是什么?-程序员宅基地

文章浏览阅读175次。react radar 雷达:无线电探测和测距 (RADAR: Radio Detection And Ranging)RADAR is an abbreviation of Radio Detection And Ranging. It is an electronic device which detects objects by using ultra-high frequency or ..._radar-radar

jQuery aiax 无刷新提交表单_jquery 无刷新提交表单-程序员宅基地

文章浏览阅读1.1k次。jQuery Ajax 代码:_jquery 无刷新提交表单