[HN Gopher] Ninja is a small build system with a focus on speed
       ___________________________________________________________________
        
       Ninja is a small build system with a focus on speed
        
       Author : tosh
       Score  : 92 points
       Date   : 2026-03-27 10:23 UTC (3 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | woctordho wrote:
       | If someone sees this: The ninja package on PyPI [0] currently
       | stays at version 1.13.0 . There is an issue in 1.13.0 preventing
       | it building projects on Windows. The issue is already fixed in
       | 1.13.1 almost a year ago, but the PyPI package hasn't got an
       | update, see [1], and many downstream projects have to stay at
       | 1.11 . I hope it could update soon.
       | 
       | [0] https://pypi.org/project/ninja/
       | 
       | [1] https://github.com/scikit-build/ninja-python-
       | distributions/i...
        
         | endgame wrote:
         | Why is a C++ project being distributed on PyPi at all?
        
           | grim_io wrote:
           | Probably for the same reason other binaries are distributed
           | by npm: lack of cross platform general package managers and
           | registries
        
             | mikepurvis wrote:
             | Also for cases where a python project needs to depend on
             | it.
        
             | verdverm wrote:
             | Or lack of a tool like Goreleaser in the language ecosystem
             | that handles that
        
           | zahlman wrote:
           | You may be interested in this discussion:
           | https://discuss.python.org/t/use-of-pypi-as-a-generic-
           | storag...
        
           | tadfisher wrote:
           | Because the development world either hasn't heard of nix or
           | has collectively decided to not use nix.
        
         | j1elo wrote:
         | What a messy and frankly, absurd situation to be left in. To
         | fork a project in order to provide a tool through Pypi, only to
         | then stop updating it on a broken version. That's more a
         | disservice than a service for the community... If you're going
         | to stay stuck, better to drop the broken release and stay stuck
         | on the previous working one.
        
       | shevy-java wrote:
       | All the main build tools (cmake, meson/ninja and GNU configure)
       | have different benefits. For instance, I expect "--help" to work,
       | but only really GNU configure supports it as-is. I could list
       | more advantages and disadvantages in general here, but by and
       | large I prefer meson/ninja. To me it feels by far the fastest and
       | I also have the fewest issues usually (excluding python breaking
       | its pip stack but that's not the fault of meson as such). ninja
       | can be used via cmake too but most uses I see are from meson.
        
         | flohofwoe wrote:
         | > ninja can be used via cmake too but most uses I see are from
         | meson
         | 
         | How do you know though when the choice of cmake-generator is
         | entirely up to the user? E.g. you can't look at a cmake file
         | and know what generator the user will select to build the
         | project.
         | 
         | FWIW I usually prefer the Ninja generator over the Makefile
         | generator since ninja better 'auto-parallelises' - e.g. with
         | the Makefile generator the two 'simple' options are either to
         | run the build single-threaded or completely grind the machine
         | to a halt because the default setting for 'parallel build'
         | seems to heavily overcommit hardware resources. Ninja just
         | generally does the right thing (run parallel build, but not
         | enough parallelism to make the computer unusable).
        
           | plq wrote:
           | ninja supports separate build groups and different max number
           | of parallel jobs for each. CMake's ninja generator puts
           | compilation and linking steps in their own respective groups.
           | End result is by default `nproc` parallel jobs for
           | compilation but 1 job for linking. This helps because linking
           | can be way more memory intensive or sometimes the linker
           | itself has support for parallelism. Most projects have only a
           | handful of linking steps to run anyway.
        
         | Sesse__ wrote:
         | I find Meson's --help fairly useful, at least compared to the
         | disaster that is CMake's. (Try to find out, as a user not
         | experienced with either, how you'd make a debug build.) I agree
         | that configure --help is more useful for surfacing project-
         | specific options, though.
        
       | jonstewart wrote:
       | The absolute best thing about coding agents is not having to
       | waste time on build systems. I had Claude code port my autotools
       | scripts to meson (which uses ninja) and it's been a huge quality
       | of life improvement.
        
         | reactordev wrote:
         | Soon you won't even have to waste time on the code part...
        
           | tom_ wrote:
           | It's only a waste of your tine if you don't want to do it.
        
         | hakrgrl wrote:
         | Getting builds to work was some of the most tedious, least
         | interesting work. It is so satisfying to watch the agent try 4
         | different things and magically go on its way. No more makefile
         | syntax searches or cmake hell.
        
           | freedomben wrote:
           | For real. I stopped writing Makefiles because of how tedious
           | it was, but now with AI I'm back to throwing Makefiles in
           | everything. It's wonderful to have the same build, test,
           | release commands in all projects instead of mix compile in
           | one, npm build in another, etc. This is my favorite part of
           | AI
        
       | sluongng wrote:
       | My teammate has a great time reimplementing Ninja (slop-free) in
       | Go here https://github.com/buildbuddy-io/reninja to make it even
       | faster with Remote Build Execution.
        
         | setheron wrote:
         | This is cool. Going to see if I can use it at work.
        
       | amelius wrote:
       | I can remember having to uninstall ninja temporarily because it
       | messed with building packages. I only use it because other
       | packages need it.
        
       | jbonatakis wrote:
       | Postgres uses Meson+Ninja in their builds. That seems like a
       | pretty big endorsement.
        
         | ddtaylor wrote:
         | Most of Gnome is built using that too.
        
       | mizmar wrote:
       | Similar to make, it does mtime chronological comparison of
       | dependencies with target to determinate if dependencies changed.
       | This is just so flawed and simple to fool by operations on
       | filesystem that do not change mtime (move, rename):
       | 
       | 1) pick a source file and make a copy of it for for later 2) edit
       | selected source file and rebuild 3) move the copy to it's
       | original location 4) try to rebuild, nothing happens
        
         | jasonpeacock wrote:
         | My guess is that it's for drop-in compatibility with make.
         | 
         | There is (at least) one open issue about this - the
         | solution/alternatives are not trivial:
         | 
         | https://github.com/ninja-build/ninja/issues/1459
        
         | loeg wrote:
         | Copy (1) and edit (2) both bump mtime, usually. It's not
         | obvious that in the workflow you describe ninja is problematic,
         | rather than the workflow itself (which is atypical).
        
           | mizmar wrote:
           | ninja fails to detect that file changed from last build - all
           | it's mtime, ctime, inode and size can change, yet it's not
           | detected as long as mtime is not newer than target.
        
             | loeg wrote:
             | Again, this is just a weird workflow, and you're assuming
             | copy/edit don't bump mtime. That usually isn't the case. If
             | you're doing this weird thing, you can just run `touch`
             | when you move files over existing files like this to
             | explicitly bump mtime.
        
               | mizmar wrote:
               | >you're assuming copy/edit don't bump mtime
               | 
               | Incorrect, I only assume move/rename of backup to
               | original location doesn't change it's mtime (which it
               | doesn't with default flags or from IDE or file manager).
               | And I don't think this is a weird or obscure workflow, I
               | do it all the time - have two versions of a file or make
               | a backup before some experimental changes, and restore it
               | later.
        
               | MereInterest wrote:
               | I run into this issue when building against different
               | environments, each with a
               | 
               | 1. A library depends on a system package. To test against
               | the different versions of the system package, the library
               | is compiled within a container.
               | 
               | 2. To minimize the incremental rebuild time, the `build`
               | directory is mounted into the build container. Even when
               | using a different version of the system package, this
               | allows re-use of system-independent portions of the
               | build.
               | 
               | 3. When switching to a build container with a different
               | version of the system package, the mtime of the system
               | package is that of its compilation, not that of the build
               | container's initialization. Therefore, the library is
               | erroneously considered up-to-date.
               | 
               | Because the mtime is the only field checked to see if the
               | library is up to date, I need to choose between having
               | larger disk footprint (separate `build` directory for
               | each build container), slower builds (touch the system
               | package on entering the container, forcing a rebuild), or
               | less safe incremental builds (shared `build` directory,
               | manually touch files when necessary).
        
           | usefulcat wrote:
           | > 3) move the copy to it's original location
           | 
           | Copy and edit do, but move (aka rename) generally does not,
           | and that is the part that is problematic.
           | 
           | I don't think the described sequence of operations is all
           | that unusual. Not the most common case for sure, but hardly
           | unlikely in the grand scheme of things.
        
         | amavect wrote:
         | By not tracking file metadata through an index file, mtime-only
         | incremental build systems trade a lot of reliability for only
         | slightly more simplicity. https://apenwarr.ca/log/20181113
        
           | aidenn0 wrote:
           | See also
           | https://gittup.org/tup/build_system_rules_and_algorithms.pdf
        
         | evmar wrote:
         | [ninja author] I did some thinking about this problem and
         | eventually revisited with what I think is a pretty neat
         | solution. I wrote about it here:
         | https://neugierig.org/software/blog/2022/03/n2.html
        
           | actionfromafar wrote:
           | Imagine if filesystems had exposed the file hash next to its
           | mtime.
        
             | oftenwrong wrote:
             | I might be missing your sarcasm, but this is a common
             | approach for large scale builds. Virtual filesystems are
             | used to provide a pre-computed tree hash as a xattr. In a
             | more typical case, you can read the git tree hash.
        
         | hrmtst93837 wrote:
         | mtime rebuild logic is half-baked even by 1970s standards.
         | 
         | Bazel and Shake avoid this class of bug with content hashes, so
         | a rename, restore, or tar extract does not leave the build
         | graph in a stale state. Speed matters, but not enough to bet
         | your repo on timestamp luck.
        
       | p4bl0 wrote:
       | I used ninja only a few years ago when contributing to KDE
       | software (Dolphin, Kate, KTextEditor, etc.). I had no prior
       | experience with it and it was easy to apprehend, so a rather good
       | experience.
        
       | bsimpson wrote:
       | Evan Martin (evmar) started Ninja when he was working on Chrome
       | at Google:
       | 
       | https://neugierig.org/software/chromium/notes/2011/02/ninja....
       | 
       | Hence, it's used in a lot of Google projects.
        
       | ozgrakkurt wrote:
       | Ninja is one of the best tools I have used. It is extremely
       | simple and always works flawlessly.
       | 
       | Some blog posts from the creator of ninja:
       | 
       | https://neugierig.org/software/blog/2018/07/options.html
       | 
       | https://neugierig.org/software/blog/2011/04/complexity.html
       | 
       | Also there was a post about why just generating ninja using
       | python can be a good option. I do this in my project and it has
       | been very productive so far. I couldn't find this post now but it
       | was saying to use ninja_syntax.py from ninja codebase and just
       | doing something minimal for a project
        
         | fainpul wrote:
         | OMG, so many open source projects need to read this:
         | 
         | https://neugierig.org/software/blog/2018/07/options.html
         | 
         | (hello FreeCAD ;)
        
         | zem wrote:
         | we used ninja as a parallel task runner in pytype - had our
         | whole-project analyser generate a ninja file with a task graph,
         | and then just evoke ninja to run it, taking care of
         | dependencies and parallel execution. it worked very nicely
         | indeed.
        
       | Svoka wrote:
       | Ninja religions following of treating timestamps (mtime) as
       | 'modified' marker makes it useless with Git and large projects.
       | 
       | You switched some branches back and forward? Enjoy your 20
       | minutes rebuild.
       | 
       | * https://github.com/ninja-build/ninja/issues/1459
        
         | dezgeg wrote:
         | I believe the same author has made a ninja successor (n2) that
         | uses hashes instead. Haven't tried personally but hopefully get
         | around to try that in the near future
        
         | menaerus wrote:
         | I have never observed that issue, and I have been using it to
         | build MMLoC repositories. Perhaps the reason being is that I
         | always use it coupled with ccache. Have you tried that?
        
           | throwway120385 wrote:
           | ccache is a workaround for the mtime problem. You can either
           | hash with ccache or hash directly in the build system, but
           | either way there's no substitute for hashing something.
           | Ccache is hashing the input to the build, but there may be
           | elements of the build that lie outside of ccache's awareness
           | that having a hash-aware build system would take care of.
           | Partial rebuilds devolve to a cache invalidation problem
           | pretty quickly either way.
        
             | menaerus wrote:
             | I'm obviously aware that ccache solves the mtime problem
             | which is why I find disingenious to say that switching
             | branches with ninja is "totally unusable". Therefore my
             | question.
             | 
             | Hash-aware build systems like bazel, if that's what you're
             | imputing, are a nightmare to work with and come with their
             | own set of problems which make it much less appealing to
             | work with than (some) limitations found in cmake+ninja
        
       | Conscat wrote:
       | An under noticed ninja feature I adore, which was implemented
       | relatively recently, is the ability to configure how its build
       | progress is printed. In my fish config, I have the `NINJA_STATUS`
       | envvar:                   set -x NINJA_STATUS "STEP: %f/%t
       | [%p / %P]          [%w + %W]         "
       | 
       | Which prints the time elapsed and projected in a readable multi-
       | line format.
        
       | HiPhish wrote:
       | Serious question: how can a build tool be fast or slow? From my
       | understanding all it does is delegate the build steps to other
       | tools, so wouldn't those be the bottleneck? Is it the resolution
       | of order of build steps that takes so much time that a different
       | build system can make a difference?
        
         | evmar wrote:
         | [ninja author] My first post about Ninja goes into this:
         | https://neugierig.org/software/chromium/notes/2011/02/ninja....
        
           | HiPhish wrote:
           | I'm afraid I still don't understand. One factor is having
           | fewer features and not looking for obsolete files, that I can
           | understand. I guess the other thing is using better rules to
           | figure out when a file truly need to be rebuilt?
        
       | aidenn0 wrote:
       | Ninja is possibly the best example of the "Do one thing and do it
       | well" philosophy. All it does is execute commands based on a
       | static build graph.
       | 
       | It's syntax is simple enough that it's trivial to e.g. write a
       | shell script to generate the build items if you need dynamic
       | dependencies.
        
       | throwaway2046 wrote:
       | Ninja is great and feels natural coming from Make. What it lacks
       | in features it makes up for with speed, which is what ultimately
       | matters.
       | 
       | Also worth mentioning is samurai[1], a pure C implementation of
       | Ninja that's almost as fast yet easier to bootstrap needing only
       | a C compiler.
       | 
       | [1] https://github.com/michaelforney/samurai
        
       ___________________________________________________________________
       (page generated 2026-03-30 23:01 UTC)