1. 15

  2. 10

    But in most large projects you will just write a script to generate these files.

    When I read statements like this, I think of the underpants gnomes business plan wherein one just glosses over the “magic” phase.

    1. 7

      It’s not unusual at all. The de facto architecture of build systems is now to separate them into high level and low level layers.

      This started with autotools and Makefiles. Autoconf and automake are separate high level languages (implemented as m4 macros, blech), which generate shell scripts and Makefiles. GNU Make does the actual execution.

      This architecture has become more codified with Ninja as the low level and GN (Chromium) or CMake (LLVM) as the high level, portable version.

      So he’s basically saying that Fac is a low level build system. It doesn’t have Turing complete features. Lower level languages may lack Turing complete features like Ninja, but higher level build languages need them. Android is moving away from 200K lines of Makefiles that included the GNU Make Standard library, so it’s a build system bigger than most programs people write. The high level language needs to be Turing complete, which isn’t a small undertaking. CMake admitted that their language is kinda horrible.

      1. 3

        I don’t dispute the separation. But the wording (“just write a script”) belies the amount of work needed to make it into a full build system that you can actually use.

        1. 3

          I realise I’m probably being overly pedantic but every time I see arguments about the need (or not) of a language to be Turing complete I wonder if people would be better served by offering a more precise specification of the feature(s) they believe this will enable. For example, the blanket statement of whether something is Turing complete only communicates the ability to simulate a Turing machine, there are very many valid programs that can be written without that particular feature.

          Agda et al. is an example of something that is not Turing complete per-say (Partiality monad aside), yet it would not be mistaken for being in the same power-to-weight category as a Makefile.

          1. 2

            Yeah in this context “Turing complete” is perhaps not very precise or doesn’t capture the whole issue. In particular people often conflate two things: whether you can do arbitrary computation and whether you have side effects.

            Both are design issues in a build system. A side effect would be reading the source files to discover dependencies from .h files, rather than the dependency graph being purely a function of what’s in the Makefile.

            For the case of builds, my assertion is that you need arbitrary computation: memory, loops, and conditionals. And although it doesn’t affect whether it’s Turing complete or not, you need abstraction power like functions and so forth.

            If there are better terms to have this discussion with, I would be interested in hearing them. But my overall point stands: low level build systems deal with fine-grained dependency graphs and parallel execution. High level build systems have “logic” for portability and code reuse. Build systems are real code now.

      2. 5

        If you zoom in on the page you can get rid of that annoying two column layout.

        1. 5

          This seems worse than tup, which I use for several projects and can wholeheartedly recommend. fac appears to only support Linux, while tup supports Mac & Windows as well. tup is scriptable in Lua and fac requires writing an ad-hoc script to generate .fac files. From their comparison page the only point in fac’s favor that I see is that you don’t have to explicitly list inputs and outputs for each command, and I don’t buy the “using FUSE is a security risk” argument.

          1. 4

            Regarding fuse, I don’t think the point is that it’s a security risk, but that a security feature of the nfs infrastructure makes the fuse strategy unworkable.

            A bit more info: He’s clearly at a university, and they use nfs, and the common way to export to users in this situation is to enable the root_squash flag. What this does is that it forces all calls that are sent as uid=0 to get mapped to some less-privileged user on the nfs server to avoid a variety of attacks (e.g. nobody). So he’s saying that tup’s fuse process will result in a write from root to his nfs home and that’ll get squashed into user “nobody” or “nobody4” or something else, and that user won’t have access to his files.

          2. 3

            The use of ptrace is very interesting as the well as the DAG-style declarative language, but I don’t think it can be as practical as Make because of the lack of scriptability. It’s really more like an engine than a user-facing tool, but I see some interesting use cases for automating workflows.