Package: mkninja
mkninja: A python frontend for ninja filesmkninjais likeCMakeorMesonin that it is a metabuild system that
generates a build system.mkninjais also likeTuporninjaitself in
that it is 100% language agnostic.Why would I use mkninja?You might want to usemkninjafor the following reasons:You are in a project that needs a wrapper build system around several
unrelated sub-build systems (often in a cross-language tech stack).You want to execute a large number of arbitrary actions in a build graph
(perhaps treating a server configuration as a build system problem).You don't like alternative build tools and you want something with an easy
learning curve.Why would I not use mkninja?You might decide not to usemkninjafor the following reasons:You are building a single-language project where some existing build system
has tons of great tooling for you to leverage (such as C++ and CMake).You want something that is polished whilemkninjais still experimental.How do I install mkninja?You can installmkninjaviapip:pip install mkninjaHow does mkninja work?mkninjais close in spirit to CMake.  Instead of usingCMakeLists.txtand
writing in CMake script, you usemkninja.pyfiles and you write normal
python.You generate the ninja files once with:cd /path/to/build && mkninja /path/to/srcAfter initial configuration,mkninjawill automatically regenerate itsbuild.ninjafiles any time you runninjaand any of themkninja.pyfiles
have been updated, much like CMake or Meson.Whenmkninjaruns, it imports the top-levelmkninja.pyof your project as
the special module nameroot.  If you have anothermkninja.pyin a
subdirectory liketools/mkninja.pyyou may import it withimport root.toolsand use it as you would normally use a python module.Note that only themkninja.pyin the root directory is automatically
imported.  Any subdirectories containingmkninja.pyfiles must be need to be
explicitly imported to take effect.API ReferenceEverymkninja.pyfile has access to the following special values (without
importing anything):SRCBLDadd_target()add_manifest()add_glob()SRCSRCis apathlib.Pathobject pointing to source directory in which thatmkninja.pyfile exists.  Think${CMAKE_CURRENT_SOURCE_DIR}.BLDBLDis apathlib.Pathobject pointing to the directory corresponding toSRCbut in the build tree.  Think${CMAKE_CURRENT_BULID_DIR}.add_target()add_target()adds a new target (or "build edge" in ninja terminology) to
the generatedbuild.ninjafile.add_target()has the following
keyword-only arguments:command: a list of tokens as to how the command should run.  You
are allowed to provide a single string, which will be first tokenized
viashlex.split().outputs: a list of output files that the command should generate.inputs: a list of input files ormkninja.Targetobjects that the
command depends on.after: a list of order-only dependencies of the target.  Items may be
output files from anothermkninja.Targetor anothermkninja.Targetobject itself.phony: a boolean indicating that the target should always be
considered out-of-date.  Note thatmakehas the obnoxious behavior
that any target that depends on a PHONY target is also always
considered out-of-date.  The same is not true undermkninja.py.workdir: a directory tocdinto before launching thecommand,
defaults toSRC.display: a string of text to display while this step is running.dyndep: a file or target (which must also be ininputs) that ninja
should treat as a dynamic dependency file.  See ninja docs for details.add_target()returns amkninja.Targetobject which has attrubutesinputs,outputs, andafterwhich may be useful to read (but which
probably shouldn't be modified).  Additionally, themkninja.Targetobject
may be passed intoinputsorafterdirectly.add_manifest()add_manifest()adds a target to track a dynamic list of files.  Thecommandargument should write a list of files, one per line, to stdout.
Each time this target runs, thecommandis run and piped to themanifestbinary (packaged withmkninja).manifestwill ensure that
theoutfile contains an up-to-date list of files and that theoutfile
is always newer than any of the files in the list.  In this way, another
target which depends on theoutfile can be thought of as depending on
the entire list of files; it will be rebuilt any time that the list of
files changes, or any time that a file in the list is modified.add_manifest()has the following keyword-only arguments:command: the command to generate the stdin to themanifestbinary.
As withadd_target(),commandmay be either a list of tokens or a
single string.out: the output file to be generated by themanifestfile.after: a list of order-only dependencies before building the manifestworkdir: a directory tocdinto before launching thecommand,
defaults toSRC.add_manifest()returns amkninja.Target.add_glob()add_glob()adds a new target which uses thefindglobbinary (packaged
withmkninja) to search for files matching the patterns provided as
arguments.  The result is piped into themanifestbinary (described
above), so that another target which depends on the output ofadd_glob()will effectively depend on all the files matching the patterns provided.add_glob()has the following arguments:*patterns: a list of patterns to pass as command-line arguments to
thefindglobbinary.  You might use"*.c"to list all of the.cfiles in the current directory, or"**/*.c"to list all of the.cfiles in the directory tree rooted at..  See the full
output offindglob --helpbelow for more details about patterns.out: where to write the manifest file toafter: a list of order-only dependencies before searching for filesworkdir: a diretory tocdinto before launchingfindglob, defaults toSRC.add_glob()returns amkninja.Target.Appendix A:findglob --helpoutputfindglobis what runs in the ninja build edge created byadd_glob()and so
knowing how it works will help you choose patterns foradd_glob().findglob will find matching files and directories and write them to stdout.

usage: findglob PATTERN... [ANTIPATERN...]

examples:

    # find all .c files below a directory
    findglob '**/*.c'

    # find all .c AND .h files below a directory
    findglob '**/*.c' '**/*.h'

    # find all .c AND .h files below a directory, while avoid searching
    # through the .git directory
    findglob '**/*.c' '**/*.h' '!.git'

    # find all .py files below a directory, while avoid searching through
    # the git directory or any __pycache__ directories
    findglob '**/*.py' '!.git' '!**/__pycache__'

    # find all .c files below a directory but ignore any .in.c files
    findglob '**/*.c' '!**/*.in.c'

Some details of how patterns work:

  - a PATTERN starting with ** will begin searching in $PWD

  - a PATTERN starting with prefix/** will begin searching at prefix/

  - PATTERNs of a/** and b/** will search a/ and b/ in sequence

  - PATTERNs of **/a and **/b will search $PWD once for files named a or b,
    because they have the same start point ($PWD)

  - PATTERNs of a/** and a/b/** will search a/ once, since the start point
    of the first pattern is a parent of the start point of the second

  - PATTERNs ending with a file separator ('/') will only match directories

  - ANTIPATTERNs start with a '!', and cause matching files to not be
    printed and matching directories to not be searched

  - ANTIPATTERNs follow the same startpoint rules, so !**/.git will prevent
    matching anything beneath $PWD named .git, while !/**/.git, which has a
    start point of / will prevent matching anything named .git across the
    entire filesystem.  Unlike PATTERNs, an ANTIPATTERN with a start point
    of '/' is not enough to cause findglob to search through all of '/'.

  - PATTERNs and ANTIPATTERNs may have types.  Presently only dir-types and
    file-types (really, non-dir-types) exist.  Dir-type patterns will match
    directories but not files, file-types will match files but not dirs,
    and untyped patterns will match either.  Dir-type patterns may be
    specified with a trailing file separator (/).  File-type patterns must
    be specified with the extended syntax.

  - on Windows, using '\' as a separator is not allowed; use '/' instead

Extended syntax:

  - Extended-syntax patterns begin with a ':', followed by zero or more
    flags, followed by another ':', followed by the pattern.  The following
    flags are currently supported:

      - ! -> an ANTIPATTERN
      - f -> match against files
      - d -> match against directories
      - if no type flag is supplied, it matches all types

   Example:
       # find files (not dirs) named 'build' except those in build dirs:
       findglob ':f:**/build' ':!d:**/build'