Ninja Build: Simple Guide for Beginners
-
Upload
chang-w-doh -
Category
Technology
-
view
233 -
download
10
description
Transcript of Ninja Build: Simple Guide for Beginners
❝Ninja Build”Beginner’s Guide
Chang W. Doh
GDG Korea WebTech OrganizerHTML5Rocks/KO Contributor/Coordinator
</hi><hi>
Ninja?
● Designed only for speed
● File Interdependencies
● Orchestrate buildings, quickly
● Minified load & evaluations
Philosophy
● Aimed to assembler, not high-level system.
● ‘Edit-compile cycle’ as fast as possible
● Barest functionality to describe dependency graph
− Cons. : impossible to complex decisions
− Instead, use ninja file Generator!
● e.g. GYP, GN or Cmake 2.8.8+
Design Goals
● Very fast incremental builds
● Very little policy about how code is built
● Get dependencies correctly
● Convenience or Speed in conflict
− Always “SPEEEEEEED!!!”
Explicit non-goals
● Convenient syntax for writing build files by hand.− USE GENERATOR!!!!
● built-in rules− NO RULE e.g. COMPILE C CODE
● build-time customization of the build− OPTIONS HAVE TO BE GENERATED FROM GEN.
● build-time decision-making ability− NO CONDITION, NO DECISION
Comparison to ‘make’
● Similarity
− Relying on dependencies between file timestamps
● Differences
− MAKE has lots of options, rules and so on.
− Ninja has almost no features
● Punting complexity to generators
Comparison to ‘make’
● Discovering extra dependencies at build time, making it easy to get header dependencies correct for C/C++ code.
● A build edge may have multiple outputs.
● Outputs implicitly depend on the command line.
● Output directories are always implicitly created before running the command.
● Rules can provide shorter descriptions of the command being run.
● Builds are always run in parallel.
● Command output is always buffered.
Ninja is designed only for speed
● But, .ninja file is just human-readable ☹
● Recommends using Ninja in conjunction with other meta-build system.
Meta-build systems
● gyp− The meta-build system used to generate build files for Google Chrome
and related projects (v8, node.js)
● gn− Chromium is moving to gn, new META-Build system for generating .ninja
file. (Up to Dec. 2014)
− Some build generators have benn ready. Check:− $ gn gen ./out/Debug && ninja –C ./out/Debug gn
● CMake− A widely used meta-build system that can generate Ninja files on Linux as
of CMake version 2.8.8
TL;DR;
● Ninja is FAST!
− No option, No decision, No built-ins to avoid slow edit-build cycle.
− Only focused at ‘dependencies’ on your project
− But, you should GENERATE your .ninja file!
Usage
Running Ninja build
● Simply, run ‘ninja’
− By default, it looks for ‘build.ninja’ in the current directory
● Build specified target
$ ninja
$ ninja [options] TARGETs
Running Ninja build
● Changing working directory
● Specifying .ninja file
$ ninja -C WORKING_DIR
$ ninja -f NINJA_FILE
Options
● Command-line options
Option Argument Description
-C WORKING_DIR Setting working directory
-f NINJA_FILE Specifying .ninja file
-j Integer Limitations of jobs in parallel
-l Integer Limitations of load average
-v Show all commands while building
-n Dryrun, but act like build succeeded
-d MODE Debug mode:● ‘stat’ - Operation count/timing● ‘explain’ - Print what cause command● ‘keeprsp’ - Keep response files
-t TOOL Run a subtool:•Mostly, $ ninja -t clean -r RULES
Misc.
● Environment variables [link]
− export NINJA_STATUS = “STRING”
● Extra Tools [link]
− Mostly, we may use:
● ninja -t clean
Writing .ninja file
Basic syntax# VARIABLE: (referenced like $name or alternate ${name})cflag = -g
# 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
# PHONY rule: (creating alias)build ALIAS: phony INPUTS …
# DEFAULT target statement(cumulative):default TARGET1 TARGET2default TARGET3
$ ninjabuild TARGET1 TARGET2 TARGET3
ExampleSAMPLE: build.ninja
# ninja version check, ‘ninja_required_version’ is a special variable,# this variable is checked immediately when encountered in parsing.ninja_required_version = 1.3
# variablecc = g++cflags = -Wall
# rulerule cc command = gcc $cflags -c $in -o $out description = compile .cc
# buildbuild foo.o: cc foo.c
Shadowing (Scoping)cflags = -Wall -Werror
rule cc
command = gcc $cflags -c $in -o $out
# If left unspecified, builds get the outer $cflags.
build foo.o: cc foo.c
# But you can shadow variables like cflags for a particular build.
build special.o: cc special.c
cflags = -Wall
# The variable was only shadowed for the scope of special.o;
# Subsequent build lines get the outer (original) cflags.
build bar.o: cc bar.c
miscellaneous
.ninja_log
● Using this log Ninja can know when an existing output was built with a different command line
− .ninja_log will be created in the outmost scope of builddir
C/C++ header dependencies
● To get C/C++ header dependencies
− Because full list of dependencies can only be discovered by the compiler.
− Generating dependencies from where compiler emits.
● Update whenever compiling modified file
C/C++ header dependencies
● ‘depfile’ attribute
− On the Ninja side, the ‘depfile’ attribute on the build must point to a path where this data is written.
● Ninja only supports the limited subset of the Makefile syntax emitted by compilers.
rule cc
depfile = $out.d
command = gcc -MMD -MF $out.d [other gcc flags here]
C/C++ header dependencies
● ‘deps’ attribute
− Ninja 1.3 can instead process dependencies just after they’re generated and save a compacted form of the same information in a Ninja-internal database.
● deps = gcc or deps = msvc
rule cc
deps = msvc
command = cl /showIncludes -c $in /Fo$out
pool
● To get C/C++ header dependencies
− Because full list of dependencies can only be discovered by the compiler.
− Generating dependencies from where compiler emits.
● Update whenever compiling modified file
pool
● To get C/C++ header dependencies
− Because full list of dependencies can only be discovered by the compiler.
− Generating dependencies from where compiler emits.
● Update whenever compiling modified file
pool
● Declaring ‘pool’
# No more than 4 links at a time.
pool link_pool
depth = 4
# No more than 1 heavy object at a time.
pool heavy_object_pool
depth = 1
rule link
...
pool = link_pool
pool
● Using ‘pool’
# The link_pool is used here. Only 4 links will run concurrently.
build foo.exe: link input.obj
# empty pool, back into the default pool, which has infinite depth.
build other.exe: link input.obj
pool =
# A build statement can specify a pool directly. (and its scope)
build heavy_object1.obj: cc heavy_obj1.cc
pool = heavy_object_pool
build heavy_object2.obj: cc heavy_obj2.cc
pool = heavy_object_pool
submodules
● ‘subninja’− used to include another .ninja file, introduces a new scope.
● The included subninja file may use the variables from the parent file
...
subninja obj/content/content_resources.ninja
subninja obj/extensions/extensions_strings.ninja
subninja obj/third_party/expat/expat_nacl.ninja
submodules
● ‘include’− used to include another .ninja file in the current scope
● NOTE: Use this only for global configurations...
include obj/content/content_resources.ninja
include obj/extensions/extensions_strings.ninja
include obj/third_party/expat/expat_nacl.ninja
Scope rules● The full lookup order for a variable expanded in a build block (or the
rule is uses) is:
1. Special built-in variables ($in, $out).
2. Build-level variables from the build block.
3. Rule-level variables from the rule block (i.e. $command).
1. Note: Expansion that will expand "late", and may make use of in-scope bindings like $in.
4. File-level variables from the file that the build line was in.
5. Variables from the file that included that file using the subninja keyword.
Only one Reference :)
● [1] http://martine.github.io/ninja/manual.html