Earlier quoted context omitted.
Actually, the compilers do not and you are doing less than half of the job there. They don't emit information about the non-existent files that would change the build if they were to suddenly exist, such as an "x.h" in one of several standard search directories in that example. * http://jdebp.uk./FGA/introduction-to-redo.html#CompilerDefic...
Also they don't add an empty rule for the source file (like they can do for headers), so if you rename from e.g. foo.c to foo.cpp, which still produces a foo.o, your incremental build fails because the dep file still has the dep on foo.c which doesn't exist anymore.
Redo: A recursive, general-purpose build system
81–90 of 95 posts
Re: Redo: A recursive, general-purpose build system
#82Earlier quoted context omitted.
Aside from the fact that DJB barely specified redo to the point where you could make accusations claiming it did or did not do something, I think there are implementations of redo which are capable of fitting the requirements you specify. 1. Redo doesn't give you the tools to have dynamic dependencies for example, but it also doesn't concern itself with those and doesn't prevent you from having them. I have a small p…
> Aside from the fact that DJB barely specified redo to the point where you could make accusations claiming it did or did not do something, I think there are implementations of redo which are capable of fitting the requirements you specify. You're not wrong, and I think DJB did get there. However, there's a difference between the Unix way of designing a system out of disparate pieces working together (something DJB i…
The problem with working on windows is that there's no shared standard (unless you count whatever irrelevant part of the POSIX spec that windows follows a shared standard). On windows there is no bash or posix shell, there is no gcc or a compiler which takes gcc-like options, there's no posix compliant or gnu compliant make. It's all just wrong. If you plan on making a build system, it has to take a lot of things and provide an abstraction layer over them to make them work for windows. I say forget it, it's a waste of effort, just make it work on linux and by extension (through WSL or mingw or whatever) you get windows. The alternative is worse as you have to add support for every special language to your build system. One of the best tests of a build system I've found has been to get a build system to build an executable and run it to produce an output which is then consumed as part of the build process. With pure make, this is purely awful and requires either generating a bunch of rules or lots of boilerplate, and generally it's easy to get wrong. With redo I got this working with relatively little work and got it to work with cross-builds.
> cohesive whole build system is a much better platform for implementing hermetic builds
In my adventures with redo, the biggest obstacle to hermetic builds that I've found aside from just the environment (env vars) has been compilers. Compilers suck at a: telling you what they're looking for and b: where they're looking for it. The best solution seems to be to strace gcc and look for calls to fstat or something like that to figure out which candidate header files it's looking for. And I hope you agree, that's an awful solution. Surely a better build system would need some form of overhaul to the interfaces provided by compilers? (Or, some re-implementation of some compiler features so you can spoon-feed a compiler the exact flags to ensure it behaves predictably even if the environment changes.)
I guess unifying things could solve the environment problem, but I think I can solve it without unifying anything.
>However, at least in the TFA redo
TFA?
>[1]
Okay, so you mean dynamically generated .do files. I think in most cases you can avoid them, but I agree that having every depend-er explicitly depend on the .do file before depending on the file it's intended to redo is really error prone and annoying. There's at least one way to retrofit this into normal redo: by having some default.o.redo file or something and wrapping redo-ifchange and checking if any dependencies have a default*.redo file and depending on the corresponding .do file, although kludgy this at least avoids the possibility of errors if you add future depend-ers to the dependency. I agree redo is missing something here though.
>Correct. And I should have mentioned that. But again, DJB did that in an indirect way, making the system "finicky" (in my opinion).
Why finnicky? In the usual case you DON'T want anything other than just timestamps and hashes, it works for all cases, albeit slowly for some. If you NEED to customize it, you have to pull out the special tools but then you just wrap that in some little utility and mostly forget about it.
> Well, I don't think going even more basic is good here. Hermetic builds are just too good to pass up, and that requires some complexity.
What do YOU think are the obstacles to hermetic builds? I already know what I've found but I'm always looking for more input.
I'm currently working with a few people to try to make redo work for strictly hermetic builds, or alternatively to design a better redo (or alternatively something else) which solves all the build problems I think exist. Unlike you, I don't really care if people like it or like using it, I've resigned myself to the fact that almost nobody cares about simple unix-esque software anymore and that if I want something like this, I'll have to design and write it myself.
Re: Redo: A recursive, general-purpose build system
#83Earlier quoted context omitted.
> Aside from the fact that DJB barely specified redo to the point where you could make accusations claiming it did or did not do something, I think there are implementations of redo which are capable of fitting the requirements you specify. You're not wrong, and I think DJB did get there. However, there's a difference between the Unix way of designing a system out of disparate pieces working together (something DJB i…
>make it easier to make it work on Windows from the start The problem with working on windows is that there's no shared standard (unless you count whatever irrelevant part of the POSIX spec that windows follows a shared standard). On windows there is no bash or posix shell, there is no gcc or a compiler which takes gcc-like options, there's no posix compliant or gnu compliant make. It's all just wrong. If you plan on…
Part of the language builtin to my build system provides ways of running commands without a shell.
> there is no gcc or a compiler which takes gcc-like options,
No, but there is MSVC. You just need to abstract the compiler and compiler flags. CMake did it, so why can't I?
> there's no posix compliant or gnu compliant make.
I don't need a make, and neither should redo. My build system will not be like CMake in that it will generate build files for something else; it will execute them itself. No make necessary. In fact, I could implement a make easily with my build system; just a parser would be necessary.
> If you plan on making a build system, it has to take a lot of things and provide an abstraction layer over them to make them work for windows. I say forget it, it's a waste of effort, just make it work on linux and by extension (through WSL or mingw or whatever) you get windows.
I don't think it's a waste of effort. People on Windows deserve a good build system too. In fact, not having a good one means that they are dependent on Microsoft. I'd like to help them reduce that dependence.
> One of the best tests of a build system I've found has been to get a build system to build an executable and run it to produce an output which is then consumed as part of the build process. With pure make, this is purely awful and requires either generating a bunch of rules or lots of boilerplate, and generally it's easy to get wrong. With redo I got this working with relatively little work and got it to work with cross-builds.
It's not hard to get make to do that. See [1] and [2].
> In my adventures with redo, the biggest obstacle to hermetic builds that I've found aside from just the environment (env vars) has been compilers.
Yes, but however it's done, it's still easiest in a self-contained system, IMO.
> Surely a better build system would need some form of overhaul to the interfaces provided by compilers? (Or, some re-implementation of some compiler features so you can spoon-feed a compiler the exact flags to ensure it behaves predictably even if the environment changes.)
The build system should carefully control the environment. In fact, it should make sure the environment is empty. (There are details, but in general...) That's the biggest thing to make sure the compiler does not act weird.
You should also do the build in a separate directory and copy needed files into the directory. Then check all commands and their arguments for possible files before running them. This is one reason why depending on an outside shell is not ideal.
Hermetic builds won't ever be perfect, but you can make it 80% of the way with only a few things.
> TFA?
"The Famous Article". It refers to the link under discussion on HN. In this case, it refers to the apenwarr redo.
> Okay, so you mean dynamically generated .do files.
Not just that. Those were just an example of how dynamic dependencies are already awkward in redo. There are countless other uses for dynamic dependencies. To give you a taste, my build system will actually be able to build a distributed system, i.e., it will be able to be used for DevOps deployment, and it will be easy.
Surely redo can as well, but as I've thought about how to do that, it seems awkward. Perhaps you can prove me wrong?
> Why finnicky? In the usual case you DON'T want anything other than just timestamps and hashes, it works for all cases, albeit slowly for some. If you NEED to customize it, you have to pull out the special tools but then you just wrap that in some little utility and mostly forget about it.
Finicky because as far as I can tell, the build database in redo is modified by multiple commands over a build. This can cause problems should a problem occur with the database mid-build. In a self-contained system, the database is in-memory during the entire build and only written out to disk once the build is done, which can then be used as a sort of "commit" of the build, marking it as finished.
There are other reasons, but that's the first that comes to mind.
> What do YOU think are the obstacles to hermetic builds? I already know what I've found but I'm always looking for more input.
I think a good paper to read would be the Dolstra thesis on Nix. [3] If you consider Nix a build system (not just a package manager), it goes further than even Bazel. The thesis should be a good place to start.
[1]: https://git.yzena.com/gavin/bc/src/branch/master/Makefile.in...
[2]: https://git.yzena.com/gavin/bc/src/branch/master/configure.s...
Re: Redo: A recursive, general-purpose build system
#84Earlier quoted context omitted.
> I teach Bazel and help companies adopt it. The very fact that this occupation exists pushes me away from Bazel, having never used it. Makefiles are horrible, but they are well documented and I've been able to google my way out of every problem that I've either run into, inadvertently caused, or had to debug from somebody else's mess (it's always a mess). I don't actually want a better build tool. I want a tool that…
But that’s not really how it works. Build systems exist in a complex domain — whether we like it or not, that complexity can’t really be hidden away, it will leak one way or another.
That might be fine in an enterprise setting where the user likely has a mentor or support contract to turn to. But it's not what I want at home.
Re: Redo: A recursive, general-purpose build system
#85As an intensive (and reluctant) user of GNU Make, I keep looking for a more modern replacement. Redo is not it. Make is really a complicated combination of these components: - a dependency definition language with in-place evaluation and half-assed wildcards - A functional language with extremely limited datatypes (effectively just space-separated strings) - a clunky macro system - A "distributed" topological executi…
Gradle is a good make replacement as well. The kotlin DSL is much more readable and easier to follow than makefiles and has a lot of additional features.
Re: Redo: A recursive, general-purpose build system
#86Earlier quoted context omitted.
I have encountered Tup in the past and could not figure out how to define a "generator". As in: a function that defines how some output can be generated from a certain input running multiple commands. I don't want to copy those commands for every input I need to process. Edit: Generator is a term typically used in CMake and Meson for this, in Make I'd use a pattern rule mostly.
If you want to have a way to specify rules that use the same command, but still specify the rules manually, look up "!macros" in `man tup`. If the issue is that the commands need to write and read some temp files, then note that you can write temp files in a tup command (they need to be placed in $TMPDIR iirc). Note that the tup command can be calling a script that you place alongside, in case this makes specifying y…
The use-case at that time was to convert a LaTeX file containing a TIKZ image (therefore having a .tikz file extension) to an SVG which required compiling the LaTeX code to PDF, cropping the PDF and converting it to SVG. Since there were multiple occurrences of this across the project, I wanted to have that as a reusable "function" in the build system. I did not want to write a dedicated script for this because of portability issues (Shell vs. Batch).
Re: Redo: A recursive, general-purpose build system
#87Earlier quoted context omitted.
>make it easier to make it work on Windows from the start The problem with working on windows is that there's no shared standard (unless you count whatever irrelevant part of the POSIX spec that windows follows a shared standard). On windows there is no bash or posix shell, there is no gcc or a compiler which takes gcc-like options, there's no posix compliant or gnu compliant make. It's all just wrong. If you plan on…
> On windows there is no bash or posix shell Part of the language builtin to my build system provides ways of running commands without a shell. > there is no gcc or a compiler which takes gcc-like options, No, but there is MSVC. You just need to abstract the compiler and compiler flags. CMake did it, so why can't I? > there's no posix compliant or gnu compliant make. I don't need a make, and neither should redo. My b…
I didn't meant to imply that you or redo needs a make. Just that for something like autotools or cmake, there's a lot of abstraction required just to get things to work. Or you can bundle things or you can write your own things but the point is, it's a lot of work.
>I don't think it's a waste of effort. People on Windows deserve a good build system too. In fact, not having a good one means that they are dependent on Microsoft. I'd like to help them reduce that dependence.
Right, but as I point out, microsoft already took care of that by giving windows users WSL.
>It's not hard to get make to do that. See [1] and [2].
Yes I know what it takes, but if you don't think this is horrifically over-complicated then I don't know what to tell you. Instead of using implicit rules with target specific overrides you've made it slightly less boilerplaty by making it less scalable and expanding the entire build command for a specific target. I still think this is too much boilerplate and noise.
>Yes, but however it's done, it's still easiest in a self-contained system, IMO.
I think it may be easiest to implement (just like any complicated solution is easier to implement than a simple one) but I don't think it's a good goal for a build system. Complexity isn't free, even if it has a cheaper initial cost.
>The build system should carefully control the environment. In fact, it should make sure the environment is empty. (There are details, but in general...) That's the biggest thing to make sure the compiler does not act weird.
I disagree, you would also need to compile the compiler (because compilers like to take compile-time configuration). Moreover, you're going to have to have specific code for handling every different compiler with all its quirks, you're also going to have to spend a lot of time figuring out all the quirks. And you're going to have to spend a lot of time duplicating the code which implements those quirks.
Surely getting compilers to support some standard hermetic building facilities would be easier and better in the long run than maintaining a complex database of compiler quirks to handle for every specific compiler version etc?
> Hermetic builds won't ever be perfect, but you can make it 80% of the way with only a few things.
Yes but I can already get it 80% of the way with redo.
> Surely redo can as well, but as I've thought about how to do that, it seems awkward. Perhaps you can prove me wrong?
I'm still not sure we're both on the same page for what a "dynamic dependency" is but with redo I've solved the problem of having a dynamic .do file by simply depending on a dynamically generated .rc file: i.e a file containing sourcable shell variables (including bash arrays), generated using declare -p or things like the @Q parameter transformation.
>Finicky because as far as I can tell, the build database in redo is modified by multiple commands over a build. This can cause problems should a problem occur with the database mid-build. In a self-contained system, the database is in-memory during the entire build and only written out to disk once the build is done, which can then be used as a sort of "commit" of the build, marking it as finished.
There are no concurrency issues with the build database in any redo implementation worth it's salt and realistically there's nothing stopping a redo implementation from implementing its database the way you describe. It's also an implementation detail which I've never had to interact with. Not sure how that makes it finnicky.
> I think a good paper to read would be the Dolstra thesis on Nix. [3] If you consider Nix a build system (not just a package manager), it goes further than even Bazel. The thesis should be a good place to start.
From what I've seen, nix is too coarse grained for being a build system, which is where I've seen bezel recommended, but both of these fail to provide a general purpose build system which can be used outside a tightly controlled environment to build a piece of software hermetically using existing system dependencies. At the end of the day, I want to be able to build software with existing system dependencies provided by my package manager with the assurance that if I hit build, if those system dependencies have changed, the relevant parts of my code will be forced to rebuild and I will be told about it. I can see the value of totally hermetic builds, but a build system capable of solving the problem I describe should easily be extendable to solve the general problem of hermetic builds. In short, I want to be able to compile my code with my existing compiler, and if my compiler is updated, I want to be able to hit redo and have everything rebuilt correctly without worrying that something didn't get built.
Re: Redo: A recursive, general-purpose build system
#88Earlier quoted context omitted.
If you want to have a way to specify rules that use the same command, but still specify the rules manually, look up "!macros" in `man tup`. If the issue is that the commands need to write and read some temp files, then note that you can write temp files in a tup command (they need to be placed in $TMPDIR iirc). Note that the tup command can be calling a script that you place alongside, in case this makes specifying y…
Thanks, the `!macro` thing seems to be what I was looking for. Having intermediary temporary files is of course fine. The use-case at that time was to convert a LaTeX file containing a TIKZ image (therefore having a .tikz file extension) to an SVG which required compiling the LaTeX code to PDF, cropping the PDF and converting it to SVG. Since there were multiple occurrences of this across the project, I wanted to hav…
Re: Redo: A recursive, general-purpose build system
#89Earlier quoted context omitted.
> On windows there is no bash or posix shell Part of the language builtin to my build system provides ways of running commands without a shell. > there is no gcc or a compiler which takes gcc-like options, No, but there is MSVC. You just need to abstract the compiler and compiler flags. CMake did it, so why can't I? > there's no posix compliant or gnu compliant make. I don't need a make, and neither should redo. My b…
>I don't need a make, and neither should redo. I didn't meant to imply that you or redo needs a make. Just that for something like autotools or cmake, there's a lot of abstraction required just to get things to work. Or you can bundle things or you can write your own things but the point is, it's a lot of work. >I don't think it's a waste of effort. People on Windows deserve a good build system too. In fact, not havi…
I will say, though, that if you're not hearing about my build system in a few years, you can safely assume that you were right and that I was wrong.
Re: Redo: A recursive, general-purpose build system
#90Earlier quoted context omitted.
>I don't need a make, and neither should redo. I didn't meant to imply that you or redo needs a make. Just that for something like autotools or cmake, there's a lot of abstraction required just to get things to work. Or you can bundle things or you can write your own things but the point is, it's a lot of work. >I don't think it's a waste of effort. People on Windows deserve a good build system too. In fact, not havi…
At this point, it seems to me like you have already decided I am wrong, no matter what I say, and have no desire to accept what I say that is meant to help you. So I'll just leave the conversation where it is. I will say, though, that if you're not hearing about my build system in a few years, you can safely assume that you were right and that I was wrong.
It seems a bit defeatist to say this. Nobody on the internet, or the world for that matter, (unless they're agreeable and are just pretending to agree with you) is going to agree with you after the exchange of a few messages.
I should point out that I never disagreed with your fundamental claim that it would be easier to make a hermetic build system IF it's all encompassing and complicated. It's for example why systemd is easier to write if it's all tightly coupled versus if it was trying to have minimal coupling with minimal simple APIs and minimal simple tools building it up.
It's easier to write complex and tightly coupled software, it's why everyone does it instead of following the unix philosophy. I was simply pointing out that the unix philosophy was successful (for a while) for a reason, not because it was easy to follow it, but because the difficulty of making things simple paid off in the long run.
Please read what I wrote, I never made any hard claims about you being wrong, I've been mostly asking questions to get you to elaborate your stance. The sheer fact that I'm willing to entertain such long-form conversation should be enough proof of the fact that I haven't completely mentally dismissed your arguments as outright wrong.
> I will say, though, that if you're not hearing about my build system in a few years, you can safely assume that you were right and that I was wrong.
I don't think popularity (which is what you appear to be aiming for) is a good metric of the quality of software. Especially in the modern day and age where one of the most popular methods of shipping cross platform software is to ship it with its own instance of chromium and to write it as a local webapp. I think this is at least because modern day humans have become a lot more impatient and a lot more focused on short term convenience over long term benefits. But this discussion is outside of the scope.