Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> - if your paths have white space in them

This is probably my second biggest complaint about Make.

> - if you change your Makefile, nothing will be rebuilt

Heh, there’s a common trick for that: just slap Makefile on the end of prerequisite lists. I’ve worked with more complex projects that extend this to versioning the makefile with a `build/.makefile-v${MAKEFILE_VERSION}` common prerequisite so that you can bump the version if the change is such that you’ll need to rebuild everything.

> - if inkscape writes out a partial file because full disk and you fix the problem, the partial svg will no be rebuilt

Or the more common form, you run a fallible program and it produces errors but still produced a file (e.g. if you used piping, `> $@` instead of a `--output=$@` command line argument that only creates the file after processing has succeeded).

I think “build errored but produced a file” is probably my biggest complaint about Make. You can work around it in a few ways; `|| (touch --date=@0 $@; false)` is probably my favourite, which I used in https://chrismorgan.info/blog/make-and-git-diff-test-harness....

> - if you install a new version of inkscape nothing will be rebuilt

I’m curious: would Ninja rebuild on a new version of Inkscape? I’d be pleasantly surprised and view it much more favourably if it does.

In the scope of Make, prerequisite satisfaction is all reckoned with timestamps, which is a thing I’m not always fond of, so you definitely can’t do this properly. I think the closest you could get is generating a file containing the versions of all your prerequisites, and arrange for it to only be updated when they’ve changed. Basically a slight variant of the MAKEFILE_VERSION trick discussed earlier, though definitely much more involved, especially if you want it to have one filename always rather than just being a hash of all the versions.

And yes, all this is supporting your point that Make is not the best thing in this space, which I quite agree with. But for simple things I reckon it’s often still worth using despite this.



Re a new version of inkscape: Ninja does not force fully-correct builds, so it's on the author of the build.ninja file to either model this or not. (This is part of Ninja's objective of not mandating policy.)

To get this fully correct, note that you would need to model all inputs that Inkscape might read, which includes not only binaries but also configuration files or dynamically-loaded plugins. Some systems (I think tup?) track this by tracing executed binaries to see which file system operations they do.

Even with tracing it can be really subtle: for example if a C file has an #include "foo.h", creating a new file named foo.h earlier in the include search path is a meaningful change, which means a file-access-tracing build system also needs to track file-not-found results from previous executions.

(For C programs, also note that getting header dependencies correct includes similarly tracking all the headers in /usr/include that your program transitively includes. See the -MD vs -MMD flags to gcc.)


> Even with tracing it can be really subtle

The correct way of doing this is not tracing but a hermetic build. If you do a sandboxed build with nix, you will get a specific version of inkscape with a specific hash, which includes will include any inkscape extensions you include. And since the build will only be able to read files in the sandbox, none of the problems you list above can happen -- you can't pull random stuff from the network either.

https://nixos.wiki/wiki/Nix#Sandboxing


What you wrote is true, but it also seems to me unlikely that the OP is going to set up a sandboxed hermetic build to process a handful of pngs for her zine. I was instead explaining why Ninja doesn't attempt clever tricks to try to better approximate correctness.


> What you wrote is true, but it also seems to me unlikely that the OP is going to set up a sandboxed hermetic build to process a handful of pngs for her zine.

But it's trivial!

Assuming you fix the OP's Makefile (so much for Makefile syntax usability):

     # put into Makefile
     THINGS_TO_CONVERT := $(wildcard *.svg)
     all: $(patsubst %.pdf,%.svg,$(THINGS_TO_CONVERT))
          inkscape $< --export-text-to-path --export-pdf=$@

     # put into default.nix
     with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/7ad5e816faba3f808e2a8815b14d0f023a4e2160.tar.gz") {};
     stdenv.mkDerivation {
      name = "zine-images";
      src = ./.;
      buildInputs = [ inkscape ];
      installPhase = "mkdir $out && cp *.pdf $out";
    }
Now make sure you have sandbox=true in /etc/nix.conf, run `nix build` in the directory, and boom done: hermetic build of zine images. Good thing too, I got a warning about --export-pdf being deprecated when I ran this. Note that running make or the dependency on make is not explicitly specified, mkDerivation has some basic smarts to figure out from the presence of a Makefile that it should run make.

(Hardcoding the version of nixpkgs directly into the default.nix just for demo purposes, better to use niv or similar to manage a json file with versions for you).


Of course we could also get rid of the Makefile and simply add a buildPhase like this:

      buildPhase = "find -maxdepth 1 -name '*.svg' -print0 | xargs --null -I'{}' -n1 inkscape '{}' --export-text-to-path --export-pdf={}.pdf";

This should also handle filenames with spaces etc. correctly (although I have not tested it).


> I’m curious: would Ninja rebuild on a new version of Inkscape? I’d be pleasantly surprised and view it much more favourably if it does.

I haven't used ninja, but nix and (unless memory fails me) bazel derived build systems will. Nix basically has a completely hermetic world, and everything is referred to by hash that includes the recursive dependency tree.


I've never seen the `touch` version of that safety versus broken output files before. I've only seen the `rm` version. Is `touch` advantageous? Edit: oh, oops, I should've followed the link; the output file in the example seems to be test output which would be more distinctly useful to inspect after the fact on partial failure. That makes sense.


> > - if your paths have white space in them

>

> This is probably my second biggest complaint about Make.

If only more of the world used rc instead of bash, we'd be in a better place.


> If only more of the world used rc instead of bash,

Make does not use bash. Make uses whatever shell is pointed to by the SHELL env variable. If you don't pass any, it defaults to sh.

Meanwhile, you can use Python in a Makefile for what it's worth.

https://www.gnu.org/software/make/manual/html_node/Choosing-...


rc?


https://en.wikipedia.org/wiki/Rc

An alternate shell, from Plan9.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: