Make is great, and I wish more people would use it in place of whatever monstrosity is en vogue this week.
However, there is one thing which Make absolutely cannot handle, and that is file names with spaces. If you have any risk of encountering these without any possibility of renaming them, you’ll sadly have to give up on using Make; it just won’t work.
Spaces in filenames break most of make's builtin functions such as $(sort), and break the $?, $^ and $+ automatic variables. But they're OK in target names as long as you escape the spaces with backslashes. In some cases you can also use them in source file names -- you have to hard code the names in the build rules since $^ won't work (but for targets built from a single source file, $< still does work).
This applies to GNU make; not sure about AT&T make.
Make is my default. However, as the project grows, I find myself wanting to organize modules by directory and I find it cleaner to switch to CMake which then generates the Makefiles for me.
Just off the top of my head, it could be object oriented (rules could be subclassed), the language could have more sophisticated statements, it could have debugging, etc
Why is old bad? I can't tell you how often one of my team shows me some clever, non-trivial Python script that I solve in a couple of lines of awk/sed/perl. Or a small makefile. Why in the world would I want an OOP make? What do I need 'more sophisticated' in make statements that wouldn't really mean that I needed to be using a different tool that undoubtedly wasn't solving the problem make solves?
> I can't tell you how often one of my team shows me some clever, non-trivial Python script that I solve in a couple of lines of awk/sed/perl
I see you have decades of experience with those tools (awk/sed/perl), so they are second nature to you. I can sortof help my way through them but I find them very cryptic and hacky. The information density is very high, lots of implicit things happening, many abbreviations and symbols. It tenses my mind up.
It heavily depends on what you "grew up" on. I've been using Python for about 15 years now and when I switch to Python, I can feel the freedom to express things in a straightforward way without worrying about edge cases or cryptic syntax. Line by line it just does what it says, in English words. A few lines of list comprehensions .split(), sum() etc. can do a lot while still being crystal clear. In so many cases I've had some issue with Bash / Unix tools, looked on StackOverflow, found high activity questions with many answers that boil down "well, it's not really possible in a simple way" and then some hacky workaround that nobody would understand later unless I link to the SO page as a comment.
Now sure, sed, grep, awk etc. all have their uses, but for me that ends at about 100-150 characters or perhaps a bit longer ones for one-off use. Anything longer or for permanent use, I find it clearer to write it out explicitly in Python. After this, suddenly lots of powerful ways of extending it open up, which would be horribly cryptic and convoluted with the Unix tools.
I get it. And I don't disagree, per se. I confess to writing way too many baroque shell scripts that should have been Python or some such, and a couple of mission-critical awk scripts that were way longer and outside the appropriate use case than they should have been. You can really go down a rabbit hole there.
But haters (kidding) should really understand what they can do with a couple of hundred characters of sed, awk, perl, etc. before they discount them. And if it's "not really possible in a simple way", that's pretty much a good indication that they need to do it in Python, Ruby, etc. It's not either-or, black-or-white.
I wish it had a little python in it. After using pathnames in awk/sed/perl I find using os.path in python gets rid of all the special cases due to quoting and escaping. Python has nice lists and dicts and sets too.
For OO, I wish rules were a bit like python classes.
It would be wonderful for say 10 c files compiling one way, and the 11th having a different option. Or overriding a few options everywhere for the debug build.
I also think if rules had some sort of class, maybe the nuts and bolts underneath could be changed. You could be explicit about some things that are very hard with make. For example, what if you could write your own custom "out-of-date" check. Instead of "result must be newer that dependencies", maybe you could do something with checksums or source control or something and say "ok, don't rebuild this, or here is the cached result"
The pathname thing doesn't bother me probably because the quoting and escaping is muscle memory after 30 years, but fair point and an easy source of sometime hard to find mistakes.
The 11th file thing as pointed out below can be worked around easily, but yeah mixing implicit and explicit rules isn't 'elegant'. Dunno know if 'subclassing' the rule or whatever is the answer; maybe if there's a lot of exceptions. Interesting to think about.
I think the answer to your last example is one of 1) 'Unix philosophy' the problem by invoking separate scripts/tools to set things up for what 'make' expects so you get the result you want ("if the checksum of the source file changes, 'touch' it to make sure it gets rebuilt" or something) or 2) maybe 'make' isn't the right tool, because it's definitely not always the right tool.
Because that's really the key: right tool, and 'it's old' by itself is rarely the reason not to use a tool.
Yeah, I wasn't specific here. Tabs and spaces in Make are different specific things. I also like Python's significant whitespace.
It's easy to mess up whitespace in Make and it might not complain about it. Mixed whitespace in Python will either work without problem, or it will tell you when it doesn't.
I agree, and the solution to this problem is to forbid filenames with spaces. The convenience of make and similar tools is much more important than spaces in filenames. File names with spaces should not be allowed in modern filesystems. When the user types a filename with spaces, the GUI should encode the space as a non-breaking space character, that does not cause havoc in scripts.
Filenames in most Unix derivatives is an arbitrary bag of bytes only excluding '/' and '\0', they don't even have to have a valid encoding. If you can handle that spaces are the least of your concerns. Tools should be able to handle them by now, one would think.
The human friendly name should really be metadata on the file anyway. Regular users don't need to deal with raw filesystem internals, we can just say that filenames are identifiers that are always lower case, in the C locale, encoded as utf8 or 16. Any whitespace is not allowed.
Yeah, I know it's not always intentional, and I understand the need to be able to distinguish between such files. It's just annoying that there isn't a better solution than "all filesystems, forever, must support a problematic use case that serves no good purpose". To be clear, naive solutions would likely be a slippery slope w/ worse side effects. So, on a certain level I feel obliged to apologize for complaining given I can't think of what a solution I'd prefer might look like.
A way around that is to convert any spaces in a filename to non-breaking spaces (if you can). That will not only fix problems in Make, but also ease use in the command line.
For very low values of "ease use", in my opinion. Spaces in filenames are a bad idea; non-breaking spaces would be an anti-pattern or an attack, in my opinion.
How do you portably type a non-breaking space, if you don't have tab-completion?
However, there is one thing which Make absolutely cannot handle, and that is file names with spaces. If you have any risk of encountering these without any possibility of renaming them, you’ll sadly have to give up on using Make; it just won’t work.