Showing preview only (1,312K chars total). Download the full file or copy to clipboard to get everything.
Repository: ninja-build/ninja
Branch: master
Commit: 5ff92d8a51b7
Files: 186
Total size: 1.2 MB
Directory structure:
gitextract_sspkt4tm/
├── .clang-format
├── .clang-tidy
├── .editorconfig
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── linux-musl.yml
│ ├── linux.yml
│ ├── macos.yml
│ └── windows.yml
├── .gitignore
├── CMakeLists.txt
├── CONTRIBUTING.md
├── COPYING
├── README.md
├── RELEASING.md
├── appveyor.yml
├── configure.py
├── doc/
│ ├── README.md
│ ├── dblatex.xsl
│ ├── docbook.xsl
│ ├── doxygen.config
│ ├── manual.asciidoc
│ └── style.css
├── misc/
│ ├── afl-fuzz/
│ │ └── build.ninja
│ ├── afl-fuzz-tokens/
│ │ ├── kw_build
│ │ ├── kw_default
│ │ ├── kw_include
│ │ ├── kw_pool
│ │ ├── kw_rule
│ │ ├── kw_subninja
│ │ ├── misc_a
│ │ ├── misc_b
│ │ ├── misc_colon
│ │ ├── misc_cont
│ │ ├── misc_dollar
│ │ ├── misc_eq
│ │ ├── misc_indent
│ │ ├── misc_pipe
│ │ ├── misc_pipepipe
│ │ └── misc_space
│ ├── bash-completion
│ ├── ci.py
│ ├── inherited-fds.ninja
│ ├── jobserver_pool.py
│ ├── jobserver_pool_test.py
│ ├── jobserver_test.py
│ ├── jobserver_test_helper.py
│ ├── long-slow-build.ninja
│ ├── manifest_fuzzer.cc
│ ├── measure.py
│ ├── ninja.vim
│ ├── ninja_syntax.py
│ ├── ninja_syntax_test.py
│ ├── oss-fuzz/
│ │ ├── build.sh
│ │ └── sample_ninja_build
│ ├── output_test.py
│ ├── packaging/
│ │ ├── ninja.spec
│ │ └── rpmbuild.sh
│ ├── write_fake_manifests.py
│ └── zsh-completion
├── src/
│ ├── browse.cc
│ ├── browse.h
│ ├── browse.py
│ ├── build.cc
│ ├── build.h
│ ├── build_log.cc
│ ├── build_log.h
│ ├── build_log_perftest.cc
│ ├── build_log_test.cc
│ ├── build_test.cc
│ ├── canon_perftest.cc
│ ├── clean.cc
│ ├── clean.h
│ ├── clean_test.cc
│ ├── clparser.cc
│ ├── clparser.h
│ ├── clparser_perftest.cc
│ ├── clparser_test.cc
│ ├── command_collector.h
│ ├── debug_flags.cc
│ ├── debug_flags.h
│ ├── depfile_parser.cc
│ ├── depfile_parser.h
│ ├── depfile_parser.in.cc
│ ├── depfile_parser_perftest.cc
│ ├── depfile_parser_test.cc
│ ├── deps_log.cc
│ ├── deps_log.h
│ ├── deps_log_test.cc
│ ├── disk_interface.cc
│ ├── disk_interface.h
│ ├── disk_interface_test.cc
│ ├── dyndep.cc
│ ├── dyndep.h
│ ├── dyndep_parser.cc
│ ├── dyndep_parser.h
│ ├── dyndep_parser_test.cc
│ ├── edit_distance.cc
│ ├── edit_distance.h
│ ├── edit_distance_test.cc
│ ├── elide_middle.cc
│ ├── elide_middle.h
│ ├── elide_middle_perftest.cc
│ ├── elide_middle_test.cc
│ ├── eval_env.cc
│ ├── eval_env.h
│ ├── exit_status.h
│ ├── explanations.h
│ ├── explanations_test.cc
│ ├── gen_doxygen_mainpage.sh
│ ├── getopt.c
│ ├── getopt.h
│ ├── graph.cc
│ ├── graph.h
│ ├── graph_test.cc
│ ├── graphviz.cc
│ ├── graphviz.h
│ ├── hash_collision_bench.cc
│ ├── hash_map.h
│ ├── includes_normalize-win32.cc
│ ├── includes_normalize.h
│ ├── includes_normalize_test.cc
│ ├── inline.sh
│ ├── jobserver-posix.cc
│ ├── jobserver-win32.cc
│ ├── jobserver.cc
│ ├── jobserver.h
│ ├── jobserver_test.cc
│ ├── json.cc
│ ├── json.h
│ ├── json_test.cc
│ ├── lexer.cc
│ ├── lexer.h
│ ├── lexer.in.cc
│ ├── lexer_test.cc
│ ├── line_printer.cc
│ ├── line_printer.h
│ ├── load_status.h
│ ├── manifest_parser.cc
│ ├── manifest_parser.h
│ ├── manifest_parser_perftest.cc
│ ├── manifest_parser_test.cc
│ ├── metrics.cc
│ ├── metrics.h
│ ├── minidump-win32.cc
│ ├── missing_deps.cc
│ ├── missing_deps.h
│ ├── missing_deps_test.cc
│ ├── msvc_helper-win32.cc
│ ├── msvc_helper.h
│ ├── msvc_helper_main-win32.cc
│ ├── msvc_helper_test.cc
│ ├── ninja.cc
│ ├── ninja_test.cc
│ ├── parser.cc
│ ├── parser.h
│ ├── real_command_runner.cc
│ ├── state.cc
│ ├── state.h
│ ├── state_test.cc
│ ├── status.h
│ ├── status_printer.cc
│ ├── status_printer.h
│ ├── status_test.cc
│ ├── string_piece.h
│ ├── string_piece_util.cc
│ ├── string_piece_util.h
│ ├── string_piece_util_test.cc
│ ├── subprocess-posix.cc
│ ├── subprocess-win32.cc
│ ├── subprocess.h
│ ├── subprocess_test.cc
│ ├── test.cc
│ ├── test.h
│ ├── third_party/
│ │ ├── emhash/
│ │ │ ├── README.ninja
│ │ │ └── hash_table8.hpp
│ │ └── rapidhash/
│ │ ├── README.ninja
│ │ └── rapidhash.h
│ ├── timestamp.h
│ ├── util.cc
│ ├── util.h
│ ├── util_test.cc
│ ├── version.cc
│ ├── version.h
│ └── win32port.h
├── tests/
│ └── restat/
│ └── test_restat_builddir.py
└── windows/
└── ninja.manifest
================================================
FILE CONTENTS
================================================
================================================
FILE: .clang-format
================================================
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This isn't meant to be authoritative, but it's good enough to be useful.
# Still use your best judgement for formatting decisions: clang-format
# sometimes makes strange choices.
BasedOnStyle: Google
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
Cpp11BracedListStyle: false
IndentCaseLabels: false
DerivePointerBinding: false
================================================
FILE: .clang-tidy
================================================
---
Checks: '
,readability-avoid-const-params-in-decls,
,readability-inconsistent-declaration-parameter-name,
,readability-non-const-parameter,
,readability-redundant-string-cstr,
,readability-redundant-string-init,
,readability-simplify-boolean-expr,
,cppcoreguidelines-pro-type-cstyle-cast,
'
WarningsAsErrors: '
,readability-avoid-const-params-in-decls,
,readability-inconsistent-declaration-parameter-name,
,readability-non-const-parameter,
,readability-redundant-string-cstr,
,readability-redundant-string-init,
,readability-simplify-boolean-expr,
,cppcoreguidelines-pro-type-cstyle-cast,
'
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
end_of_line = lf
[CMakeLists.txt]
indent_style = tab
[*.py]
indent_size = 4
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
================================================
FILE: .github/workflows/linux-musl.yml
================================================
name: ci-linux-musl
on:
workflow_dispatch:
pull_request:
push:
branches: ['**']
tags-ignore: ['**'] # Don't trigger on tag pushes
release:
types: [published]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
build:
runs-on: ubuntu-24.04
container: alpine:edge
permissions:
contents: read
strategy:
fail-fast: false
matrix:
build_method: ["python", "cmake"]
steps:
- name: Host - checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false
- name: Install ninja build optional dependencies
run: apk update && apk add -u --no-cache python3 build-base cmake re2c
- name: Configure ninja build
if: matrix.build_method == 'cmake'
run: cmake -B build -D CMAKE_BUILD_TYPE="Release" -D CMAKE_COMPILE_WARNING_AS_ERROR="ON"
- name: Cmake Build ninja
if: matrix.build_method == 'cmake'
run: cmake --build build --parallel --config Release
- name: Cmake test ninja
if: matrix.build_method == 'cmake'
run: build/ninja_test --gtest_color=yes
- name: Python Build ninja
if: matrix.build_method == 'python'
run: python3 configure.py --warnings-as-errors --bootstrap --verbose
- name: Python test ninja
if: matrix.build_method == 'python'
run: |
./ninja all
python3 misc/ninja_syntax_test.py
# python3 misc/output_test.py
- name: Move ninja binary
if: matrix.build_method == 'cmake'
run: mv -f build/ninja ninja
- name: ninja-ninja --version
run: ./ninja --version >> $GITHUB_STEP_SUMMARY
- name: binary info via file
run: file ./ninja >> $GITHUB_STEP_SUMMARY
================================================
FILE: .github/workflows/linux.yml
================================================
name: Linux
on:
pull_request:
push:
branches: ['**']
tags-ignore: ['**'] # Don't trigger on tag pushes
release:
types: [published]
jobs:
fedora:
runs-on: [ubuntu-latest]
container:
image: fedora:40
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: dnf install -y ninja-build cmake gtest-devel re2c clang util-linux clang-tools-extra
- name: Linting
run: misc/ci.py
- name: Configure with CMake
run: cmake -Bbuild -G"Ninja Multi-Config" -DNINJA_CLANG_TIDY=1
- name: Build debug ninja
run: CLICOLOR_FORCE=1 ninja
working-directory: build
- name: Test debug ninja
working-directory: build/Debug
run: |
./ninja_test --gtest_color=yes
../../misc/output_test.py
../../misc/jobserver_test.py
- name: Build release ninja
run: CLICOLOR_FORCE=1 ninja -f build-Release.ninja
working-directory: build
- name: Test release ninja
working-directory: build/Release
run: |
./ninja_test --gtest_color=yes
../../misc/output_test.py
../../misc/jobserver_test.py
build:
strategy:
matrix:
host-os: ["ubuntu-latest", "ubuntu-24.04-arm"]
include:
- host-os: "ubuntu-24.04-arm"
arch: "-aarch64"
fail-fast: false
defaults:
run:
shell: bash
runs-on: ${{ matrix.host-os }}
container: rockylinux/rockylinux:8
steps:
- uses: actions/checkout@v6
- uses: codespell-project/actions-codespell@master
with:
ignore_words_list: fo,wee,addin,notin
- name: Install dependencies
run: |
dnf install -y make gcc-c++ libasan clang-analyzer cmake dnf-plugins-core epel-release
dnf config-manager --set-enabled powertools
dnf install -y gtest-devel p7zip p7zip-plugins ninja-build
- name: Build debug ninja
env:
CFLAGS: -fstack-protector-all -fsanitize=address
CXXFLAGS: -fstack-protector-all -fsanitize=address
run: |
scan-build -o scanlogs cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -B debug-build
scan-build -o scanlogs cmake --build debug-build --parallel --config Debug
- name: Test debug ninja
run: ASAN_OPTIONS=detect_leaks=0 ./ninja_test
working-directory: debug-build
- name: Build release ninja
run: |
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -B release-build -DCMAKE_COMPILE_WARNING_AS_ERROR=1
cmake --build release-build --parallel --config Release
strip release-build/ninja
- name: Test release ninja
run: ./ninja_test
working-directory: release-build
- name: Create ninja archive
run: |
mkdir artifact
7z a artifact/ninja-linux${{ matrix.arch }}.zip ./release-build/ninja
# Upload ninja binary archive as an artifact
- name: Upload artifact
uses: actions/upload-artifact@v6
with:
name: ninja${{ matrix.arch }}-binary-archives
path: artifact
- name: Upload release asset
if: github.event.action == 'published'
uses: ncipollo/release-action@v1
with:
allowUpdates: true # if release exists it will edit it.
artifactContentType: "application/zip" # if empty defaults to raw
replacesArtifacts: true # will update existing release assets if needed.
omitBodyDuringUpdate: true # don't edit release body when published via webui
artifacts: ./artifact/ninja-linux${{ matrix.arch }}.zip # release asset
test:
permissions: # https://docs.zizmor.sh/audits/#excessive-permissions
contents: read
strategy:
matrix:
host-os: ["ubuntu-latest", "ubuntu-24.04-arm"]
image: ["ubuntu:22.04", "ubuntu:24.04"]
fail-fast: false
defaults:
run:
shell: bash
runs-on: ${{ matrix.host-os }}
container: ${{ matrix.image }}
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: |
apt update
apt install -y cmake python3-pytest ninja-build python3-pip clang libgtest-dev
- name: Configure (GCC)
run: cmake -Bbuild-gcc -DCMAKE_BUILD_TYPE=Debug -G'Ninja Multi-Config'
- name: Build (GCC, Debug)
run: cmake --build build-gcc --config Debug
- name: Unit tests (GCC, Debug)
run: ./build-gcc/Debug/ninja_test
- name: Python tests (GCC, Debug)
run: pytest-3 --color=yes ../..
working-directory: build-gcc/Debug
- name: Build (GCC, Release)
run: cmake --build build-gcc --config Release
- name: Unit tests (GCC, Release)
run: ./build-gcc/Release/ninja_test
- name: Python tests (GCC, Release)
run: pytest-3 --color=yes ../..
working-directory: build-gcc/Release
- name: Configure (Clang)
run: CC=clang CXX=clang++ cmake -Bbuild-clang -DCMAKE_BUILD_TYPE=Debug -G'Ninja Multi-Config'
- name: Build (Clang, Debug)
run: cmake --build build-clang --config Debug
- name: Unit tests (Clang, Debug)
run: ./build-clang/Debug/ninja_test
- name: Python tests (Clang, Debug)
run: pytest-3 --color=yes ../..
working-directory: build-clang/Debug
- name: Build (Clang, Release)
run: cmake --build build-clang --config Release
- name: Unit tests (Clang, Release)
run: ./build-clang/Release/ninja_test
- name: Python tests (Clang, Release)
run: pytest-3 --color=yes ../..
working-directory: build-clang/Release
build-with-python:
permissions: # https://docs.zizmor.sh/audits/#excessive-permissions
contents: read
strategy:
matrix:
host-os: ["ubuntu-latest", "ubuntu-24.04-arm"]
image: ["ubuntu:22.04", "ubuntu:24.04"]
fail-fast: false
defaults:
run:
shell: bash
runs-on: ${{ matrix.host-os }}
container: ${{ matrix.image }}
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false #https://docs.zizmor.sh/audits/#artipacked
- name: Install dependencies
run: |
apt update
apt install -y g++ python3
- name: ${{ matrix.host-os }} ${{ matrix.image }}
run: |
# Do not set --warnings-as-errors here as that triggers an irrelevant
# compiler warnings in <stdio.h> with ubuntu:24.04. See issue #2615
python3 configure.py --bootstrap
./ninja all
python3 misc/ninja_syntax_test.py
./misc/output_test.py
================================================
FILE: .github/workflows/macos.yml
================================================
name: macOS
on:
pull_request:
push:
branches: ['**']
tags-ignore: ['**'] # Don't trigger on tag pushes
release:
types: [published]
jobs:
build:
runs-on: macos-14
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: brew install re2c
- name: Build ninja
shell: bash
env:
MACOSX_DEPLOYMENT_TARGET: 10.15
run: |
cmake -Bbuild -GXcode '-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64' -DCMAKE_COMPILE_WARNING_AS_ERROR=1
cmake --build build --config Release
- name: Test ninja (Release)
run: ./ninja_test
working-directory: build/Release
- name: Create ninja archive
shell: bash
run: |
mkdir artifact
7z a artifact/ninja-mac.zip ./build/Release/ninja
# Upload ninja binary archive as an artifact
- name: Upload artifact
uses: actions/upload-artifact@v6
with:
name: ninja-binary-archives
path: artifact
- name: Upload release asset
if: github.event.action == 'published'
uses: ncipollo/release-action@v1
with:
allowUpdates: true # if release exists it will edit it.
artifactContentType: "application/zip" # if empty defaults to raw
replacesArtifacts: true # will update existing release assets if needed.
omitBodyDuringUpdate: true # don't edit release body when published via webui
artifacts: ./artifact/ninja-mac.zip # release asset
================================================
FILE: .github/workflows/windows.yml
================================================
name: Windows
on:
pull_request:
push:
branches: ['**']
tags-ignore: ['**'] # Don't trigger on tag pushes
release:
types: [published]
jobs:
build:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- arch: 'x64'
suffix: ''
- arch: 'arm64'
suffix: 'arm64'
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: choco install re2c
- name: Build ninja
shell: bash
run: |
cmake -Bbuild -A ${{ matrix.arch }} -DCMAKE_COMPILE_WARNING_AS_ERROR=1
cmake --build build --parallel --config Debug
cmake --build build --parallel --config Release
- name: Test ninja (Debug)
if: matrix.arch != 'arm64'
run: .\ninja_test.exe
working-directory: build/Debug
- name: Test ninja (Release)
if: matrix.arch != 'arm64'
run: .\ninja_test.exe
working-directory: build/Release
- name: Create ninja archive
shell: bash
run: |
mkdir artifact
7z a artifact/ninja-win${{ matrix.suffix }}.zip ./build/Release/ninja.exe
# Upload ninja binary archive as an artifact
- name: Upload artifact
uses: actions/upload-artifact@v6
with:
name: ninja-binary-archives${{ matrix.suffix }}
path: artifact
- name: Upload release asset
if: github.event.action == 'published'
uses: ncipollo/release-action@v1
with:
allowUpdates: true # if release exists it will edit it.
artifactContentType: "application/zip" # if empty defaults to raw
replacesArtifacts: true # will update existing release assets if needed.
omitBodyDuringUpdate: true # don't edit release body when published via webui
artifacts: ./artifact/ninja-win${{ matrix.suffix }}.zip # release asset
================================================
FILE: .gitignore
================================================
*.pyc
*.obj
*.exe
*.pdb
*.ilk
/build*/
/build.ninja
/ninja
/ninja.bootstrap
/build_log_perftest
/canon_perftest
/clparser_perftest
/elide_middle_perftest
/depfile_parser_perftest
/hash_collision_bench
/ninja_test
/manifest_parser_perftest
/graph.png
/doc/manual.html
/doc/doxygen
*.patch
.DS_Store
# Eclipse project files
.project
.cproject
# SublimeText project files
*.sublime-project
*.sublime-workspace
# Ninja output
.ninja_deps
.ninja_log
# Visual Studio Code project files
/.vscode/
/.ccls-cache/
# Qt Creator project files
/CMakeLists.txt.user
# clangd
/.clangd/
/compile_commands.json
/.cache/
# Visual Studio files
/.vs/
/out/
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.15)
include(CheckSymbolExists)
include(CheckIPOSupported)
option(NINJA_BUILD_BINARY "Build ninja binary" ON)
option(NINJA_FORCE_PSELECT "Use pselect() even on platforms that provide ppoll()" OFF)
project(ninja CXX)
# --- optional link-time optimization
check_ipo_supported(RESULT lto_supported OUTPUT error)
if(lto_supported)
message(STATUS "IPO / LTO enabled")
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
else()
message(STATUS "IPO / LTO not supported: <${error}>")
endif()
# --- compiler flags
if(MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
string(REPLACE "/GR" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
# Note that these settings are separately specified in configure.py, and
# these lists should be kept in sync.
add_compile_options(/W4 /wd4100 /wd4267 /wd4706 /wd4702 /wd4244 /GR- /Zc:__cplusplus)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
else()
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-Wno-deprecated flag_no_deprecated)
if(flag_no_deprecated)
add_compile_options(-Wno-deprecated)
endif()
if(CMAKE_VERSION VERSION_LESS 3.24)
check_cxx_compiler_flag(-fdiagnostics-color flag_color_diag)
if(flag_color_diag)
add_compile_options(-fdiagnostics-color)
endif()
elseif(NOT DEFINED ENV{CMAKE_COLOR_DIAGNOSTICS})
set(CMAKE_COLOR_DIAGNOSTICS ON)
endif()
if(NOT NINJA_FORCE_PSELECT)
# Check whether ppoll() is usable on the target platform.
# Set -DUSE_PPOLL=1 if this is the case.
#
# NOTE: Use check_cxx_symbol_exists() instead of check_symbol_exists()
# because on Linux, <poll.h> only exposes the symbol when _GNU_SOURCE
# is defined.
#
# Both g++ and clang++ define the symbol by default, because the C++
# standard library headers require it, but *not* gcc and clang, which
# are used by check_symbol_exists().
include(CheckCXXSymbolExists)
check_cxx_symbol_exists(ppoll poll.h HAVE_PPOLL)
if(HAVE_PPOLL)
add_compile_definitions(USE_PPOLL=1)
endif()
endif()
endif()
# --- optional re2c
set(RE2C_MAJOR_VERSION 0)
find_program(RE2C re2c)
if(RE2C)
execute_process(COMMAND "${RE2C}" --vernum OUTPUT_VARIABLE RE2C_RAW_VERSION)
math(EXPR RE2C_MAJOR_VERSION "${RE2C_RAW_VERSION} / 10000")
endif()
if(${RE2C_MAJOR_VERSION} GREATER 1)
# the depfile parser and ninja lexers are generated using re2c.
function(re2c IN OUT)
add_custom_command(DEPENDS ${IN} OUTPUT ${OUT}
COMMAND ${RE2C} -b -i --no-generation-date --no-version -o ${OUT} ${IN}
)
endfunction()
re2c(${PROJECT_SOURCE_DIR}/src/depfile_parser.in.cc ${PROJECT_BINARY_DIR}/depfile_parser.cc)
re2c(${PROJECT_SOURCE_DIR}/src/lexer.in.cc ${PROJECT_BINARY_DIR}/lexer.cc)
add_library(libninja-re2c OBJECT ${PROJECT_BINARY_DIR}/depfile_parser.cc ${PROJECT_BINARY_DIR}/lexer.cc)
else()
message(WARNING "re2c 2 or later was not found; changes to src/*.in.cc will not affect your build.")
add_library(libninja-re2c OBJECT src/depfile_parser.cc src/lexer.cc)
endif()
target_include_directories(libninja-re2c PRIVATE src)
# --- Check for 'browse' mode support
function(check_platform_supports_browse_mode RESULT)
# Make sure the inline.sh script works on this platform.
# It uses the shell commands such as 'od', which may not be available.
execute_process(
COMMAND sh -c "echo 'TEST' | src/inline.sh var"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE inline_result
OUTPUT_QUIET
ERROR_QUIET
)
if(NOT inline_result EQUAL "0")
# The inline script failed, so browse mode is not supported.
set(${RESULT} "0" PARENT_SCOPE)
if(NOT WIN32)
message(WARNING "browse feature omitted due to inline script failure")
endif()
return()
endif()
# Now check availability of the unistd header
check_symbol_exists(fork "unistd.h" HAVE_FORK)
check_symbol_exists(pipe "unistd.h" HAVE_PIPE)
set(browse_supported 0)
if (HAVE_FORK AND HAVE_PIPE)
set(browse_supported 1)
endif ()
set(${RESULT} "${browse_supported}" PARENT_SCOPE)
if(NOT browse_supported)
message(WARNING "browse feature omitted due to missing `fork` and `pipe` functions")
endif()
endfunction()
set(NINJA_PYTHON "python" CACHE STRING "Python interpreter to use for the browse tool")
check_platform_supports_browse_mode(platform_supports_ninja_browse)
# Core source files all build into ninja library.
add_library(libninja OBJECT
src/build_log.cc
src/build.cc
src/clean.cc
src/clparser.cc
src/dyndep.cc
src/dyndep_parser.cc
src/debug_flags.cc
src/deps_log.cc
src/disk_interface.cc
src/edit_distance.cc
src/elide_middle.cc
src/eval_env.cc
src/graph.cc
src/graphviz.cc
src/jobserver.cc
src/json.cc
src/line_printer.cc
src/manifest_parser.cc
src/metrics.cc
src/missing_deps.cc
src/parser.cc
src/real_command_runner.cc
src/state.cc
src/status_printer.cc
src/string_piece_util.cc
src/util.cc
src/version.cc
)
if(WIN32)
target_sources(libninja PRIVATE
src/subprocess-win32.cc
src/includes_normalize-win32.cc
src/jobserver-win32.cc
src/msvc_helper-win32.cc
src/msvc_helper_main-win32.cc
src/getopt.c
src/minidump-win32.cc
)
# Build getopt.c, which can be compiled as either C or C++, as C++
# so that build environments which lack a C compiler, but have a C++
# compiler may build ninja.
set_source_files_properties(src/getopt.c PROPERTIES LANGUAGE CXX)
# windows.h defines min() and max() which conflict with std::min()
# and std::max(), which both might be used in sources. Avoid compile
# errors by telling windows.h to not define those two.
add_compile_definitions(NOMINMAX)
else()
target_sources(libninja PRIVATE
src/jobserver-posix.cc
src/subprocess-posix.cc
)
if(CMAKE_SYSTEM_NAME STREQUAL "OS400" OR CMAKE_SYSTEM_NAME STREQUAL "AIX")
target_sources(libninja PRIVATE src/getopt.c)
# Build getopt.c, which can be compiled as either C or C++, as C++
# so that build environments which lack a C compiler, but have a C++
# compiler may build ninja.
set_source_files_properties(src/getopt.c PROPERTIES LANGUAGE CXX)
endif()
# Needed for perfstat_cpu_total
if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
target_link_libraries(libninja PUBLIC "-lperfstat")
endif()
endif()
target_compile_features(libninja PUBLIC cxx_std_17)
target_compile_features(libninja-re2c PUBLIC cxx_std_17)
#Fixes GetActiveProcessorCount on MinGW
if(MINGW)
target_compile_definitions(libninja PRIVATE _WIN32_WINNT=0x0601 __USE_MINGW_ANSI_STDIO=1)
endif()
# On IBM i (identified as "OS400" for compatibility reasons) and AIX, this fixes missing
# PRId64 (and others) at compile time in C++ sources
if(CMAKE_SYSTEM_NAME STREQUAL "OS400" OR CMAKE_SYSTEM_NAME STREQUAL "AIX")
add_compile_definitions(__STDC_FORMAT_MACROS)
endif()
# Main executable is library plus main() function.
if(NINJA_BUILD_BINARY)
add_executable(ninja src/ninja.cc)
target_link_libraries(ninja PRIVATE libninja libninja-re2c)
if(WIN32)
target_sources(ninja PRIVATE windows/ninja.manifest)
endif()
option(NINJA_CLANG_TIDY "Run clang-tidy on source files" OFF)
if(NINJA_CLANG_TIDY)
set_target_properties(libninja PROPERTIES CXX_CLANG_TIDY "clang-tidy;--use-color")
set_target_properties(ninja PROPERTIES CXX_CLANG_TIDY "clang-tidy;--use-color")
endif()
endif()
# Adds browse mode into the ninja binary if it's supported by the host platform.
if(platform_supports_ninja_browse)
# Inlines src/browse.py into the browse_py.h header, so that it can be included
# by src/browse.cc
add_custom_command(
OUTPUT build/browse_py.h
MAIN_DEPENDENCY src/browse.py
DEPENDS src/inline.sh
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/build
COMMAND src/inline.sh kBrowsePy
< src/browse.py
> ${PROJECT_BINARY_DIR}/build/browse_py.h
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
VERBATIM
)
if(NINJA_BUILD_BINARY)
target_compile_definitions(ninja PRIVATE NINJA_HAVE_BROWSE)
target_sources(ninja PRIVATE src/browse.cc)
endif()
set_source_files_properties(src/browse.cc
PROPERTIES
OBJECT_DEPENDS "${PROJECT_BINARY_DIR}/build/browse_py.h"
INCLUDE_DIRECTORIES "${PROJECT_BINARY_DIR}"
COMPILE_DEFINITIONS NINJA_PYTHON="${NINJA_PYTHON}"
)
endif()
include(CTest)
if(BUILD_TESTING)
# Can be removed if cmake min version is >=3.24
if (POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()
find_package(GTest)
if(NOT GTest_FOUND)
include(FetchContent)
FetchContent_Declare(
googletest
# GoogleTest v1.17.0 requires at least cmake 3.16, v1.16.0 requires at least cmake 3.13 which
# is within the ninja project minimum requirement.
URL https://github.com/google/googletest/releases/download/v1.16.0/googletest-1.16.0.tar.gz
URL_HASH SHA256=78c676fc63881529bf97bf9d45948d905a66833fbfa5318ea2cd7478cb98f399
)
FetchContent_MakeAvailable(googletest)
endif()
# Tests all build into ninja_test executable.
add_executable(ninja_test
src/build_log_test.cc
src/build_test.cc
src/clean_test.cc
src/clparser_test.cc
src/depfile_parser_test.cc
src/deps_log_test.cc
src/disk_interface_test.cc
src/dyndep_parser_test.cc
src/edit_distance_test.cc
src/elide_middle_test.cc
src/explanations_test.cc
src/graph_test.cc
src/jobserver_test.cc
src/json_test.cc
src/lexer_test.cc
src/manifest_parser_test.cc
src/missing_deps_test.cc
src/ninja_test.cc
src/state_test.cc
src/string_piece_util_test.cc
src/subprocess_test.cc
src/test.cc
src/util_test.cc
)
if(WIN32)
target_sources(ninja_test PRIVATE src/includes_normalize_test.cc src/msvc_helper_test.cc
windows/ninja.manifest)
if(MSVC)
# Silence warnings about using unlink rather than _unlink
target_compile_definitions(ninja_test PRIVATE _CRT_NONSTDC_NO_DEPRECATE)
endif()
endif()
find_package(Threads REQUIRED)
target_link_libraries(ninja_test PRIVATE libninja libninja-re2c GTest::gtest Threads::Threads)
foreach(perftest
build_log_perftest
canon_perftest
clparser_perftest
depfile_parser_perftest
elide_middle_perftest
hash_collision_bench
manifest_parser_perftest
)
add_executable(${perftest} src/${perftest}.cc)
target_link_libraries(${perftest} PRIVATE libninja libninja-re2c)
endforeach()
if(CMAKE_SYSTEM_NAME STREQUAL "AIX" AND CMAKE_SIZEOF_VOID_P EQUAL 4)
# These tests require more memory than will fit in the standard AIX shared stack/heap (256M)
target_link_options(hash_collision_bench PRIVATE "-Wl,-bmaxdata:0x80000000")
target_link_options(manifest_parser_perftest PRIVATE "-Wl,-bmaxdata:0x80000000")
endif()
add_test(NAME NinjaTest COMMAND ninja_test)
endif()
if(NINJA_BUILD_BINARY)
install(TARGETS ninja)
endif()
================================================
FILE: CONTRIBUTING.md
================================================
# How to successfully make changes to Ninja
We're very wary of changes that increase the complexity of Ninja (in particular,
new build file syntax or command-line flags) or increase the maintenance burden
of Ninja. Ninja is already successfully used by hundreds of developers for large
projects and it already achieves (most of) the goals we set out for it to do.
It's probably best to discuss new feature ideas on the
[mailing list](https://groups.google.com/forum/#!forum/ninja-build) or in an
issue before creating a PR.
## Coding guidelines
Generally it's the
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) with
a few additions:
* We have used `using namespace std;` a lot in the past. For new contributions,
please try to avoid relying on it and instead whenever possible use `std::`.
However, please do not change existing code simply to add `std::` unless your
contribution already needs to change that line of code anyway.
* Use `///` for [Doxygen](http://www.doxygen.nl/) (use `\a` to refer to
arguments).
* It's not necessary to document each argument, especially when they're
relatively self-evident (e.g. in
`CanonicalizePath(string* path, string* err)`, the arguments are hopefully
obvious).
If you're unsure about code formatting, please use
[clang-format](https://clang.llvm.org/docs/ClangFormat.html). However, please do
not format code that is not otherwise part of your contribution.
================================================
FILE: COPYING
================================================
Apache License
Version 2.0, January 2010
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
# Ninja
Ninja is a small build system with a focus on speed.
https://ninja-build.org/
See [the manual](https://ninja-build.org/manual.html) or
`doc/manual.asciidoc` included in the distribution for background
and more details.
Binaries for Linux, Mac and Windows are available on
[GitHub](https://github.com/ninja-build/ninja/releases).
Run `./ninja -h` for Ninja help.
Installation is not necessary because the only required file is the
resulting ninja binary. However, to enable features like Bash
completion and Emacs and Vim editing modes, some files in misc/ must be
copied to appropriate locations.
If you're interested in making changes to Ninja, read
[CONTRIBUTING.md](CONTRIBUTING.md) first.
## Building Ninja itself
You can either build Ninja via the custom generator script written in Python or
via CMake. For more details see
[the wiki](https://github.com/ninja-build/ninja/wiki).
### Python
```
./configure.py --bootstrap
```
This will generate the `ninja` binary and a `build.ninja` file you can now use
to build Ninja with itself.
If you have a GoogleTest source directory, you can build the tests
by passing its path with `--gtest-source-dir=PATH` option, or the
`GTEST_SOURCE_DIR` environment variable, e.g.:
```sh
./configure.py --bootstrap --gtest-source-dir=/path/to/googletest
./ninja all # build ninja_test and other auxiliary binaries
./ninja_test # run the unit-test suite.
```
Use the CMake build below if you want to use a preinstalled binary
version of the library.
### CMake
To build the ninja binary without building the unit tests, disable test building
by setting `BUILD_TESTING` to `OFF`:
```
cmake -Bbuild-cmake -DBUILD_TESTING=OFF
cmake --build build-cmake
```
The `ninja` binary will now be inside the `build-cmake` directory (you can
choose any other name you like).
To run the unit tests, omit the `-DBUILD_TESTING=OFF` option, and after
building, run:
```
build-cmake/ninja_test
```
## Generating documentation
### Ninja Manual
You must have `asciidoc` and `xsltproc` in your PATH, then do:
```
./configure.py
ninja manual doc/manual.html
```
Which will generate `doc/manual.html`.
To generate the PDF version of the manual, you must have `dblatext` in your PATH
then do:
```sh
./configure.py # only if you didn't do it previously.
ninja doc/manual.pdf
```
Which will generate `doc/manual.pdf`.
### Doxygen documentation
If you have `doxygen` installed, you can build documentation extracted from C++
declarations and comments to help you navigate the code. Note that Ninja is a
standalone executable, not a library, so there is no public API, all details
exposed here are internal.
```sh
./configure.py # if needed
ninja doxygen
```
Then open `doc/doxygen/html/index.html` in a browser to look at it.
================================================
FILE: RELEASING.md
================================================
Notes to myself on all the steps to make for a Ninja release.
### Push new release branch:
1. Run afl-fuzz for a day or so and run ninja_test
2. Consider sending a heads-up to the ninja-build mailing list first
3. Make sure branches 'master' and 'release' are synced up locally
4. Update src/version.cc with new version (with ".git"), then
```
git commit -am 'mark this 1.5.0.git'
```
5. git checkout release; git merge master
6. Fix version number in src/version.cc (it will likely conflict in the above)
7. Fix version in doc/manual.asciidoc (exists only on release branch)
8. commit, tag, push (don't forget to push --tags)
```
git commit -am v1.5.0; git push origin release
git tag v1.5.0; git push --tags
# Push the 1.5.0.git change on master too:
git checkout master; git push origin master
```
9. Construct release notes from prior notes
credits: `git shortlog -s --no-merges REV..`
### Release on GitHub:
1. Go to [Tags](https://github.com/ninja-build/ninja/tags)
2. Open the newly created tag and select "Create release from tag"
3. Create the release which will trigger a build which automatically attaches
the binaries
### Make announcement on mailing list:
1. copy old mail
### Update website:
1. Make sure your ninja checkout is on the v1.5.0 tag
2. Clone https://github.com/ninja-build/ninja-build.github.io
3. In that repo, `./update-docs.sh`
4. Update index.html with newest version and link to release notes
5. `git commit -m 'run update-docs.sh, 1.5.0 release'`
6. `git push origin master`
================================================
FILE: appveyor.yml
================================================
version: 1.0.{build}
image:
- Visual Studio 2017
- Ubuntu2204
environment:
CLICOLOR_FORCE: 1
CHERE_INVOKING: 1 # Tell Bash to inherit the current working directory
matrix:
- MSYSTEM: MINGW64
- MSYSTEM: LINUX
matrix:
exclude:
- image: Visual Studio 2017
MSYSTEM: LINUX
- image: Ubuntu2204
MSYSTEM: MINGW64
for:
-
matrix:
only:
- MSYSTEM: MINGW64
build_script:
ps: "C:\\msys64\\usr\\bin\\bash -lc @\"\n
pacman -S --quiet --noconfirm --needed re2c 2>&1\n
./configure.py --bootstrap --platform mingw 2>&1\n
./ninja all\n
./misc/ninja_syntax_test.py 2>&1\n\"@"
- matrix:
only:
- image: Ubuntu2204
build_script:
- ./configure.py --bootstrap
- ./ninja all
- misc/ninja_syntax_test.py
- misc/output_test.py
test: off
================================================
FILE: configure.py
================================================
#!/usr/bin/env python3
#
# Copyright 2001 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Script that generates the build.ninja for ninja itself.
Projects that use ninja themselves should either write a similar script
or use a meta-build system that supports Ninja output."""
from optparse import OptionParser
import os
import shlex
import subprocess
import sys
from typing import Optional, Union, Dict, List, Any, TYPE_CHECKING
sourcedir = os.path.dirname(os.path.realpath(__file__))
sys.path.insert(0, os.path.join(sourcedir, 'misc'))
if TYPE_CHECKING:
import misc.ninja_syntax as ninja_syntax
else:
import ninja_syntax
class Platform(object):
"""Represents a host/target platform and its specific build attributes."""
def __init__(self, platform: Optional[str]) -> None:
self._platform = platform
if self._platform is not None:
return
self._platform = sys.platform
if self._platform.startswith('linux'):
self._platform = 'linux'
elif self._platform.startswith('freebsd'):
self._platform = 'freebsd'
elif self._platform.startswith('gnukfreebsd'):
self._platform = 'freebsd'
elif self._platform.startswith('openbsd'):
self._platform = 'openbsd'
elif self._platform.startswith('solaris') or self._platform == 'sunos5':
self._platform = 'solaris'
elif self._platform.startswith('mingw'):
self._platform = 'mingw'
elif self._platform.startswith('win'):
self._platform = 'msvc'
elif self._platform.startswith('bitrig'):
self._platform = 'bitrig'
elif self._platform.startswith('netbsd'):
self._platform = 'netbsd'
elif self._platform.startswith('aix'):
self._platform = 'aix'
elif self._platform.startswith('os400'):
self._platform = 'os400'
elif self._platform.startswith('dragonfly'):
self._platform = 'dragonfly'
@staticmethod
def known_platforms() -> List[str]:
return ['linux', 'darwin', 'freebsd', 'openbsd', 'solaris', 'sunos5',
'mingw', 'msvc', 'gnukfreebsd', 'bitrig', 'netbsd', 'aix',
'dragonfly']
def platform(self) -> str:
return self._platform # type: ignore # Incompatible return value type
def is_linux(self) -> bool:
return self._platform == 'linux'
def is_mingw(self) -> bool:
return self._platform == 'mingw'
def is_msvc(self) -> bool:
return self._platform == 'msvc'
def msvc_needs_fs(self) -> bool:
popen = subprocess.Popen(['cl', '/nologo', '/help'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = popen.communicate()
return b'/FS' in out
def is_windows(self) -> bool:
return self.is_mingw() or self.is_msvc()
def is_solaris(self) -> bool:
return self._platform == 'solaris'
def is_aix(self) -> bool:
return self._platform == 'aix'
def is_os400_pase(self) -> bool:
return self._platform == 'os400' or os.uname().sysname.startswith('OS400') # type: ignore # Module has no attribute "uname"
def uses_usr_local(self) -> bool:
return self._platform in ('freebsd', 'openbsd', 'bitrig', 'dragonfly', 'netbsd')
def supports_ppoll(self) -> bool:
return self._platform in ('freebsd', 'linux', 'openbsd', 'bitrig',
'dragonfly')
def supports_ninja_browse(self) -> bool:
return (not self.is_windows()
and not self.is_solaris()
and not self.is_aix())
def can_rebuild_in_place(self) -> bool:
return not (self.is_windows() or self.is_aix())
class Bootstrap:
"""API shim for ninja_syntax.Writer that instead runs the commands.
Used to bootstrap Ninja from scratch. In --bootstrap mode this
class is used to execute all the commands to build an executable.
It also proxies all calls to an underlying ninja_syntax.Writer, to
behave like non-bootstrap mode.
"""
def __init__(self, writer: ninja_syntax.Writer, verbose: bool = False) -> None:
self.writer = writer
self.verbose = verbose
# Map of variable name => expanded variable value.
self.vars: Dict[str, str] = {}
# Map of rule name => dict of rule attributes.
self.rules: Dict[str, Dict[str, Any]] = {
'phony': {}
}
def comment(self, text: str) -> None:
return self.writer.comment(text)
def newline(self) -> None:
return self.writer.newline()
def variable(self, key: str, val: str) -> None:
# In bootstrap mode, we have no ninja process to catch /showIncludes
# output.
self.vars[key] = self._expand(val).replace('/showIncludes', '')
return self.writer.variable(key, val)
def rule(self, name: str, **kwargs: Any) -> None:
self.rules[name] = kwargs
return self.writer.rule(name, **kwargs)
def build(
self,
outputs: Union[str, List[str]],
rule: str,
inputs: Optional[Union[str, List[str]]] = None,
**kwargs: Any
) -> List[str]:
ruleattr = self.rules[rule]
cmd = ruleattr.get('command')
if cmd is None: # A phony rule, for example.
return # type: ignore # Return value expected
# Implement just enough of Ninja variable expansion etc. to
# make the bootstrap build work.
local_vars = {
'in': self._expand_paths(inputs),
'out': self._expand_paths(outputs)
}
for key, val in kwargs.get('variables', []):
local_vars[key] = ' '.join(ninja_syntax.as_list(val))
self._run_command(self._expand(cmd, local_vars))
return self.writer.build(outputs, rule, inputs, **kwargs)
def default(self, paths: Union[str, List[str]]) -> None:
return self.writer.default(paths)
def _expand_paths(self, paths: Optional[Union[str, List[str]]]) -> str:
"""Expand $vars in an array of paths, e.g. from a 'build' block."""
paths = ninja_syntax.as_list(paths)
return ' '.join(map(self._shell_escape, (map(self._expand, paths))))
def _expand(self, str: str, local_vars: Dict[str, str] = {}) -> str:
"""Expand $vars in a string."""
return ninja_syntax.expand(str, self.vars, local_vars)
def _shell_escape(self, path: str) -> str:
"""Quote paths containing spaces."""
return '"%s"' % path if ' ' in path else path
def _run_command(self, cmdline: str) -> None:
"""Run a subcommand, quietly. Prints the full command on error."""
try:
if self.verbose:
print(cmdline)
subprocess.check_call(cmdline, shell=True)
except subprocess.CalledProcessError:
print('when running: ', cmdline)
raise
parser = OptionParser()
profilers = ['gmon', 'pprof']
parser.add_option('--bootstrap', action='store_true',
help='bootstrap a ninja binary from nothing')
parser.add_option('--verbose', action='store_true',
help='enable verbose build')
parser.add_option('--platform',
help='target platform (' +
'/'.join(Platform.known_platforms()) + ')',
choices=Platform.known_platforms())
parser.add_option('--host',
help='host platform (' +
'/'.join(Platform.known_platforms()) + ')',
choices=Platform.known_platforms())
parser.add_option('--debug', action='store_true',
help='enable debugging extras',)
parser.add_option('--warnings-as-errors', action='store_true',
help='convert warnings into errors during build',)
parser.add_option('--profile', metavar='TYPE',
choices=profilers,
help='enable profiling (' + '/'.join(profilers) + ')',)
parser.add_option('--gtest-source-dir', metavar='PATH',
help='Path to GoogleTest source directory. If not provided ' +
'GTEST_SOURCE_DIR will be probed in the environment. ' +
'Tests will not be built without a value.')
parser.add_option('--with-python', metavar='EXE',
help='use EXE as the Python interpreter',
default=os.path.basename(sys.executable))
parser.add_option('--force-pselect', action='store_true',
help='ppoll() is used by default where available, '
'but some platforms may need to use pselect instead',)
(options, args) = parser.parse_args()
if args:
print('ERROR: extra unparsed command-line arguments:', args)
sys.exit(1)
platform = Platform(options.platform)
if options.host:
host = Platform(options.host)
else:
host = platform
BUILD_FILENAME = 'build.ninja'
ninja_writer = ninja_syntax.Writer(open(BUILD_FILENAME, 'w'))
n: Union[ninja_syntax.Writer, Bootstrap] = ninja_writer
if options.bootstrap:
# Make the build directory.
try:
os.mkdir('build')
except OSError:
pass
# Wrap ninja_writer with the Bootstrapper, which also executes the
# commands.
print('bootstrapping ninja...')
n = Bootstrap(n, verbose=options.verbose) # type: ignore # Incompatible types in assignment
n.comment('This file is used to build ninja itself.')
n.comment('It is generated by ' + os.path.basename(__file__) + '.')
n.newline()
n.variable('ninja_required_version', '1.3')
n.newline()
n.comment('The arguments passed to configure.py, for rerunning it.')
configure_args = sys.argv[1:]
if '--bootstrap' in configure_args:
configure_args.remove('--bootstrap')
n.variable('configure_args', ' '.join(configure_args))
env_keys = set(['CXX', 'AR', 'CFLAGS', 'CXXFLAGS', 'LDFLAGS'])
configure_env = dict((k, os.environ[k]) for k in os.environ if k in env_keys)
if configure_env:
config_str = ' '.join([k + '=' + shlex.quote(configure_env[k])
for k in configure_env])
n.variable('configure_env', config_str + '$ ')
n.newline()
CXX = configure_env.get('CXX', 'c++')
objext = '.o'
if platform.is_msvc():
CXX = 'cl'
objext = '.obj'
def src(filename: str) -> str:
return os.path.join('$root', 'src', filename)
def built(filename: str) -> str:
return os.path.join('$builddir', filename)
def doc(filename: str) -> str:
return os.path.join('$root', 'doc', filename)
def cc(name: str, **kwargs: Any) -> List[str]:
return n.build(built(name + objext), 'cxx', src(name + '.c'), **kwargs)
def cxx(name: str, **kwargs: Any) -> List[str]:
return n.build(built(name + objext), 'cxx', src(name + '.cc'), **kwargs)
def binary(name: str) -> str:
if platform.is_windows():
exe = name + '.exe'
n.build(name, 'phony', exe)
return exe
return name
root = sourcedir
if root == os.getcwd():
# In the common case where we're building directly in the source
# tree, simplify all the paths to just be cwd-relative.
root = '.'
n.variable('root', root)
n.variable('builddir', 'build')
n.variable('cxx', CXX)
if platform.is_msvc():
n.variable('ar', 'link')
else:
n.variable('ar', configure_env.get('AR', 'ar'))
def search_system_path(file_name: str) -> Optional[str]: # type: ignore # Missing return statement
"""Find a file in the system path."""
for dir in os.environ['path'].split(';'):
path = os.path.join(dir, file_name)
if os.path.exists(path):
return path
# Note that build settings are separately specified in CMakeLists.txt and
# these lists should be kept in sync.
if platform.is_msvc():
if not search_system_path('cl.exe'):
raise Exception('cl.exe not found. Run again from the Developer Command Prompt for VS')
cflags = ['/showIncludes',
'/nologo', # Don't print startup banner.
'/utf-8',
'/std:c++17',
'/Zi', # Create pdb with debug info.
'/W4', # Highest warning level.
'/WX', # Warnings as errors.
'/wd4530', '/wd4100', '/wd4706', '/wd4244',
'/wd4512', '/wd4800', '/wd4702',
# Disable warnings about constant conditional expressions.
'/wd4127',
# Disable warnings about passing "this" during initialization.
'/wd4355',
# Disable warnings about ignored typedef in DbgHelp.h
'/wd4091',
'/GR-', # Disable RTTI.
'/Zc:__cplusplus',
# Disable size_t -> int truncation warning.
# We never have strings or arrays larger than 2**31.
'/wd4267',
'/DNOMINMAX', '/D_CRT_SECURE_NO_WARNINGS',
'/D_HAS_EXCEPTIONS=0',
'/DNINJA_PYTHON="%s"' % options.with_python]
if options.warnings_as_errors:
cflags.append('/WX')
if platform.msvc_needs_fs():
cflags.append('/FS')
ldflags = ['/DEBUG', '/libpath:$builddir']
if not options.debug:
cflags += ['/Ox', '/DNDEBUG', '/GL']
ldflags += ['/LTCG', '/OPT:REF', '/OPT:ICF']
else:
cflags = ['-g', '-Wall', '-Wextra',
'-Wno-deprecated',
'-Wno-missing-field-initializers',
'-Wno-unused-parameter',
'-fno-rtti',
'-fno-exceptions',
'-std=c++17',
'-fvisibility=hidden', '-pipe',
'-DNINJA_PYTHON="%s"' % options.with_python]
if options.warnings_as_errors:
cflags += [ "-Werror" ]
if options.debug:
cflags += ['-D_GLIBCXX_DEBUG', '-D_GLIBCXX_DEBUG_PEDANTIC']
cflags.remove('-fno-rtti') # Needed for above pedanticness.
else:
cflags += ['-O2', '-DNDEBUG']
try:
proc = subprocess.Popen(
[CXX, '-fdiagnostics-color', '-c', '-x', 'c++', '/dev/null',
'-o', '/dev/null'],
stdout=open(os.devnull, 'wb'), stderr=subprocess.STDOUT)
if proc.wait() == 0:
cflags += ['-fdiagnostics-color']
except Exception:
pass
if platform.is_mingw():
cflags += ['-D_WIN32_WINNT=0x0601', '-D__USE_MINGW_ANSI_STDIO=1']
ldflags = ['-L$builddir']
if platform.uses_usr_local():
cflags.append('-I/usr/local/include')
ldflags.append('-L/usr/local/lib')
if platform.is_aix():
# printf formats for int64_t, uint64_t; large file support
cflags.append('-D__STDC_FORMAT_MACROS')
cflags.append('-D_LARGE_FILES')
libs = []
if platform.is_mingw():
cflags.remove('-fvisibility=hidden');
ldflags.append('-static')
elif platform.is_solaris():
cflags.remove('-fvisibility=hidden')
elif platform.is_aix():
cflags.remove('-fvisibility=hidden')
elif platform.is_msvc():
pass
else:
if options.profile == 'gmon':
cflags.append('-pg')
ldflags.append('-pg')
elif options.profile == 'pprof':
cflags.append('-fno-omit-frame-pointer')
libs.extend(['-Wl,--no-as-needed', '-lprofiler'])
if platform.supports_ppoll() and not options.force_pselect:
cflags.append('-DUSE_PPOLL')
if platform.supports_ninja_browse():
cflags.append('-DNINJA_HAVE_BROWSE')
# Search for generated headers relative to build dir.
cflags.append('-I.')
def shell_escape(str: str) -> str:
"""Escape str such that it's interpreted as a single argument by
the shell."""
# This isn't complete, but it's just enough to make NINJA_PYTHON work.
if platform.is_windows():
return str
if '"' in str:
return "'%s'" % str.replace("'", "\\'")
return str
if 'CFLAGS' in configure_env:
cflags.append(configure_env['CFLAGS'])
ldflags.append(configure_env['CFLAGS'])
if 'CXXFLAGS' in configure_env:
cflags.append(configure_env['CXXFLAGS'])
ldflags.append(configure_env['CXXFLAGS'])
n.variable('cflags', ' '.join(shell_escape(flag) for flag in cflags))
if 'LDFLAGS' in configure_env:
ldflags.append(configure_env['LDFLAGS'])
n.variable('ldflags', ' '.join(shell_escape(flag) for flag in ldflags))
n.newline()
if platform.is_msvc():
n.rule('cxx',
command='$cxx $cflags -c $in /Fo$out /Fd' + built('$pdb'),
description='CXX $out',
deps='msvc' # /showIncludes is included in $cflags.
)
else:
n.rule('cxx',
command='$cxx -MMD -MT $out -MF $out.d $cflags -c $in -o $out',
depfile='$out.d',
deps='gcc',
description='CXX $out')
n.newline()
if host.is_msvc():
n.rule('ar',
command='lib /nologo /ltcg /out:$out $in',
description='LIB $out')
elif host.is_mingw():
n.rule('ar',
command='$ar crs $out $in',
description='AR $out')
else:
n.rule('ar',
command='rm -f $out && $ar crs $out $in',
description='AR $out')
n.newline()
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')
n.newline()
objs = []
if platform.supports_ninja_browse():
n.comment('browse_py.h is used to inline browse.py.')
n.rule('inline',
command='"%s"' % src('inline.sh') + ' $varname < $in > $out',
description='INLINE $out')
n.build(built('browse_py.h'), 'inline', src('browse.py'),
implicit=src('inline.sh'),
variables=[('varname', 'kBrowsePy')])
n.newline()
objs += cxx('browse', order_only=built('browse_py.h'))
n.newline()
n.comment('the depfile parser and ninja lexers are generated using re2c.')
def has_re2c() -> bool:
try:
proc = subprocess.Popen(['re2c', '-V'], stdout=subprocess.PIPE)
return int(proc.communicate()[0], 10) >= 1503
except OSError:
return False
if has_re2c():
n.rule('re2c',
command='re2c -b -i --no-generation-date --no-version -o $out $in',
description='RE2C $out')
# Generate the .cc files in the source directory so we can check them in.
n.build(src('depfile_parser.cc'), 're2c', src('depfile_parser.in.cc'))
n.build(src('lexer.cc'), 're2c', src('lexer.in.cc'))
else:
print("warning: A compatible version of re2c (>= 0.15.3) was not found; "
"changes to src/*.in.cc will not affect your build.")
n.newline()
cxxvariables = []
if platform.is_msvc():
cxxvariables = [('pdb', 'ninja.pdb')]
n.comment('Generate a library for `ninja-re2c`.')
re2c_objs = []
for name in ['depfile_parser', 'lexer']:
re2c_objs += cxx(name, variables=cxxvariables)
if platform.is_msvc():
n.build(built('ninja-re2c.lib'), 'ar', re2c_objs)
else:
n.build(built('libninja-re2c.a'), 'ar', re2c_objs)
n.newline()
n.comment('Core source files all build into ninja library.')
objs.extend(re2c_objs)
for name in ['build',
'build_log',
'clean',
'clparser',
'debug_flags',
'deps_log',
'disk_interface',
'dyndep',
'dyndep_parser',
'edit_distance',
'elide_middle',
'eval_env',
'graph',
'graphviz',
'jobserver',
'json',
'line_printer',
'manifest_parser',
'metrics',
'missing_deps',
'parser',
'real_command_runner',
'state',
'status_printer',
'string_piece_util',
'util',
'version']:
objs += cxx(name, variables=cxxvariables)
if platform.is_windows():
for name in ['subprocess-win32',
'includes_normalize-win32',
'jobserver-win32',
'msvc_helper-win32',
'msvc_helper_main-win32']:
objs += cxx(name, variables=cxxvariables)
if platform.is_msvc():
objs += cxx('minidump-win32', variables=cxxvariables)
objs += cc('getopt')
else:
for name in ['jobserver-posix',
'subprocess-posix']:
objs += cxx(name, variables=cxxvariables)
if platform.is_aix():
objs += cc('getopt')
if platform.is_msvc():
ninja_lib = n.build(built('ninja.lib'), 'ar', objs)
else:
ninja_lib = n.build(built('libninja.a'), 'ar', objs)
n.newline()
if platform.is_msvc():
libs.append('ninja.lib')
else:
libs.append('-lninja')
if platform.is_aix() and not platform.is_os400_pase():
libs.append('-lperfstat')
all_targets = []
n.comment('Main executable is library plus main() function.')
objs = cxx('ninja', variables=cxxvariables)
ninja = n.build(binary('ninja'), 'link', objs, implicit=ninja_lib,
variables=[('libs', libs)])
n.newline()
all_targets += ninja
if options.bootstrap:
# We've built the ninja binary. Don't run any more commands
# through the bootstrap executor, but continue writing the
# build.ninja file.
n = ninja_writer
# Build the ninja_test executable only if the GTest source directory
# is provided explicitly. Either from the environment with GTEST_SOURCE_DIR
# or with the --gtest-source-dir command-line option.
#
# Do not try to look for an installed binary version, and link against it
# because doing so properly is platform-specific (use the CMake build for
# this).
if options.gtest_source_dir:
gtest_src_dir = options.gtest_source_dir
else:
gtest_src_dir = os.environ.get('GTEST_SOURCE_DIR')
if gtest_src_dir:
# Verify GoogleTest source directory, and add its include directory
# to the global include search path (even for non-test sources) to
# keep the build plan generation simple.
gtest_all_cc = os.path.join(gtest_src_dir, 'googletest', 'src', 'gtest-all.cc')
if not os.path.exists(gtest_all_cc):
print('ERROR: Missing GoogleTest source file: %s' % gtest_all_cc)
sys.exit(1)
n.comment('Tests all build into ninja_test executable.')
# Test-specific version of cflags, must include the GoogleTest
# include directory.
test_cflags = cflags.copy()
test_cflags.append('-I' + os.path.join(gtest_src_dir, 'googletest', 'include'))
test_variables = [('cflags', test_cflags)]
if platform.is_msvc():
test_variables += [('pdb', 'ninja_test.pdb')]
test_names = [
'build_log_test',
'build_test',
'clean_test',
'clparser_test',
'depfile_parser_test',
'deps_log_test',
'disk_interface_test',
'dyndep_parser_test',
'edit_distance_test',
'elide_middle_test',
'explanations_test',
'graph_test',
'jobserver_test',
'json_test',
'lexer_test',
'manifest_parser_test',
'ninja_test',
'state_test',
'string_piece_util_test',
'subprocess_test',
'test',
'util_test',
]
if platform.is_windows():
test_names += [
'includes_normalize_test',
'msvc_helper_test',
]
objs = []
for name in test_names:
objs += cxx(name, variables=test_variables)
# Build GTest as a monolithic source file.
# This requires one extra include search path, so replace the
# value of 'cflags' in our list.
gtest_all_variables = test_variables[1:] + [
('cflags', test_cflags + ['-I' + os.path.join(gtest_src_dir, 'googletest') ]),
]
# Do not use cxx() directly to ensure the object file is under $builddir.
objs += n.build(built('gtest_all' + objext), 'cxx', gtest_all_cc, variables=gtest_all_variables)
ninja_test = n.build(binary('ninja_test'), 'link', objs, implicit=ninja_lib,
variables=[('libs', libs)])
n.newline()
all_targets += ninja_test
n.comment('Ancillary executables.')
if platform.is_aix() and '-maix64' not in ldflags:
# Both hash_collision_bench and manifest_parser_perftest require more
# memory than will fit in the standard 32-bit AIX shared stack/heap (256M)
libs.append('-Wl,-bmaxdata:0x80000000')
for name in ['build_log_perftest',
'canon_perftest',
'elide_middle_perftest',
'depfile_parser_perftest',
'hash_collision_bench',
'manifest_parser_perftest',
'clparser_perftest']:
if platform.is_msvc():
cxxvariables = [('pdb', name + '.pdb')]
objs = cxx(name, variables=cxxvariables)
all_targets += n.build(binary(name), 'link', objs,
implicit=ninja_lib, variables=[('libs', libs)])
n.newline()
n.comment('Generate a graph using the "graph" tool.')
n.rule('gendot',
command='./ninja -t graph all > $out')
n.rule('gengraph',
command='dot -Tpng $in > $out')
dot = n.build(built('graph.dot'), 'gendot', ['ninja', 'build.ninja'])
n.build('graph.png', 'gengraph', dot)
n.newline()
n.comment('Generate the manual using asciidoc.')
n.rule('asciidoc',
command='asciidoc -b docbook -d book -o $out $in',
description='ASCIIDOC $out')
n.rule('xsltproc',
command='xsltproc --nonet doc/docbook.xsl $in > $out',
description='XSLTPROC $out')
docbookxml = n.build(built('manual.xml'), 'asciidoc', doc('manual.asciidoc'))
manual = n.build(doc('manual.html'), 'xsltproc', docbookxml,
implicit=[doc('style.css'), doc('docbook.xsl')])
n.build('manual', 'phony',
order_only=manual)
n.newline()
n.rule('dblatex',
command='dblatex -q -o $out -p doc/dblatex.xsl $in',
description='DBLATEX $out')
n.build(doc('manual.pdf'), 'dblatex', docbookxml,
implicit=[doc('dblatex.xsl')])
n.comment('Generate Doxygen.')
n.rule('doxygen',
command='doxygen $in',
description='DOXYGEN $in')
n.variable('doxygen_mainpage_generator',
src('gen_doxygen_mainpage.sh'))
n.rule('doxygen_mainpage',
command='$doxygen_mainpage_generator $in > $out',
description='DOXYGEN_MAINPAGE $out')
mainpage = n.build(built('doxygen_mainpage'), 'doxygen_mainpage',
['README.md', 'COPYING'],
implicit=['$doxygen_mainpage_generator'])
n.build('doxygen', 'doxygen', doc('doxygen.config'),
implicit=mainpage)
n.newline()
if not host.is_mingw():
n.comment('Regenerate build files if build script changes.')
n.rule('configure',
command='${configure_env}%s $root/configure.py $configure_args' %
options.with_python,
generator=True)
n.build('build.ninja', 'configure',
implicit=['$root/configure.py',
os.path.normpath('$root/misc/ninja_syntax.py')])
n.newline()
n.default(ninja)
n.newline()
if host.is_linux():
n.comment('Packaging')
n.rule('rpmbuild',
command="misc/packaging/rpmbuild.sh",
description='Building rpms..')
n.build('rpm', 'rpmbuild')
n.newline()
n.build('all', 'phony', all_targets)
n.close() # type: ignore # Item "Bootstrap" of "Writer | Bootstrap" has no attribute "close"
print('wrote %s.' % BUILD_FILENAME)
if options.bootstrap:
print('bootstrap complete. rebuilding...')
rebuild_args = []
if platform.can_rebuild_in_place():
rebuild_args.append('./ninja')
else:
if platform.is_windows():
bootstrap_exe = 'ninja.bootstrap.exe'
final_exe = 'ninja.exe'
else:
bootstrap_exe = './ninja.bootstrap'
final_exe = './ninja'
if os.path.exists(bootstrap_exe):
os.unlink(bootstrap_exe)
os.rename(final_exe, bootstrap_exe)
rebuild_args.append(bootstrap_exe)
if options.verbose:
rebuild_args.append('-v')
subprocess.check_call(rebuild_args)
================================================
FILE: doc/README.md
================================================
This directory contains the Ninja manual and support files used in
building it. Here's a brief overview of how it works.
The source text, `manual.asciidoc`, is written in the AsciiDoc format.
AsciiDoc can generate HTML but it doesn't look great; instead, we use
AsciiDoc to generate the Docbook XML format and then provide our own
Docbook XSL tweaks to produce HTML from that.
In theory using AsciiDoc and DocBook allows us to produce nice PDF
documentation etc. In reality it's not clear anyone wants that, but the
build rules are in place to generate it if you install dblatex.
================================================
FILE: doc/dblatex.xsl
================================================
<!-- This custom XSL tweaks the dblatex XML settings. -->
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
<!-- These parameters disable the list of collaborators and revisions.
Together remove a useless page from the front matter. -->
<xsl:param name='doc.collab.show'>0</xsl:param>
<xsl:param name='latex.output.revhistory'>0</xsl:param>
</xsl:stylesheet>
================================================
FILE: doc/docbook.xsl
================================================
<!-- This custom XSL tweaks the DocBook XML -> HTML settings to produce
an OK-looking manual. -->
<!DOCTYPE xsl:stylesheet [
<!ENTITY css SYSTEM "style.css">
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version='1.0'>
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl"/>
<!-- Embed our stylesheet as the user-provided <head> content. -->
<xsl:template name="user.head.content"><style>&css;</style></xsl:template>
<!-- Remove the body.attributes block, which specifies a bunch of
useless bgcolor etc. attrs on the <body> tag. -->
<xsl:template name="body.attributes"></xsl:template>
<!-- Specify that in "book" form (which we're using), we only want a
single table of contents at the beginning of the document. -->
<xsl:param name="generate.toc">book toc</xsl:param>
<!-- Don't put the "Chapter 1." prefix on the "chapters". -->
<xsl:param name="chapter.autolabel">0</xsl:param>
<!-- Make builds reproducible by generating the same IDs from the same inputs -->
<xsl:param name="generate.consistent.ids">1</xsl:param>
<!-- Use <ul> for the table of contents. By default DocBook uses a
<dl>, which makes no semantic sense. I imagine they just did
it because it looks nice? -->
<xsl:param name="toc.list.type">ul</xsl:param>
<xsl:output method="html" encoding="utf-8" indent="no"
doctype-public=""/>
</xsl:stylesheet>
================================================
FILE: doc/doxygen.config
================================================
# Doxyfile 1.4.5
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = "Ninja"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
# PROJECT_NUMBER = "0"
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = "doc/doxygen/"
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
# format and will distribute the generated files over these directories.
# Enabling this option can be useful when feeding doxygen a huge amount of
# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.
CREATE_SUBDIRS = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
# Swedish, and Ukrainian.
OUTPUT_LANGUAGE = English
# This tag can be used to specify the encoding used in the generated output.
# The encoding is not always determined by the language that is chosen,
# but also whether or not the output is meant for Windows or non-Windows users.
# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
# forces the Windows encoding (this is the default for the Windows binary),
# whereas setting the tag to NO uses a Unix-style encoding (the default for
# all platforms other than Windows).
# Obsolet option.
#USE_WINDOWS_ENCODING = YES
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator
# that is used to form the text in various listings. Each string
# in this list, if found as the leading text of the brief description, will be
# stripped from the text and the result after processing the whole list, is
# used as the annotated text. Otherwise, the brief description is used as-is.
# If left blank, the following values are used ("$name" is automatically
# replaced with the name of the entity): "The $name class" "The $name widget"
# "The $name file" "is" "provides" "specifies" "contains"
# "represents" "a" "an" "the"
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
INLINE_INHERITED_MEMB = YES
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = YES
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the
# path to strip.
STRIP_FROM_PATH = src
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
# the path mentioned in the documentation of a class, which tells
# the reader which header file to include in order to use a class.
# If left blank only the name of the header file containing the class
# definition is used. Otherwise one should specify the include paths that
# are normally passed to the compiler using the -I flag.
STRIP_FROM_INC_PATH = src/
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
# (but less readable) file names. This can be useful is your file systems
# doesn't support long names like on DOS, Mac, or CD-ROM.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like the Qt-style comments (thus requiring an
# explicit @brief command for a brief description.
JAVADOC_AUTOBRIEF = YES
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
# treat a multi-line C++ special comment block (i.e. a block of //! or ///
# comments) as a brief description. This used to be the default behaviour.
# The new default is to treat a multi-line C++ comment block as a detailed
# description. Set this tag to YES if you prefer the old behaviour instead.
MULTILINE_CPP_IS_BRIEF = NO
# If the DETAILS_AT_TOP tag is set to YES then Doxygen
# will output the detailed description near the top, like JavaDoc.
# If set to NO, the detailed description appears after the member
# documentation.
# Has become obsolete.
#DETAILS_AT_TOP = NO
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
# a new page for each member. If set to NO, the documentation of a member will
# be part of the file/class/namespace that contains it.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 2
# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
# put the command \sideeffect (or @sideeffect) in the documentation, which
# will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
ALIASES =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
# sources only. Doxygen will then generate output that is more tailored for Java.
# For instance, namespaces will be presented as packages, qualified scopes
# will look different, etc.
OPTIMIZE_OUTPUT_JAVA = NO
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
# include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
# func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# BUILTIN_STL_SUPPORT = NO
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
# the same type (for instance a group of public functions) to be put as a
# subgroup of that type (e.g. under the Public Functions section). Set it to
# NO to prevent subgrouping. Alternatively, this can be done per class using
# the \nosubgrouping command.
SUBGROUPING = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = YES
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
EXTRACT_LOCAL_CLASSES = YES
# This flag is only useful for Objective-C code. When set to YES local
# methods, which are defined in the implementation section but not in
# the interface are included in the documentation.
# If set to NO (the default) only methods in the interface are included.
EXTRACT_LOCAL_METHODS = NO
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
# friend (class|struct|union) declarations.
# If set to NO (the default) these declarations will be included in the
# documentation.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
# documentation blocks found inside the body of a function.
# If set to NO (the default) these blocks will be appended to the
# function's detailed documentation block.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
# file names in lower-case letters. If set to YES upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
# will sort the (detailed) documentation of file and class members
# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
# brief documentation of file, namespace and class members alphabetically
# by member name. If set to NO (the default) the members will appear in
# declaration order.
SORT_BRIEF_DOCS = YES
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
# sorted by fully-qualified names, including namespaces. If set to
# NO (the default), the class list will be sorted only by class name,
# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the
# alphabetical list.
SORT_BY_SCOPE_NAME = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or
# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.
GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
# disable (NO) the deprecated list. This list is created by putting
# \deprecated commands in the documentation.
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
# the initial value of a variable or define consists of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
# The appearance of the initializer of individual variables and defines in the
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
# If the sources in your project are distributed over multiple directories
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
# in the documentation. The default is YES.
SHOW_DIRECTORIES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from the
# version control system). Doxygen will invoke the program by executing (via
# popen()) the command <command> <input-file>, where <command> is the value of
# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
# provided by doxygen. Whatever the program writes to standard output
# is used as the file version. See the manual for examples.
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = YES
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = YES
# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some
# parameters in a documented function, or documenting parameters that
# don't exist or using markup commands wrongly.
WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be abled to get warnings for
# functions that are documented, but have no documentation for their parameters
# or return value. If set to NO (the default) doxygen will only warn about
# wrong or incomplete parameter documentation, but not about the absence of
# documentation.
WARN_NO_PARAMDOC = NO
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
# warning originated and the warning text. Optionally the format may contain
# $version, which will be replaced by the version of the file (if it could
# be obtained via FILE_VERSION_FILTER)
WARN_FORMAT = "$file:$line: $text "
# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = src \
build/doxygen_mainpage
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
FILE_PATTERNS = *.cc \
*.h
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
# from the input.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories. Note that the wildcards are matched
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
EXCLUDE_PATTERNS =
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH = src
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS = *.cpp \
*.cc \
*.h \
*.hh \
INSTALL DEPENDENCIES CHANGELOG LICENSE LGPL
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude
# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.
EXAMPLE_RECURSIVE = YES
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH = src
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output. If FILTER_PATTERNS is specified, this tag will be
# ignored.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form:
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
# is applied to all files.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse (i.e. when SOURCE_BROWSER is set to YES).
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = NO
# If the REFERENCED_BY_RELATION tag is set to YES (the default)
# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES (the default)
# then for each documented function all documented entities
# called/used by that function will be listed.
REFERENCES_RELATION = YES
# If the USE_HTAGS tag is set to YES then the references to source code
# will point to the HTML generated by the htags(1) tool instead of doxygen
# built-in source browser. The htags tool is part of GNU's global source
# tagging system (see http://www.gnu.org/software/global/global.html). You
# will need version 4.8.6 or higher.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = YES
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 2
# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
# doxygen will generate files with .html extension.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
# will generate a default style sheet. Note that doxygen will try to copy
# the style sheet file to the HTML output directory, so don't put your own
# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET =
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
HTML_ALIGN_MEMBERS = YES
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = YES
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
# can add a path in front of the file if the result should not be
# written to the html output directory.
CHM_FILE =
# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
# be used to specify the location (absolute path including file name) of
# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
# the HTML help compiler on the generated index.hhp.
HHC_LOCATION =
# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).
GENERATE_CHI = NO
# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the HTML help documentation and to the tree view.
TOC_EXPAND = NO
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
DISABLE_INDEX = NO
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
ENUM_VALUES_PER_LINE = 4
# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
# generated containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
# probably better off using the HTML help feature.
GENERATE_TREEVIEW = YES
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
LATEX_CMD_NAME =
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
# generate index for LaTeX. If left blank `makeindex' will be used as the
# default command name.
MAKEINDEX_CMD_NAME =
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
LATEX_HEADER =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = YES
# If LATEX_HIDE_INDICES is set to YES then doxygen will not
# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
# contain links (just like the HTML output) instead of page references.
# This makes the output suitable for online browsing using WORD or other
# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an rtf document.
# Syntax is similar to doxygen's config file.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION = .3
# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
# then it will generate one additional man file for each entity
# documented in the real man page(s). These additional files
# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
# the code including all documentation.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `xml' will be used as the default path.
XML_OUTPUT = xml
# The XML_SCHEMA tag can be used to specify an XML schema,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_SCHEMA =
# The XML_DTD tag can be used to specify an XML DTD,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_DTD =
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
# dump the program listings (including syntax highlighting
# and cross-referencing information) to the XML output. Note that
# enabling this will significantly increase the size of the XML output.
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
# generate an AutoGen Definitions (see autogen.sf.net) file
# that captures the structure of the code including all
# documentation. Note that this feature is still experimental
# and incomplete at the moment.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
# If the GENERATE_PERLMOD tag is set to YES Doxygen will
# generate a Perl module file that captures the structure of
# the code including all documentation. Note that this
# feature is still experimental and incomplete at the
# moment.
GENERATE_PERLMOD = NO
# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
# the necessary Makefile rules, Perl scripts and LaTeX code to be able
# to generate PDF and DVI output from the Perl module output.
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
# nicely formatted so it can be parsed by a human reader. This is useful
# if you want to understand what is going on. On the other hand, if this
# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file
# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
# This is useful so different doxyrules.make files included by the same
# Makefile don't overwrite each other's variables.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
EXPAND_ONLY_PREDEF = YES
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed. To prevent a macro definition from being
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
# doxygen's preprocessor will remove all function-like macros that are alone
# on a line, have an all uppercase name, and do not end with a semicolon. Such
# function macros are typically used for boiler-plate code, and will confuse
# the parser if not removed.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
# The TAGFILES option can be used to specify one or more tagfiles.
# Optionally an initial location of the external documentation
# can be added for each tagfile. The format of a tag file without
# this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where "loc1" and "loc2" can be relative or absolute paths or
# URLs. If a location is present for each tag, the installdox tool
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
# If a tag file is not located in the directory in which doxygen
# is run, you must also specify the path to the tagfile here.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
GENERATE_TAGFILE = doc/doxygen/html/Ninja.TAGFILE
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = YES
# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will
# be listed.
EXTERNAL_GROUPS = YES
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
# or super classes. Setting the tag to NO turns the diagrams off. Note that
# this option is superseded by the HAVE_DOT option below. This is only a
# fallback. It is recommended to install and use dot, since it yields more
# powerful graphs.
CLASS_DIAGRAMS = YES
# If set to YES, the inheritance and collaboration graphs will hide
# inheritance and usage relations if the target is undocumented
# or is not a class.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = YES
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = NO
# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for groups, showing the direct groups dependencies
GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
UML_LOOK = NO
# UML_LOOK = YES
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
TEMPLATE_RELATIONS = YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
# tags are set to YES then doxygen will generate a graph for each documented
# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH = YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
# documented header file showing the documented files that directly or
# indirectly include this file.
INCLUDED_BY_GRAPH = YES
# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
# generate a call dependency graph for every global function or class method.
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
# functions only using the \callgraph command.
CALL_GRAPH = NO
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are png, jpg, or gif
# If left blank png will be used.
DOT_IMAGE_FORMAT = png
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the
# \dotfile command).
DOTFILE_DIRS =
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
# Obsolet option.
#MAX_DOT_GRAPH_WIDTH = 1280
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
# the specified constraint. Beware that most browsers cannot cope with very
# large images.
# Obsolet option.
#MAX_DOT_GRAPH_HEIGHT = 1024
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
# graphs generated by dot. A depth value of 3 means that only nodes reachable
# from the root by following a path via at most 3 edges will be shown. Nodes
# that lay further from the root node will be omitted. Note that setting this
# option to 1 or 2 may greatly reduce the computation time needed for large
# code bases. Also note that a graph may be further truncated if the graph's
# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
# the graph is not depth-constrained.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, which results in a white background.
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.
# JW
# DOT_MULTI_TARGETS = NO
DOT_MULTI_TARGETS = YES
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
# remove the intermediate dot files that are used to generate
# the various graphs.
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
# JW SEARCHENGINE = NO
SEARCHENGINE = YES
================================================
FILE: doc/manual.asciidoc
================================================
The Ninja build system
======================
Introduction
------------
Ninja is yet another build system. It takes as input the
interdependencies of files (typically source code and output
executables) and orchestrates building them, _quickly_.
Ninja joins a sea of other build systems. Its distinguishing goal is
to be fast. It is born from
http://neugierig.org/software/chromium/notes/2011/02/ninja.html[my
work on the Chromium browser project], which has over 30,000 source
files and whose other build systems (including one built from custom
non-recursive Makefiles) would take ten seconds to start building
after changing one file. Ninja is under a second.
Philosophical overview
~~~~~~~~~~~~~~~~~~~~~~
Where other build systems are high-level languages, Ninja aims to be
an assembler.
Build systems get slow when they need to make decisions. When you are
in an edit-compile cycle you want it to be as fast as possible -- you
want the build system to do the minimum work necessary to figure out
what needs to be built immediately.
Ninja contains the barest functionality necessary to describe
arbitrary dependency graphs. Its lack of syntax makes it impossible
to express complex decisions.
Instead, Ninja is intended to be used with a separate program
generating its input files. The generator program (like the
`./configure` found in autotools projects) can analyze system
dependencies and make as many decisions as possible up front so that
incremental builds stay fast. Going beyond autotools, even build-time
decisions like "which compiler flags should I use?" or "should I
build a debug or release-mode binary?" belong in the `.ninja` file
generator.
Design goals
~~~~~~~~~~~~
Here are the design goals of Ninja:
* very fast (i.e., instant) incremental builds, even for very large
projects.
* very little policy about how code is built. Different projects and
higher-level build systems have different opinions about how code
should be built; for example, should built objects live alongside
the sources or should all build output go into a separate directory?
Is there a "package" rule that builds a distributable package of
the project? Sidestep these decisions by trying to allow either to
be implemented, rather than choosing, even if that results in
more verbosity.
* get dependencies correct, and in particular situations that are
difficult to get right with Makefiles (e.g. outputs need an implicit
dependency on the command line used to generate them; to build C
source code you need to use gcc's `-M` flags for header
dependencies).
* when convenience and speed are in conflict, prefer speed.
Some explicit _non-goals_:
* convenient syntax for writing build files by hand. _You should
generate your ninja files using another program_. This is how we
can sidestep many policy decisions.
* built-in rules. _Out of the box, Ninja has no rules for
e.g. compiling C code._
* build-time customization of the build. _Options belong in
the program that generates the ninja files_.
* build-time decision-making ability such as conditionals or search
paths. _Making decisions is slow._
To restate, Ninja is faster than other build systems because it is
painfully simple. You must tell Ninja exactly what to do when you
create your project's `.ninja` files.
Comparison to Make
~~~~~~~~~~~~~~~~~~
Ninja is closest in spirit and functionality to Make, relying on
simple dependencies between file timestamps.
But fundamentally, make has a lot of _features_: suffix rules,
functions, built-in rules that e.g. search for RCS files when building
source. Make's language was designed to be written by humans. Many
projects find make alone adequate for their build problems.
In contrast, Ninja has almost no features; just those necessary to get
builds correct while punting most complexity to generation of the
ninja input files. Ninja by itself is unlikely to be useful for most
projects.
Here are some of the features Ninja adds to Make. (These sorts of
features can often be implemented using more complicated Makefiles,
but they are not part of make itself.)
* Ninja has special support for discovering extra dependencies at build
time, making it easy to get <<ref_headers,header dependencies>>
correct for C/C++ code.
* A build edge may have multiple outputs.
* Outputs implicitly depend on the command line that was used to generate
them, which means that changing e.g. compilation flags will cause
the outputs to rebuild.
* Output directories are always implicitly created before running the
command that relies on them.
* Rules can provide shorter descriptions of the command being run, so
you can print e.g. `CC foo.o` instead of a long command line while
building.
* Builds are always run in parallel, based by default on the number of
CPUs your system has. Underspecified build dependencies will result
in incorrect builds.
* Command output is always buffered. This means commands running in
parallel don't interleave their output, and when a command fails we
can print its failure output next to the full command line that
produced the failure.
Using Ninja for your project
----------------------------
Ninja currently works on Unix-like systems and Windows. It's seen the
most testing on Linux (and has the best performance there) but it runs
fine on Mac OS X and FreeBSD.
If your project is small, Ninja's speed impact is likely unnoticeable.
(However, even for small projects it sometimes turns out that Ninja's
limited syntax forces simpler build rules that result in faster
builds.) Another way to say this is that if you're happy with the
edit-compile cycle time of your project already then Ninja won't help.
There are many other build systems that are more user-friendly or
featureful than Ninja itself. For some recommendations: the Ninja
author found http://gittup.org/tup/[the tup build system] influential
in Ninja's design, and thinks https://github.com/apenwarr/redo[redo]'s
design is quite clever.
Ninja's benefit comes from using it in conjunction with a smarter
meta-build system.
https://gn.googlesource.com/gn/[gn]:: The meta-build system used to
generate build files for Google Chrome and related projects (v8,
node.js), as well as Google Fuchsia. gn can generate Ninja files for
all platforms supported by Chrome.
https://cmake.org/[CMake]:: A widely used meta-build system that
can generate Ninja files on Linux as of CMake version 2.8.8. Newer versions
of CMake support generating Ninja files on Windows and Mac OS X too.
https://github.com/ninja-build/ninja/wiki/List-of-generators-producing-ninja-build-files[others]:: Ninja ought to fit perfectly into other meta-build software
like https://premake.github.io/[premake]. If you do this work,
please let us know!
Running Ninja
~~~~~~~~~~~~~
Run `ninja`. By default, it looks for a file named `build.ninja` in
the current directory and builds all out-of-date targets. You can
specify which targets (files) to build as command line arguments.
There is also a special syntax `target^` for specifying a target
as the first output of some rule containing the source you put in
the command line, if one exists. For example, if you specify target as
`foo.c^` then `foo.o` will get built (assuming you have those targets
in your build files).
`ninja -h` prints help output. Many of Ninja's flags intentionally
match those of Make; e.g `ninja -C build -j 20` changes into the
`build` directory and runs 20 build commands in parallel. (Note that
Ninja defaults to running commands in parallel anyway, so typically
you don't need to pass `-j`.)
GNU Jobserver support
~~~~~~~~~~~~~~~~~~~~~
Since version 1.13., Ninja builds can follow the
https://www.gnu.org/software/make/manual/html_node/Job-Slots.html[GNU Make jobserver]
client protocol. This is useful when Ninja is invoked as part of a larger
build system controlled by a top-level GNU Make instance, or any other
jobserver pool implementation, as it allows better coordination between
concurrent build tasks.
This feature is automatically enabled under the following conditions:
- Dry-run (i.e. `-n` or `--dry-run`) is not enabled.
- No explicit job count (e.g. `-j<COUNT>`) is passed on the command
line.
- The `MAKEFLAGS` environment variable is defined and describes a valid
jobserver mode using `--jobserver-auth=SEMAPHORE_NAME` on Windows, or
`--jobserver-auth=fifo:PATH` on Posix.
In this case, Ninja will use the jobserver pool of job slots to control
parallelism, instead of its default parallel implementation.
Note that load-average limitations (i.e. when using `-l<count>`)
are still being enforced in this mode.
IMPORTANT: On Posix, only the FIFO-based version of the protocol, which is
implemented by GNU Make 4.4 and higher, is supported. Ninja will detect
when a pipe-based jobserver is being used (i.e. when `MAKEFLAGS` contains
`--jobserver-auth=<read>,<write>`) and will print a warning, but will
otherwise ignore it.
Environment variables
~~~~~~~~~~~~~~~~~~~~~
Ninja supports two environment variables to control its behavior:
`NINJA_STATUS`, the progress status printed before the rule being run.
Several placeholders are available:
`%s`:: The number of started edges.
`%t`:: The total number of edges that must be run to complete the build.
`%p`:: The percentage of finished edges.
`%r`:: The number of currently running edges.
`%u`:: The number of remaining edges to start.
`%f`:: The number of finished edges.
`%o`:: Overall rate of finished edges per second
`%c`:: Current rate of finished edges per second (average over builds
specified by `-j` or its default)
`%e`:: Elapsed time in seconds. _(Available since Ninja 1.2.)_
`%E`:: Remaining time (ETA) in seconds. _(Available since Ninja 1.12.)_
`%w`:: Elapsed time in [h:]mm:ss format. _(Available since Ninja 1.12.)_
`%W`:: Remaining time (ETA) in [h:]mm:ss format. _(Available since Ninja 1.12.)_
`%P`:: The percentage (in ppp% format) of time elapsed out of predicted total runtime. _(Available since Ninja 1.12.)_
`%%`:: A plain `%` character.
The default progress status is `"[%f/%t] "` (note the trailing space
to separate from the build rule). Another example of possible progress status
could be `"[%u/%r/%f] "`.
If `MAKEFLAGS` is defined in the environment, if may alter how
Ninja dispatches parallel build commands. See the GNU Jobserver support
section for details.
Extra tools
~~~~~~~~~~~
The `-t` flag on the Ninja command line runs some tools that we have
found useful during Ninja's development. The current tools are:
[horizontal]
`query`:: dump the inputs and outputs of a given target.
`browse`:: browse the dependency graph in a web browser. Clicking a
file focuses the view on that file, showing inputs and outputs. This
feature requires a Python installation. By default, port 8000 is used
and a web browser will be opened. This can be changed as follows:
+
----
ninja -t browse --port=8000 --no-browser mytarget
----
+
Use `--help` to see a full list of options.
+
`graph`:: output a file in the syntax used by `graphviz`, an automatic
graph layout tool. Use it like:
+
----
ninja -t graph mytarget | dot -Tpng -ograph.png
----
+
In the Ninja source tree, `ninja graph.png`
generates an image for Ninja itself. If no target is given generate a
graph for all root targets.
`targets`:: output a list of targets either by rule or by depth. If used
like +ninja -t targets rule _name_+ it prints the list of targets
using the given rule to be built. If no rule is given, it prints the source
files (the leaves of the graph). If used like
+ninja -t targets depth _digit_+ it
prints the list of targets in a depth-first manner starting by the root
targets (the ones with no outputs). Indentation is used to mark dependencies.
If the depth is zero it prints all targets. If no arguments are provided
+ninja -t targets depth 1+ is assumed. In this mode targets may be listed
several times. If used like this +ninja -t targets all+ it
prints all the targets available without indentation and it is faster
than the _depth_ mode.
`commands`:: given a list of targets, print a list of commands which, if
executed in order, may be used to rebuild those targets, assuming that all
output files are out of date. Use `-s` to only print the final command, not the chain.
`inputs`:: given a list of targets, print a list of all inputs used to
rebuild those targets. For compatibility reasons, inputs are shell-quoted by default.
Use `--no-shell-escape` to disable quoting. See `ninja -t inputs --help` for all options.
_Available since Ninja 1.11._
`multi-inputs`:: print one or more sets of inputs required to build targets.
Each line will consist of a target, a delimiter, an input and a terminator character.
The list produced by the tool can be helpful if one would like to know which targets
that are affected by a certain input.
+
The output will be a series of lines with the following elements:
+
----
<target> <delimiter> <input> <terminator>
----
+
The default `<delimiter>` is a single TAB character.
The delimiter can be modified to any string using the `--delimiter` argument.
+
The default `<terminator>` is a line terminator (i.e. `\n` on Posix and `\r\n` on Windows).
The terminator can be changed to `\0` by using the `--print0` argument.
+
----
----
+
Example usage of the `multi-inputs` tool:
+
----
ninja -t multi-inputs target1 target2 target3
----
+
Example of produced output from the `multi-inputs` tool:
+
----
target1 file1.c
target2 file1.c
target2 file2.c
target3 file1.c
target3 file2.c
target3 file3.c
----
+
_Note that a given input may appear for several targets if it is used by more
than one targets._
_Available since Ninja 1.13._
`clean`:: remove built files. By default, it removes all built files
except for those created by the generator. Adding the `-g` flag also
removes built files created by the generator (see <<ref_rule,the rule
reference for the +generator+ attribute>>). Additional arguments are
targets, which removes the given targets and recursively all files
built for them.
+
If used like +ninja -t clean -r _rules_+ it removes all files built using
the given rules.
+
Files created but not referenced in the graph are not removed. This
tool takes in account the +-v+ and the +-n+ options (note that +-n+
implies +-v+).
`cleandead`:: remove files produced by previous builds that are no longer in the
build file. _Available since Ninja 1.10._
`compdb`:: given a list of rules, each of which is expected to be a
C family language compiler rule whose first input is the name of the
source file, prints on standard output a compilation database in the
http://clang.llvm.org/docs/JSONCompilationDatabase.html[JSON format] expected
by the Clang tooling interface. Use `-x` to expand `@rspfile` response file invocations.
_Available since Ninja 1.2._
`compdb-targets`:: like `compdb`, but takes a list of targets instead of rules,
and expects at least one target. The resulting compilation database contains
all commands required to build the indicated targets, and _only_ those
commands. Use `-x` to expand `@rspfile` response file invocations.
`deps`:: show all dependencies stored in the `.ninja_deps` file. When given a
target, show just the target's dependencies. _Available since Ninja 1.4._
`missingdeps`:: given a list of targets, look for targets that depend on
a generated file, but do not have a properly (possibly transitive) dependency
on the generator. Such targets may cause build flakiness on clean builds.
+
The broken targets can be found assuming deps log / depfile dependency
information is correct. Any target that depends on a generated file (output
of a generator-target) implicitly, but does not have an explicit or order-only
dependency path to the generator-target, is considered broken.
+
The tool's findings can be verified by trying to build the listed targets in
a clean outdir without building any other targets. The build should fail for
each of them with a missing include error or equivalent pointing to the
generated file.
_Available since Ninja 1.11._
`recompact`:: recompact the `.ninja_deps` file. _Available since Ninja 1.4._
`restat`:: updates all recorded file modification timestamps in the `.ninja_log`
file. _Available since Ninja 1.10._
+
The build manifest won't be parsed when running this tool. If you're using a
`builddir` you must pass it via `--builddir=DIR`. _Available since Ninja 1.14._
`rules`:: output the list of all rules. It can be used to know which rule name
to pass to +ninja -t targets rule _name_+ or +ninja -t compdb+. Adding the `-d`
flag also prints the description of the rules.
`msvc`:: Available on Windows hosts only.
Helper tool to invoke the `cl.exe` compiler with a pre-defined set of
environment variables, as in:
+
----
ninja -t msvc -e ENVFILE -- cl.exe <arguments>
----
+
Where `ENVFILE` is a binary file that contains an environment block suitable
for CreateProcessA() on Windows (i.e. a series of zero-terminated strings that
look like NAME=VALUE, followed by an extra zero terminator). Note that this uses
the local codepage encoding.
+
This tool also supports a deprecated way of parsing the compiler's output when
the `/showIncludes` flag is used, and generating a GCC-compatible depfile from it:
+
----
ninja -t msvc -o DEPFILE [-p STRING] -- cl.exe /showIncludes <arguments>
----
+
When using this option, `-p STRING` can be used to pass the localized line prefix
that `cl.exe` uses to output dependency information. For English-speaking regions
this is `"Note: including file: "` without the double quotes, but will be different
for other regions.
+
Note that Ninja supports this natively now, with the use of `deps = msvc` and
`msvc_deps_prefix` in Ninja files. Native support also avoids launching an extra
tool process each time the compiler must be called, which can speed up builds
noticeably on Windows.
`wincodepage`:: Available on Windows hosts (_since Ninja 1.11_).
Prints the Windows code page whose encoding is expected in the build file.
The output has the form:
+
----
Build file encoding: <codepage>
----
+
Additional lines may be added in future versions of Ninja.
+
The `<codepage>` is one of:
`UTF-8`::: Encode as UTF-8.
`ANSI`::: Encode to the system-wide ANSI code page.
Writing your own Ninja files
----------------------------
The remainder of this manual is only useful if you are constructing
Ninja files yourself: for example, if you're writing a meta-build
system or supporting a new language.
Conceptual overview
~~~~~~~~~~~~~~~~~~~
Ninja evaluates a graph of dependencies between files, and runs
whichever commands are necessary to make your build target up to date
as determined by file modification times. If you are familiar with
Make, Ninja is very similar.
A build file (default name: `build.ninja`) provides a list of _rules_
-- short names for longer commands, like how to run the compiler --
along with a list of _build_ statements saying how to build files
using the rules -- which rule to apply to which inputs to produce
which outputs.
Conceptually, `build` statements describe the dependency graph of your
project, while `rule` statements describe how to generate the files
along a given edge of the graph.
Syntax example
~~~~~~~~~~~~~~
Here's a basic `.ninja` file that demonstrates most of the syntax.
It will be used as an example for the following sections.
---------------------------------
cflags = -Wall
rule cc
command = gcc $cflags -c $in -o $out
build foo.o: cc foo.c
---------------------------------
Variables
~~~~~~~~~
Despite the non-goal of being convenient to write by hand, to keep
build files readable (debuggable), Ninja supports declaring shorter
reusable names for strings. A declaration like the following
----------------
cflags = -g
----------------
can be used on the right side of an equals sign, dereferencing it with
a dollar sign, like this:
----------------
rule cc
command = gcc $cflags -c $in -o $out
----------------
Variables can also be referenced using curly braces like `${in}`.
Variables might better be called "bindings", in that a given variable
cannot be changed, only shadowed. There is more on how shadowing works
later in this document.
Rules
~~~~~
Rules declare a short name for a command line. They begin with a line
consisting of the `rule` keyword and a name for the rule. Then
follows an indented set of `variable = value` lines.
The basic example above declares a new rule named `cc`, along with the
command to run. In the context of a rule, the `command` variable
defines the command to run, `$in` expands to the list of
input files (`foo.c`), and `$out` to the output files (`foo.o`) for the
command. A full list of special variables is provided in
<<ref_rule,the reference>>.
Build statements
~~~~~~~~~~~~~~~~
Build statements declare a relationship between input and output
files. They begin with the `build` keyword, and have the format
+build _outputs_: _rulename_ _inputs_+. Such a declaration says that
all of the output files are derived from the input files. When the
output files are missing or when the inputs change, Ninja will run the
rule to regenerate the outputs.
The basic example above describes how to build `foo.o`, using the `cc`
rule.
In the scope of a `build` block (including in the evaluation of its
associated `rule`), the variable `$in` is the list of inputs and the
variable `$out` is the list of outputs.
A build statement may be followed by an indented set of `key = value`
pairs, much like a rule. These variables will shadow any variables
when evaluating the variables in the command. For example:
----------------
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
----------------
For more discussion of how scoping works, consult <<ref_scope,the
reference>>.
If you need more complicated information passed from the build
statement to the rule (for example, if the rule needs "the file
extension of the first input"), pass that through as an extra
variable, like how `cflags` is passed above.
If the top-level Ninja file is specified as an output of any build
statement and it is out of date, Ninja will rebuild and reload it
before building the targets requested by the user.
Generating Ninja files from code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`misc/ninja_syntax.py` in the Ninja distribution is a tiny Python
module to facilitate generating Ninja files. It allows you to make
Python calls like `ninja.rule(name='foo', command='bar',
depfile='$out.d')` and it will generate the appropriate syntax. Feel
free to just inline it into your project's build system if it's
useful.
More details
------------
The `phony` rule
~~~~~~~~~~~~~~~~
The special rule name `phony` can be used to create aliases for other
targets. For example:
----------------
build foo: phony some/file/in/a/faraway/subdir/foo
----------------
This makes `ninja foo` build the longer path. Semantically, the
`phony` rule is equivalent to a plain rule where the `command` does
nothing, but phony rules are handled specially in that they aren't
printed when run, logged (see below), nor do they contribute to the
command count printed as part of the build process.
When a `phony` target is used as an input to another build rule, the
other build rule will, semantically, consider the inputs of the
`phony` rule as its own. Therefore, `phony` rules can be used to group
inputs, e.g. header files.
`phony` can also be used to create dummy targets for files which
may not exist at build time. If a phony build statement is written
without any dependencies, the target will be considered out of date if
it does not exist. Without a phony build statement, Ninja will report
an error if the file does not exist and is required by the build.
To create a rule that never rebuilds, use a build rule without any input:
----------------
rule touch
command = touch $out
build file_that_always_exists.dummy: touch
build dummy_target_to_follow_a_pattern: phony file_that_always_exists.dummy
----------------
Default target statements
~~~~~~~~~~~~~~~~~~~~~~~~~
By default, if no targets are specified on the command line, Ninja
will build every output that is not named as an input elsewhere.
You can override this behavior using a default target statement.
A default target statement causes Ninja to build only a given subset
of output files if none are specified on the command line.
Default target statements begin with the `default` keyword, and have
the format +default _targets_+. A default target statement must appear
after the build statement that declares the target as an output file.
They are cumulative, so multiple statements may be used to extend
the list of default targets. For example:
----------------
default foo bar
default baz
----------------
This causes Ninja to build the `foo`, `bar` and `baz` targets by
default.
[[ref_log]]
The Ninja log
~~~~~~~~~~~~~
For each built file, Ninja keeps a log of the command used to build
it. Using this log Ninja can know when an existing output was built
with a different command line than the build files specify (i.e., the
command line changed) and knows to rebuild the file.
The log file is kept in the build root in a file called `.ninja_log`.
If you provide a variable named `builddir` in the outermost scope,
`.ninja_log` will be kept in that directory instead.
[[ref_versioning]]
Version compatibility
~~~~~~~~~~~~~~~~~~~~~
_Available since Ninja 1.2._
Ninja version labels follow the standard major.minor.patch format,
where the major version is increased on backwards-incompatible
syntax/behavioral changes and the minor version is increased on new
behaviors. Your `build.ninja` may declare a variable named
`ninja_required_version` that asserts the minimum Ninja version
required to use the generated file. For example,
-----
ninja_required_version = 1.1
-----
declares that the build file relies on some feature that was
introduced in Ninja 1.1 (perhaps the `pool` syntax), and that
Ninja 1.1 or greater must be used to build. Unlike other Ninja
variables, this version requirement is checked immediately when
the variable is encountered in parsing, so it's best to put it
at the top of the build file.
Ninja always warns if the major versions of Ninja and the
`ninja_required_version` don't match; a major version change hasn't
come up yet so it's difficult to predict what behavior might be
required.
[[ref_headers]]
C/C++ header dependencies
~~~~~~~~~~~~~~~~~~~~~~~~~
To get C/C++ header dependencies (or any other build dependency that
works in a similar way) correct Ninja has some extra functionality.
The problem with headers is that the full list of files that a given
source file depends on can only be discovered by the compiler:
different preprocessor defines and include paths cause different files
to be used. Some compilers can emit this information while building,
and Ninja can use that to get its dependencies perfect.
Consider: if the file has never been compiled, it must be built anyway,
generating the header dependencies as a side effect. If any file is
later modified (even in a way that changes which headers it depends
on) the modification will cause a rebuild as well, keeping the
dependencies up to date.
When loading these special dependencies, Ninja implicitly adds extra
build edges such that it is not an error if the listed dependency is
missing. This allows you to delete a header file and rebuild without
the build aborting due to a missing input.
depfile
^^^^^^^
`gcc` (and other compilers like `clang`) support emitting dependency
information in the syntax of a Makefile. (Any command that can write
dependencies in this form can be used, not just `gcc`.)
To bring this information into Ninja requires cooperation. 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.) Then the command
must know to write dependencies into the `depfile` path.
Use it like in the following example:
----
rule cc
depfile = $out.d
command = gcc -MD -MF $out.d [other gcc flags here]
----
The `-MD` flag to `gcc` tells it to output header dependencies, and
the `-MF` flag tells it where to write them.
deps
^^^^
_(Available since Ninja 1.3.)_
It turns out that for large projects (and particularly on Windows,
where the file system is slow) loading these dependency files on
startup is slow.
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.
Ninja supports this processing in two forms.
1. `deps = gcc` specifies that the tool outputs `gcc`-style dependencies
in the form of Makefiles. Adding this to the above example will
cause Ninja to process the `depfile` immediately after the
compilation finishes, then delete the `.d` file (which is only used
as a temporary).
2. `deps = msvc` specifies that the tool outputs header dependencies
in the form produced by the Visual Studio compiler's
http://msdn.microsoft.com/en-us/library/hdkef6tk(v=vs.90).aspx[`/showIncludes`
flag]. Briefly, this means the tool outputs specially-formatted lines
to its stdout. Ninja then filters these lines from the displayed
output. No `depfile` attribute is necessary, but the localized string
in front of the header file path should be globally defined. For instance,
`msvc_deps_prefix = Note: including file:`
for an English Visual Studio (the default).
+
----
msvc_deps_prefix = Note: including file:
rule cc
deps = msvc
command = cl /showIncludes -c $in /Fo$out
----
If the include directory directives are using absolute paths, your depfile
may result in a mixture of relative and absolute paths. Paths used by other
build rules need to match exactly. Therefore, it is recommended to use
relative paths in these cases.
[[ref_pool]]
Pools
~~~~~
_Available since Ninja 1.1._
Pools allow you to allocate one or more rules or edges a finite number
of concurrent jobs which is more tightly restricted than the default
parallelism.
This can be useful, for example, to restrict a particular expensive rule
(like link steps for huge executables), or to restrict particular build
statements which you know perform poorly when run concurrently.
Each pool has a `depth` variable which is specified in the build file.
The pool is then referred to with the `pool` variable on either a rule
or a build statement.
No matter what pools you specify, ninja will never run more concurrent jobs
than the default parallelism, or the number of jobs specified on the command
line (with `-j`).
----------------
# 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
rule cc
...
# The link_pool is used here. Only 4 links will run concurrently.
build foo.exe: link input.obj
# A build statement can be exempted from its rule's pool by setting an
# empty pool. This effectively puts the build statement back into the default
# pool, which has infinite depth.
build other.exe: link input.obj
pool =
# A build statement can specify a pool directly.
# Only one of these builds will run at a time.
build heavy_object1.obj: cc heavy_obj1.cc
pool = heavy_object_pool
build heavy_object2.obj: cc heavy_obj2.cc
pool = heavy_object_pool
----------------
The `console` pool
^^^^^^^^^^^^^^^^^^
_Available since Ninja 1.5._
There exists a pre-defined pool named `console` with a depth of 1. It has
the special property that any task in the pool has direct access to the
standard input, output and error streams provided to Ninja, which are
normally connected to the user's console (hence the name) but could be
redirected. This can be useful for interactive tasks or long-running tasks
which produce status updates on the console (such as test suites).
While a task in the `console` pool is running, Ninja's regular output (such
as progress status and output from concurrent tasks) is buffered until
it completes.
[[ref_ninja_file]]
Ninja file reference
--------------------
A file is a series of declarations. A declaration can be one of:
1. A rule declaration, which begins with +rule _rulename_+, and
then has a series of indented lines defining variables.
2. A build edge, which looks like +build _output1_ _output2_:
_rulename_ _input1_ _input2_+. +
Implicit dependencies may be tacked on the end with +|
_dependency1_ _dependency2_+. +
Order-only dependencies may be tacked on the end with +||
_dependency1_ _dependency2_+. (See <<ref_dependencies,the reference on
dependency types>>.)
Validations may be tacked on the end with +|@ _validation1_ _validation2_+.
(See <<validations,the reference on validations>>.)
+
Implicit outputs _(available since Ninja 1.7)_ may be added before
the `:` with +| _output1_ _output2_+ and do not appear in `$out`.
(See <<ref_outputs,the reference on output types>>.)
3. Variable declarations, which look like +_variable_ = _value_+.
4. Default target statements, which look like +default _target1_ _target2_+.
5. References to more files, which look like +subninja _path_+ or
+include _path_+. The difference between these is explained below
<<ref_scope,in the discussion about scoping>>.
6. A pool declaration, which looks like +pool _poolname_+. Pools are explained
<<ref_pool, in the section on pools>>.
[[ref_lexer]]
Lexical syntax
~~~~~~~~~~~~~~
Ninja is mostly encoding agnostic, as long as the bytes Ninja cares
about (like slashes in paths) are ASCII. This means e.g. UTF-8 or
ISO-8859-1 input files ought to work.
Comments begin with `#` and extend to the end of the line.
Newlines are significant. Statements like `build foo bar` are a set
of space-separated tokens that end at the newline. Newlines and
spaces within a token must be escaped.
There is only one escape character, `$`, and it has the following
behaviors:
`$` followed by a newline:: escape the newline (continue the current line
across a line break).
`$` followed by text:: a variable reference.
`${varname}`:: alternate syntax for `$varname`.
`$` followed by space:: a space. (This is only necessary in lists of
paths, where a space would otherwise separate filenames. See below.)
`$:` :: a colon. (This is only necessary in `build` lines, where a colon
would otherwise terminate the list of outputs.)
`$^` :: a newline _(available since Ninja 1.14)_.
Inserts '\n' into the resulting string. This is useful to
write build commands that require several shell lines as a single `command`
value in the build plan.
Requires `ninja_required_version` to be specified and greater or equal to 1.14
in the build file.
`$$`:: a literal `$`.
A `build` or `default` statement is first parsed as a space-separated
list of filenames and then each name is expanded. This means that
spaces within a variable will result in spaces in the expanded
filename.
----
spaced = foo bar
build $spaced/baz other$ file: ...
# The above build line has two outputs: "foo bar/baz" and "other file".
----
In a `name = value` statement, whitespace at the beginning of a value
is always stripped. Whitespace at the beginning of a line after a
line continuation is also stripped.
----
two_words_with_one_space = foo $
bar
one_word_with_no_space = foo$
bar
----
Other whitespace is only significant if it's at the beginning of a
line. If a line is indented more than the previous one, it's
considered part of its parent's scope; if it is indented less than the
previous one, it closes the previous scope.
[[ref_toplevel]]
Top-level variables
~~~~~~~~~~~~~~~~~~~
Two variables are significant when declared in the outermost file scope.
`builddir`:: a directory for some Ninja output files. See <<ref_log,the
discussion of the build log>>. (You can also store other build output
in this directory.)
`ninja_required_version`:: the minimum version of Ninja required to process
the build correctly. See <<ref_versioning,the discussion of versioning>>.
[[ref_rule]]
Rule variables
~~~~~~~~~~~~~~
A `rule` block contains a list of `key = value` declarations that
affect the processing of the rule. Here is a full list of special
keys.
`command` (_required_):: the command line to run. Each `rule` may
have only one `command` declaration. See <<ref_rule_command,the next
section>> for more details on quoting and executing multiple commands.
`depfile`:: path to an optional `Makefile` that contains extra
_implicit dependencies_ (see <<ref_dependencies,the reference on
dependency types>>). This is explicitly to support C/C++ header
dependencies; see <<ref_headers,the full discussion>>.
`deps`:: _(Available since Ninja 1.3.)_ if present, must be one of
`gcc` or `msvc` to specify special dependency processing. See
<<ref_headers,the full discussion>>. The generated database is
stored as `.ninja_deps` in the `builddir`, see <<ref_toplevel,the
discussion of `builddir`>>.
`msvc_deps_prefix`:: _(Available since Ninja 1.5.)_ defines the string
which should be stripped from msvc's /showIncludes output. Only
needed when `deps = msvc` and no English Visual Studio version is used.
`description`:: a short description of the command, used to pretty-print
the command as it's running. The `-v` flag controls whether to print
the full command or its description; if a command fails, the full command
line will always be printed before the command's output.
`dyndep`:: _(Available since Ninja 1.10.)_ Used only on build statements.
If present, must name one of the build statement inputs. Dynamically
discovered dependency information will be loaded from the file.
See the <<ref_dyndep,dynamic dependencies>> section for details.
`generator`:: if present, specifies that this rule is used to
re-invoke the generator program. Files built using `generator`
rules are treated specially in two ways: firstly, they will not be
rebuilt if the command line changes; and secondly, they are not
cleaned by default.
`in`:: the space-separated list of files provided as inputs to the build line
referencing this `rule`, shell-quoted if it appears in commands. (`$in` is
provided solely for convenience; if you need some subset or variant of this
list of files, just construct a new variable with that list and use
that instead.)
`in_newline`:: the same as `$in` except that multiple inputs are
separated by newlines rather than spaces. (For use with
`$rspfile_content`; this works around a bug in the MSVC linker where
it uses a fixed-size buffer for processing input.)
`out`:: the space-separated list of files provided as outputs to the build line
referencing this `rule`, shell-quoted if it appears in commands.
`restat`:: if present, causes Ninja to re-stat the command's outputs
after execution of the command. Each output whose modification time
the command did not change will be treated as though it had never
needed to be built. This may cause the output's reverse
dependencies to be removed from the list of pending build actions.
`rspfile`, `rspfile_content`:: if present (both), Ninja will use a
response file for the given command, i.e. write the selected string
(`rspfile_content`) to the given file (`rspfile`) before calling the
command and delete the file after successful execution of the
command.
+
This is particularly useful on Windows OS, where the maximal length of
a command line is limited and response files must be used instead.
+
Use it like in the following example:
+
----
rule link
command = link.exe /OUT$out [usual link flags here] @$out.rsp
rspfile = $out.rsp
rspfile_content = $in
build myapp.exe: link a.obj b.obj [possibly many other .obj files]
----
[[ref_rule_command]]
Interpretation of the `command` variable
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Fundamentally, command lines behave differently on Unixes and Windows.
On Unixes, commands are arrays of arguments. The Ninja `command`
variable is passed directly to `sh -c`, which is then responsible for
interpreting that string into an argv array. Therefore, the quoting
rules are those of the shell, and you can use all the normal shell
operators, like `&&` to chain multiple commands, or `VAR=value cmd` to
set environment variables.
On Windows, commands are strings, so Ninja passes the `command` string
directly to `CreateProcess`. (In the common case of simply executing
a compiler this means there is less overhead.) Consequently, the
quoting rules are determined by the called program, which on Windows
are usually provided by the C library. If you need shell
interpretation of the command (such as the use of `&&` to chain
multiple commands), make the command execute the Windows shell by
prefixing the command with `cmd /c`. Ninja may error with "invalid parameter"
which usually indicates that the command line length has been exceeded.
[[ref_outputs]]
Build outputs
~~~~~~~~~~~~~
There are two types of build outputs which are subtly different.
1. _Explicit outputs_, as listed in a build line. These are
available as the `$out` variable in the rule.
+
This is the standard form of output to be used for e.g. the
object file of a compile command.
2. _Implicit outputs_, as listed in a build line with the syntax +|
_out1_ _out2_+ before the `:` of a build line _(available since
Ninja 1.7)_. The semantics are identical to explicit outputs,
the only difference is that implicit outputs don't show up in the
`$out` variable.
+
This is for expressing outputs that don't show up on the
command line of the command.
[[ref_dependencies]]
Build dependencies
~~~~~~~~~~~~~~~~~~
There are three types of build dependencies which are subtly different.
1. _Explicit dependencies_, as listed in a build line. These are
available as the `$in` variable in the rule. Changes in these files
cause the output to be rebuilt; if these files are missing and
Ninja doesn't know how to build them, the build is aborted.
+
This is the standard form of dependency to be used e.g. for the
source file of a compile command.
2. _Implicit dependencies_, either as picked up from
a `depfile` attribute on a rule or from the syntax +| _dep1_
_dep2_+ on the end of a build line. The semantics are identical to
explicit dependencies, the only difference is that implicit dependencies
don't show up in the `$in` variable.
+
This is for expressing dependencies that don't show up on the
command line of the command; for example, for a rule that runs a
script that reads a hardcoded file, the hardcoded file should
be an implicit dependency, as changes to the file should cause
the output to rebuild, even though it doesn't show up in the arguments.
+
Note that dependencies as loaded through depfiles have slightly different
semantics, as described in the <<ref_rule,rule reference>>.
3. _Order-only dependencies_, expressed with the syntax +|| _dep1_
_dep2_+ on the end of a build line. When these are out of date, the
output is not rebuilt until they are built, but changes in order-only
dependencies alone do not cause the output to be rebuilt.
+
Order-only dependencies can be useful for bootstrapping dependencies
that are only discovered during build time: for example, to generate a
header file before starting a subsequent compilation step. (Once the
header is used in compilation, a generated dependency file will then
express the implicit dependency.)
File paths are compared as is, which means that an absolute path and a
relative path, pointing to the same file, are considered different by Ninja.
[[validations]]
Validations
~~~~~~~~~~~
_Available since Ninja 1.11._
Validations listed on the build line cause the specified files to be
added to the top level of the build graph (as if they were specified
on the Ninja command line) whenever the build line is a transitive
dependency of one of the targets specified on the command line or a
default target.
Validations are added to the build graph regardless of whether the output
files of the build statement are dirty are not, and the dirty state of
the build statement that outputs the file being used as a validation
has no effect on the dirty state of the build statement that requested it.
A build edge can list another build edge as a validation even if the second
edge depends on the first.
Validations are designed to handle rules that perform error checking but
don't produce any artifacts needed by the build, for example, static
analysis tools. Marking the static analysis rule as an implicit input
of the main build rule of the source files or of the rules that depend
on the main build rule would slow down the critical path of the build,
but using a validation would allow the build to proceed in parallel with
the static analysis rule once the main build rule is complete.
Variable expansion
~~~~~~~~~~~~~~~~~~
Variables are expanded in paths (in a `build` or `default` statement)
and on the right side of a `name = value` statement.
When a `name = value` statement is evaluated, its right-hand side is
expanded immediately (according to the below scoping rules), and
from then on `$name` expands to the static string as the result of the
expansion. It is never the case that you'll need to "double-escape" a
value to prevent it from getting expanded twice.
All variables are expanded immediately as they're encountered in parsing,
with one important exception: variables in `rule` blocks are expanded
when the rule is _used_, not when it is declared. In the following
example, the `demo` rule prints "this is a demo of bar".
----
rule demo
command = echo "this is a demo of $foo"
build out: demo
foo = bar
----
[[ref_scope]]
Evaluation and scoping
~~~~~~~~~~~~~~~~~~~~~~
Top-level variable declarations are scoped to the file they occur in.
Rule declarations are also scoped to the file they occur in.
_(Available since Ninja 1.6)_
The `subninja` keyword, used to include another `.ninja` file,
introduces a new scope. The included `subninja` file may use the
variables and rules from the parent file, and shadow their values for the file's
scope, but it won't affect values of the variables in the parent.
To include another `.ninja` file in the current scope, much like a C
`#include` statement, use `include` instead of `subninja`.
Variable declarations indented in a `build` block are scoped to the
`build` block. 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`).
(Note from the above discussion on expansion that these are
expanded "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.
[[ref_dyndep]]
Dynamic Dependencies
--------------------
_Available since Ninja 1.10._
Some use cases require implicit dependency information to be dynamically
discovered from source file content _during the build_ in order to build
correctly on the first run (e.g. Fortran module dependencies). This is
unlike <<ref_headers,header dependencies>> which are only needed on the
second run and later to rebuild correctly. A build statement may have a
`dyndep` binding naming one of its inputs to specify that dynamic
dependency information must be loaded from the file. For example:
----
build out: ... || foo
dyndep = foo
build foo: ...
----
This specifies that file `foo` is a dyndep file. Since it is an input,
the build statement for `out` can never be executed before `foo` is built.
As soon as `foo` is finished Ninja will read it to load dynamically
discovered dependency information for `out`. This may include additional
implicit inputs and/or outputs. Ninja will update the build graph
accordingly and the build will proceed as if the information was known
originally.
Dyndep file reference
~~~~~~~~~~~~~~~~~~~~~
Files specified by `dyndep` bindings use the same <<ref_lexer,lexical syntax>>
as <<ref_ninja_file,ninja build files>> and have the following layout.
1. A version number in the form `<major>[.<minor>][<suffix>]`:
+
----
ninja_dyndep_version = 1
----
+
Currently the version number must always be `1` or `1.0` but may have
an arbitrary suffix.
2. One or more build statements of the form:
+
----
build out | imp-outs... : dyndep | imp-ins...
----
+
Every statement must specify exactly one explicit output and must use
the rule name `dyndep`. The `| imp-outs...` and `| imp-ins...` portions
are optional.
3. An optional `restat` <<ref_rule,variable binding>> on each build statement.
The build statements in a dyndep file must have a one-to-one correspondence
to build statements in the <<ref_ninja_file,ninja build file>> that name the
dyndep file in a `dyndep` binding. No dyndep build statement may be omitted
and no extra build statements may be specified.
Dyndep Examples
~~~~~~~~~~~~~~~
Fortran Modules
^^^^^^^^^^^^^^^
Consider a Fortran source file `foo.f90` that provides a module
`foo.mod` (an implicit output of compilation) and another source file
`bar.f90` that uses the module (an implicit input of compilation). This
implicit dependency must be discovered before we compile either source
in order to ensure that `bar.f90` never compiles before `foo.f90`, and
that `bar.f90` recompiles when `foo.mod` changes. We can achieve this
as follows:
----
rule f95
command = f95 -o $out -c $in
rule fscan
command = fscan -o $out $in
build foobar.dd: fscan foo.f90 bar.f90
build foo.o: f95 foo.f90 || foobar.dd
dyndep = foobar.dd
build bar.o: f95 bar.f90 || foobar.dd
dyndep = foobar.dd
----
In this example the order-only dependencies ensure that `foobar.dd` is
generated before either source compiles. The hypothetical `fscan` tool
scans the source files, assumes each will be compiled to a `.o` of the
same name, and writes `foobar.dd` with content such as:
----
ninja_dyndep_version = 1
build foo.o | foo.mod: dyndep
build bar.o: dyndep | foo.mod
----
Ninja will load this file to add `foo.mod` as an implicit output of
`foo.o` and implicit input of `bar.o`. This ensures that the Fortran
sources are always compiled in the proper order and recompiled when
needed.
Tarball Extraction
^^^^^^^^^^^^^^^^^^
Consider a tarball `foo.tar` that we want to extract. The extraction time
can be recorded with a `foo.tar.stamp` file so that extraction repeats if
the tarball changes, but we also would like to re-extract if any of the
outputs is missing. However, the list of outputs depends on the content
of the tarball and cannot be spelled out explicitly in the ninja build file.
We can achieve this as follows:
----
rule untar
command = tar xf $in && touch $out
rule scantar
command = scantar --stamp=$stamp --dd=$out $in
build foo.tar.dd: scantar foo.tar
stamp = foo.tar.stamp
build foo.tar.stamp: untar foo.tar || foo.tar.dd
dyndep = foo.tar.dd
----
In this example the order-only dependency ensures that `foo.tar.dd` is
built before the tarball extracts. The hypothetical `scantar` tool
will read the tarball (e.g. via `tar tf`) and write `foo.tar.dd` with
content such as:
----
ninja_dyndep_version = 1
build foo.tar.stamp | file1.txt file2.txt : dyndep
restat = 1
----
Ninja will load this file to add `file1.txt` and `file2.txt` as implicit
outputs of `foo.tar.stamp`, and to mark the build statement for `restat`.
On future builds, if any implicit output is missing the tarball will be
extracted again. The `restat` binding tells Ninja to tolerate the fact
that the implicit outputs may not have modification times newer than
the tarball itself (avoiding re-extraction on every build).
================================================
FILE: doc/style.css
================================================
:root {
color-scheme: light dark;
}
body {
margin: 5ex 10ex;
max-width: 80ex;
line-height: 1.5;
font-family: sans-serif;
}
h1, h2, h3 {
font-weight: normal;
}
pre, code {
font-family: x, monospace;
}
pre {
padding: 1ex;
background: #eee;
border: solid 1px #ddd;
min-width: 0;
font-size: 90%;
}
@media (prefers-color-scheme: dark) {
pre {
background: #333;
border: solid 1px #444;
}
}
code {
color: #007;
}
@media (prefers-color-scheme: dark) {
code {
color: #a7cec8;
}
}
div.chapter {
margin-top: 4em;
border-top: solid 2px black;
}
@media (prefers-color-scheme: dark) {
div.chapter {
border-top: solid 2px white;
}
}
p {
margin-top: 0;
}
/* The following applies to the left column of a [horizontal] labeled list: */
table.horizontal > tbody > tr > td:nth-child(1) {
/* prevent the insertion of a line-break in the middle of a label: */
white-space: nowrap;
/* insert a little horizontal padding between the two columns: */
padding-right: 1.5em;
/* right-justify labels: */
text-align: end;
}
================================================
FILE: misc/afl-fuzz/build.ninja
================================================
rule b
command = clang -MMD -MF $out.d -o $out -c $in
description = building $out
build a.o: b a.c
================================================
FILE: misc/afl-fuzz-tokens/kw_build
================================================
build
================================================
FILE: misc/afl-fuzz-tokens/kw_default
================================================
default
================================================
FILE: misc/afl-fuzz-tokens/kw_include
================================================
include
================================================
FILE: misc/afl-fuzz-tokens/kw_pool
================================================
pool
================================================
FILE: misc/afl-fuzz-tokens/kw_rule
================================================
rule
================================================
FILE: misc/afl-fuzz-tokens/kw_subninja
================================================
subninja
================================================
FILE: misc/afl-fuzz-tokens/misc_a
================================================
a
================================================
FILE: misc/afl-fuzz-tokens/misc_b
================================================
b
================================================
FILE: misc/afl-fuzz-tokens/misc_colon
================================================
:
================================================
FILE: misc/afl-fuzz-tokens/misc_cont
================================================
$
================================================
FILE: misc/afl-fuzz-tokens/misc_dollar
================================================
$
================================================
FILE: misc/afl-fuzz-tokens/misc_eq
================================================
=
================================================
FILE: misc/afl-fuzz-tokens/misc_indent
================================================
================================================
FILE: misc/afl-fuzz-tokens/misc_pipe
================================================
|
================================================
FILE: misc/afl-fuzz-tokens/misc_pipepipe
================================================
||
================================================
FILE: misc/afl-fuzz-tokens/misc_space
================================================
================================================
FILE: misc/bash-completion
================================================
# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Add the following to your .bashrc to tab-complete ninja targets
# . path/to/ninja/misc/bash-completion
_ninja_target() {
local cur prev targets dir line targets_command OPTIND
# When available, use bash_completion to:
# 1) Complete words when the cursor is in the middle of the word
# 2) Complete paths with files or directories, as appropriate
if _get_comp_words_by_ref cur prev &>/dev/null ; then
case $prev in
-f)
_filedir
return 0
;;
-C)
_filedir -d
return 0
;;
esac
else
cur="${COMP_WORDS[COMP_CWORD]}"
fi
if [[ "$cur" == "--"* ]]; then
# there is currently only one argument that takes --
COMPREPLY=($(compgen -P '--' -W 'version' -- "${cur:2}"))
else
dir="."
line=$(echo ${COMP_LINE} | cut -d" " -f 2-)
# filter out all non relevant arguments but keep C for dirs
while getopts :C:f:j:l:k:nvd:t: opt $line; do
case $opt in
# eval for tilde expansion
C) eval dir="$OPTARG" ;;
esac
done;
targets_command="eval ninja -C \"${dir}\" -t targets all 2>/dev/null | cut -d: -f1"
COMPREPLY=($(compgen -W '`${targets_command}`' -- "$cur"))
fi
return
}
complete -F _ninja_target ninja
================================================
FILE: misc/ci.py
================================================
#!/usr/bin/env python3
import os
ignores = [
'.git/',
'misc/afl-fuzz-tokens/',
'src/depfile_parser.cc',
'src/lexer.cc',
]
error_count = 0
def error(path: str, msg: str) -> None:
global error_count
error_count += 1
print('\x1b[1;31m{}\x1b[0;31m{}\x1b[0m'.format(path, msg))
try:
import git
repo = git.Repo('.')
except Exception:
repo = None
for root, directory, filenames in os.walk('.'):
for filename in filenames:
path = os.path.join(root, filename)[2:]
if any([path.startswith(x) for x in ignores]) or (repo is not None and repo.ignored(path)):
continue
with open(path, 'rb') as file:
line_nr = 1
try:
for line in [x.decode() for x in file.readlines()]:
if len(line) == 0 or line[-1] != '\n':
error(path, ' missing newline at end of file.')
if len(line) > 1:
if line[-2] == '\r':
error(path, ' has Windows line endings.')
break
if line[-2] == ' ' or line[-2] == '\t':
error(path, ':{} has trailing whitespace.'.format(line_nr))
line_nr += 1
except UnicodeError:
pass # binary file
exit(error_count)
================================================
FILE: misc/inherited-fds.ninja
================================================
# This build file prints out a list of open file descriptors in
# Ninja subprocesses, to help verify we don't accidentally leak
# any.
# Because one fd leak was in the code managing multiple subprocesses,
# this test brings up multiple subprocesses and then dumps the fd
# table of the last one.
# Use like: ./ninja -f misc/inherited-fds.ninja
rule sleep
command = sleep 10000
rule dump
command = sleep 1; ls -l /proc/self/fd; exit 1
build all: phony a b c d e
build a: sleep
build b: sleep
build c: sleep
build d: sleep
build e: dump
================================================
FILE: misc/jobserver_pool.py
================================================
#!/usr/bin/env python3
# Copyright 2024 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Setup a GNU Make Jobserver jobs pool then launch a command with it.
On Windows, this only supports the semaphore-based scheme.
On Posix, this uses a fifo by default, use --pipe for pipe mode.
On exit, this script verifies that all job slots were returned to
the pool, and will print an error message if this is not the case.
This is useful to catch the use of broken protocol clients.
Use the `--no-check` flag to disable this.
See --help-usage for usage examples.
"""
import argparse
import os
import platform
import subprocess
import sys
import typing as T
# Technical note about the MAKEFLAGS values set by this script.
#
# All the MAKEFLAGS values created by this script begin
# with " -j{count} ", i.e. an initial space, the "-j" characters
# followed by a job slot count then another space.
#
# The initial space is only there to mimic what GNU Make 4.3
# does. Other pool implementations do not use one and thus
# clients should not expect it (even GNU Make doesn't seem
# to care when used as a jobserver client).
#
# The {count} value is also not available in many pool
# implementations, but is useful to better debug multi-builds
# using this script (i.e. to verify that the pool has the
# expected size). Protocol clients should not depend on it
# though.
_DEFAULT_NAME = "jobserver_pool"
_IS_WINDOWS = sys.platform in ("win32", "cygwin")
if _IS_WINDOWS:
try:
# This requires pywin32 to be installed.
import pywintypes
import win32event
import win32api
except ModuleNotFoundError:
print(
"\nERROR: Could not import Win32 API, please install pywin32, e.g. `python -m pip install pywin32`.\n",
file=sys.stderr,
)
raise
# It seems impossible to import a proper mypy-compatible type definition for PyHANDLE
# 'from pywintypes import PyHANDLE' fails stating there is no such name.
# 'from pywintypes import HANDLE as PyHANDLE' fails because HANDLE is a function, not a type.
PyHandle: T.TypeAlias = T.Any
def create_sem(
sem_name: str, jobs_count: int
) -> T.Tuple[PyHandle, T.Dict[str, str]]:
"""Create and initialize Win32 semaphore."""
assert jobs_count > 0, f"Jobs count must be strictly positive"
# The win32event documentation states that the first argument to CreateSemaphore()
# can be None to indicate default security attributes, but mypy only wants
# a PySECURITY_ATTRIBUTES for some reason.
handle = win32event.CreateSemaphore(
None, # type: ignore
jobs_count - 1,
jobs_count - 1,
sem_name,
)
assert bool(handle), f"Error creating Win32 semaphore {win32api.GetLastError()}"
# See technical note above about MAKEFLAGS format.
env = dict(os.environ)
env["MAKEFLAGS"] = f" -j{jobs_count} --jobserver-auth=" + sem_name
return handle, env
def check_sem_count(handle: PyHandle, jobs_count: int) -> int:
if jobs_count <= 1:
# Nothing to check here.
return 0
expected_count = jobs_count - 1
read_count = win32event.ReleaseSemaphore(handle, 1)
if read_count < expected_count:
print(
f"ERROR: {expected_count - read_count} were missing from the jobs pool (got {read_count}, expected {expected_count})",
file=sys.stderr,
)
return 1
if read_count > expected_count:
print(
f"ERROR: {read_count - expected_count} extra tokens were released to the jobs pool (got {read_count}, expected {expected_count})",
file=sys.stderr,
)
return 1
return 0
def print_usage() -> int:
print(
r"""Example usage:
# Start <command> after setting the server to provide as many jobs
# as available CPUs (the default)
python \path\to\jobserver_pool.py <command>
# Start <command> with a fixed number of job slots.
python \path\to\jobserver_pool.py -j10 <command>
# Disable the feature with a non-positive count. This is equivalent
# to running <command> directly.
python \path\to\jobserver_pool.py -j0 <command>
# Use a specific semaphore name
python \path\to\jobserver_pool.py --name=my_build_jobs <command>
# Setup jobserver then start new interactive PowerShell
# session, print MAKEFLAGS value, build stuff, then exit.
python \path\to\jobserver_pool.py powershell.exe
$env:MAKEFLAGS
... build stuff ...
exit
"""
)
return 0
else: # !_IS_WINDOWS
def create_pipe(jobs_count: int) -> T.Tuple[int, int, T.Dict[str, str]]:
"""Create and fill Posix PIPE."""
read_fd, write_fd = os.pipe()
os.set_inheritable(read_fd, True)
os.set_inheritable(write_fd, True)
assert jobs_count > 0, f"Token count must be strictly positive"
os.write(write_fd, (jobs_count - 1) * b"x")
# See technical note above about MAKEFLAGS format.
env = dict(os.environ)
env["MAKEFLAGS"] = (
f" -j{jobs_count} --jobserver-fds={read_fd},{write_fd} --jobserver-auth={read_fd},{write_fd}"
)
return read_fd, write_fd, env
def create_fifo(path: str, jobs_count: int) -> T.Tuple[int, int, T.Dict[str, str]]:
"""Create and fill Posix FIFO."""
if os.path.exists(path):
os.remove(path)
# mypy complains that this does not exit on Windows.
os.mkfifo(path) # type: ignore
read_fd = os.open(path, os.O_RDONLY | os.O_NONBLOCK)
write_fd = os.open(path, os.O_WRONLY | os.O_NONBLOCK)
assert jobs_count > 0, f"Token count must be strictly positive"
os.write(write_fd, (jobs_count - 1) * b"x")
# See technical note above about MAKEFLAGS format.
env = dict(os.environ)
env["MAKEFLAGS"] = f" -j{jobs_count} --jobserver-auth=fifo:" + path
return read_fd, write_fd, env
def print_usage() -> int:
print(
r"""Example usage:
# Start <command> after setting the job pool to provide as many jobs
# as available CPUs (the default)
/path/to/jobserver_pool.py <command>
# Start <command> with a fixed number of jobs
/path/to/jobserver_pool.py -j10 <command>
# Disable the feature with a non-positive count. This is equivalent
# to running <command> directly.
/path/to/jobserver_pool.py -j0 <command>
# Use a specific FIFO path
/path/to/jobserver_pool.py --fifo=/tmp/my_build_jobs <command>
# Setup jobserver then start new interactive Bash shell
# session, print MAKEFLAGS value, build stuff, then exit.
/path/to/jobserver_pool.py bash -i
echo "$MAKEFLAGS"
... build stuff ...
exit
"""
)
return 0
def check_pipe_tokens(read_fd: int, jobs_count: int) -> int:
if jobs_count <= 1: # Nothing to check
return 0
# Remove implicit token from the expected count.
expected_count = jobs_count - 1
os.set_blocking(read_fd, False)
read_count = 0
while True:
try:
token = os.read(read_fd, 1)
if len(token) == 0: # End of pipe?
break
read_count += 1
except BlockingIOError:
break
if read_count < expected_count:
print(
f"ERROR: {expected_count - read_count} tokens were missing from the jobs pool (got {read_count}, expected {expected_count})",
file=sys.stderr,
)
return 1
if read_count > expected_count:
print(
f"ERROR: {read_count - expected_count} extra tokens were released to the jobs pool (got {read_count}, expected {expected_count})",
file=sys.stderr,
)
return 1
return 0
def main() -> int:
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawTextHelpFormatter
)
if _IS_WINDOWS:
parser.add_argument(
"--name",
help=f"Specify semaphore name, default is {_DEFAULT_NAME}",
default=_DEFAULT_NAME,
)
else:
mutex_group = parser.add_mutually_exclusive_group()
mutex_group.add_argument(
"--pipe",
action="store_true",
help="Implement the pool with a Unix pipe (default is FIFO).",
)
mutex_group.add_argument(
"--fifo",
default=_DEFAULT_NAME,
help=f"Specify pool FIFO file path (default ./{_DEFAULT_NAME})",
)
parser.add_argument(
"--no-check",
action="store_true",
help="Disable the final check that verifies that all job slots were returned to the pool on exit.",
)
parser.add_argument(
"--help-usage", action="store_true", help="Print usage examples."
)
parser.add_argument(
"-j",
"--jobs",
action="store",
metavar="COUNT",
dest="jobs_count",
type=int,
default=os.cpu_count(),
help="Set job slots ccount, default is available CPUs count",
)
parser.add_argument("command", nargs=argparse.REMAINDER, help="Command to run.")
args = parser.parse_args()
if args.help_usage:
return print_usage()
if not args.command:
parser.error("This script requires at least one command argument!")
jobs_count = args.jobs_count
if jobs_count <= 0:
# Disable the feature.
ret = subprocess.run(args.command)
exit_code = ret.returncode
elif _IS_WINDOWS:
# Run with a Window semaphore.
try:
handle, env = create_sem(args.name, jobs_count)
ret = subprocess.run(args.command, env=env)
exit_code = ret.returncode
if exit_code == 0 and not args.no_check:
exit_code = check_sem_count(handle, jobs_count)
finally:
win32api.CloseHandle(handle)
else:
# Run with pipe descriptors by default, or a FIFO if --fifo is used.
exit_code = 0
fifo_path = ""
try:
if not args.pipe:
fifo_path = os.path.abspath(args.fifo)
read_fd, write_fd, env = create_fifo(fifo_path, args.jobs_count)
ret = subprocess.run(args.command, env=env)
else:
read_fd, write_fd, env = create_pipe(args.jobs_count)
ret = subprocess.run(
args.command, env=env, pass_fds=(read_fd, write_fd)
)
exit_code = ret.returncode
if exit_code == 0 and not args.no_check:
exit_code = check_pipe_tokens(read_fd, jobs_count)
finally:
os.close(read_fd)
os.close(write_fd)
if fifo_path:
os.remove(fifo_path)
return exit_code
if __name__ == "__main__":
sys.exit(main())
================================================
FILE: misc/jobserver_pool_test.py
================================================
#!/usr/bin/env python3
"""Regression tests for the jobserver_pool.py script."""
import os
import re
import platform
import subprocess
import sys
import tempfile
import unittest
import typing as T
_SCRIPT_DIR = os.path.dirname(__file__)
_JOBSERVER_SCRIPT = os.path.join(_SCRIPT_
gitextract_sspkt4tm/
├── .clang-format
├── .clang-tidy
├── .editorconfig
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── linux-musl.yml
│ ├── linux.yml
│ ├── macos.yml
│ └── windows.yml
├── .gitignore
├── CMakeLists.txt
├── CONTRIBUTING.md
├── COPYING
├── README.md
├── RELEASING.md
├── appveyor.yml
├── configure.py
├── doc/
│ ├── README.md
│ ├── dblatex.xsl
│ ├── docbook.xsl
│ ├── doxygen.config
│ ├── manual.asciidoc
│ └── style.css
├── misc/
│ ├── afl-fuzz/
│ │ └── build.ninja
│ ├── afl-fuzz-tokens/
│ │ ├── kw_build
│ │ ├── kw_default
│ │ ├── kw_include
│ │ ├── kw_pool
│ │ ├── kw_rule
│ │ ├── kw_subninja
│ │ ├── misc_a
│ │ ├── misc_b
│ │ ├── misc_colon
│ │ ├── misc_cont
│ │ ├── misc_dollar
│ │ ├── misc_eq
│ │ ├── misc_indent
│ │ ├── misc_pipe
│ │ ├── misc_pipepipe
│ │ └── misc_space
│ ├── bash-completion
│ ├── ci.py
│ ├── inherited-fds.ninja
│ ├── jobserver_pool.py
│ ├── jobserver_pool_test.py
│ ├── jobserver_test.py
│ ├── jobserver_test_helper.py
│ ├── long-slow-build.ninja
│ ├── manifest_fuzzer.cc
│ ├── measure.py
│ ├── ninja.vim
│ ├── ninja_syntax.py
│ ├── ninja_syntax_test.py
│ ├── oss-fuzz/
│ │ ├── build.sh
│ │ └── sample_ninja_build
│ ├── output_test.py
│ ├── packaging/
│ │ ├── ninja.spec
│ │ └── rpmbuild.sh
│ ├── write_fake_manifests.py
│ └── zsh-completion
├── src/
│ ├── browse.cc
│ ├── browse.h
│ ├── browse.py
│ ├── build.cc
│ ├── build.h
│ ├── build_log.cc
│ ├── build_log.h
│ ├── build_log_perftest.cc
│ ├── build_log_test.cc
│ ├── build_test.cc
│ ├── canon_perftest.cc
│ ├── clean.cc
│ ├── clean.h
│ ├── clean_test.cc
│ ├── clparser.cc
│ ├── clparser.h
│ ├── clparser_perftest.cc
│ ├── clparser_test.cc
│ ├── command_collector.h
│ ├── debug_flags.cc
│ ├── debug_flags.h
│ ├── depfile_parser.cc
│ ├── depfile_parser.h
│ ├── depfile_parser.in.cc
│ ├── depfile_parser_perftest.cc
│ ├── depfile_parser_test.cc
│ ├── deps_log.cc
│ ├── deps_log.h
│ ├── deps_log_test.cc
│ ├── disk_interface.cc
│ ├── disk_interface.h
│ ├── disk_interface_test.cc
│ ├── dyndep.cc
│ ├── dyndep.h
│ ├── dyndep_parser.cc
│ ├── dyndep_parser.h
│ ├── dyndep_parser_test.cc
│ ├── edit_distance.cc
│ ├── edit_distance.h
│ ├── edit_distance_test.cc
│ ├── elide_middle.cc
│ ├── elide_middle.h
│ ├── elide_middle_perftest.cc
│ ├── elide_middle_test.cc
│ ├── eval_env.cc
│ ├── eval_env.h
│ ├── exit_status.h
│ ├── explanations.h
│ ├── explanations_test.cc
│ ├── gen_doxygen_mainpage.sh
│ ├── getopt.c
│ ├── getopt.h
│ ├── graph.cc
│ ├── graph.h
│ ├── graph_test.cc
│ ├── graphviz.cc
│ ├── graphviz.h
│ ├── hash_collision_bench.cc
│ ├── hash_map.h
│ ├── includes_normalize-win32.cc
│ ├── includes_normalize.h
│ ├── includes_normalize_test.cc
│ ├── inline.sh
│ ├── jobserver-posix.cc
│ ├── jobserver-win32.cc
│ ├── jobserver.cc
│ ├── jobserver.h
│ ├── jobserver_test.cc
│ ├── json.cc
│ ├── json.h
│ ├── json_test.cc
│ ├── lexer.cc
│ ├── lexer.h
│ ├── lexer.in.cc
│ ├── lexer_test.cc
│ ├── line_printer.cc
│ ├── line_printer.h
│ ├── load_status.h
│ ├── manifest_parser.cc
│ ├── manifest_parser.h
│ ├── manifest_parser_perftest.cc
│ ├── manifest_parser_test.cc
│ ├── metrics.cc
│ ├── metrics.h
│ ├── minidump-win32.cc
│ ├── missing_deps.cc
│ ├── missing_deps.h
│ ├── missing_deps_test.cc
│ ├── msvc_helper-win32.cc
│ ├── msvc_helper.h
│ ├── msvc_helper_main-win32.cc
│ ├── msvc_helper_test.cc
│ ├── ninja.cc
│ ├── ninja_test.cc
│ ├── parser.cc
│ ├── parser.h
│ ├── real_command_runner.cc
│ ├── state.cc
│ ├── state.h
│ ├── state_test.cc
│ ├── status.h
│ ├── status_printer.cc
│ ├── status_printer.h
│ ├── status_test.cc
│ ├── string_piece.h
│ ├── string_piece_util.cc
│ ├── string_piece_util.h
│ ├── string_piece_util_test.cc
│ ├── subprocess-posix.cc
│ ├── subprocess-win32.cc
│ ├── subprocess.h
│ ├── subprocess_test.cc
│ ├── test.cc
│ ├── test.h
│ ├── third_party/
│ │ ├── emhash/
│ │ │ ├── README.ninja
│ │ │ └── hash_table8.hpp
│ │ └── rapidhash/
│ │ ├── README.ninja
│ │ └── rapidhash.h
│ ├── timestamp.h
│ ├── util.cc
│ ├── util.h
│ ├── util_test.cc
│ ├── version.cc
│ ├── version.h
│ └── win32port.h
├── tests/
│ └── restat/
│ └── test_restat_builddir.py
└── windows/
└── ninja.manifest
SYMBOL INDEX (1266 symbols across 119 files)
FILE: configure.py
class Platform (line 37) | class Platform(object):
method __init__ (line 39) | def __init__(self, platform: Optional[str]) -> None:
method known_platforms (line 70) | def known_platforms() -> List[str]:
method platform (line 75) | def platform(self) -> str:
method is_linux (line 78) | def is_linux(self) -> bool:
method is_mingw (line 81) | def is_mingw(self) -> bool:
method is_msvc (line 84) | def is_msvc(self) -> bool:
method msvc_needs_fs (line 87) | def msvc_needs_fs(self) -> bool:
method is_windows (line 94) | def is_windows(self) -> bool:
method is_solaris (line 97) | def is_solaris(self) -> bool:
method is_aix (line 100) | def is_aix(self) -> bool:
method is_os400_pase (line 103) | def is_os400_pase(self) -> bool:
method uses_usr_local (line 106) | def uses_usr_local(self) -> bool:
method supports_ppoll (line 109) | def supports_ppoll(self) -> bool:
method supports_ninja_browse (line 113) | def supports_ninja_browse(self) -> bool:
method can_rebuild_in_place (line 118) | def can_rebuild_in_place(self) -> bool:
class Bootstrap (line 121) | class Bootstrap:
method __init__ (line 129) | def __init__(self, writer: ninja_syntax.Writer, verbose: bool = False)...
method comment (line 139) | def comment(self, text: str) -> None:
method newline (line 142) | def newline(self) -> None:
method variable (line 145) | def variable(self, key: str, val: str) -> None:
method rule (line 151) | def rule(self, name: str, **kwargs: Any) -> None:
method build (line 155) | def build(
method default (line 180) | def default(self, paths: Union[str, List[str]]) -> None:
method _expand_paths (line 183) | def _expand_paths(self, paths: Optional[Union[str, List[str]]]) -> str:
method _expand (line 188) | def _expand(self, str: str, local_vars: Dict[str, str] = {}) -> str:
method _shell_escape (line 192) | def _shell_escape(self, path: str) -> str:
method _run_command (line 196) | def _run_command(self, cmdline: str) -> None:
function src (line 290) | def src(filename: str) -> str:
function built (line 292) | def built(filename: str) -> str:
function doc (line 294) | def doc(filename: str) -> str:
function cc (line 296) | def cc(name: str, **kwargs: Any) -> List[str]:
function cxx (line 298) | def cxx(name: str, **kwargs: Any) -> List[str]:
function binary (line 300) | def binary(name: str) -> str:
function search_system_path (line 320) | def search_system_path(file_name: str) -> Optional[str]: # type: ignore...
function shell_escape (line 428) | def shell_escape(str: str) -> str:
function has_re2c (line 506) | def has_re2c() -> bool:
FILE: misc/ci.py
function error (line 14) | def error(path: str, msg: str) -> None:
FILE: misc/jobserver_pool.py
function create_sem (line 75) | def create_sem(
function check_sem_count (line 95) | def check_sem_count(handle: PyHandle, jobs_count: int) -> int:
function print_usage (line 118) | def print_usage() -> int:
function create_pipe (line 148) | def create_pipe(jobs_count: int) -> T.Tuple[int, int, T.Dict[str, str]]:
function create_fifo (line 162) | def create_fifo(path: str, jobs_count: int) -> T.Tuple[int, int, T.Dict[...
function print_usage (line 179) | def print_usage() -> int:
function check_pipe_tokens (line 207) | def check_pipe_tokens(read_fd: int, jobs_count: int) -> int:
function main (line 240) | def main() -> int:
FILE: misc/jobserver_pool_test.py
function _simple_scanf (line 24) | def _simple_scanf(pattern: str, input: str) -> T.Sequence[T.Any]:
class JobserverPool (line 77) | class JobserverPool(unittest.TestCase):
method _run_jobserver_echo_MAKEFLAGS (line 78) | def _run_jobserver_echo_MAKEFLAGS(
method _test_echo_MAKEFLAGS (line 95) | def _test_echo_MAKEFLAGS(self, cmd_args_prefix, expected_core_count: i...
method test_MAKEFLAGS_default (line 140) | def test_MAKEFLAGS_default(self):
method test_MAKEFLAGS_with_10_jobs (line 143) | def test_MAKEFLAGS_with_10_jobs(self):
method test_MAKEFLAGS_with_no_jobs (line 148) | def test_MAKEFLAGS_with_no_jobs(self):
method test_MAKEFLAGS_with_fifo (line 154) | def test_MAKEFLAGS_with_fifo(self):
method test_MAKEFLAGS_with_name (line 164) | def test_MAKEFLAGS_with_name(self):
FILE: misc/jobserver_test.py
class BuildDir (line 42) | class BuildDir:
method __init__ (line 43) | def __init__(self, build_ninja: str):
method __enter__ (line 47) | def __enter__(self):
method __exit__ (line 53) | def __exit__(self, exc_type, exc_val, exc_tb):
method path (line 57) | def path(self) -> str:
method run (line 61) | def run(
method ninja_run (line 70) | def ninja_run(
method ninja_clean (line 85) | def ninja_clean(self) -> None:
method ninja_spawn (line 88) | def ninja_spawn(
function span_output_file (line 109) | def span_output_file(span_n: int) -> str:
function generate_build_plan (line 113) | def generate_build_plan(command_count: int) -> str:
function compute_max_overlapped_spans (line 134) | def compute_max_overlapped_spans(build_dir: str, command_count: int) -> ...
class JobserverTest (line 168) | class JobserverTest(unittest.TestCase):
method test_no_jobserver_client (line 170) | def test_no_jobserver_client(self):
method _run_client_test (line 185) | def _run_client_test(self, jobserver_args: T.List[str]) -> None:
method test_jobserver_client_with_posix_fifo (line 251) | def test_jobserver_client_with_posix_fifo(self):
method test_jobserver_client_with_posix_pipe (line 255) | def test_jobserver_client_with_posix_pipe(self):
method _test_MAKEFLAGS_value (line 293) | def _test_MAKEFLAGS_value(
method test_client_passes_MAKEFLAGS (line 317) | def test_client_passes_MAKEFLAGS(self):
FILE: misc/jobserver_test_helper.py
function main (line 24) | def main():
FILE: misc/manifest_fuzzer.cc
function LLVMFuzzerTestOneInput (line 22) | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
FILE: misc/measure.py
function run (line 27) | def run(cmd: Union[str, List[str]], repeat: int = 10) -> None:
FILE: misc/ninja_syntax.py
function escape_path (line 29) | def escape_path(word: str) -> str:
class Writer (line 32) | class Writer(object):
method __init__ (line 33) | def __init__(self, output: TextIOWrapper, width: int = 78) -> None:
method newline (line 37) | def newline(self) -> None:
method comment (line 40) | def comment(self, text: str) -> None:
method variable (line 45) | def variable(
method pool (line 57) | def pool(self, name: str, depth: int) -> None:
method rule (line 61) | def rule(
method build (line 93) | def build(
method include (line 146) | def include(self, path: str) -> None:
method subninja (line 149) | def subninja(self, path: str) -> None:
method default (line 152) | def default(self, paths: Union[str, List[str]]) -> None:
method _count_dollars_before_index (line 155) | def _count_dollars_before_index(self, s: str, i: int) -> int:
method _line (line 164) | def _line(self, text: str, indent: int = 0) -> None:
method close (line 200) | def close(self) -> None:
function as_list (line 204) | def as_list(input: Optional[Union[str, List[str]]]) -> List[str]:
function escape (line 212) | def escape(string: str) -> str:
function expand (line 220) | def expand(string: str, vars: Dict[str, str], local_vars: Dict[str, str]...
FILE: misc/ninja_syntax_test.py
class TestLineWordWrap (line 31) | class TestLineWordWrap(unittest.TestCase):
method setUp (line 32) | def setUp(self) -> None:
method test_single_long_word (line 36) | def test_single_long_word(self) -> None:
method test_few_long_words (line 41) | def test_few_long_words(self) -> None:
method test_comment_wrap (line 49) | def test_comment_wrap(self) -> None:
method test_short_words_indented (line 55) | def test_short_words_indented(self) -> None:
method test_few_long_words_indented (line 67) | def test_few_long_words_indented(self) -> None:
method test_escaped_spaces (line 75) | def test_escaped_spaces(self) -> None:
method test_fit_many_words (line 82) | def test_fit_many_words(self) -> None:
method test_leading_space (line 92) | def test_leading_space(self) -> None:
method test_embedded_dollar_dollar (line 101) | def test_embedded_dollar_dollar(self) -> None:
method test_two_embedded_dollar_dollars (line 110) | def test_two_embedded_dollar_dollars(self) -> None:
method test_leading_dollar_dollar (line 119) | def test_leading_dollar_dollar(self) -> None:
method test_trailing_dollar_dollar (line 128) | def test_trailing_dollar_dollar(self) -> None:
class TestBuild (line 137) | class TestBuild(unittest.TestCase):
method setUp (line 138) | def setUp(self) -> None:
method test_variables_dict (line 142) | def test_variables_dict(self) -> None:
method test_variables_list (line 150) | def test_variables_list(self) -> None:
method test_implicit_outputs (line 158) | def test_implicit_outputs(self) -> None:
class TestExpand (line 165) | class TestExpand(unittest.TestCase):
method test_basic (line 166) | def test_basic(self) -> None:
method test_var (line 170) | def test_var(self) -> None:
method test_vars (line 174) | def test_vars(self) -> None:
method test_space (line 178) | def test_space(self) -> None:
method test_locals (line 182) | def test_locals(self) -> None:
method test_double (line 188) | def test_double(self) -> None:
FILE: misc/output_test.py
function remove_non_visible_lines (line 25) | def remove_non_visible_lines(raw_output: bytes) -> str:
class BuildDir (line 60) | class BuildDir:
method __init__ (line 61) | def __init__(self, build_ninja: str):
method __enter__ (line 65) | def __enter__(self):
method __exit__ (line 72) | def __exit__(self, exc_type, exc_val, exc_tb):
method path (line 76) | def path(self) -> str:
method run (line 80) | def run(
function run (line 133) | def run(
class Output (line 147) | class Output(unittest.TestCase):
method _test_expected_error (line 157) | def _test_expected_error(self, plan: str, flags: T.Optional[str],expec...
method test_issue_1418 (line 171) | def test_issue_1418(self) -> None:
method test_issue_1214 (line 192) | def test_issue_1214(self) -> None:
method test_issue_1966 (line 226) | def test_issue_1966(self) -> None:
method test_issue_2499 (line 238) | def test_issue_2499(self) -> None:
method test_pr_1685 (line 262) | def test_pr_1685(self) -> None:
method test_issue_2048 (line 267) | def test_issue_2048(self) -> None:
method test_pr_2540 (line 290) | def test_pr_2540(self)->None:
method test_depfile_directory_creation (line 359) | def test_depfile_directory_creation(self) -> None:
method test_status (line 374) | def test_status(self) -> None:
method test_ninja_status_default (line 379) | def test_ninja_status_default(self) -> None:
method test_ninja_status_quiet (line 383) | def test_ninja_status_quiet(self) -> None:
method test_entering_directory_on_stdout (line 388) | def test_entering_directory_on_stdout(self) -> None:
method test_tool_inputs (line 392) | def test_tool_inputs(self) -> None:
method test_tool_compdb_targets (line 474) | def test_tool_compdb_targets(self) -> None:
method test_tool_multi_inputs (line 539) | def test_tool_multi_inputs(self) -> None:
method test_explain_output (line 573) | def test_explain_output(self):
method test_issue_2586 (line 603) | def test_issue_2586(self):
method test_issue_2621 (line 623) | def test_issue_2621(self):
method test_issue_2681 (line 648) | def test_issue_2681(self):
FILE: misc/write_fake_manifests.py
function paretoint (line 26) | def paretoint(avg: float, alpha: float) -> int:
function moar (line 35) | def moar(avg_options: float, p_suffix: float) -> str:
class GenRandom (line 53) | class GenRandom(object):
method __init__ (line 54) | def __init__(self, src_dir: str) -> None:
method _unique_string (line 59) | def _unique_string(self, seen: Set[Optional[str]], avg_options: float ...
method _n_unique_strings (line 66) | def _n_unique_strings(self, n: int) -> List[str]:
method target_name (line 71) | def target_name(self) -> str:
method path (line 74) | def path(self) -> str:
method src_obj_pairs (line 79) | def src_obj_pairs(self, path: str, name: str) -> List[Tuple[str, str]]:
method defines (line 85) | def defines(self) -> List[str]:
class Target (line 92) | class Target(object):
method __init__ (line 93) | def __init__(self, gen: GenRandom, kind: int) -> None:
function write_target_ninja (line 109) | def write_target_ninja(ninja: ninja_syntax.Writer, target: Target, src_d...
function write_sources (line 137) | def write_sources(target: Target, root_dir: str) -> None:
function write_master_ninja (line 178) | def write_master_ninja(master_ninja: ninja_syntax.Writer, targets: List[...
function FileWriter (line 216) | def FileWriter(path: str) -> Generator[ninja_syntax.Writer, None, None]:
function random_targets (line 227) | def random_targets(num_targets: int, src_dir: str) -> List[Target]:
function main (line 242) | def main() -> None:
FILE: src/browse.cc
function RunBrowsePython (line 27) | void RunBrowsePython(State* state, const char* ninja_command,
FILE: src/browse.h
type State (line 18) | struct State
FILE: src/browse.py
function match_strip (line 61) | def match_strip(line: str, prefix: str) -> Tuple[bool, str]:
function html_escape (line 66) | def html_escape(text: str) -> str:
function parse (line 69) | def parse(text: str) -> Node:
function create_page (line 106) | def create_page(body: str) -> str:
function generate_html (line 134) | def generate_html(node: Node) -> str:
function ninja_dump (line 160) | def ninja_dump(target: str) -> Tuple[str, str, int]:
class RequestHandler (line 166) | class RequestHandler(httpserver.BaseHTTPRequestHandler):
method do_GET (line 167) | def do_GET(self) -> None:
method log_message (line 194) | def log_message(self, format: str, *args: Any) -> None:
class HTTPServer (line 212) | class HTTPServer(socketserver.ThreadingMixIn, httpserver.HTTPServer):
FILE: src/build.cc
type DryRunCommandRunner (line 50) | struct DryRunCommandRunner : public CommandRunner {
function Edge (line 161) | Edge* Plan::FindWork() {
function EdgeWeightHeuristic (line 465) | int64_t EdgeWeightHeuristic(Edge *edge) {
type TopoSort (line 486) | struct TopoSort {
method VisitTarget (line 487) | void VisitTarget(const Node* target) {
method Visit (line 509) | void Visit(Edge* edge) {
function Node (line 656) | Node* Builder::AddTarget(const string& name, string* err) {
function ExitStatus (line 698) | ExitStatus Builder::Build(string* err) {
FILE: src/build.h
type BuildLog (line 30) | struct BuildLog
type Builder (line 31) | struct Builder
type DiskInterface (line 32) | struct DiskInterface
type Edge (line 33) | struct Edge
type Explanations (line 34) | struct Explanations
type Node (line 35) | struct Node
type State (line 36) | struct State
type Status (line 37) | struct Status
function Dump (line 41) | struct Plan {
type Want (line 89) | enum Want
type BuildConfig (line 145) | struct BuildConfig
type CommandRunner (line 150) | struct CommandRunner {
function Abort (line 166) | void Abort() {}
type BuildConfig (line 175) | struct BuildConfig {
type Builder (line 196) | struct Builder {
function AlreadyUpToDate (line 217) | bool AlreadyUpToDate() const;
type std (line 254) | typedef std::map<const Edge*, int> RunningEdgeMap;
FILE: src/build_log.cc
type LineReader (line 157) | struct LineReader {
method LineReader (line 158) | explicit LineReader(FILE* file)
method ReadLine (line 167) | bool ReadLine(char** line_start, char** line_end) {
function LoadStatus (line 208) | LoadStatus BuildLog::Load(const std::string& path, std::string* err) {
FILE: src/build_log.h
type DiskInterface (line 28) | struct DiskInterface
type Edge (line 29) | struct Edge
type BuildLogUser (line 32) | struct BuildLogUser {
type LogEntry (line 60) | struct LogEntry {
type ExternalStringHashMap (line 95) | typedef ExternalStringHashMap<std::unique_ptr<LogEntry>>::Type Entries;
FILE: src/build_log_perftest.cc
type NoDeadPaths (line 33) | struct NoDeadPaths : public BuildLogUser {
method IsPathDead (line 34) | virtual bool IsPathDead(StringPiece) const { return false; }
function WriteTestData (line 37) | bool WriteTestData(string* err) {
function main (line 103) | int main() {
FILE: src/build_log_test.cc
type BuildLogTest (line 34) | struct BuildLogTest : public StateTestWithBuiltinRules, public BuildLogU...
method SetUp (line 35) | virtual void SetUp() {
method TearDown (line 39) | virtual void TearDown() {
method IsPathDead (line 42) | virtual bool IsPathDead(StringPiece s) const { return false; }
function TEST_F (line 45) | TEST_F(BuildLogTest, WriteRead) {
function TEST_F (line 73) | TEST_F(BuildLogTest, FirstWriteAddsSignature) {
function TEST_F (line 103) | TEST_F(BuildLogTest, DoubleEntry) {
function TEST_F (line 122) | TEST_F(BuildLogTest, Truncate) {
function TEST_F (line 164) | TEST_F(BuildLogTest, ObsoleteOldVersion) {
function TEST_F (line 176) | TEST_F(BuildLogTest, SpacesInOutput) {
function TEST_F (line 196) | TEST_F(BuildLogTest, DuplicateVersionHeader) {
type TestDiskInterface (line 229) | struct TestDiskInterface : public DiskInterface {
method TimeStamp (line 230) | TimeStamp Stat(const std::string& path, std::string* err) const overri...
method WriteFile (line 233) | bool WriteFile(const std::string& path, const std::string& contents,
method MakeDir (line 238) | bool MakeDir(const std::string& path) override {
method Status (line 242) | Status ReadFile(const std::string& path, std::string* contents,
method RemoveFile (line 247) | int RemoveFile(const std::string& path) override {
function TEST_F (line 253) | TEST_F(BuildLogTest, Restat) {
function TEST_F (line 279) | TEST_F(BuildLogTest, VeryLongInputLine) {
function TEST_F (line 308) | TEST_F(BuildLogTest, MultiTargetEdge) {
type BuildLogRecompactTest (line 328) | struct BuildLogRecompactTest : public BuildLogTest {
method IsPathDead (line 329) | virtual bool IsPathDead(StringPiece s) const { return s == "out2"; }
function TEST_F (line 332) | TEST_F(BuildLogRecompactTest, Recompact) {
FILE: src/build_test.cc
type CompareEdgesByOutput (line 30) | struct CompareEdgesByOutput {
method cmp (line 31) | static bool cmp(const Edge* a, const Edge* b) {
type PlanTest (line 39) | struct PlanTest : public StateTestWithBuiltinRules {
method FindWorkSorted (line 45) | void FindWorkSorted(deque<Edge*>* ret, int count) {
method PrepareForTarget (line 56) | void PrepareForTarget(const char* node, BuildLog *log=NULL) {
function TEST_F (line 67) | TEST_F(PlanTest, Basic) {
function TEST_F (line 100) | TEST_F(PlanTest, DoubleOutputDirect) {
function TEST_F (line 126) | TEST_F(PlanTest, DoubleOutputIndirect) {
function TEST_F (line 166) | TEST_F(PlanTest, DoubleDependent) {
function TEST_F (line 242) | TEST_F(PlanTest, PoolWithDepthOne) {
function TEST_F (line 253) | TEST_F(PlanTest, ConsolePool) {
function TEST_F (line 262) | TEST_F(PlanTest, PoolsWithDepthTwo) {
function TEST_F (line 342) | TEST_F(PlanTest, PoolWithRedundantEdges) {
function TEST_F (line 424) | TEST_F(PlanTest, PoolWithFailingEdge) {
function TEST_F (line 469) | TEST_F(PlanTest, PriorityWithoutBuildLog) {
type FakeCommandRunner (line 520) | struct FakeCommandRunner : public CommandRunner {
method FakeCommandRunner (line 521) | explicit FakeCommandRunner(VirtualFileSystem* fs) :
class SafeRelease (line 537) | class SafeRelease {
method SafeRelease (line 542) | SafeRelease(Builder* builder) {
type BuildTest (line 548) | struct BuildTest : public StateTestWithBuiltinRules, public BuildLogUser {
method BuildTest (line 549) | BuildTest() : config_(MakeConfig()), command_runner_(&fs_), status_(co...
method BuildTest (line 553) | explicit BuildTest(DepsLog* log)
method SetUp (line 557) | virtual void SetUp() {
method IsPathDead (line 574) | virtual bool IsPathDead(StringPiece s) const { return false; }
method BuildConfig (line 586) | BuildConfig MakeConfig() {
function TEST_F (line 826) | TEST_F(BuildTest, NoWork) {
function TEST_F (line 831) | TEST_F(BuildTest, OneStep) {
function TEST_F (line 845) | TEST_F(BuildTest, OneStep2) {
function TEST_F (line 859) | TEST_F(BuildTest, TwoStep) {
function TEST_F (line 892) | TEST_F(BuildTest, TwoOutputs) {
function TEST_F (line 909) | TEST_F(BuildTest, ImplicitOutput) {
function TEST_F (line 927) | TEST_F(BuildTest, MultiOutIn) {
function TEST_F (line 945) | TEST_F(BuildTest, Chain) {
function TEST_F (line 981) | TEST_F(BuildTest, MissingInput) {
function TEST_F (line 990) | TEST_F(BuildTest, MissingTarget) {
function TEST_F (line 997) | TEST_F(BuildTest, MissingInputTarget) {
function TEST_F (line 1005) | TEST_F(BuildTest, MakeDirs) {
function TEST_F (line 1025) | TEST_F(BuildTest, DepFileMissing) {
function TEST_F (line 1038) | TEST_F(BuildTest, DepFileOK) {
function TEST_F (line 1074) | TEST_F(BuildTest, DepFileParseError) {
function TEST_F (line 1085) | TEST_F(BuildTest, EncounterReadyTwice) {
function TEST_F (line 1108) | TEST_F(BuildTest, OrderOnlyDeps) {
function TEST_F (line 1178) | TEST_F(BuildTest, RebuildOrderOnlyDeps) {
function TEST_F (line 1226) | TEST_F(BuildTest, DepFileCanonicalize) {
function TEST_F (line 1256) | TEST_F(BuildTest, Phony) {
function TEST_F (line 1273) | TEST_F(BuildTest, PhonyNoWork) {
function TEST_F (line 1289) | TEST_F(BuildTest, PhonySelfReference) {
function TestPhonyUseCase (line 1319) | void TestPhonyUseCase(BuildTest* t, int i) {
function TEST_F (line 1439) | TEST_F(BuildTest, PhonyUseCase1) { TestPhonyUseCase(this, 1); }
function TEST_F (line 1440) | TEST_F(BuildTest, PhonyUseCase2) { TestPhonyUseCase(this, 2); }
function TEST_F (line 1441) | TEST_F(BuildTest, PhonyUseCase3) { TestPhonyUseCase(this, 3); }
function TEST_F (line 1442) | TEST_F(BuildTest, PhonyUseCase4) { TestPhonyUseCase(this, 4); }
function TEST_F (line 1443) | TEST_F(BuildTest, PhonyUseCase5) { TestPhonyUseCase(this, 5); }
function TEST_F (line 1444) | TEST_F(BuildTest, PhonyUseCase6) { TestPhonyUseCase(this, 6); }
function TEST_F (line 1446) | TEST_F(BuildTest, Fail) {
function TEST_F (line 1461) | TEST_F(BuildTest, SwallowFailures) {
function TEST_F (line 1482) | TEST_F(BuildTest, SwallowFailuresLimit) {
function TEST_F (line 1503) | TEST_F(BuildTest, SwallowFailuresPool) {
function TEST_F (line 1527) | TEST_F(BuildTest, PoolEdgesReadyButNotWanted) {
type BuildWithLogTest (line 1552) | struct BuildWithLogTest : public BuildTest {
method BuildWithLogTest (line 1553) | BuildWithLogTest() {
function TEST_F (line 1560) | TEST_F(BuildWithLogTest, ImplicitGeneratedOutOfDate) {
function TEST_F (line 1578) | TEST_F(BuildWithLogTest, ImplicitGeneratedOutOfDate2) {
function TEST_F (line 1632) | TEST_F(BuildWithLogTest, NotInLogButOnDisk) {
function TEST_F (line 1657) | TEST_F(BuildWithLogTest, RebuildAfterFailure) {
function TEST_F (line 1702) | TEST_F(BuildWithLogTest, RebuildWithNoInputs) {
function TEST_F (line 1733) | TEST_F(BuildWithLogTest, RestatTest) {
function TEST_F (line 1798) | TEST_F(BuildWithLogTest, RestatMissingFile) {
function TEST_F (line 1839) | TEST_F(BuildWithLogTest, RestatSingleDependentOutputDirty) {
function TEST_F (line 1881) | TEST_F(BuildWithLogTest, RestatMissingInput) {
function TEST_F (line 1933) | TEST_F(BuildWithLogTest, RestatInputChangesDueToRule) {
function TEST_F (line 1979) | TEST_F(BuildWithLogTest, GeneratedPlainDepfileMtime) {
type BuildDryRun (line 2006) | struct BuildDryRun : public BuildWithLogTest {
method BuildDryRun (line 2007) | BuildDryRun() {
function TEST_F (line 2012) | TEST_F(BuildDryRun, AllCommandsShown) {
function TEST_F (line 2041) | TEST_F(BuildDryRun, WithDyndep) {
function TEST_F (line 2066) | TEST_F(BuildTest, RspFileSuccess)
function TEST_F (line 2119) | TEST_F(BuildTest, RspFileFailure) {
function TEST_F (line 2159) | TEST_F(BuildWithLogTest, RspFileCmdLineChange) {
function TEST_F (line 2205) | TEST_F(BuildTest, InterruptCleanup) {
function TEST_F (line 2239) | TEST_F(BuildTest, StatFailureAbortsBuild) {
function TEST_F (line 2254) | TEST_F(BuildTest, PhonyWithNoInputs) {
function TEST_F (line 2280) | TEST_F(BuildTest, DepsGccWithEmptyDepfileErrorsOut) {
function TEST_F (line 2298) | TEST_F(BuildTest, StatusFormatElapsed_e) {
function TEST_F (line 2304) | TEST_F(BuildTest, StatusFormatElapsed_w) {
function TEST_F (line 2310) | TEST_F(BuildTest, StatusFormatETA) {
function TEST_F (line 2316) | TEST_F(BuildTest, StatusFormatTimeProgress) {
function TEST_F (line 2322) | TEST_F(BuildTest, StatusFormatReplacePlaceholder) {
function TEST_F (line 2327) | TEST_F(BuildTest, FailedDepsParse) {
type BuildWithQueryDepsLogTest (line 2345) | struct BuildWithQueryDepsLogTest : public BuildTest {
method BuildWithQueryDepsLogTest (line 2346) | BuildWithQueryDepsLogTest()
method SetUp (line 2353) | virtual void SetUp() {
function TEST_F (line 2370) | TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileMSVC) {
function TEST_F (line 2398) | TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileGCCOneLine) {
function TEST_F (line 2429) | TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileGCCMultiLineInput) {
function TEST_F (line 2460) | TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileGCCMultiLineOutput) {
function TEST_F (line 2491) | TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileGCCOnlyMainOutput) {
function TEST_F (line 2522) | TEST_F(BuildWithQueryDepsLogTest, TwoOutputsDepFileGCCOnlySecondaryOutpu...
type BuildWithDepsLogTest (line 2558) | struct BuildWithDepsLogTest : public BuildTest {
method BuildWithDepsLogTest (line 2559) | BuildWithDepsLogTest()
method SetUp (line 2562) | virtual void SetUp() {
method TearDown (line 2568) | virtual void TearDown() {
function TEST_F (line 2581) | TEST_F(BuildWithDepsLogTest, Straightforward) {
function TEST_F (line 2648) | TEST_F(BuildWithDepsLogTest, ObsoleteDeps) {
function TEST_F (line 2717) | TEST_F(BuildWithDepsLogTest, DepsIgnoredInDryRun) {
function TEST_F (line 2745) | TEST_F(BuildWithDepsLogTest, TestInputMtimeRaceCondition) {
function TEST_F (line 2822) | TEST_F(BuildWithDepsLogTest, TestInputMtimeRaceConditionWithDepFile) {
function TEST_F (line 2942) | TEST_F(BuildTest, RestatDepfileDependency) {
function TEST_F (line 2965) | TEST_F(BuildWithDepsLogTest, RestatDepfileDependencyDepsLog) {
function TEST_F (line 3027) | TEST_F(BuildWithDepsLogTest, DepFileOKDepsLog) {
function TEST_F (line 3088) | TEST_F(BuildWithDepsLogTest, DiscoveredDepDuringBuildChanged) {
function TEST_F (line 3173) | TEST_F(BuildWithDepsLogTest, DepFileDepsLogCanonicalize) {
function TEST_F (line 3238) | TEST_F(BuildTest, RestatMissingDepfile) {
function TEST_F (line 3262) | TEST_F(BuildWithDepsLogTest, RestatMissingDepfileDepslog) {
function TEST_F (line 3316) | TEST_F(BuildTest, WrongOutputInDepfileCausesRebuild) {
function TEST_F (line 3336) | TEST_F(BuildTest, Console) {
function TEST_F (line 3353) | TEST_F(BuildTest, DyndepMissingAndNoRule) {
function TEST_F (line 3368) | TEST_F(BuildTest, DyndepReadyImplicitConnection) {
function TEST_F (line 3396) | TEST_F(BuildTest, DyndepReadySyntaxError) {
function TEST_F (line 3414) | TEST_F(BuildTest, DyndepReadyCircular) {
function TEST_F (line 3435) | TEST_F(BuildTest, DyndepBuild) {
function TEST_F (line 3471) | TEST_F(BuildTest, DyndepBuildSyntaxError) {
function TEST_F (line 3495) | TEST_F(BuildTest, DyndepBuildUnrelatedOutput) {
function TEST_F (line 3527) | TEST_F(BuildTest, DyndepBuildDiscoverNewOutput) {
function TEST_F (line 3558) | TEST_F(BuildTest, DyndepBuildDiscoverNewOutputWithMultipleRules1) {
function TEST_F (line 3589) | TEST_F(BuildTest, DyndepBuildDiscoverNewOutputWithMultipleRules2) {
function TEST_F (line 3629) | TEST_F(BuildTest, DyndepBuildDiscoverNewInput) {
function TEST_F (line 3661) | TEST_F(BuildTest, DyndepBuildDiscoverNewInputWithValidation) {
function TEST_F (line 3688) | TEST_F(BuildTest, DyndepBuildDiscoverNewInputWithTransitiveValidation) {
function TEST_F (line 3722) | TEST_F(BuildTest, DyndepBuildDiscoverImplicitConnection) {
function TEST_F (line 3754) | TEST_F(BuildTest, DyndepBuildDiscoverOutputAndDepfileInput) {
function TEST_F (line 3796) | TEST_F(BuildTest, DyndepBuildDiscoverNowWantEdge) {
function TEST_F (line 3828) | TEST_F(BuildTest, DyndepBuildDiscoverNowWantEdgeAndDependent) {
function TEST_F (line 3859) | TEST_F(BuildTest, DyndepBuildDiscoverCircular) {
function TEST_F (line 3893) | TEST_F(BuildWithLogTest, DyndepBuildDiscoverRestat) {
function TEST_F (line 3943) | TEST_F(BuildTest, DyndepBuildDiscoverScheduledEdge) {
function TEST_F (line 3991) | TEST_F(BuildTest, DyndepTwoLevelDirect) {
function TEST_F (line 4038) | TEST_F(BuildTest, DyndepTwoLevelIndirect) {
function TEST_F (line 4083) | TEST_F(BuildTest, DyndepTwoLevelDiscoveredReady) {
function TEST_F (line 4124) | TEST_F(BuildTest, DyndepTwoLevelDiscoveredDirty) {
function TEST_F (line 4165) | TEST_F(BuildTest, Validation) {
function TEST_F (line 4217) | TEST_F(BuildTest, ValidationDependsOnOutput) {
function TEST_F (line 4267) | TEST_F(BuildWithDepsLogTest, ValidationThroughDepfile) {
function TEST_F (line 4346) | TEST_F(BuildTest, ValidationCircular) {
function TEST_F (line 4396) | TEST_F(BuildTest, ValidationWithCircularDependency) {
FILE: src/canon_perftest.cc
function main (line 27) | int main() {
FILE: src/clean.h
type State (line 25) | struct State
type Node (line 26) | struct Node
type Rule (line 27) | struct Rule
type DiskInterface (line 28) | struct DiskInterface
type Cleaner (line 30) | struct Cleaner {
FILE: src/clean_test.cc
type CleanTest (line 31) | struct CleanTest : public StateTestWithBuiltinRules {
method SetUp (line 34) | virtual void SetUp() {
function TEST_F (line 39) | TEST_F(CleanTest, CleanAll) {
function TEST_F (line 70) | TEST_F(CleanTest, CleanAllDryRun) {
function TEST_F (line 102) | TEST_F(CleanTest, CleanTarget) {
function TEST_F (line 133) | TEST_F(CleanTest, CleanTargetDryRun) {
function TEST_F (line 165) | TEST_F(CleanTest, CleanRule) {
function TEST_F (line 198) | TEST_F(CleanTest, CleanRuleDryRun) {
function TEST_F (line 232) | TEST_F(CleanTest, CleanRuleGenerator) {
function TEST_F (line 254) | TEST_F(CleanTest, CleanDepFile) {
function TEST_F (line 269) | TEST_F(CleanTest, CleanDepFileOnCleanTarget) {
function TEST_F (line 284) | TEST_F(CleanTest, CleanDepFileOnCleanRule) {
function TEST_F (line 299) | TEST_F(CleanTest, CleanDyndep) {
function TEST_F (line 326) | TEST_F(CleanTest, CleanDyndepMissing) {
function TEST_F (line 348) | TEST_F(CleanTest, CleanRspFile) {
function TEST_F (line 365) | TEST_F(CleanTest, CleanRsp) {
function TEST_F (line 406) | TEST_F(CleanTest, CleanFailure) {
function TEST_F (line 414) | TEST_F(CleanTest, CleanPhony) {
function TEST_F (line 440) | TEST_F(CleanTest, CleanDepFileAndRspFileWithSpaces) {
type CleanDeadTest (line 469) | struct CleanDeadTest : public CleanTest, public BuildLogUser{
method SetUp (line 470) | virtual void SetUp() {
method TearDown (line 475) | virtual void TearDown() {
method IsPathDead (line 478) | virtual bool IsPathDead(StringPiece) const { return false; }
function TEST_F (line 481) | TEST_F(CleanDeadTest, CleanDead) {
function TEST_F (line 541) | TEST_F(CleanDeadTest, CleanDeadPreservesInputs) {
FILE: src/clparser.cc
function EndsWith (line 36) | bool EndsWith(const string& input, const string& needle) {
function string (line 44) | string CLParser::FilterShowIncludes(const string& line,
FILE: src/clparser.h
type CLParser (line 25) | struct CLParser {
FILE: src/clparser_perftest.cc
function main (line 23) | int main(int argc, char* argv[]) {
FILE: src/clparser_test.cc
function TEST (line 22) | TEST(CLParserTest, ShowIncludes) {
function TEST (line 38) | TEST(CLParserTest, FilterInputFilename) {
function TEST (line 49) | TEST(CLParserTest, ParseSimple) {
function TEST (line 63) | TEST(CLParserTest, ParseFilenameFilter) {
function TEST (line 73) | TEST(CLParserTest, NoFilenameFilterAfterShowIncludes) {
function TEST (line 84) | TEST(CLParserTest, ParseSystemInclude) {
function TEST (line 99) | TEST(CLParserTest, DuplicatedHeader) {
function TEST (line 112) | TEST(CLParserTest, DuplicatedHeaderPathConverted) {
FILE: src/command_collector.h
type CommandCollector (line 35) | struct CommandCollector {
FILE: src/debug_flags.h
type Edge (line 20) | struct Edge
type Node (line 21) | struct Node
FILE: src/depfile_parser.h
type DepfileParserOptions (line 23) | struct DepfileParserOptions {
type DepfileParser (line 28) | struct DepfileParser {
FILE: src/depfile_parser_perftest.cc
function main (line 24) | int main(int argc, char* argv[]) {
FILE: src/depfile_parser_test.cc
type DepfileParserTest (line 21) | struct DepfileParserTest : public testing::Test {
function TEST_F (line 33) | TEST_F(DepfileParserTest, Basic) {
function TEST_F (line 44) | TEST_F(DepfileParserTest, EarlyNewlineAndWhitespace) {
function TEST_F (line 53) | TEST_F(DepfileParserTest, Continuation) {
function TEST_F (line 65) | TEST_F(DepfileParserTest, WindowsDrivePaths) {
function TEST_F (line 75) | TEST_F(DepfileParserTest, AmpersandsAndQuotes) {
function TEST_F (line 89) | TEST_F(DepfileParserTest, CarriageReturnContinuation) {
function TEST_F (line 101) | TEST_F(DepfileParserTest, BackSlashes) {
function TEST_F (line 117) | TEST_F(DepfileParserTest, Spaces) {
function TEST_F (line 135) | TEST_F(DepfileParserTest, MultipleBackslashes) {
function TEST_F (line 157) | TEST_F(DepfileParserTest, Escapes) {
function TEST_F (line 171) | TEST_F(DepfileParserTest, EscapedColons)
function TEST_F (line 189) | TEST_F(DepfileParserTest, EscapedTargetColon)
function TEST_F (line 206) | TEST_F(DepfileParserTest, SpecialChars) {
function TEST_F (line 234) | TEST_F(DepfileParserTest, UnifyMultipleOutputs) {
function TEST_F (line 246) | TEST_F(DepfileParserTest, MultipleDifferentOutputs) {
function TEST_F (line 259) | TEST_F(DepfileParserTest, MultipleEmptyRules) {
function TEST_F (line 270) | TEST_F(DepfileParserTest, UnifyMultipleRulesLF) {
function TEST_F (line 284) | TEST_F(DepfileParserTest, UnifyMultipleRulesCRLF) {
function TEST_F (line 298) | TEST_F(DepfileParserTest, UnifyMixedRulesLF) {
function TEST_F (line 312) | TEST_F(DepfileParserTest, UnifyMixedRulesCRLF) {
function TEST_F (line 326) | TEST_F(DepfileParserTest, IndentedRulesLF) {
function TEST_F (line 339) | TEST_F(DepfileParserTest, IndentedRulesCRLF) {
function TEST_F (line 352) | TEST_F(DepfileParserTest, TolerateMP) {
function TEST_F (line 366) | TEST_F(DepfileParserTest, MultipleRulesTolerateMP) {
function TEST_F (line 382) | TEST_F(DepfileParserTest, MultipleRulesDifferentOutputs) {
function TEST_F (line 397) | TEST_F(DepfileParserTest, BuggyMP) {
function TEST_F (line 406) | TEST_F(DepfileParserTest, EmptyFile) {
function TEST_F (line 413) | TEST_F(DepfileParserTest, EmptyLines) {
function TEST_F (line 420) | TEST_F(DepfileParserTest, MissingColon) {
FILE: src/deps_log.cc
function LoadStatus (line 154) | LoadStatus DepsLog::Load(const string& path, State* state, string* err) {
function Node (line 313) | Node* DepsLog::GetFirstReverseDepsNode(Node* node) {
FILE: src/deps_log.h
type Node (line 26) | struct Node
type State (line 27) | struct State
type DepsLog (line 68) | struct DepsLog {
FILE: src/deps_log_test.cc
type DepsLogTest (line 33) | struct DepsLogTest : public testing::Test {
method SetUp (line 34) | virtual void SetUp() {
method TearDown (line 38) | virtual void TearDown() { platformAwareUnlink(kTestFilename); }
function TEST_F (line 41) | TEST_F(DepsLogTest, WriteRead) {
function TEST_F (line 91) | TEST_F(DepsLogTest, LotsOfDeps) {
function TEST_F (line 125) | TEST_F(DepsLogTest, DoubleEntry) {
function TEST_F (line 179) | TEST_F(DepsLogTest, Recompact) {
function TEST_F (line 354) | TEST_F(DepsLogTest, InvalidHeader) {
function TEST_F (line 380) | TEST_F(DepsLogTest, Truncated) {
function TEST_F (line 444) | TEST_F(DepsLogTest, TruncatedRecovery) {
function TEST_F (line 517) | TEST_F(DepsLogTest, ReverseDepsNodes) {
function TEST_F (line 544) | TEST_F(DepsLogTest, MalformedDepsLog) {
FILE: src/disk_interface.cc
function string (line 41) | string DirName(const string& path) {
function MakeDir (line 58) | int MakeDir(const string& path) {
function TimeStamp (line 67) | TimeStamp TimeStampFromFileTime(const FILETIME& filetime) {
function TimeStamp (line 77) | TimeStamp StatSingleFile(const string& path, string* err) {
function IsWindows7OrLater (line 116) | bool IsWindows7OrLater() {
function StatAllFilesInDir (line 126) | bool StatAllFilesInDir(const string& dir, map<string, TimeStamp>* stamps,
type stat64 (line 255) | struct stat64
type stat (line 258) | struct stat
FILE: src/disk_interface.h
function Status (line 25) | struct FileReader {
function FileReader (line 45) | struct DiskInterface: public FileReader {
function DiskInterface (line 73) | struct RealDiskInterface : public DiskInterface {
FILE: src/disk_interface_test.cc
type DiskInterfaceTest (line 31) | struct DiskInterfaceTest : public testing::Test {
method SetUp (line 32) | virtual void SetUp() {
method TearDown (line 37) | virtual void TearDown() {
method Touch (line 41) | bool Touch(const char* path) {
function TEST_F (line 52) | TEST_F(DiskInterfaceTest, StatMissingFile) {
function TEST_F (line 69) | TEST_F(DiskInterfaceTest, StatMissingFileWithCache) {
function TEST_F (line 80) | TEST_F(DiskInterfaceTest, StatBadPath) {
function TEST_F (line 93) | TEST_F(DiskInterfaceTest, StatExistingFile) {
function TEST_F (line 101) | TEST_F(DiskInterfaceTest, StatExistingFileWithLongPath) {
function TEST_F (line 118) | TEST_F(DiskInterfaceTest, StatSymlink) {
function TEST_F (line 139) | TEST_F(DiskInterfaceTest, StatExistingDir) {
function TEST_F (line 161) | TEST_F(DiskInterfaceTest, StatCache) {
function TEST_F (line 222) | TEST_F(DiskInterfaceTest, ReadFile) {
function TEST_F (line 244) | TEST_F(DiskInterfaceTest, MakeDirs) {
function TEST_F (line 259) | TEST_F(DiskInterfaceTest, RemoveFile) {
function TEST_F (line 273) | TEST_F(DiskInterfaceTest, RemoveDirectory) {
type StatTest (line 281) | struct StatTest : public StateTestWithBuiltinRules,
method StatTest (line 283) | StatTest() : scan_(&state_, NULL, NULL, this, NULL, NULL) {}
method WriteFile (line 287) | bool WriteFile(const string& path, const string& contents,
method MakeDir (line 292) | bool MakeDir(const string& path) override {
method Status (line 296) | Status ReadFile(const string& path, string* contents, string* err) ove...
method RemoveFile (line 300) | int RemoveFile(const string& path) override {
function TimeStamp (line 310) | TimeStamp StatTest::Stat(const string& path, string* err) const {
function TEST_F (line 318) | TEST_F(StatTest, Simple) {
function TEST_F (line 333) | TEST_F(StatTest, TwoStep) {
function TEST_F (line 352) | TEST_F(StatTest, Tree) {
function TEST_F (line 370) | TEST_F(StatTest, Middle) {
FILE: src/dyndep.h
type DiskInterface (line 24) | struct DiskInterface
type Edge (line 25) | struct Edge
type Node (line 26) | struct Node
type State (line 27) | struct State
type Dyndeps (line 30) | struct Dyndeps {
type DyndepFile (line 42) | struct DyndepFile
type DyndepLoader (line 46) | struct DyndepLoader {
FILE: src/dyndep_parser.h
type DyndepFile (line 21) | struct DyndepFile
type EvalString (line 22) | struct EvalString
function Parser (line 25) | struct DyndepParser: public Parser {
FILE: src/dyndep_parser_test.cc
type DyndepParserTest (line 27) | struct DyndepParserTest : public testing::Test {
method AssertParse (line 28) | void AssertParse(const char* input) {
method SetUp (line 35) | virtual void SetUp() {
function TEST_F (line 47) | TEST_F(DyndepParserTest, Empty) {
function TEST_F (line 56) | TEST_F(DyndepParserTest, Version1) {
function TEST_F (line 61) | TEST_F(DyndepParserTest, Version1Extra) {
function TEST_F (line 66) | TEST_F(DyndepParserTest, Version1_0) {
function TEST_F (line 71) | TEST_F(DyndepParserTest, Version1_0Extra) {
function TEST_F (line 76) | TEST_F(DyndepParserTest, CommentVersion) {
function TEST_F (line 82) | TEST_F(DyndepParserTest, BlankLineVersion) {
function TEST_F (line 88) | TEST_F(DyndepParserTest, VersionCRLF) {
function TEST_F (line 93) | TEST_F(DyndepParserTest, CommentVersionCRLF) {
function TEST_F (line 99) | TEST_F(DyndepParserTest, BlankLineVersionCRLF) {
function TEST_F (line 105) | TEST_F(DyndepParserTest, VersionUnexpectedEOF) {
function TEST_F (line 116) | TEST_F(DyndepParserTest, UnsupportedVersion0) {
function TEST_F (line 127) | TEST_F(DyndepParserTest, UnsupportedVersion1_1) {
function TEST_F (line 138) | TEST_F(DyndepParserTest, DuplicateVersion) {
function TEST_F (line 148) | TEST_F(DyndepParserTest, MissingVersionOtherVar) {
function TEST_F (line 159) | TEST_F(DyndepParserTest, MissingVersionBuild) {
function TEST_F (line 168) | TEST_F(DyndepParserTest, UnexpectedEqual) {
function TEST_F (line 177) | TEST_F(DyndepParserTest, UnexpectedIndent) {
function TEST_F (line 186) | TEST_F(DyndepParserTest, OutDuplicate) {
function TEST_F (line 199) | TEST_F(DyndepParserTest, OutDuplicateThroughOther) {
function TEST_F (line 212) | TEST_F(DyndepParserTest, NoOutEOF) {
function TEST_F (line 224) | TEST_F(DyndepParserTest, NoOutColon) {
function TEST_F (line 236) | TEST_F(DyndepParserTest, OutNoStatement) {
function TEST_F (line 248) | TEST_F(DyndepParserTest, OutEOF) {
function TEST_F (line 260) | TEST_F(DyndepParserTest, OutNoRule) {
function TEST_F (line 272) | TEST_F(DyndepParserTest, OutBadRule) {
function TEST_F (line 284) | TEST_F(DyndepParserTest, BuildEOF) {
function TEST_F (line 296) | TEST_F(DyndepParserTest, ExplicitOut) {
function TEST_F (line 308) | TEST_F(DyndepParserTest, ExplicitIn) {
function TEST_F (line 320) | TEST_F(DyndepParserTest, OrderOnlyIn) {
function TEST_F (line 332) | TEST_F(DyndepParserTest, BadBinding) {
function TEST_F (line 345) | TEST_F(DyndepParserTest, RestatTwice) {
function TEST_F (line 357) | TEST_F(DyndepParserTest, NoImplicit) {
function TEST_F (line 370) | TEST_F(DyndepParserTest, EmptyImplicit) {
function TEST_F (line 383) | TEST_F(DyndepParserTest, ImplicitIn) {
function TEST_F (line 397) | TEST_F(DyndepParserTest, ImplicitIns) {
function TEST_F (line 412) | TEST_F(DyndepParserTest, ImplicitOut) {
function TEST_F (line 426) | TEST_F(DyndepParserTest, ImplicitOuts) {
function TEST_F (line 441) | TEST_F(DyndepParserTest, ImplicitInsAndOuts) {
function TEST_F (line 458) | TEST_F(DyndepParserTest, Restat) {
function TEST_F (line 472) | TEST_F(DyndepParserTest, OtherOutput) {
function TEST_F (line 485) | TEST_F(DyndepParserTest, MultipleEdges) {
FILE: src/edit_distance.cc
function EditDistance (line 20) | int EditDistance(const StringPiece& s1,
FILE: src/edit_distance_test.cc
function TEST (line 19) | TEST(EditDistanceTest, TestEmpty) {
function TEST (line 25) | TEST(EditDistanceTest, TestMaxDistance) {
function TEST (line 34) | TEST(EditDistanceTest, TestAllowReplacements) {
function TEST (line 44) | TEST(EditDistanceTest, TestBasics) {
FILE: src/elide_middle.cc
type AnsiColorSequenceIterator (line 33) | struct AnsiColorSequenceIterator {
method AnsiColorSequenceIterator (line 35) | AnsiColorSequenceIterator(const std::string& input)
method HasSequence (line 41) | bool HasSequence() const { return cur_end_ != 0; }
method SequenceStart (line 44) | size_t SequenceStart() const { return cur_start_; }
method SequenceEnd (line 48) | size_t SequenceEnd() const { return cur_end_; }
method SequenceSize (line 51) | size_t SequenceSize() const { return cur_end_ - cur_start_; }
method SequenceContains (line 54) | bool SequenceContains(size_t input_index) const {
method NextSequence (line 60) | bool NextSequence() {
method Reset (line 70) | void Reset() {
method FindNextSequenceFrom (line 80) | bool FindNextSequenceFrom(const char* from) {
type VisibleInputCharsIterator (line 153) | struct VisibleInputCharsIterator {
method VisibleInputCharsIterator (line 154) | VisibleInputCharsIterator(const std::string& input)
method HasChar (line 158) | bool HasChar() const { return input_index_ < input_size_; }
method InputIndex (line 161) | size_t InputIndex() const { return input_index_; }
method VisiblePosition (line 164) | size_t VisiblePosition() const { return visible_pos_; }
method IsVisible (line 168) | bool IsVisible() const { return !ansi_iter_.SequenceContains(input_ind...
method NextChar (line 171) | void NextChar() {
function ElideMiddleInPlace (line 185) | void ElideMiddleInPlace(std::string& str, size_t max_width) {
FILE: src/elide_middle_perftest.cc
function main (line 31) | int main() {
FILE: src/elide_middle_test.cc
function ElideMiddle (line 21) | std::string ElideMiddle(const std::string& str, size_t width) {
function TEST (line 30) | TEST(ElideMiddle, NothingToElide) {
function TEST (line 40) | TEST(ElideMiddle, ElideInTheMiddle) {
function TEST (line 58) | TEST(ElideMiddle, ElideAnsiEscapeCodes) {
FILE: src/eval_env.cc
function string (line 21) | string BindingEnv::LookupVariable(const string& var) {
function Rule (line 39) | const Rule* BindingEnv::LookupRuleCurrentScope(const string& rule_name) {
function Rule (line 46) | const Rule* BindingEnv::LookupRule(const string& rule_name) {
function EvalString (line 59) | const EvalString* Rule::GetBinding(const string& key) const {
function string (line 95) | string BindingEnv::LookupWithFallback(const string& var,
function string (line 111) | string EvalString::Evaluate(Env* env) const {
function string (line 146) | string EvalString::Serialize() const {
function string (line 164) | string EvalString::Unparse() const {
FILE: src/eval_env.h
type Rule (line 25) | struct Rule
type Env (line 28) | struct Env {
function empty (line 35) | struct EvalString {
function explicit (line 95) | explicit BindingEnv(BindingEnv* parent) : parent_(parent) {}
function virtual (line 97) | virtual ~BindingEnv() {}
FILE: src/exit_status.h
type ExitStatus (line 27) | enum ExitStatus
FILE: src/explanations.h
function RecordArgs (line 27) | struct Explanations {
function LookupAndAppend (line 46) | void LookupAndAppend(const void* item, std::vector<std::string>* out) {
function RecordArgs (line 61) | struct OptionalExplanations {
function LookupAndAppend (line 79) | void LookupAndAppend(const void* item, std::vector<std::string>* out) {
function Explanations (line 84) | Explanations* ptr() const { return explanations_; }
FILE: src/explanations_test.cc
function TEST (line 27) | TEST(Explanations, Explanations) {
function TEST (line 53) | TEST(Explanations, OptionalExplanationsNonNull) {
function TEST (line 80) | TEST(Explanations, OptionalExplanationsWithNullPointer) {
FILE: src/getopt.c
type GETOPT_ORDERING_T (line 97) | typedef enum GETOPT_ORDERING_T
function reverse_argv_elements (line 113) | static void
function permute (line 128) | static void
function is_option (line 137) | static int
function getopt_internal (line 145) | static int
function getopt (line 389) | int
function getopt_long (line 396) | int
function getopt_long_only (line 403) | int
FILE: src/getopt.h
type GETOPT_LONG_OPTION_T (line 14) | typedef struct GETOPT_LONG_OPTION_T
type GETOPT_LONG_OPTION_T (line 28) | typedef GETOPT_LONG_OPTION_T option;
FILE: src/graph.cc
type EdgeEnv (line 397) | struct EdgeEnv : public Env {
type EscapeKind (line 398) | enum EscapeKind { kShellEscape, kDoNotEscape }
method EdgeEnv (line 400) | EdgeEnv(const Edge* const edge, const EscapeKind escape)
function string (line 415) | string EdgeEnv::LookupVariable(const string& var) {
function string (line 526) | string Edge::GetUnescapedDepfile() const {
function string (line 531) | string Edge::GetUnescapedDyndep() const {
function string (line 586) | string Node::PathDecanonicalized(const string& path, uint64_t slash_bits) {
type matches (line 637) | struct matches {
method matches (line 638) | explicit matches(std::vector<StringPiece>::iterator i) : i_(i) {}
FILE: src/graph.h
type BuildLog (line 31) | struct BuildLog
type DepfileParserOptions (line 32) | struct DepfileParserOptions
type DiskInterface (line 33) | struct DiskInterface
type DepsLog (line 34) | struct DepsLog
type Edge (line 35) | struct Edge
type Node (line 36) | struct Node
type Pool (line 37) | struct Pool
type State (line 38) | struct State
function ResetState (line 42) | struct Node {
function MarkMissing (line 67) | void MarkMissing() {
function set_dirty (line 94) | void set_dirty(bool dirty) { dirty_ = dirty; }
function MarkDirty (line 95) | void MarkDirty() { dirty_ = true; }
function set_dyndep_pending (line 98) | void set_dyndep_pending(bool pending) { dyndep_pending_ = pending; }
function Edge (line 100) | Edge* in_edge() const { return in_edge_; }
function set_in_edge (line 101) | void set_in_edge(Edge* edge) { in_edge_ = edge; }
function set_generated_by_dep_loader (line 107) | void set_generated_by_dep_loader(bool value) {
function set_id (line 112) | void set_id(int id) { id_ = id; }
function AddOutEdge (line 116) | void AddOutEdge(Edge* edge) { out_edges_.push_back(edge); }
function AddValidationOutEdge (line 117) | void AddValidationOutEdge(Edge* edge) { validation_out_edges_.push_back(...
type ExistenceStatus (line 134) | enum ExistenceStatus : char {
function set_critical_path_weight (line 175) | struct Edge {
function Pool (line 235) | Pool* pool() const { return pool_; }
function is_implicit (line 249) | bool is_implicit(size_t index) {
function is_order_only (line 253) | bool is_order_only(size_t index) {
function is_implicit_out (line 263) | bool is_implicit_out(size_t index) const {
function is_phony (line 267) | bool is_phony() const;
type EdgePriorityLess (line 401) | struct EdgePriorityLess {
type EdgePriorityGreater (line 413) | struct EdgePriorityGreater {
type InputsCollector (line 443) | struct InputsCollector {
function Reset (line 457) | void Reset() {
FILE: src/graph_test.cc
type GraphTest (line 23) | struct GraphTest : public StateTestWithBuiltinRules {
method GraphTest (line 24) | GraphTest() : scan_(&state_, NULL, NULL, &fs_, NULL, NULL) {}
function TEST_F (line 30) | TEST_F(GraphTest, MissingImplicit) {
function TEST_F (line 46) | TEST_F(GraphTest, ModifiedImplicit) {
function TEST_F (line 62) | TEST_F(GraphTest, FunkyMakefilePath) {
function TEST_F (line 83) | TEST_F(GraphTest, ExplicitImplicit) {
function TEST_F (line 107) | TEST_F(GraphTest, ImplicitOutputParse) {
function TEST_F (line 119) | TEST_F(GraphTest, ImplicitOutputMissing) {
function TEST_F (line 133) | TEST_F(GraphTest, ImplicitOutputOutOfDate) {
function TEST_F (line 149) | TEST_F(GraphTest, ImplicitOutputOnlyParse) {
function TEST_F (line 160) | TEST_F(GraphTest, ImplicitOutputOnlyMissing) {
function TEST_F (line 172) | TEST_F(GraphTest, ImplicitOutputOnlyOutOfDate) {
function TEST_F (line 186) | TEST_F(GraphTest, PathWithCurrentDirectory) {
function TEST_F (line 203) | TEST_F(GraphTest, RootNodes) {
function TEST_F (line 219) | TEST_F(GraphTest, InputsCollector) {
function TEST_F (line 286) | TEST_F(GraphTest, InputsCollectorWithEscapes) {
function TEST_F (line 314) | TEST_F(GraphTest, CommandCollector) {
function TEST_F (line 362) | TEST_F(GraphTest, VarInOutPathEscaping) {
function TEST_F (line 377) | TEST_F(GraphTest, DepfileWithCanonicalizablePath) {
function TEST_F (line 395) | TEST_F(GraphTest, DepfileRemoved) {
function TEST_F (line 420) | TEST_F(GraphTest, RuleVariablesInScope) {
function TEST_F (line 431) | TEST_F(GraphTest, DepfileOverride) {
function TEST_F (line 443) | TEST_F(GraphTest, DepfileOverrideParent) {
function TEST_F (line 455) | TEST_F(GraphTest, NestedPhonyPrintsDone) {
function TEST_F (line 472) | TEST_F(GraphTest, PhonySelfReferenceError) {
function TEST_F (line 484) | TEST_F(GraphTest, DependencyCycle) {
function TEST_F (line 496) | TEST_F(GraphTest, CycleInEdgesButNotInNodes1) {
function TEST_F (line 504) | TEST_F(GraphTest, CycleInEdgesButNotInNodes2) {
function TEST_F (line 512) | TEST_F(GraphTest, CycleInEdgesButNotInNodes3) {
function TEST_F (line 521) | TEST_F(GraphTest, CycleInEdgesButNotInNodes4) {
function TEST_F (line 535) | TEST_F(GraphTest, CycleWithLengthZeroFromDepfile) {
function TEST_F (line 557) | TEST_F(GraphTest, CycleWithLengthOneFromDepfile) {
function TEST_F (line 583) | TEST_F(GraphTest, CycleWithLengthOneFromDepfileOneHopAway) {
function TEST_F (line 609) | TEST_F(GraphTest, Decanonicalize) {
function TEST_F (line 629) | TEST_F(GraphTest, DyndepLoadTrivial) {
function TEST_F (line 658) | TEST_F(GraphTest, DyndepLoadImplicit) {
function TEST_F (line 689) | TEST_F(GraphTest, DyndepLoadMissingFile) {
function TEST_F (line 703) | TEST_F(GraphTest, DyndepLoadMissingEntry) {
function TEST_F (line 720) | TEST_F(GraphTest, DyndepLoadExtraEntry) {
function TEST_F (line 741) | TEST_F(GraphTest, DyndepLoadOutputWithMultipleRules1) {
function TEST_F (line 760) | TEST_F(GraphTest, DyndepLoadOutputWithMultipleRules2) {
function TEST_F (line 787) | TEST_F(GraphTest, DyndepLoadMultiple) {
function TEST_F (line 843) | TEST_F(GraphTest, DyndepFileMissing) {
function TEST_F (line 856) | TEST_F(GraphTest, DyndepFileError) {
function TEST_F (line 872) | TEST_F(GraphTest, DyndepImplicitInputNewer) {
function TEST_F (line 898) | TEST_F(GraphTest, DyndepFileReady) {
function TEST_F (line 927) | TEST_F(GraphTest, DyndepFileNotClean) {
function TEST_F (line 952) | TEST_F(GraphTest, DyndepFileNotReady) {
function TEST_F (line 976) | TEST_F(GraphTest, DyndepFileSecondNotReady) {
function TEST_F (line 1006) | TEST_F(GraphTest, DyndepFileCircular) {
function TEST_F (line 1037) | TEST_F(GraphTest, Validation) {
function TEST_F (line 1056) | TEST_F(GraphTest, PhonyDepsMtimes) {
function TEST_F (line 1093) | TEST_F(GraphTest, EdgeQueuePriority) {
function TEST_F (line 1143) | TEST_F(GraphTest, PhonyOutputWithValidation) {
FILE: src/graphviz.h
type DiskInterface (line 23) | struct DiskInterface
type Node (line 24) | struct Node
type Edge (line 25) | struct Edge
type State (line 26) | struct State
type GraphViz (line 29) | struct GraphViz {
FILE: src/hash_collision_bench.cc
function random (line 24) | int random(int low, int high) {
function RandomCommand (line 28) | void RandomCommand(char** s) {
function main (line 36) | int main() {
FILE: src/hash_map.h
function namespace (line 26) | namespace std {
type emhash8 (line 44) | typedef emhash8::HashMap<StringPiece, V> Type;
FILE: src/includes_normalize-win32.cc
function InternalGetFullPathName (line 31) | bool InternalGetFullPathName(const StringPiece& file_name, char* buffer,
function IsPathSeparator (line 46) | bool IsPathSeparator(char c) {
function SameDriveFast (line 53) | bool SameDriveFast(StringPiece a, StringPiece b) {
function SameDrive (line 74) | bool SameDrive(StringPiece a, StringPiece b, string* err) {
function IsFullPathName (line 97) | bool IsFullPathName(StringPiece s) {
function string (line 138) | string IncludesNormalize::AbsPath(StringPiece s, string* err) {
function string (line 159) | string IncludesNormalize::Relativize(
FILE: src/includes_normalize.h
type StringPiece (line 21) | struct StringPiece
type IncludesNormalize (line 25) | struct IncludesNormalize {
FILE: src/includes_normalize_test.cc
function string (line 29) | string GetCurDir() {
function string (line 36) | string NormalizeAndCheckNoError(const string& input) {
function string (line 44) | string NormalizeRelativeAndCheckNoError(const string& input,
function TEST (line 55) | TEST(IncludesNormalize, Simple) {
function TEST (line 62) | TEST(IncludesNormalize, WithRelative) {
function TEST (line 77) | TEST(IncludesNormalize, Case) {
function TEST (line 86) | TEST(IncludesNormalize, DifferentDrive) {
function TEST (line 102) | TEST(IncludesNormalize, LongInvalidPath) {
function TEST (line 148) | TEST(IncludesNormalize, ShortRelativeButTooLongAbsolutePath) {
FILE: src/jobserver-posix.cc
function IsJobserverDescriptor (line 30) | bool IsJobserverDescriptor(int fd) {
class PosixJobserverClient (line 38) | class PosixJobserverClient : public Jobserver::Client {
method TryAcquire (line 47) | Jobserver::Slot TryAcquire() override {
method Release (line 63) | void Release(Jobserver::Slot slot) override {
method InitWithFifo (line 82) | bool InitWithFifo(const std::string& fifo_path, std::string* error) {
FILE: src/jobserver-win32.cc
class Win32JobserverClient (line 27) | class Win32JobserverClient : public Jobserver::Client {
method TryAcquire (line 36) | Jobserver::Slot TryAcquire() override {
method Release (line 52) | void Release(Jobserver::Slot slot) override {
method InitWithSemaphore (line 66) | bool InitWithSemaphore(const std::string& name, std::string* error) {
method IsValid (line 77) | bool IsValid() const {
FILE: src/jobserver.cc
function GetPrefixedValue (line 28) | bool GetPrefixedValue(StringPiece input, StringPiece prefix,
function GetFileDescriptorPair (line 42) | bool GetFileDescriptorPair(StringPiece input, Jobserver::Config* config) {
FILE: src/jobserver.h
type Jobserver (line 28) | struct Jobserver {
function GetExplicitValue (line 86) | uint8_t GetExplicitValue() const;
type Config (line 106) | struct Config {
function class (line 189) | class Client {
FILE: src/jobserver_test.cc
type ScopedTestFd (line 27) | struct ScopedTestFd {
method ScopedTestFd (line 28) | explicit ScopedTestFd(int fd) : fd_(fd) {}
method IsValid (line 35) | bool IsValid() const { return fd_ >= 0; }
function TEST (line 43) | TEST(Jobserver, SlotTest) {
function TEST (line 81) | TEST(Jobserver, ParseMakeFlagsValue) {
function TEST (line 183) | TEST(Jobserver, ParseNativeMakeFlagsValue) {
function TEST (line 227) | TEST(Jobserver, NullJobserver) {
type ScopedSemaphoreHandle (line 243) | struct ScopedSemaphoreHandle {
method ScopedSemaphoreHandle (line 244) | ScopedSemaphoreHandle(HANDLE handle) : handle_(handle) {}
method HANDLE (line 249) | HANDLE get() const { return handle_; }
function TEST (line 255) | TEST(Jobserver, Win32SemaphoreClient) {
function TEST (line 319) | TEST(Jobserver, PosixFifoClient) {
function TEST (line 372) | TEST(Jobserver, PosixFifoClientWithWrongPath) {
FILE: src/json.cc
function EncodeJSONString (line 20) | std::string EncodeJSONString(const std::string& in) {
function PrintJSONString (line 50) | void PrintJSONString(const std::string& in) {
FILE: src/json_test.cc
function TEST (line 19) | TEST(JSONTest, RegularAscii) {
function TEST (line 23) | TEST(JSONTest, EscapedChars) {
function TEST (line 31) | TEST(JSONTest, ControlChars) {
function TEST (line 37) | TEST(JSONTest, UTF8) {
FILE: src/lexer.cc
function string (line 110) | string Lexer::DescribeLastError() {
FILE: src/lexer.h
type EvalString (line 25) | struct EvalString
function ReadVarValue (line 27) | struct Lexer {
FILE: src/lexer.in.cc
function string (line 109) | string Lexer::DescribeLastError() {
FILE: src/lexer_test.cc
function TEST (line 22) | TEST(Lexer, ReadVarValue) {
function TEST (line 32) | TEST(Lexer, ReadEvalStringEscapes) {
function TEST (line 42) | TEST(Lexer, ReadIdent) {
function TEST (line 55) | TEST(Lexer, ReadIdentCurlies) {
function TEST (line 71) | TEST(Lexer, Error) {
function TEST (line 82) | TEST(Lexer, CommentEOF) {
function TEST (line 90) | TEST(Lexer, Tabs) {
function TEST (line 100) | TEST(Lexer, EscapedNewlines) {
FILE: src/line_printer.h
function set_smart_terminal (line 23) | struct LinePrinter {
type LineType (line 31) | enum LineType {
FILE: src/load_status.h
type LoadStatus (line 18) | enum LoadStatus {
FILE: src/manifest_parser.h
type BindingEnv (line 23) | struct BindingEnv
type EvalString (line 24) | struct EvalString
type DupeEdgeAction (line 26) | enum DupeEdgeAction {
type PhonyCycleAction (line 31) | enum PhonyCycleAction {
type ManifestParserOptions (line 36) | struct ManifestParserOptions {
function Parser (line 41) | struct ManifestParser : public Parser {
FILE: src/manifest_parser_perftest.cc
function WriteFakeManifests (line 45) | bool WriteFakeManifests(const string& dir, string* err) {
function LoadManifests (line 60) | int LoadManifests(bool measure_command_evaluation) {
function main (line 79) | int main(int argc, char* argv[]) {
FILE: src/manifest_parser_test.cc
type ParserTest (line 26) | struct ParserTest : public testing::Test {
method AssertParse (line 27) | void AssertParse(const char* input) {
function TEST_F (line 39) | TEST_F(ParserTest, Empty) {
function TEST_F (line 43) | TEST_F(ParserTest, Rules) {
function TEST_F (line 60) | TEST_F(ParserTest, RuleAttributes) {
function TEST_F (line 75) | TEST_F(ParserTest, IgnoreIndentedComments) {
function TEST_F (line 94) | TEST_F(ParserTest, IgnoreIndentedBlankLines) {
function TEST_F (line 109) | TEST_F(ParserTest, ResponseFiles) {
function TEST_F (line 128) | TEST_F(ParserTest, InNewline) {
function TEST_F (line 146) | TEST_F(ParserTest, Variables) {
function TEST_F (line 171) | TEST_F(ParserTest, VariableScope) {
function TEST_F (line 188) | TEST_F(ParserTest, Continuation) {
function TEST_F (line 203) | TEST_F(ParserTest, Backslash) {
function TEST_F (line 212) | TEST_F(ParserTest, Comment) {
function TEST_F (line 219) | TEST_F(ParserTest, Dollars) {
function TEST_F (line 235) | TEST_F(ParserTest, EscapeSpaces) {
function TEST_F (line 248) | TEST_F(ParserTest, CanonicalizeFile) {
function TEST_F (line 263) | TEST_F(ParserTest, CanonicalizeFileBackslashes) {
function TEST_F (line 282) | TEST_F(ParserTest, PathVariables) {
function TEST_F (line 293) | TEST_F(ParserTest, CanonicalizePaths) {
function TEST_F (line 306) | TEST_F(ParserTest, CanonicalizePathsBackslashes) {
function TEST_F (line 333) | TEST_F(ParserTest, DuplicateEdgeWithMultipleOutputsError) {
function TEST_F (line 346) | TEST_F(ParserTest, DuplicateEdgeInIncludedFile) {
function TEST_F (line 361) | TEST_F(ParserTest, PhonySelfReferenceIgnored) {
function TEST_F (line 371) | TEST_F(ParserTest, PhonySelfReferenceKept) {
function TEST_F (line 387) | TEST_F(ParserTest, ReservedWords) {
function TEST_F (line 395) | TEST_F(ParserTest, Errors) {
function TEST_F (line 824) | TEST_F(ParserTest, MissingInput) {
function TEST_F (line 832) | TEST_F(ParserTest, MultipleOutputs) {
function TEST_F (line 842) | TEST_F(ParserTest, MultipleOutputsWithDeps) {
function TEST_F (line 852) | TEST_F(ParserTest, SubNinja) {
function TEST_F (line 877) | TEST_F(ParserTest, MissingSubNinja) {
function TEST_F (line 887) | TEST_F(ParserTest, DuplicateRuleInDifferentSubninjas) {
function TEST_F (line 898) | TEST_F(ParserTest, DuplicateRuleInDifferentSubninjasWithInclude) {
function TEST_F (line 911) | TEST_F(ParserTest, Include) {
function TEST_F (line 922) | TEST_F(ParserTest, BrokenInclude) {
function TEST_F (line 933) | TEST_F(ParserTest, Implicit) {
function TEST_F (line 943) | TEST_F(ParserTest, OrderOnly) {
function TEST_F (line 952) | TEST_F(ParserTest, Validations) {
function TEST_F (line 962) | TEST_F(ParserTest, ImplicitOutput) {
function TEST_F (line 973) | TEST_F(ParserTest, ImplicitOutputEmpty) {
function TEST_F (line 984) | TEST_F(ParserTest, ImplicitOutputDupeError) {
function TEST_F (line 995) | TEST_F(ParserTest, ImplicitOutputDupesError) {
function TEST_F (line 1006) | TEST_F(ParserTest, NoExplicitOutput) {
function TEST_F (line 1015) | TEST_F(ParserTest, DefaultDefault) {
function TEST_F (line 1028) | TEST_F(ParserTest, DefaultDefaultCycle) {
function TEST_F (line 1038) | TEST_F(ParserTest, DefaultStatements) {
function TEST_F (line 1058) | TEST_F(ParserTest, UTF8) {
function TEST_F (line 1065) | TEST_F(ParserTest, CRLF) {
function TEST_F (line 1081) | TEST_F(ParserTest, DyndepNotSpecified) {
function TEST_F (line 1090) | TEST_F(ParserTest, DyndepNotInput) {
function TEST_F (line 1103) | TEST_F(ParserTest, DyndepExplicitInput) {
function TEST_F (line 1115) | TEST_F(ParserTest, DyndepImplicitInput) {
function TEST_F (line 1127) | TEST_F(ParserTest, DyndepOrderOnlyInput) {
function TEST_F (line 1139) | TEST_F(ParserTest, DyndepRuleInput) {
FILE: src/metrics.cc
function HighResTimer (line 33) | int64_t HighResTimer() {
function TimerToMicros (line 40) | int64_t TimerToMicros(int64_t dt) {
function TimerToMicros (line 47) | int64_t TimerToMicros(double dt) {
function Metric (line 73) | Metric* Metrics::NewMetric(const string& name) {
function GetTimeMillis (line 111) | int64_t GetTimeMillis() {
FILE: src/metrics.h
type Metric (line 27) | struct Metric {
type ScopedMetric (line 37) | struct ScopedMetric {
type Metrics (line 49) | struct Metrics {
type Stopwatch (line 65) | struct Stopwatch {
FILE: src/minidump-win32.cc
function CreateWin32MiniDump (line 35) | void CreateWin32MiniDump(_EXCEPTION_POINTERS* pep) {
FILE: src/missing_deps.cc
type NodeStoringImplicitDepLoader (line 32) | struct NodeStoringImplicitDepLoader : public ImplicitDepLoader {
method NodeStoringImplicitDepLoader (line 33) | NodeStoringImplicitDepLoader(
FILE: src/missing_deps.h
type DepsLog (line 24) | struct DepsLog
type DiskInterface (line 25) | struct DiskInterface
type Edge (line 26) | struct Edge
type Node (line 27) | struct Node
type Rule (line 28) | struct Rule
type State (line 29) | struct State
function class (line 31) | class MissingDependencyScannerDelegate {
function class (line 38) | class MissingDependencyPrinter : public MissingDependencyScannerDelegate {
type MissingDependencyScanner (line 45) | struct MissingDependencyScanner {
FILE: src/missing_deps_test.cc
class MissingDependencyTestDelegate (line 25) | class MissingDependencyTestDelegate : public MissingDependencyScannerDel...
method OnMissingDep (line 26) | void OnMissingDep(Node* node, const std::string& path,
type MissingDependencyScannerTest (line 30) | struct MissingDependencyScannerTest : public testing::Test {
method MissingDependencyScannerTest (line 31) | MissingDependencyScannerTest()
method MissingDependencyScanner (line 44) | MissingDependencyScanner& scanner() { return scanner_; }
method RecordDepsLogDep (line 46) | void RecordDepsLogDep(const std::string& from, const std::string& to) {
method ProcessAllNodes (line 51) | void ProcessAllNodes() {
method CreateInitialState (line 61) | void CreateInitialState() {
method CreateGraphDependencyBetween (line 72) | void CreateGraphDependencyBetween(const char* from, const char* to) {
method AssertMissingDependencyBetween (line 78) | void AssertMissingDependencyBetween(const char* flaky, const char* gen...
function TEST_F (line 97) | TEST_F(MissingDependencyScannerTest, EmptyGraph) {
function TEST_F (line 102) | TEST_F(MissingDependencyScannerTest, NoMissingDep) {
function TEST_F (line 108) | TEST_F(MissingDependencyScannerTest, MissingDepPresent) {
function TEST_F (line 120) | TEST_F(MissingDependencyScannerTest, MissingDepFixedDirect) {
function TEST_F (line 129) | TEST_F(MissingDependencyScannerTest, MissingDepFixedIndirect) {
function TEST_F (line 141) | TEST_F(MissingDependencyScannerTest, CyclicMissingDep) {
function TEST_F (line 157) | TEST_F(MissingDependencyScannerTest, CycleInGraph) {
FILE: src/msvc_helper-win32.cc
function string (line 25) | string Replace(const string& input, const string& find, const string& re...
function string (line 37) | string EscapeForDepfile(const string& path) {
FILE: src/msvc_helper.h
type CLWrapper (line 23) | struct CLWrapper {
FILE: src/msvc_helper_main-win32.cc
function Usage (line 31) | void Usage() {
function PushPathIntoEnvironment (line 41) | void PushPathIntoEnvironment(const string& env_block) {
function WriteDepFileOrDie (line 53) | void WriteDepFileOrDie(const char* object_path, const CLParser& parse) {
function MSVCHelperMain (line 82) | int MSVCHelperMain(int argc, char** argv) {
FILE: src/msvc_helper_test.cc
function TEST (line 22) | TEST(EscapeForDepfileTest, SpacesInFilename) {
function TEST (line 27) | TEST(MSVCHelperTest, EnvBlock) {
function TEST (line 36) | TEST(MSVCHelperTest, NoReadOfStderr) {
FILE: src/ninja.cc
type Tool (line 71) | struct Tool
type Options (line 74) | struct Options {
type NinjaMain (line 90) | struct NinjaMain : public BuildLogUser {
method NinjaMain (line 91) | NinjaMain(const char* ninja_command, const BuildConfig& config) :
method IsPathDead (line 178) | virtual bool IsPathDead(StringPiece s) const {
type Tool (line 202) | struct Tool {
function Usage (line 227) | void Usage(const BuildConfig& config) {
function GuessParallelism (line 254) | int GuessParallelism() {
function Node (line 317) | Node* NinjaMain::CollectTarget(const char* cpath, string* err) {
function ToolTargetsList (line 489) | int ToolTargetsList(const vector<Node*>& nodes, int depth, int indent) {
function ToolTargetsSourceList (line 507) | int ToolTargetsSourceList(State* state) {
function ToolTargetsList (line 519) | int ToolTargetsList(State* state, const string& rule_name) {
function ToolTargetsList (line 542) | int ToolTargetsList(State* state) {
type PrintCommandMode (line 716) | enum PrintCommandMode { PCM_Single, PCM_All }
function PrintCommands (line 717) | void PrintCommands(Edge* edge, EdgeSet* seen, PrintCommandMode mode) {
type EvaluateCommandMode (line 976) | enum EvaluateCommandMode {
function EvaluateCommandWithRspfile (line 980) | std::string EvaluateCommandWithRspfile(const Edge* edge,
function PrintCompdbObjectsForEdge (line 1014) | void PrintCompdbObjectsForEdge(std::string const& directory, const Edge*...
type CompdbTargets (line 1172) | struct CompdbTargets {
type Action (line 1173) | enum class Action { kDisplayHelpAndExit, kEmitCommands }
method CompdbTargets (line 1180) | static CompdbTargets CreateFromArgs(int argc, char* argv[]) {
function PrintCompdb (line 1225) | void PrintCompdb(std::string const& directory, std::vector<Edge*> const&...
function Tool (line 1312) | const Tool* ChooseTool(const string& tool_name) {
function DebugEnable (line 1389) | bool DebugEnable(const string& name) {
function WarningEnable (line 1433) | bool WarningEnable(const string& name, Options* options) {
function ExitStatus (line 1607) | ExitStatus NinjaMain::RunBuild(int argc, char** argv, Status* status) {
function TerminateHandler (line 1669) | void TerminateHandler() {
function ExceptionFilter (line 1676) | int ExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {
class DeferGuessParallelism (line 1685) | class DeferGuessParallelism {
method DeferGuessParallelism (line 1690) | DeferGuessParallelism(BuildConfig* config)
method Refresh (line 1693) | void Refresh() {
function ReadFlags (line 1704) | int ReadFlags(int* argc, char*** argv,
function NORETURN (line 1802) | NORETURN void real_main(int argc, char** argv) {
function main (line 1894) | int main(int argc, char** argv) {
FILE: src/ninja_test.cc
function main (line 17) | int main(int argc, char **argv) {
FILE: src/parser.h
type FileReader (line 22) | struct FileReader
type State (line 23) | struct State
type Parser (line 26) | struct Parser {
FILE: src/real_command_runner.cc
type RealCommandRunner (line 20) | struct RealCommandRunner : public CommandRunner {
method RealCommandRunner (line 21) | explicit RealCommandRunner(const BuildConfig& config,
method ClearJobTokens (line 30) | void ClearJobTokens() {
function CommandRunner (line 119) | CommandRunner* CommandRunner::factory(const BuildConfig& config,
FILE: src/state.cc
function Pool (line 78) | Pool* State::LookupPool(const string& pool_name) {
function Edge (line 85) | Edge* State::AddEdge(const Rule* rule) {
function Node (line 95) | Node* State::GetNode(StringPiece path, uint64_t slash_bits) {
function Node (line 104) | Node* State::LookupNode(StringPiece path) const {
function Node (line 111) | Node* State::SpellcheckNode(const string& path) {
FILE: src/state.h
type Edge (line 28) | struct Edge
type Node (line 29) | struct Node
type Rule (line 30) | struct Rule
function depth (line 40) | struct Pool {
type WeightedEdgeCmp (line 78) | struct WeightedEdgeCmp {
type std (line 90) | typedef std::set<Edge*, WeightedEdgeCmp> DelayedEdges;
type State (line 95) | struct State {
FILE: src/state_test.cc
function TEST (line 23) | TEST(State, Basic) {
FILE: src/status.h
type BuildConfig (line 21) | struct BuildConfig
type Edge (line 22) | struct Edge
type Explanations (line 23) | struct Explanations
type Status (line 27) | struct Status {
FILE: src/status_printer.cc
function Status (line 40) | Status* Status::factory(const BuildConfig& config) {
function string (line 264) | string StatusPrinter::FormatProgressStatus(const char* progress_status_f...
FILE: src/status_printer.h
function Status (line 26) | struct StatusPrinter : Status {
FILE: src/status_test.cc
function TEST (line 19) | TEST(StatusTest, StatusFormatElapsed) {
function TEST (line 30) | TEST(StatusTest, StatusFormatReplacePlaceholder) {
FILE: src/string_piece.h
function AsString (line 25) | struct StringPiece {
function const (line 58) | char operator[](size_t pos) const {
FILE: src/string_piece_util.cc
function SplitStringPiece (line 22) | vector<StringPiece> SplitStringPiece(StringPiece input, char sep) {
function string (line 41) | string JoinStringPiece(const vector<StringPiece>& list, char sep) {
function EqualsCaseInsensitiveASCII (line 66) | bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b) {
FILE: src/string_piece_util.h
function ToLowerASCII (line 27) | inline char ToLowerASCII(char c) {
FILE: src/string_piece_util_test.cc
function TEST (line 21) | TEST(StringPieceUtilTest, SplitStringPiece) {
function TEST (line 75) | TEST(StringPieceUtilTest, JoinStringPiece) {
function TEST (line 112) | TEST(StringPieceUtilTest, ToLowerASCII) {
function TEST (line 121) | TEST(StringPieceUtilTest, EqualsCaseInsensitiveASCII) {
FILE: src/subprocess-posix.cc
function ExitStatus (line 178) | ExitStatus Subprocess::Finish() {
function ExitStatus (line 188) | ExitStatus ParseExitStatus(int status) {
function string (line 222) | const string& Subprocess::GetOutput() const {
type sigaction (line 264) | struct sigaction
function Subprocess (line 311) | Subprocess *SubprocessSet::Add(const string& command, bool use_console) {
function Subprocess (line 443) | Subprocess* SubprocessSet::NextFinished() {
FILE: src/subprocess-win32.cc
function HANDLE (line 42) | HANDLE Subprocess::SetupPipe(HANDLE ioport) {
function ExitStatus (line 189) | ExitStatus Subprocess::Finish() {
function string (line 210) | const string& Subprocess::GetOutput() const {
function BOOL (line 231) | BOOL WINAPI SubprocessSet::NotifyInterrupted(DWORD dwCtrlType) {
function Subprocess (line 241) | Subprocess *SubprocessSet::Add(const string& command, bool use_console) {
function Subprocess (line 283) | Subprocess* SubprocessSet::NextFinished() {
FILE: src/subprocess.h
type SubprocessSet (line 55) | struct SubprocessSet
type SubprocessSet (line 101) | struct SubprocessSet {
FILE: src/subprocess_test.cc
type SubprocessTest (line 38) | struct SubprocessTest : public testing::Test {
function TEST_F (line 45) | TEST_F(SubprocessTest, BadCommandStderr) {
function TEST_F (line 60) | TEST_F(SubprocessTest, NoSuchCommand) {
function TEST_F (line 80) | TEST_F(SubprocessTest, InterruptChild) {
function TEST_F (line 91) | TEST_F(SubprocessTest, InterruptParent) {
function TEST_F (line 104) | TEST_F(SubprocessTest, InterruptChildWithSigTerm) {
function TEST_F (line 115) | TEST_F(SubprocessTest, InterruptParentWithSigTerm) {
function TEST_F (line 128) | TEST_F(SubprocessTest, InterruptChildWithSigHup) {
function TEST_F (line 139) | TEST_F(SubprocessTest, InterruptParentWithSigHup) {
function TEST_F (line 152) | TEST_F(SubprocessTest, Console) {
function TEST_F (line 169) | TEST_F(SubprocessTest, SetWithSingle) {
function TEST_F (line 182) | TEST_F(SubprocessTest, SetWithMulti) {
function TEST_F (line 223) | TEST_F(SubprocessTest, SetWithLots) {
function TEST_F (line 258) | TEST_F(SubprocessTest, ReadStdin) {
FILE: src/test.cc
function string (line 69) | string GetSystemTempDir() {
function Node (line 95) | Node* StateTestWithBuiltinRules::GetNode(const string& path) {
function AssertParse (line 100) | void AssertParse(State* state, const char* input,
function AssertHash (line 109) | void AssertHash(const char* expected, uint64_t actual) {
function VerifyGraph (line 113) | void VerifyGraph(const State& state) {
function TimeStamp (line 152) | TimeStamp VirtualFileSystem::Stat(const string& path, string* err) const {
function ScopedFilePath (line 252) | ScopedFilePath& ScopedFilePath::operator=(ScopedFilePath&& other) noexce...
FILE: src/test.h
type Node (line 26) | struct Node
type StateTestWithBuiltinRules (line 30) | struct StateTestWithBuiltinRules
function DiskInterface (line 51) | struct VirtualFileSystem : public DiskInterface {
type ScopedTempDir (line 90) | struct ScopedTempDir {
FILE: src/third_party/emhash/hash_table8.hpp
type emhash8 (line 65) | namespace emhash8 {
type DefaultPolicy (line 67) | struct DefaultPolicy {
class HashMap (line 78) | class HashMap
type Index (line 108) | struct Index
class const_iterator (line 114) | class const_iterator
method const_iterator (line 182) | const_iterator(const iterator& it) {
method const_iterator (line 186) | const_iterator (const htype* hash_map, size_type bucket) {
method const_iterator (line 190) | const_iterator& operator++()
method const_iterator (line 196) | const_iterator operator++(int)
method const_iterator (line 202) | const_iterator& operator--()
method const_iterator (line 208) | const_iterator operator--(int)
method const_reference (line 214) | const_reference operator*() const { return *kv_; }
method const_pointer (line 215) | const_pointer operator->() const { return kv_; }
class iterator (line 115) | class iterator
method iterator (line 126) | iterator() : kv_(nullptr) {}
method iterator (line 127) | iterator(const_iterator& cit) {
method iterator (line 131) | iterator(const htype* hash_map, size_type bucket) {
method iterator (line 135) | iterator& operator++()
method iterator (line 141) | iterator operator++(int)
method iterator (line 147) | iterator& operator--()
method iterator (line 153) | iterator operator--(int)
method reference (line 159) | reference operator*() const { return *kv_; }
method pointer (line 160) | pointer operator->() const { return kv_; }
class const_iterator (line 171) | class const_iterator
method const_iterator (line 182) | const_iterator(const iterator& it) {
method const_iterator (line 186) | const_iterator (const htype* hash_map, size_type bucket) {
method const_iterator (line 190) | const_iterator& operator++()
method const_iterator (line 196) | const_iterator operator++(int)
method const_iterator (line 202) | const_iterator& operator--()
method const_iterator (line 208) | const_iterator operator--(int)
method const_reference (line 214) | const_reference operator*() const { return *kv_; }
method const_pointer (line 215) | const_pointer operator->() const { return kv_; }
method init (line 225) | void init(size_type bucket, float mlf = EMH_DEFAULT_LOAD_FACTOR)
method HashMap (line 236) | HashMap(size_type bucket = 2, float mlf = EMH_DEFAULT_LOAD_FACTOR)
method HashMap (line 241) | HashMap(const HashMap& rhs)
method HashMap (line 254) | HashMap(HashMap&& rhs) noexcept
method HashMap (line 260) | HashMap(std::initializer_list<value_type> ilist)
method HashMap (line 268) | HashMap(InputIt first, InputIt last, size_type bucket_count=4)
method HashMap (line 275) | HashMap& operator=(const HashMap& rhs)
method HashMap (line 300) | HashMap& operator=(HashMap&& rhs) noexcept
method clone (line 335) | void clone(const HashMap& rhs)
method swap (line 360) | void swap(HashMap& rhs)
method iterator (line 378) | iterator first() const { return {this, 0}; }
method iterator (line 126) | iterator() : kv_(nullptr) {}
method iterator (line 127) | iterator(const_iterator& cit) {
method iterator (line 131) | iterator(const htype* hash_map, size_type bucket) {
method iterator (line 135) | iterator& operator++()
method iterator (line 141) | iterator operator++(int)
method iterator (line 147) | iterator& operator--()
method iterator (line 153) | iterator operator--(int)
method reference (line 159) | reference operator*() const { return *kv_; }
method pointer (line 160) | pointer operator->() const { return kv_; }
method iterator (line 379) | iterator last() const { return {this, _num_filled - 1}; }
method iterator (line 126) | iterator() : kv_(nullptr) {}
method iterator (line 127) | iterator(const_iterator& cit) {
method iterator (line 131) | iterator(const htype* hash_map, size_type bucket) {
method iterator (line 135) | iterator& operator++()
method iterator (line 141) | iterator operator++(int)
method iterator (line 147) | iterator& operator--()
method iterator (line 153) | iterator operator--(int)
method reference (line 159) | reference operator*() const { return *kv_; }
method pointer (line 160) | pointer operator->() const { return kv_; }
method value_type (line 381) | value_type& front() { return _pairs[0]; }
method value_type (line 382) | const value_type& front() const { return _pairs[0]; }
method value_type (line 383) | value_type& back() { return _pairs[_num_filled - 1]; }
method value_type (line 384) | const value_type& back() const { return _pairs[_num_filled - 1]; }
method pop_front (line 386) | void pop_front() { erase(begin()); }
method pop_back (line 387) | void pop_back() { erase(last()); }
method iterator (line 389) | iterator begin() { return first(); }
method iterator (line 126) | iterator() : kv_(nullptr) {}
method iterator (line 127) | iterator(const_iterator& cit) {
method iterator (line 131) | iterator(const htype* hash_map, size_type bucket) {
method iterator (line 135) | iterator& operator++()
method iterator (line 141) | iterator operator++(int)
method iterator (line 147) | iterator& operator--()
method iterator (line 153) | iterator operator--(int)
method reference (line 159) | reference operator*() const { return *kv_; }
method pointer (line 160) | pointer operator->() const { return kv_; }
method const_iterator (line 390) | const_iterator cbegin() const { return first(); }
method const_iterator (line 182) | const_iterator(const iterator& it) {
method const_iterator (line 186) | const_iterator (const htype* hash_map, size_type bucket) {
method const_iterator (line 190) | const_iterator& operator++()
method const_iterator (line 196) | const_iterator operator++(int)
method const_iterator (line 202) | const_iterator& operator--()
method const_iterator (line 208) | const_iterator operator--(int)
method const_reference (line 214) | const_reference operator*() const { return *kv_; }
method const_pointer (line 215) | const_pointer operator->() const { return kv_; }
method const_iterator (line 391) | const_iterator begin() const { return first(); }
method const_iterator (line 182) | const_iterator(const iterator& it) {
method const_iterator (line 186) | const_iterator (const htype* hash_map, size_type bucket) {
method const_iterator (line 190) | const_iterator& operator++()
method const_iterator (line 196) | const_iterator operator++(int)
method const_iterator (line 202) | const_iterator& operator--()
method const_iterator (line 208) | const_iterator operator--(int)
method const_reference (line 214) | const_reference operator*() const { return *kv_; }
method const_pointer (line 215) | const_pointer operator->() const { return kv_; }
method iterator (line 393) | iterator end() { return {this, _num_filled}; }
method iterator (line 126) | iterator() : kv_(nullptr) {}
method iterator (line 127) | iterator(const_iterator& cit) {
method iterator (line 131) | iterator(const htype* hash_map, size_type bucket) {
method iterator (line 135) | iterator& operator++()
method iterator (line 141) | iterator operator++(int)
method iterator (line 147) | iterator& operator--()
method iterator (line 153) | iterator operator--(int)
method reference (line 159) | reference operator*() const { return *kv_; }
method pointer (line 160) | pointer operator->() const { return kv_; }
method const_iterator (line 394) | const_iterator cend() const { return {this, _num_filled}; }
method const_iterator (line 182) | const_iterator(const iterator& it) {
method const_iterator (line 186) | const_iterator (const htype* hash_map, size_type bucket) {
method const_iterator (line 190) | const_iterator& operator++()
method const_iterator (line 196) | const_iterator operator++(int)
method const_iterator (line 202) | const_iterator& operator--()
method const_iterator (line 208) | const_iterator operator--(int)
method const_reference (line 214) | const_reference operator*() const { return *kv_; }
method const_pointer (line 215) | const_pointer operator->() const { return kv_; }
method const_iterator (line 395) | const_iterator end() const { return cend(); }
method const_iterator (line 182) | const_iterator(const iterator& it) {
method const_iterator (line 186) | const_iterator (const htype* hash_map, size_type bucket) {
method const_iterator (line 190) | const_iterator& operator++()
method const_iterator (line 196) | const_iterator operator++(int)
method const_iterator (line 202) | const_iterator& operator--()
method const_iterator (line 208) | const_iterator operator--(int)
method const_reference (line 214) | const_reference operator*() const { return *kv_; }
method const_pointer (line 215) | const_pointer operator->() const { return kv_; }
method value_type (line 397) | const value_type* values() const { return _pairs; }
method Index (line 398) | const Index* index() const { return _index; }
method size_type (line 400) | size_type size() const { return _num_filled; }
method empty (line 401) | bool empty() const { return _num_filled == 0; }
method size_type (line 402) | size_type bucket_count() const { return _num_buckets; }
method load_factor (line 405) | float load_factor() const { return static_cast<float>(_num_filled) /...
method HashT (line 407) | HashT& hash_function() const { return _hasher; }
method EqT (line 408) | EqT& key_eq() const { return _eq; }
method max_load_factor (line 410) | void max_load_factor(float mlf)
method max_load_factor (line 418) | constexpr float max_load_factor() const { return (1 << 27) / (float)...
method size_type (line 419) | constexpr size_type max_size() const { return (1ull << (sizeof(size_...
method size_type (line 420) | constexpr size_type max_bucket_count() const { return max_size(); }
method size_type (line 424) | size_type bucket(const KeyT& key) const
method size_type (line 437) | size_type bucket_size(const size_type bucket) const
method size_type (line 458) | size_type get_main_bucket(const size_type bucket) const
method size_type (line 467) | size_type get_diss(size_type bucket, size_type next_bucket, const si...
method get_bucket_info (line 479) | int get_bucket_info(const size_type bucket, size_type steps[], const...
method dump_statics (line 506) | void dump_statics() const
method pack_zero (line 547) | void pack_zero(ValueT zero)
method iterator (line 554) | iterator find(const K& key) noexcept
method iterator (line 126) | iterator() : kv_(nullptr) {}
method iterator (line 127) | iterator(const_iterator& cit) {
method iterator (line 131) | iterator(const htype* hash_map, size_type bucket) {
method iterator (line 135) | iterator& operator++()
method iterator (line 141) | iterator operator++(int)
method iterator (line 147) | iterator& operator--()
method iterator (line 153) | iterator operator--(int)
method reference (line 159) | reference operator*() const { return *kv_; }
method pointer (line 160) | pointer operator->() const { return kv_; }
method const_iterator (line 560) | const_iterator find(const K& key) const noexcept
method const_iterator (line 182) | const_iterator(const iterator& it) {
method const_iterator (line 186) | const_iterator (const htype* hash_map, size_type bucket) {
method const_iterator (line 190) | const_iterator& operator++()
method const_iterator (line 196) | const_iterator operator++(int)
method const_iterator (line 202) | const_iterator& operator--()
method const_iterator (line 208) | const_iterator operator--(int)
method const_reference (line 214) | const_reference operator*() const { return *kv_; }
method const_pointer (line 215) | const_pointer operator->() const { return kv_; }
method ValueT (line 566) | ValueT& at(const K& key)
method ValueT (line 574) | const ValueT& at(const K& key) const
method ValueT (line 581) | const ValueT& index(const uint32_t index) const
method ValueT (line 586) | ValueT& index(const uint32_t index)
method contains (line 592) | bool contains(const K& key) const noexcept
method size_type (line 598) | size_type count(const K& key) const noexcept
method equal_range (line 606) | std::pair<iterator, iterator> equal_range(const K& key)
method merge (line 615) | void merge(HashMap& rhs)
method try_get (line 634) | bool try_get(const KeyT& key, ValueT& val) const noexcept
method ValueT (line 645) | ValueT* try_get(const KeyT& key) noexcept
method ValueT (line 652) | ValueT* try_get(const KeyT& key) const noexcept
method try_set (line 659) | bool try_set(const KeyT& key, const ValueT& val) noexcept
method try_set (line 670) | bool try_set(const KeyT& key, ValueT&& val) noexcept
method ValueT (line 681) | ValueT get_or_return_default(const KeyT& key) const noexcept
method do_insert (line 688) | std::pair<iterator, bool> do_insert(const value_type& value) noexcept
method do_insert (line 701) | std::pair<iterator, bool> do_insert(value_type&& value) noexcept
method do_insert (line 715) | std::pair<iterator, bool> do_insert(K&& key, V&& val) noexcept
method do_assign (line 729) | std::pair<iterator, bool> do_assign(K&& key, V&& val) noexcept
method insert (line 745) | std::pair<iterator, bool> insert(const value_type& p)
method insert (line 751) | std::pair<iterator, bool> insert(value_type && p)
method insert (line 757) | void insert(std::initializer_list<value_type> ilist)
method insert (line 765) | void insert(Iter first, Iter last)
method insert_unique (line 774) | void insert_unique(Iter begin, Iter end)
method size_type (line 784) | size_type insert_unique(K&& key, V&& val)
method size_type (line 793) | size_type insert_unique(value_type&& value)
method size_type (line 798) | size_type insert_unique(const value_type& value)
method emplace (line 804) | std::pair<iterator, bool> emplace(Args&&... args) noexcept
method iterator (line 812) | iterator emplace_hint(const_iterator hint, Args&&... args)
method iterator (line 126) | iterator() : kv_(nullptr) {}
method iterator (line 127) | iterator(const_iterator& cit) {
method iterator (line 131) | iterator(const htype* hash_map, size_type bucket) {
method iterator (line 135) | iterator& operator++()
method iterator (line 141) | iterator operator++(int)
method iterator (line 147) | iterator& operator--()
method iterator (line 153) | iterator operator--(int)
method reference (line 159) | reference operator*() const { return *kv_; }
method pointer (line 160) | pointer operator->() const { return kv_; }
method try_emplace (line 820) | std::pair<iterator, bool> try_emplace(const KeyT& k, Args&&... args)
method try_emplace (line 827) | std::pair<iterator, bool> try_emplace(KeyT&& k, Args&&... args)
method size_type (line 834) | size_type emplace_unique(Args&&... args)
method insert_or_assign (line 839) | std::pair<iterator, bool> insert_or_assign(const KeyT& key, ValueT&&...
method insert_or_assign (line 840) | std::pair<iterator, bool> insert_or_assign(KeyT&& key, ValueT&& val)...
method ValueT (line 843) | ValueT set_get(const KeyT& key, const ValueT& val)
method ValueT (line 860) | ValueT& operator[](const KeyT& key) noexcept
method ValueT (line 874) | ValueT& operator[](KeyT&& key) noexcept
method size_type (line 889) | size_type erase(const KeyT& key) noexcept
method iterator (line 902) | iterator erase(const const_iterator& cit) noexcept
method iterator (line 126) | iterator() : kv_(nullptr) {}
method iterator (line 127) | iterator(const_iterator& cit) {
method iterator (line 131) | iterator(const htype* hash_map, size_type bucket) {
method iterator (line 135) | iterator& operator++()
method iterator (line 141) | iterator operator++(int)
method iterator (line 147) | iterator& operator--()
method iterator (line 153) | iterator operator--(int)
method reference (line 159) | reference operator*() const { return *kv_; }
method pointer (line 160) | pointer operator->() const { return kv_; }
method iterator (line 912) | iterator erase(const_iterator first, const_iterator last) noexcept
method iterator (line 126) | iterator() : kv_(nullptr) {}
method iterator (line 127) | iterator(const_iterator& cit) {
method iterator (line 131) | iterator(const htype* hash_map, size_type bucket) {
method iterator (line 135) | iterator& operator++()
method iterator (line 141) | iterator operator++(int)
method iterator (line 147) | iterator& operator--()
method iterator (line 153) | iterator operator--(int)
method reference (line 159) | reference operator*() const { return *kv_; }
method pointer (line 160) | pointer operator->() const { return kv_; }
method size_type (line 932) | size_type erase_if(Pred pred)
method is_triviall_destructable (line 944) | static constexpr bool is_triviall_destructable()
method is_copy_trivially (line 953) | static constexpr bool is_copy_trivially()
method clearkv (line 962) | void clearkv()
method clear (line 971) | void clear() noexcept
method shrink_to_fit (line 986) | void shrink_to_fit(const float min_factor = EMH_DEFAULT_LOAD_FACTOR ...
method set_empty (line 994) | void set_empty()
method clear_empty (line 1014) | void clear_empty()
method size_type (line 1026) | size_type pop_empty(const size_type bucket)
method push_empty (line 1039) | void push_empty(const int32_t bucket)
method reserve (line 1054) | bool reserve(uint64_t num_elems, bool force)
method value_type (line 1088) | static value_type* alloc_bucket(size_type num_buckets)
method Index (line 1098) | static Index* alloc_index(size_type num_buckets)
method reserve (line 1104) | bool reserve(size_type required_buckets) noexcept
method rebuild (line 1138) | void rebuild(size_type num_buckets) noexcept
method rehash (line 1160) | void rehash(uint64_t required_buckets)
method check_expand_need (line 1233) | bool check_expand_need()
method prefetch_heap_block (line 1238) | static void prefetch_heap_block(char* ctrl)
method size_type (line 1249) | size_type slot_to_bucket(const size_type slot) const noexcept
method erase_slot (line 1256) | void erase_slot(const size_type sbucket, const size_type main_bucket...
method size_type (line 1284) | size_type erase_bucket(const size_type bucket, const size_type main_...
method size_type (line 1304) | size_type find_slot_bucket(const size_type slot, size_type& main_buc...
method size_type (line 1322) | size_type find_filled_bucket(const KeyT& key, uint64_t key_hash) con...
method size_type (line 1356) | size_type find_filled_slot(const K& key) const noexcept
method size_type (line 1390) | size_type find_hash_bucket(const KeyT& key) const noexcept
method size_type (line 1422) | size_type find_sorted_bucket(const KeyT& key) const noexcept
method size_type (line 1462) | size_type kickout_bucket(const size_type kmain, const size_type buck...
method size_type (line 1485) | size_type find_or_allocate(const K& key, uint64_t key_hash) noexcept
method size_type (line 1532) | size_type find_unique_bucket(uint64_t key_hash) noexcept
method size_type (line 1568) | size_type find_empty_bucket(const size_type bucket_from, uint32_t cs...
method size_type (line 1628) | size_type find_last_bucket(size_type main_bucket) const
method size_type (line 1642) | size_type find_prev_bucket(const size_type main_bucket, const size_t...
method size_type (line 1656) | size_type hash_bucket(const KeyT& key) const noexcept
method size_type (line 1661) | size_type hash_main(const size_type bucket) const noexcept
method hash64 (line 1669) | static uint64_t hash64(uint64_t key)
method wymix (line 1709) | static uint64_t wymix(uint64_t A, uint64_t B)
method wyr8 (line 1741) | static inline uint64_t wyr8(const uint8_t *p) { uint64_t v; memcpy(&...
method wyr4 (line 1742) | static inline uint64_t wyr4(const uint8_t *p) { uint32_t v; memcpy(&...
method wyr3 (line 1743) | static inline uint64_t wyr3(const uint8_t *p, size_t k) {
method wyhashstr (line 1752) | static uint64_t wyhashstr(const char *key, const size_t len)
method hash_key (line 1790) | inline uint64_t hash_key(const UType key) const
method hash_key (line 1802) | inline uint64_t hash_key(const UType& key) const
method hash_key (line 1812) | inline uint64_t hash_key(const UType& key) const
FILE: src/third_party/rapidhash/rapidhash.h
function RAPIDHASH_INLINE (line 146) | RAPIDHASH_INLINE void rapid_mum(uint64_t *A, uint64_t *B) RAPIDHASH_NOEX...
function RAPIDHASH_INLINE (line 196) | RAPIDHASH_INLINE uint64_t rapid_mix(uint64_t A, uint64_t B) RAPIDHASH_NO...
function RAPIDHASH_INLINE (line 202) | RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXC...
function RAPIDHASH_INLINE (line 203) | RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXC...
function RAPIDHASH_INLINE (line 205) | RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXC...
function RAPIDHASH_INLINE (line 206) | RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXC...
function RAPIDHASH_INLINE (line 208) | RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXC...
function RAPIDHASH_INLINE (line 209) | RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXC...
function RAPIDHASH_INLINE (line 211) | RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXC...
function RAPIDHASH_INLINE (line 215) | RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXC...
function RAPIDHASH_INLINE (line 232) | RAPIDHASH_INLINE uint64_t rapid_readSmall(const uint8_t *p, size_t k) RA...
function RAPIDHASH_INLINE (line 244) | RAPIDHASH_INLINE uint64_t rapidhash_internal(const void *key, size_t len...
function RAPIDHASH_INLINE (line 307) | RAPIDHASH_INLINE uint64_t rapidhash_withSeed(const void *key, size_t len...
function RAPIDHASH_INLINE (line 321) | RAPIDHASH_INLINE uint64_t rapidhash(const void *key, size_t len) RAPIDHA...
FILE: src/timestamp.h
type TimeStamp (line 31) | typedef int64_t TimeStamp;
FILE: src/util.cc
function Fatal (line 67) | void Fatal(const char* msg, ...) {
function Warning (line 85) | void Warning(const char* msg, va_list ap) {
function Warning (line 91) | void Warning(const char* msg, ...) {
function Error (line 98) | void Error(const char* msg, va_list ap) {
function Error (line 104) | void Error(const char* msg, ...) {
function Info (line 111) | void Info(const char* msg, va_list ap) {
function Info (line 117) | void Info(const char* msg, ...) {
function CanonicalizePath (line 124) | void CanonicalizePath(string* path, uint64_t* slash_bits) {
function IsPathSeparator (line 133) | static bool IsPathSeparator(char c) {
function CanonicalizePath (line 141) | void CanonicalizePath(char* path, size_t* len, uint64_t* slash_bits) {
function IsKnownShellSafeCharacter (line 312) | static inline bool IsKnownShellSafeCharacter(char ch) {
function IsKnownWin32SafeCharacter (line 329) | static inline bool IsKnownWin32SafeCharacter(char ch) {
function StringNeedsShellEscaping (line 339) | static inline bool StringNeedsShellEscaping(const string& input) {
function StringNeedsWin32Escaping (line 346) | static inline bool StringNeedsWin32Escaping(const string& input) {
function GetShellEscapedString (line 353) | void GetShellEscapedString(const string& input, string* result) {
function GetWin32EscapedString (line 380) | void GetWin32EscapedString(const string& input, string* result) {
type stat64 (line 450) | struct stat64
type stat (line 453) | struct stat
function SetCloseOnExec (line 480) | void SetCloseOnExec(int fd) {
function string (line 531) | string GetLastErrorString() {
function Win32Fatal (line 557) | void Win32Fatal(const char* function, const char* hint) {
function islatinalpha (line 566) | bool islatinalpha(int c) {
function string (line 571) | string StripAnsiEscapeCodes(const string& in) {
function readCount (line 595) | std::pair<int64_t, bool> readCount(const std::string& path) {
type MountPoint (line 606) | struct MountPoint {
method parse (line 617) | bool parse(const string& line) {
method string (line 645) | string translate(string& path) const {
type CGroupSubSys (line 658) | struct CGroupSubSys {
method parse (line 662) | bool parse(string& line) {
function ParseMountInfo (line 682) | map<string, string> ParseMountInfo(map<string, CGroupSubSys>& subsystems) {
function ParseSelfCGroup (line 725) | map<string, CGroupSubSys> ParseSelfCGroup() {
function ParseCgroupV1 (line 743) | int ParseCgroupV1(std::string& path) {
function ParseCgroupV2 (line 755) | int ParseCgroupV2(std::string& path) {
function ParseCPUFromCGroup (line 796) | int ParseCPUFromCGroup() {
function GetProcessorCount (line 814) | int GetProcessorCount() {
function CalculateProcessorLoad (line 890) | static double CalculateProcessorLoad(uint64_t idle_ticks, uint64_t total...
function FileTimeToTickCount (line 926) | static uint64_t FileTimeToTickCount(const FILETIME & ft)
function GetLoadAverage (line 933) | double GetLoadAverage() {
function GetLoadAverage (line 956) | double GetLoadAverage() {
function GetLoadAverage (line 960) | double GetLoadAverage() {
function GetLoadAverage (line 970) | double GetLoadAverage() {
function GetLoadAverage (line 977) | double GetLoadAverage() {
function GetLoadAverage (line 981) | double GetLoadAverage() {
function GetWorkingDirectory (line 992) | std::string GetWorkingDirectory() {
function Truncate (line 1007) | bool Truncate(const string& path, size_t size, string* err) {
function ReplaceContent (line 1025) | bool ReplaceContent(const string& file_dst, const string& new_content,
function platformAwareUnlink (line 1060) | int platformAwareUnlink(const char* filename) {
FILE: src/util.h
function To (line 140) | To FunctionCast(From from) {
FILE: src/util_test.cc
function CanonicalizePath (line 23) | void CanonicalizePath(string* path) {
function TEST (line 30) | TEST(CanonicalizePath, PathSamples) {
function TEST (line 162) | TEST(CanonicalizePath, PathSamplesWindows) {
function TEST (line 225) | TEST(CanonicalizePath, SlashTracking) {
function TEST (line 310) | TEST(CanonicalizePath, CanonicalizeNotExceedingLen) {
function TEST (line 320) | TEST(CanonicalizePath, TooManyComponents) {
function TEST (line 394) | TEST(CanonicalizePath, TooManyComponents) {
function TEST (line 420) | TEST(CanonicalizePath, UpDir) {
function TEST (line 431) | TEST(CanonicalizePath, AbsolutePath) {
function TEST (line 438) | TEST(CanonicalizePath, NotNullTerminated) {
function TEST (line 458) | TEST(PathEscaping, TortureTest) {
function TEST (line 469) | TEST(PathEscaping, SensiblePathsAreNotNeedlesslyEscaped) {
function TEST (line 481) | TEST(PathEscaping, SensibleWin32PathsAreNotNeedlesslyEscaped) {
function TEST (line 489) | TEST(StripAnsiEscapeCodes, EscapeAtEnd) {
function TEST (line 497) | TEST(StripAnsiEscapeCodes, StripColors) {
FILE: src/version.cc
function ParseVersion (line 25) | void ParseVersion(const string& version, int* major, int* minor) {
function CheckNinjaVersion (line 36) | void CheckNinjaVersion(const string& version, int* file_major,
FILE: tests/restat/test_restat_builddir.py
class RestatBuildDirTest (line 14) | class RestatBuildDirTest(unittest.TestCase):
method setUp (line 17) | def setUp(self):
method tearDown (line 23) | def tearDown(self):
method test_restat_with_builddir (line 30) | def test_restat_with_builddir(self):
Condensed preview — 186 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,354K chars).
[
{
"path": ".clang-format",
"chars": 1054,
"preview": "# Copyright 2014 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": ".clang-tidy",
"chars": 624,
"preview": "---\nChecks: '\n ,readability-avoid-const-params-in-decls,\n ,readability-inconsistent-declaration-parameter-name,\n ,rea"
},
{
"path": ".editorconfig",
"chars": 176,
"preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\nend_of_line = lf\n\n[CMa"
},
{
"path": ".github/dependabot.yml",
"chars": 163,
"preview": "version: 2\nupdates:\n # Maintain dependencies for GitHub Actions\n - package-ecosystem: \"github-actions\"\n directory: "
},
{
"path": ".github/workflows/linux-musl.yml",
"chars": 1857,
"preview": "name: ci-linux-musl\n\non:\n workflow_dispatch:\n pull_request:\n push:\n branches: ['**']\n tags-ignore: ['**'] # Do"
},
{
"path": ".github/workflows/linux.yml",
"chars": 6720,
"preview": "name: Linux\n\non:\n pull_request:\n push:\n branches: ['**']\n tags-ignore: ['**'] # Don't trigger on tag pushes\n r"
},
{
"path": ".github/workflows/macos.yml",
"chars": 1480,
"preview": "name: macOS\n\non:\n pull_request:\n push:\n branches: ['**']\n tags-ignore: ['**'] # Don't trigger on tag pushes\n r"
},
{
"path": ".github/workflows/windows.yml",
"chars": 1869,
"preview": "name: Windows\n\non:\n pull_request:\n push:\n branches: ['**']\n tags-ignore: ['**'] # Don't trigger on tag pushes\n "
},
{
"path": ".gitignore",
"chars": 644,
"preview": "*.pyc\n*.obj\n*.exe\n*.pdb\n*.ilk\n/build*/\n/build.ninja\n/ninja\n/ninja.bootstrap\n/build_log_perftest\n/canon_perftest\n/clparse"
},
{
"path": "CMakeLists.txt",
"chars": 10738,
"preview": "cmake_minimum_required(VERSION 3.15)\n\ninclude(CheckSymbolExists)\ninclude(CheckIPOSupported)\n\noption(NINJA_BUILD_BINARY \""
},
{
"path": "CONTRIBUTING.md",
"chars": 1450,
"preview": "# How to successfully make changes to Ninja\n\nWe're very wary of changes that increase the complexity of Ninja (in partic"
},
{
"path": "COPYING",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2010\n "
},
{
"path": "README.md",
"chars": 2785,
"preview": "# Ninja\n\nNinja is a small build system with a focus on speed.\nhttps://ninja-build.org/\n\nSee [the manual](https://ninja-b"
},
{
"path": "RELEASING.md",
"chars": 1547,
"preview": "Notes to myself on all the steps to make for a Ninja release.\n\n### Push new release branch:\n1. Run afl-fuzz for a day or"
},
{
"path": "appveyor.yml",
"chars": 851,
"preview": "version: 1.0.{build}\nimage:\n - Visual Studio 2017\n - Ubuntu2204\n\nenvironment:\n CLICOLOR_FORCE: 1\n CHERE_INVOKING: 1 "
},
{
"path": "configure.py",
"chars": 28387,
"preview": "#!/usr/bin/env python3\n#\n# Copyright 2001 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Versio"
},
{
"path": "doc/README.md",
"chars": 584,
"preview": "This directory contains the Ninja manual and support files used in\nbuilding it. Here's a brief overview of how it works"
},
{
"path": "doc/dblatex.xsl",
"chars": 402,
"preview": "<!-- This custom XSL tweaks the dblatex XML settings. -->\n<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transfor"
},
{
"path": "doc/docbook.xsl",
"chars": 1460,
"preview": "<!-- This custom XSL tweaks the DocBook XML -> HTML settings to produce\n an OK-looking manual. -->\n<!DOCTYPE xsl:st"
},
{
"path": "doc/doxygen.config",
"chars": 51098,
"preview": "# Doxyfile 1.4.5\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) "
},
{
"path": "doc/manual.asciidoc",
"chars": 52392,
"preview": "The Ninja build system\n======================\n\n\nIntroduction\n------------\n\nNinja is yet another build system. It takes "
},
{
"path": "doc/style.css",
"chars": 1121,
"preview": ":root {\n color-scheme: light dark;\n}\n\nbody {\n margin: 5ex 10ex;\n max-width: 80ex;\n line-height: 1.5;\n fon"
},
{
"path": "misc/afl-fuzz/build.ninja",
"chars": 104,
"preview": "rule b\n command = clang -MMD -MF $out.d -o $out -c $in\n description = building $out\n\nbuild a.o: b a.c\n"
},
{
"path": "misc/afl-fuzz-tokens/kw_build",
"chars": 5,
"preview": "build"
},
{
"path": "misc/afl-fuzz-tokens/kw_default",
"chars": 7,
"preview": "default"
},
{
"path": "misc/afl-fuzz-tokens/kw_include",
"chars": 7,
"preview": "include"
},
{
"path": "misc/afl-fuzz-tokens/kw_pool",
"chars": 4,
"preview": "pool"
},
{
"path": "misc/afl-fuzz-tokens/kw_rule",
"chars": 4,
"preview": "rule"
},
{
"path": "misc/afl-fuzz-tokens/kw_subninja",
"chars": 8,
"preview": "subninja"
},
{
"path": "misc/afl-fuzz-tokens/misc_a",
"chars": 1,
"preview": "a"
},
{
"path": "misc/afl-fuzz-tokens/misc_b",
"chars": 1,
"preview": "b"
},
{
"path": "misc/afl-fuzz-tokens/misc_colon",
"chars": 1,
"preview": ":"
},
{
"path": "misc/afl-fuzz-tokens/misc_cont",
"chars": 2,
"preview": "$\n"
},
{
"path": "misc/afl-fuzz-tokens/misc_dollar",
"chars": 1,
"preview": "$"
},
{
"path": "misc/afl-fuzz-tokens/misc_eq",
"chars": 1,
"preview": "="
},
{
"path": "misc/afl-fuzz-tokens/misc_indent",
"chars": 2,
"preview": " "
},
{
"path": "misc/afl-fuzz-tokens/misc_pipe",
"chars": 1,
"preview": "|"
},
{
"path": "misc/afl-fuzz-tokens/misc_pipepipe",
"chars": 2,
"preview": "||"
},
{
"path": "misc/afl-fuzz-tokens/misc_space",
"chars": 1,
"preview": " "
},
{
"path": "misc/bash-completion",
"chars": 1926,
"preview": "# Copyright 2011 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "misc/ci.py",
"chars": 1099,
"preview": "#!/usr/bin/env python3\n\nimport os\n\nignores = [\n\t'.git/',\n\t'misc/afl-fuzz-tokens/',\n\t'src/depfile_parser.cc',\n\t'src/lexer"
},
{
"path": "misc/inherited-fds.ninja",
"chars": 545,
"preview": "# This build file prints out a list of open file descriptors in\n# Ninja subprocesses, to help verify we don't accidental"
},
{
"path": "misc/jobserver_pool.py",
"chars": 11565,
"preview": "#!/usr/bin/env python3\n# Copyright 2024 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version "
},
{
"path": "misc/jobserver_pool_test.py",
"chars": 5818,
"preview": "#!/usr/bin/env python3\n\n\"\"\"Regression tests for the jobserver_pool.py script.\"\"\"\n\nimport os\nimport re\nimport platform\nim"
},
{
"path": "misc/jobserver_test.py",
"chars": 11838,
"preview": "#!/usr/bin/env python3\n# Copyright 2024 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version "
},
{
"path": "misc/jobserver_test_helper.py",
"chars": 1334,
"preview": "#!/usr/bin/env python3\n# Copyright 2024 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version "
},
{
"path": "misc/long-slow-build.ninja",
"chars": 793,
"preview": "# An input file for running a \"slow\" build.\n# Use like: ninja -f misc/long-slow-build.ninja all\n\nrule sleep\n command = "
},
{
"path": "misc/manifest_fuzzer.cc",
"chars": 1214,
"preview": "// Copyright 2020 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "misc/measure.py",
"chars": 1846,
"preview": "#!/usr/bin/env python3\n\n# Copyright 2011 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version"
},
{
"path": "misc/ninja.vim",
"chars": 2889,
"preview": "\" ninja build file syntax.\n\" Language: ninja build file as described at\n\" http://ninja-build.org/manual.html\n\""
},
{
"path": "misc/ninja_syntax.py",
"chars": 8148,
"preview": "#!/usr/bin/python\n\n# Copyright 2011 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 "
},
{
"path": "misc/ninja_syntax_test.py",
"chars": 6831,
"preview": "#!/usr/bin/env python3\n\n# Copyright 2011 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version"
},
{
"path": "misc/oss-fuzz/build.sh",
"chars": 1012,
"preview": "#!/bin/bash -eu\n# Copyright 2020 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you m"
},
{
"path": "misc/oss-fuzz/sample_ninja_build",
"chars": 216,
"preview": "# build.ninja\ncc = clang\ncflags = -Weverything\n\nrule compile\n command = $cc $cflags -c $in -o $out\n\nrule link\n com"
},
{
"path": "misc/output_test.py",
"chars": 19780,
"preview": "#!/usr/bin/env python3\n\n\"\"\"Runs ./ninja and checks if the output is correct.\n\nIn order to simulate a smart terminal it u"
},
{
"path": "misc/packaging/ninja.spec",
"chars": 1246,
"preview": "Summary: Ninja is a small build system with a focus on speed.\nName: ninja\nVersion: %{ver}\nRelease: %{rel}%{?dist}\nGroup:"
},
{
"path": "misc/packaging/rpmbuild.sh",
"chars": 1054,
"preview": "#!/bin/bash\n\necho Building ninja RPMs..\nGITROOT=$(git rev-parse --show-toplevel)\ncd $GITROOT\n\nVER=1.0\nREL=$(git rev-pars"
},
{
"path": "misc/write_fake_manifests.py",
"chars": 10413,
"preview": "#!/usr/bin/env python3\n\n\"\"\"Writes large manifest files, for manifest parser performance testing.\n\nThe generated manifest"
},
{
"path": "misc/zsh-completion",
"chars": 2855,
"preview": "#compdef ninja\n# Copyright 2011 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "src/browse.cc",
"chars": 2549,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/browse.h",
"chars": 1145,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/browse.py",
"chars": 7755,
"preview": "#!/usr/bin/env python3\n#\n# Copyright 2001 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Versio"
},
{
"path": "src/build.cc",
"chars": 33634,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/build.h",
"chars": 9524,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/build_log.cc",
"chars": 12002,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/build_log.h",
"chars": 3500,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/build_log_perftest.cc",
"chars": 4130,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/build_log_test.cc",
"chars": 10800,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/build_test.cc",
"chars": 136607,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/canon_perftest.cc",
"chars": 1573,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/clean.cc",
"chars": 7518,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/clean.h",
"chars": 3655,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/clean_test.cc",
"chars": 17269,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/clparser.cc",
"chars": 3897,
"preview": "// Copyright 2015 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/clparser.h",
"chars": 2100,
"preview": "// Copyright 2015 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/clparser_perftest.cc",
"chars": 15010,
"preview": "// Copyright 2017 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/clparser_test.cc",
"chars": 4283,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/command_collector.h",
"chars": 2063,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/debug_flags.cc",
"chars": 823,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/debug_flags.h",
"chars": 855,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/depfile_parser.cc",
"chars": 10815,
"preview": "/* Generated by re2c */\n// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/depfile_parser.h",
"chars": 1352,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/depfile_parser.in.cc",
"chars": 6750,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/depfile_parser_perftest.cc",
"chars": 2110,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/depfile_parser_test.cc",
"chars": 13379,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/deps_log.cc",
"chars": 13461,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/deps_log.h",
"chars": 5199,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/deps_log_test.cc",
"chars": 21761,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/disk_interface.cc",
"chars": 12728,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/disk_interface.h",
"chars": 3789,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/disk_interface_test.cc",
"chars": 11247,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/dyndep.cc",
"chars": 3994,
"preview": "// Copyright 2015 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/dyndep.h",
"chars": 2363,
"preview": "// Copyright 2015 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/dyndep_parser.cc",
"chars": 6439,
"preview": "// Copyright 2015 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/dyndep_parser.h",
"chars": 1472,
"preview": "// Copyright 2015 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/dyndep_parser_test.cc",
"chars": 15780,
"preview": "// Copyright 2015 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/edit_distance.cc",
"chars": 2374,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/edit_distance.h",
"chars": 909,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/edit_distance_test.cc",
"chars": 1753,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/elide_middle.cc",
"chars": 9013,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/elide_middle.h",
"chars": 1080,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/elide_middle_perftest.cc",
"chars": 1966,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/elide_middle_test.cc",
"chars": 3931,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/eval_env.cc",
"chars": 4888,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/eval_env.h",
"chars": 3993,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/exit_status.h",
"chars": 1025,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/explanations.h",
"chars": 2641,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/explanations_test.cc",
"chars": 2920,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/gen_doxygen_mainpage.sh",
"chars": 1500,
"preview": "#!/bin/sh\n\n# Copyright 2011 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Li"
},
{
"path": "src/getopt.c",
"chars": 12477,
"preview": "/****************************************************************************\n\ngetopt.c - Read command line options\n\nAUT"
},
{
"path": "src/getopt.h",
"chars": 1711,
"preview": "#ifndef GETOPT_H\n#define GETOPT_H\n\n/* include files needed by this include file */\n\n/* macros defined by this include fi"
},
{
"path": "src/graph.cc",
"chars": 27106,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/graph.h",
"chars": 16565,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/graph_test.cc",
"chars": 33502,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/graphviz.cc",
"chars": 2690,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/graphviz.h",
"chars": 1153,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/hash_collision_bench.cc",
"chars": 1895,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/hash_map.h",
"chars": 1404,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/includes_normalize-win32.cc",
"chars": 5799,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/includes_normalize.h",
"chars": 1702,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/includes_normalize_test.cc",
"chars": 6256,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/inline.sh",
"chars": 1307,
"preview": "#!/bin/sh\n#\n# Copyright 2001 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"L"
},
{
"path": "src/jobserver-posix.cc",
"chars": 3767,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/jobserver-win32.cc",
"chars": 3074,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/jobserver.cc",
"chars": 7191,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/jobserver.h",
"chars": 8642,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/jobserver_test.cc",
"chars": 12886,
"preview": "// Copyright 2024 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/json.cc",
"chars": 1538,
"preview": "// Copyright 2021 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/json.h",
"chars": 908,
"preview": "// Copyright 2021 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/json_test.cc",
"chars": 1246,
"preview": "// Copyright 2021 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/lexer.cc",
"chars": 17863,
"preview": "/* Generated by re2c */\n// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Vers"
},
{
"path": "src/lexer.h",
"chars": 3037,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/lexer.in.cc",
"chars": 7128,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/lexer_test.cc",
"chars": 3356,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/line_printer.cc",
"chars": 5217,
"preview": "// Copyright 2013 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/line_printer.h",
"chars": 2304,
"preview": "// Copyright 2013 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/load_status.h",
"chars": 771,
"preview": "// Copyright 2019 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/manifest_parser.cc",
"chars": 12513,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/manifest_parser.h",
"chars": 2352,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/manifest_parser_perftest.cc",
"chars": 3686,
"preview": "// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/manifest_parser_test.cc",
"chars": 33018,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/metrics.cc",
"chars": 3132,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/metrics.h",
"chars": 3050,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/minidump-win32.cc",
"chars": 2933,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/missing_deps.cc",
"chars": 7105,
"preview": "// Copyright 2019 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/missing_deps.h",
"chars": 2360,
"preview": "// Copyright 2019 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/missing_deps_test.cc",
"chars": 6152,
"preview": "// Copyright 2019 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/msvc_helper-win32.cc",
"chars": 3399,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/msvc_helper.h",
"chars": 1222,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/msvc_helper_main-win32.cc",
"chars": 4073,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/msvc_helper_test.cc",
"chars": 1238,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/ninja.cc",
"chars": 57765,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/ninja_test.cc",
"chars": 738,
"preview": "// Copyright 2013 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/parser.cc",
"chars": 1691,
"preview": "// Copyright 2018 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/parser.h",
"chars": 1465,
"preview": "// Copyright 2018 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/real_command_runner.cc",
"chars": 3540,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/state.cc",
"chars": 5942,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/state.h",
"chars": 4776,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/state_test.cc",
"chars": 1370,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/status.h",
"chars": 1904,
"preview": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/status_printer.cc",
"chars": 15244,
"preview": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/status_printer.h",
"chars": 4314,
"preview": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/status_test.cc",
"chars": 1252,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/string_piece.h",
"chars": 2019,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/string_piece_util.cc",
"chars": 1904,
"preview": "// Copyright 2017 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/string_piece_util.h",
"chars": 1090,
"preview": "// Copyright 2017 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/string_piece_util_test.cc",
"chars": 3303,
"preview": "// Copyright 2017 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/subprocess-posix.cc",
"chars": 13025,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/subprocess-win32.cc",
"chars": 9432,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/subprocess.h",
"chars": 4590,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/subprocess_test.cc",
"chars": 6947,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/test.cc",
"chars": 7437,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/test.h",
"chars": 4181,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/third_party/emhash/README.ninja",
"chars": 362,
"preview": "Description: emhash8::HashMap for C++14/17\nVersion: 1.6.5 (commit bdebddbdce1b473bbc189178fd523ef4a876ea01)\nURL: https:/"
},
{
"path": "src/third_party/emhash/hash_table8.hpp",
"chars": 58453,
"preview": "// emhash8::HashMap for C++14/17\n// version 1.6.5\n// https://github.com/ktprime/emhash/blob/master/hash_table8.hpp\n//\n//"
},
{
"path": "src/third_party/rapidhash/README.ninja",
"chars": 367,
"preview": "Description: Very fast, high quality, platform-independent hashing algorithm.\nVersion: commit 4a6b2570e868536be84800353e"
},
{
"path": "src/third_party/rapidhash/rapidhash.h",
"chars": 11517,
"preview": "/*\n * rapidhash - Very fast, high quality, platform-independent hashing algorithm.\n * Copyright (C) 2024 Nicolas De Carl"
},
{
"path": "src/timestamp.h",
"chars": 1138,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/util.cc",
"chars": 28934,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/util.h",
"chars": 5067,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/util_test.cc",
"chars": 13507,
"preview": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/version.cc",
"chars": 1788,
"preview": "// Copyright 2013 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/version.h",
"chars": 1182,
"preview": "// Copyright 2013 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "src/win32port.h",
"chars": 1140,
"preview": "// Copyright 2012 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "tests/restat/test_restat_builddir.py",
"chars": 4179,
"preview": "#!/usr/bin/env python3\n\n\"\"\"Integration test for 'ninja -t restat' with builddir.\"\"\"\n\nimport os\nimport subprocess\nimport "
},
{
"path": "windows/ninja.manifest",
"chars": 432,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com"
}
]
About this extraction
This page contains the full source code of the ninja-build/ninja GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 186 files (1.2 MB), approximately 345.3k tokens, and a symbol index with 1266 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.