News for hackers. Stuff that matters.
Re:Using Make – writing less Makefile by masspro on Tuesday December 26, 2023 @04:18PM (#38776164)
Quasi-tangent: I was once hit by a coworker doing first code review on a new repo with "hmm...I'm not familiar with using Makefiles as a project management tool. So something something [don't remember] we should replace that." It struck me as weird because I don't see `make` as a build tool so much as automating shell script snippets you would/could type at the command line. From that POV I conceptually see Makefiles as like a `bin/` folder full of little scripts, honestly the main advantage for me being every command runs with working dir being where the Makefile is; no need to write a `set -euo pipefail; HERE="$(dirname "$0")"` dingleberry at the top of every hypothetical `bin/` script. And having incremental rebuild is sugar on top when it's possible to write :)

I don't see `make` as a build tool because I believe from experience that is where the road to hell begins. But it is convenient to have `make` call CMake/Cargo/pip/whatever. Plain `make` can build, `make test` can test, `make fmt` can auto-format... Even better if you alias `m` to `make` in your shell.

Re:Using Make – writing less Makefile by gregwebs on Tuesday December 26, 2023 @04:30PM (#38776271)
Your coworker's experience is more principled: Make is a mediocre tool for executing commands. It wasn't ever designed for that. Although it is pretty common to see what you are mentioning in projects because it doesn't require installing a dependency.

For a repo where an easy to install (single binary) dependency is a non-issue, consider using just. [1] You get `just -l` where you can see all the command available, the ability to use different languages, and overall simpler command writing.

[1] https://github.com/casey/just

Re:Using Make – writing less Makefile by hathawsh on Tuesday December 26, 2023 @05:23PM (#38776748)
With all due respect, I don't understand the first part of your comment. Make's core purpose is to execute commands, isn't it? How was it not designed to execute commands?
Re:Using Make – writing less Makefile by nine_k on Tuesday December 26, 2023 @05:40PM (#38776884)
No, no. Make's principal purpose is to put a set of files into a desired state. It can "make" a particular file by invoking a dependent graph of commands that produce that file from other files. It checks timestamps and only run steps where the resulting files are older than some of the (transitive) source files.

You can invoke it by naming a named rule, not a file, but the logic will remain.

If this is not what you want to be doing, and if your Makefile is full of .PHONY targets, you likely need a Justfile instead, or (worse) plain shell scripts.

Re:Using Make – writing less Makefile by KajMagnus on Tuesday December 26, 2023 @06:11PM (#38777090)
I also don't like Make for running commands.

I was using Make for running commands, but it interprets all command line parameters as build targets, which was annoying. And Bash scripts in Makefiles aren't type safe, became messy.

Nowadays I use Make only for building. And Deno + Typescript instead, for running commands & scripts.

(Hadn't heard about Just — the scrips aren't type safe though?)

Re:Using Make – writing less Makefile by maleldil on Tuesday December 26, 2023 @07:14PM (#38777538)
> Hadn't heard about Just — the scrips aren't type safe though?

Just runs code written in other languages. It's `sh` by default, but you can define anything (e.g. `python3 -c` to run Python scripts).

Re:Using Make – writing less Makefile by gregwebs on Wednesday December 27, 2023 @10:33AM (#38782940)
depends on how you define type-safe. Even in TypeScript you are still executing strings when running commands. You can turn those strings into variables and share them as a form of type safety- the type check will fail if you mis-type the variable name. Just supports that- you will get an error if a variable that is being inserted doesn't actually exist. The error will occur at startup before usage or can be checked ahead of time with just --check --fmt. So for quick usage there's not much benefit to TS, but over time in TS you could build up type safe interfaces to commands and obviously if you want to run TS scripts instead of shell scripts that's going to have more opportunities for strong typing then invoking TS from just.
Re:Using Make – writing less Makefile by BeetleB on Tuesday December 26, 2023 @09:11PM (#38778324)
I tell people not to use make if there's no need for a dependency graph.

Just don't.

And do just :-)

Re:Using Make – writing less Makefile by twaw on Wednesday December 27, 2023 @01:14AM (#38779545)
Yeah, use make -j8 instead.
Re:Using Make – writing less Makefile by alwillis on Tuesday December 26, 2023 @05:54PM (#38776988)
> Make's core purpose is to execute commands, isn't it? How was it not designed to execute commands?

Some people on HN believe that if you use make primarily as a task runner that you're doing it wrong and should use something else. I don't agree.

Most users are using multiple aspects of make: as a task runner and as something that handles the dependency graph when building something digital.

As a web developer, I used npm scripts, grunt, gulp, etc. to manage web builds but now I only use make and have gotten off the merry-go-round of web build tools.

Re:Using Make – writing less Makefile by TheSoftwareGuy on Tuesday December 26, 2023 @09:03PM (#38778286)
What’s the point of using another tool to manage your shell scripts though? Why not just use shell scripts
Re:Using Make – writing less Makefile by alwillis on Wednesday December 27, 2023 @01:11AM (#38779535)
> What’s the point of using another tool to manage your shell scripts though? Why not just use shell scripts.

When you create a Makefile, you're describing a dependency graph of what depends on what and the order tasks need to take to produce a particular set of digital artifacts--you're not writing shell scripts.

Turns out there are all kinds of edge cases and foot guns that make handles for you that you'd otherwise have to deal with if you wrote a bespoke shell script.

Plus make is battle tested and has been around since the dawn of Unix--there's literally no build scenario it can't handle.

I hadn't used make until a few years ago but it's been one of the best investments I've made in my workflow.

Re:Using Make – writing less Makefile by jcelerier on Wednesday December 27, 2023 @07:04AM (#38781180)
> there's literally no build scenario it can't handle.

Well except this little case where some files or folders in your paths have spaces in them...

Re:Using Make – writing less Makefile by Izkata on Wednesday December 27, 2023 @03:57AM (#38780261)
Makefiles coordinate your shell scripts, using a dependency tree you'd have to reimplement if you did it purely with shell scripts.

For example:

A) You have a recipe that installs dependencies if they're not up-to-date (such as "pip install").

B) You have a recipe that compiles stuff if it's not up-to-date; it's made to depend on A.

C) "make" can be an interface recipe that depends on B and does nothing else.

D) "make test" can be an interface recipe that depends on B, then runs tests.

E) "make run" can be an interface recipe that depends on B, then actually runs the code / a webserver to interact with.

Nowadays whenever I put one of these together there's 2 versions of A (one for python, one for node), 1+ versions of B (webpack build without watch, maybe others depending on the project), 3 versions of D ("test-js", "test-python", and "test" that does both, and each of them only requires the relevant parts of A and B).

Makes it trivial to ensure you're up-to-date after a "git pull" without having to waste time waiting on things that don't need updating.

Re:Using Make – writing less Makefile by alwillis on Tuesday December 26, 2023 @06:34PM (#38777252)
Out of the box with no configuration, Fish shell provides target completions for a Makefile in the current directory [1].

[1]: https://fishshell.com/docs/current/interactive.html

Re:Using Make – writing less Makefile by sime2009 on Tuesday December 26, 2023 @05:14PM (#38776670)
A similar tool is `task` https://taskfile.dev/ . It is quite capable and also a single executable. I've grown to quite like it.
Re:Using Make – writing less Makefile by wirrbel on Tuesday December 26, 2023 @05:54PM (#38776991)
I prefer task over just, while I am not a huge fan of YAML, we now use it everywhere so it just makes sense to not learn yet another DSL for Just and just use YAML.
Re:Using Make – writing less Makefile by bravura on Tuesday December 26, 2023 @05:58PM (#38777020)
How do task and just compare to SCons?

Although SCons is Python (which is a pro or con depending upon your perspective), it has strong dependency management. Or is the argument that dependency management is part of build, not general project maintenance?

Re:Using Make – writing less Makefile by wirrbel on Tuesday December 26, 2023 @06:34PM (#38777256)
Starting out from the blog post, it talks essentially about Make as it was intended, as a build system to compile programs with. Make maps this to the task of producing a file from input files, which are written down in the form of rules in a Makefile. a key ingredient from make is that it checks for timestamps on disk for the source files and updates targets only if the source files have been modified after the targets have been built.

If you go a bit further down this route, you end up with build tools that generate the compilation rules for you in some form: These are Automake/CMake/Meson and SCons. I did use scons years ago and it was nice, but its definitely completely lost its market share. IIRC Scons does this without generating Makefiles.

Task and Just are following a different route. The problem people have solved by using a "hack" in Makefiles (PHONY targets), so that you can easily run "sub-commands" in Make (make install_deps, etc). It would never occur to me to use Scons in that space.

Btw. a third option is to use a shell script like the following (POSIX-shell compatible actually).

  sub_install_deps() {
   set -e -x
   # ...
  }

  sc=$1
  case $sc in
  "" | "-h" | "--help")
   sub_help
   ;;
  *)
   shift
   "sub_${sc}" "$@"
   if [ $? = 127 ]; then
    echo "Error: '${sc}' is not a known sc." >&2
    echo "       Run '${prog_name} --help' for a list of known scs." >&2
    exit 1
   fi
   ;;
  esac
Re:Using Make – writing less Makefile by MrOxiMoron on Tuesday December 26, 2023 @04:33PM (#38776302)
just is great, I add it everywhere, just test, just run, just fix, just shell. just works ;-)
Re:Using Make – writing less Makefile by mort96 on Tuesday December 26, 2023 @05:45PM (#38776916)
Honestly Make is a pretty decent tool for executing shell snippets plus some lacklustre dependency resolution stuff on top.
Re:Using Make – writing less Makefile by masspro on Tuesday December 26, 2023 @04:40PM (#38776370)
This looks really nice. But then should `j` alias to `just` or to `jobs`? Non-starter. /s
Re:Using Make – writing less Makefile by hathawsh on Tuesday December 26, 2023 @05:15PM (#38776689)
I really like GNU Make because it has a hidden superpower: the "-j" parameter enables instant, easy parallelization. I have a project with many subprojects and I use "-j16" to invoke the same command in all of the subprojects, 16 at a time. It saves a lot of time and it works for all commands that don't touch other subprojects.

Like you, I use Make as a front end to lower level build tools. It seems to fit that role well.

Re:Using Make – writing less Makefile by maccard on Tuesday December 26, 2023 @08:05PM (#38777892)
I think this is a great example of tools being stuck in the 90's, actually. Make should be parallel by default.

I get it, I do. I know there's all sorts of legacy reasons, but my 4k resolution screen with 12GB vram and 32 cores still runs make build serially, outpitx to an 80x24 window and is bottlenecked down by stdout flushing, all because we can't change defaults.

Re:Using Make – writing less Makefile by stouset on Tuesday December 26, 2023 @08:13PM (#38777953)
And annoyingly, I don’t think there’s a way to tell `make` that a particular `Makefile` should be built with multiple threads by default. So you have to specify `-j` every time.
Re:Using Make – writing less Makefile by maccard on Wednesday December 27, 2023 @12:14PM (#38784067)
Yep. If it was opt-in in a per-makefile way, it would be ok (or preferably opt-out).

I think cmake got this absolutely right, fwiw. You define the version of cmake you're writing against, and they go to great pains to ensure that they preserve behaviour even in newer versions of cmake. As an example, we could have a special variable:

    make_ver = 4.5
And even running with a future version of make the behaviour would be that of 4.5. if it's not present, it defaults to the latest version before the versions were introduced.

This would let make do things like accept spaces instead of tabs, be parallel by default, etc in future versions while presenting old behaviour.

Re:Using Make – writing less Makefile by ttyprintk on Tuesday December 26, 2023 @06:24PM (#38777177)
‘-j -l $MAXLOAD’ is even more polite on shared systems. Avoids most runaways, but not all.
Re:Using Make – writing less Makefile by t43562 on Tuesday December 26, 2023 @05:18PM (#38776713)
Make is declarative - that's roughly the point of it. You give it rules and dependencies and variables and it's supposed to work out what to do.

If your build is extremely simple and fast then it cannot add value.