Live data from Hacker News

Using Make – writing less Makefile

text.causal.agency

91–100 of 200 posts

Re: Using Make – writing less Makefile

#91

Earlier quoted context omitted.

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,…

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?

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

#92
I honestly wish that make's default rules were available to import and view the source of, but we're disabled by default.

Then a beginner could see what happens in a straightforward way, and then import the C rules. And we could all stop importing the VCS rules which aren't useful anymore.

Re: Using Make – writing less Makefile

#94
post #51

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…

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,…

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

#95
post #59

Earlier quoted context omitted.

Discovering the dependencies depends on the compilers, not on the platform. I have stopped using MSVC many years ago, so I do not know how it handles dependencies, but with gcc or clang that works regardless of platform, with compiler-specific options. Moreover, software for one platform can be built on another platform. What matters is only the platform used for building, where the compilers are hosted, not the targ…

I should rephrase, by dependencies I mean third party dependencies. That is on the build system not the compiler. And make tends to fall significantly behind Ninja in my experience for cold builds. Here’s a post from someone else that echoes my experience https://david.rothlis.net/ninja-benchmark/ but for a sufficiently complex project even a well tuned make build is about 20% slower on CI, which is about 10-20m per…

The link provided by you shows correctly that Ninja is indeed faster in the cases when almost nothing is recompiled, so the command execution time is dominated by the dependency evaluation time, which is faster in Ninja.

However, the same link shows that even for relatively large projects the time difference is less than a second, which matches my experience.

Ninja requires much more effort for using, as it is not a complete build system, but just the execution component, and except for projects of chrome size that effort is not worthwhile for a subsecond gain in certain scenarios.

I cannot imagine how a "tuned" make build can be 20% slower, except when the project is not really tuned, but it is badly organized. A "tuned" Makefile means that the execution time for "make" is negligible in comparison with the execution times of the compilers and linkers. The time spent in "make" should be measured in seconds an most, never in minutes.

Only a very slow file system can cause "make" to be much slower than Ninja, because the dependencies for "make" are stored in many ".d" files, equal in number with the source files. On modern SSDs or RAM disks, that is never a problem.

Perhaps you are right about CMake. I cannot be certain whether CMake is good or bad, because I have never created a CMake project myself, I have only built CMake projects created by others. Nevertheless, there certainly is a problem with the CMake users that I have not seen yet one that can explain which are the advantages of CMake. All the tutorials that I have ever seen about CMake were showing how to do in a complex way things that can be done in a simple way with GNU make, so I never had any reason to investigate any further.

What I know for sure is that much fewer understand how to use CMake than how to use make, because the frequency of bugs in CMake projects is much greater.

I would like to see how CMake can provide minimal work. With GNU make, creating a new very simple project needs only copying a template Makefile in the source directory. For a more typical software project, the template Makefile must be edited to add a list of directories, those that must be searched for source files (I actually write the list as a prefix directory plus a list of subdirectories for it, as that is how I normally structure the projects).

For external dependencies, up to 3 lists may be added, of libraries, include directories and perhaps of library directories, which should suffice.

That is all. Nothing more. I normally build each target file of a project, e.g. executable or library, in a separate subdirectory of the build directory, so by default it is not necessary to write it in the Makefile, because the name of the subdirectory will be used for the target. The root of the build directory contains a Makefile that I never change and which descends in each subdirectory to build its target.

How can be CMake more simple to use than this? All CMake projects that I have ever seen were much more complicated and they were very difficult to modify, with a very large number of project-specific details that have no place in the project configuration files, because the building system should be able to deduce them.

All the examples of using CMake that I have ever seen have demonstrated a tool with a much lower level of abstraction than GNU make and which is tedious to use.

GNU make does not need any such thing like the CMakeLists that are ubiquitous with CMake.

Re: Using Make – writing less Makefile

#96

Earlier quoted context omitted.

Globbing is possible but unwise. You do want a variable with an explicit list of sources, even while trying to make things as automatic and dynamic as possible.

Why would you want that? In decades of programming in very varied environments I have never compiled any software project otherwise than by using globbing, so that I have never needed to waste time to write the name of any source file in a Makefile. I have never seen any reason to do otherwise. For instance, using special compilation flags for a certain source file, different from the others, is something that I cons…

[deleted]

Re: Using Make – writing less Makefile

#97

I say this as someone with 20+ years of experience in C and C++: Using make is a huge waste of time in 2023 (and forward). Learning the intricacies of make actively blocks you from Getting Things Done. Yeah, make is kind of neat because it has this functional what_I_want : how_to_get_it syntax, but it doesn't actually work that way. It's a huge waste of time to try to get it working so unless you meet the following c…

Lost me at "making past from scratch".

In some sense, don't we all make the past from scratch? [stares into middle distance]

Re: Using Make – writing less Makefile

#98
post #8

With gnu make you don't even need OBJs for a simple directory in which all the .c files are compiled: .SECONDEXPANSION foo: $$(patsubst %.c,%.o,$$(wildcard *.c)) $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ Admittedly you can end up with short, very general Makefiles that look like they were a Prolog program written in TECO. But the advantage is that they are general so don't need to be fiddled with as your project grows. I m…

I admittedly don't have a ton of experience with make, but what's the point of doing this vs just throwing the compile commands in a shell script?

Make is declarative. You tell it how to make an A from a B and a B from a C or a D and it then works out that it needs to do "CBA" or "DBA" depending on whether it finds a D or a C in the filesystem.

The more possible variations you have to cater for the worse build scripts get.

If you try not to redo work that you did 5 minutes ago that's still valid then build scripts become even more complicated whereas the makefile doesn't change at all.

Other tools do declarative even more than make does but as they get easier to understand they tend to lose abilities.

Re: Using Make – writing less Makefile

#99

Earlier quoted context omitted.

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,…

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?

> 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

#100

Earlier quoted context omitted.

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,…

A similar tool is `task` https://taskfile.dev/ . It is quite capable and also a single executable. I've grown to quite like it.

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.
Post reply on HN