A properly hand-tailored Makefile is a thing of beauty, and it is not difficult.
A properly hand-tailored Makefile is a thing of beauty, and it is not difficult.
I'll write Makefiles by hand for small C/C++ projects, but for anything serious I'll use cmake/etc.
Source: We made a "properly hand-tailored Makefile" for Rust. It started out short and elegant, but it quickly grew into a nightmare lasting 4 or 5 long years. Only about one or two people (Alex Crichton and Brian Anderson IIRC) had any clue how it operated. Proper cross-compiling support involved multiple levels of nested variable expansion all over the place to find the right build/host/target compilers so that Canadian cross builds worked. Alex ended up doing some heroic effort to throw away all the Makefiles and going to (effectively) a custom build system using Cargo, which was a massive simplification.
Then again, as a ROS user, I'm also a defacto CMake expert, so perhaps I underestimate how difficult CMake is.
I only came into KDE when the switch to CMake had already happened, and remember it as reasonably approachable (even if quirky). Most developers were familiar with it and actively authoring the CMakeLists.txt files for their own projects. (That doesn't mean that there weren't some experts again, but they focused on implementing reusable modules that the others could easily integrate into their own build system.)
my_function("${MY_VAR}")
Avoid the quotes if your variable contains spaces or other separators, and it's your intention for the separate pieces to go into the function or macro independently.The other case is builtin macros that expect to be passed the name of a variable that they themselves are manipulating. For example the list and string operations. See: https://cmake.org/cmake/help/v3.0/command/list.html
Most hand-tailored Makefiles have seen aside from well known OSS projects (Linux Kernel, suckless stuff) generally had major issues.
Here is a sample of what I've seen:
* not supporting common variables, specially DESTDIR in install target, but also PREFIX, BINDIR, etc, or CC and CFLAGS for compilation. (https://www.gnu.org/prep/standards/html_node/Directory-Varia...)
* bad ordering, at least preventing parallel build (-j N)
* bad error handling which result in silent failures, I've seen it in Makefiles using for/while loops, if/then/else, or successions of commands (cmd1;cmd2) inside targets for example.
Makefiles are also a little too crude for somewhat complex projects. Doing things like searching header pathes, detecting which OS you're on, what is the CPU endianness, searching the required dependencies and recovering information such as version about said dependencies would be extremely painful to do with only plain Makefile.
CMake contains a lot of ready to use modules to tackle the most common issues, and you can easily write your own modules if you need to.
Aside from very simple project, I would not recommend using plain Makefiles, there are just to easy to do wrong.
https://github.com/devkitPro/nds-examples
They're very clearly hand made, do just enough to be immensely useful, and are well commented enough to be easy to modify for a Make beginner, just like I was back in the day. I'm sure there are other great examples floating around the 'net, but I cut my teeth on GBA and NDS development, and taught myself make by following in their footsteps.
...but scaling from the small to the large elegantly is what make doesn't do well; and there's an astonishing number of tools designed to try to work around the problem.
A lot of people hate CMake for its strange language and (arguably) questionable design choices; but it scales to large projects without significant problems; you only have to look as far as the android native client makefiles to see how the truely heroic efforts to use make have resulted in makefiles that are only... moderately terrible, instead of absolutely aweful.
I feel like there's this nostalgic desire from many programmers to 'embrace simplicity' and avoid the complexity and annoyance of learning and using complex 3rd party tools when 'simple' solutions are good enough.
...but often those simple solutions are ever any good at a trivial scale.
Meson seems to be the latest fashion in Linux circles, it seems...
You are trying to solve a Turing complete problem in a simplest low impact way as possible.
There is no good solution. Everyone will fall short in one way or another. Hence a new build system. The wheel never stops.
Most build tools do have some kind of Turing-complete tooling built in with their DSL. But I don't think that's an absolute necessity.
These symbols are artifacts/files. Elementary recursive Build-Scripts can be Turing complete even if the overall language isn't.
I've seen failures of such schemes to rebuild stuff when command line parameters (defines, environment) changed.
It also brings all sorts of trouble in parallel builds as Make is weak at handling dependencies that are not generated in the exact Makefile you run. (Thus non-recursive Makefile which still fail and have other warts.)
Even cmake and autoconf generated Makefile have trouble with complex projects. (Part of the reason why cmake can now generate Ninja files instead.)
Recursive Make Considered Harmful
I have a recursive-make project at the moment that suffers from none of the problems described in the paper. We will likely move to an include-based scheme before long, which will take some minor tweaking of targets in the leaf Makefiles.
Also - Considered harmful essays considered harmful - http://meyerweb.com/eric/comment/chech.html