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

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.


A Haskell library for parsing, pretty-printing, and compiling the Ninja build language. The best place to start reading this documentation is the Language.Ninja module.

[Skip to ReadMe]


Versions0.1.0, 0.1.0, 0.2.0
Dependenciesaeson (>=1.0 && <1.3), aeson-pretty (==0.8.*), base (>=4.8 && <5.0), bytestring (==0.10.*), containers (==0.5.*), deepseq (==1.4.*), flow (==1.0.*), hashable (==1.2.*), intern (==0.9.*), language-ninja, lens (==4.15.*), megaparsec (==5.2.*), mtl (==2.2.*), optparse-generic (==1.1.*), QuickCheck (==2.9.*), quickcheck-instances (==0.3.*), smallcheck (==1.1.*), system-filepath (==0.4.*), text (==1.2.*), transformers (==0.5.*), unordered-containers (==0.2.*), versions (>=3.1.1 && <3.2) [details]
CopyrightCopyright 2017 Awake Security
AuthorAwake Security
CategoryBuild, Language
Home page
Bug tracker
Source repositoryhead: git clone -b master
this: git clone release-0.1.0)
Executablesninja-compile, ninja-parse, ninja-lex
UploadedWed Jul 19 21:23:07 UTC 2017 by taktoa




Maintainers' corner

For package maintainers and hackage trustees

Readme for language-ninja-0.1.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.