I use Nix and make(1) to develop
glorifiedgluer.com
glorifiedgluer.com
This means that we lose the non-Nix build processes, but I get to keep the best of both worlds, and don't have to run `nix shell` or setup direnv.
"Uhm, actually" I use Guix, but the idea is the same:
SHELL = guix shell -m manifest.scm -- bash
public: hugo content
emacs $(pwd) --batch -l export.el
[...]
Or without an external manifest: SHELL = guix shell --pure bash coreutils emacs emacs-ox-hugo hugo -- bash
This is equivalent to the common shebang trick: #!/use/bin/env -S guix shell -m manifest.scm -- bash
Or just invoking Guix inside the recipe: public: hugo content
guix shell -m manifest.scm -- emacs $(pwd) --batch -l export.el
Depending on the complexity of `export.el` (< 5 lines?), I'll often keep that inside the Makefile too; the less files, the better!But I get it if one wants that file available to call from elsewhere.
And there you have it: the fundamental problem. What if I want to port your package to Nix?
In practice, I'm sure it's doable, but you are introducing a lot of overhead and complexity by putting that work into that place.
Rather than maintaining documentation that inevitably gets out of date, if a project has a Makefile, it self documents the build process, language independently. No need to read a README to see if people are currently using yarn or npm, or find external documentation on a build tool you haven't used before; the Makefile shows the targets and what commands they run.
Besides, I would guess that every JavaScript developer when jumping on the new project will know how to use npm, just like every Java developer would know enough maven, and adding some supposedly general standard tool on top of already standard tools in that area wouldn't help.
Many only know Gradle.
True, but maybe 1% knows make. And since many of them run Windows, many don't even know how to install the correct version of make on their development box.
Still those ci/cd configs should always be very thin wrappers (single command for single thing) around whatever script tooling is used internally.
They're not that hard to understand and follow.
I had a makefile a while ago that would incrementally build docker containers based on containers metadata (for the dockerfile content hash) and would update those changed automatically, and it took like 2 minutes, instead of complaining while waiting, it's crazy how much simplicity is just ignored
Not arguing makefile has value but I worked on legacy projects with makefiles that break in mysterious ways and in those cases I would take the same stuff with hows and whys spelled out in plain English instead!
I think the main/only reason to go out of your way to use `make` as a task runner is its ubiquity.
However, if you're already using nix, it's probably not much of an issue to use a better task runner.
I'd recommend 'just' instead https://github.com/casey/just -- It has a nicer UX, with a few significant quality-of-life improvements out-of-the-box compared to `make`. e.g.
- you can get a list of tasks, and select one using `fzf` with `just --choose`.
- can inline use of bash, or python, etc.
- `just` automatically searches up a directory tree for a `justfile`.
It feels akin to handling HTML as a long string and fumbling around in it, as was done in the past in many PHP projects, instead of handling HTML as structured data, an XML tree or similar.
NPM package.json scripts is a Makefile for the very poor. Yes it can be used like that. Should it? When commands start to have prerequisites probably not.
You still don't get to define output files as dependencies, so it's not quite Make, but it's really not that bad if your project is already node/js/ts
In fairness, that's a pretty big reason.
For personal projects like "how I generate my static site", and where you're already using a tool like nix, 'tool already installed' isn't worth going out of your way for.
https://www.samlogic.net/articles/program-files-folder-diffe...
It claims we have localised names in Swedish. I have literally never found a computer that have those. They're always named in English.
It's only a bad idea because of assumptions programmers make about file paths not containing spaces that they then build into their code and cause problems.
The Mac (and user-friendly file names that contain things like spaces) has been around since 1984. Why has it taken this long to just accept that file paths might contain spaces? Is it just because (essentially) Bash is a huge pain about quoting?
It's about the user aesthetics, not the ease of the coder.
I'd much prefer if the space was encoded somehow like with URL encoding, or just make underscore and space interchangeable.
Hear, hear! I would love a mount option that disallows them for good (or replaces them transparently by nbsp U+00A0).
Do people also want variable names with spaces in their programs? Filenames are variable names, and the file contents are the data that the variable refers to. Allowing spaces in variable names is just brain damage.
I'd also argue it makes your code overall less volatile. If you ever wanted to build your code outside of Nix for whatever reason (such as migrating to another reproducible packaging tool), having everything in unopinionated `make` is a whole lot easier. Plus, it leverages the advantages of a tool that is dedicated to building code.
./configure
make all
Will actually have a good chance of working, which is not something my makefiles can live up to!
That said it all makes it easier to just use config for make that can be edited. For example config.mk included by Makefile. I learned this trick from Suckless.
Has anyone compared these two approaches?
With Nix, if it built once, it will build again, consistently and deterministically. It reduces fear of changing things because it just works. You don't have to cross your fingers and hope the build succeeds this time.
If Dockerfiles were guaranteed to succeed, and Docker hosted a cache of hashed binaries instead of a cache of Docker images (the former is far more efficient than the latter, btw), then all you'd need are Dockerfiles.
Enter Nix (and its flake.nix/flake.lock files).
Nix essentially solves a problem that Docker can't by treating a build as an immutable function with binary-hashed inputs and binary-hashed dependencies and completely controlled environment variables (with a few exceptions and special cases)
It also builds your environment on demand rather than having to manage the two step thing of building the image and then making sure you're using the right one.
I've found this much more flexible and convenient than anything with docker.