language-ninja: A library for dealing with the Ninja build language.

[ apache, build, language, library, program ] [ Propose Tags ]
Versions [RSS] 0.1.0, 0.2.0
Change log
Dependencies aeson (>=1.0 && <1.3), aeson-pretty (>=0.8 && <0.9), base (>=4.8 && <5.0), bytestring (>=0.10 && <0.11), containers (>=0.5 && <0.6), deepseq (>=1.4 && <1.5), flow (>=1.0 && <1.1), hashable (>=1.2 && <1.3), intern (>=0.9 && <0.10), language-ninja, lens (>=4.15 && <4.16), megaparsec (>=5.2 && <5.3), mtl (>=2.2 && <2.3), optparse-generic (>=1.1 && <1.2), QuickCheck (>=2.9 && <2.10), semigroups (>=0.18 && <0.19), smallcheck (>=1.1 && <1.2), system-filepath (>=0.4 && <0.5), text (>=1.2 && <1.3), transformers (>=0.4 && <0.6), unordered-containers (>=0.2 && <0.3), versions (>=3.1.1 && <3.2) [details]
License Apache-2.0
Copyright Copyright 2017 Awake Security
Author Awake Security
Category Build, Language
Home page
Bug tracker
Source repo head: git clone -b master
this: git clone release-0.2.0)
Uploaded by taktoa at 2017-08-02T00:16:29Z
Executables ninja-compile, ninja-parse, ninja-lex
Downloads 1662 total (7 in the last 30 days)
Rating 2.0 (votes: 1) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for language-ninja-0.2.0

[back to package description]


Hackage Stackage License

language-ninja is a Haskell library for parsing, pretty-printing, and compiling the Ninja build language.


language-ninja was written as a part of Awake Security's efforts in creating incremental build infrastructure for the Nix package manager, and in particular for Haskell packages. This library is the basis for a tool, ninja2nix, that, given a Ninja file, will output a JSON file containing information that a Nix function can use to compute a derivation representing an incremental build using one derivation per build edge in the parsed Ninja build graph.

In conjunction with an as-of-yet unwritten tool, cabal2ninja, that will generate a Ninja file based on information from cabal and ghc -M, we will have incremental builds for any Haskell package that uses a default Setup.hs file.

Using Ninja as an intermediate representation has advantages here, since it means that ninja2nix could be useful for building other projects that use a build system that can output Ninja, like the Linux kernel (with kninja), Chromium, any CMake project, any Bazel project, or some Make-based projects (with kati).


Originally, language-ninja used the Ninja lexer/parser from Neil Mitchell's shake project. However, we now use a megaparsec-based lexer and a highly modified version of the old parser. There is still work to be done on improving the diagnostic data and pretty-printability of the AST from this parser. In my view, it is very important that a parser output an AST that can be pretty-printed exactly to same sequence of bytes that were in the parsed file, as this makes tests and diagnostics much easier to write.


Currently there is a rudimentary pretty-printer in Language.Ninja.Pretty. It simply outputs text such that if that text is parsed and the parsed data is pretty-printed again, the resulting text will be identical to the original text (this is tested on a variety of Ninja files in the test suite).


The Ninja type from Language.Ninja.IR.Ninja contains precisely the data that must be acted on dynamically in a Ninja. In converting from the parsed AST to the intermediate representation using Language.Ninja.Compile.compile, you are eliminating all statically-dischargeable language features in Ninja, like variables. It also "monomorphizes" Ninja rules, since rule-level $out references are a kind of parametric polymorphism. This IR is thus far more suitable for processing than the original parsed AST.


The staging branch is used for active development; i.e.: force pushes may happen on staging but will not happen on master.

To build this, I recommend installing the Nix package manager and running nix-build release.nix -A language-ninja.