Hacker News new | past | comments | ask | show | jobs | submit login

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.


Make is useful and the concept is sound.

However, the implementation is dated.

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?

OK...debugging could be better. Got me there.


> 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.

But


I've used make extensively.

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"


> I wish it had a little python in it.

GNU Make can have Scheme in it:

https://www.gnu.org/software/make/manual/make.html#Guile-Int...


> It would be wonderful for say 10 c files compiling one way, and the 11th having a different option.

You can do this by combining implicit and explicit rules:

  target: $(OBJ)
  
  # default rule
  %.o: %.c
      cc -o $@ $^
  
  # special case
  special.o: special.c
      specialc -o $@ $^


Another way, with target-specific variables (might be a GNUism):

    special.o: CFLAGS += -Wno-blah
    
    %.o: %.c
     echo $(CC) $(CFLAGS) -o $@ $<


OK...I can see where you're coming from.

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.


It could have non-significant whitespace.


That would be great, but significant whitespace doesn't seem to stop all the Python users out there.


I will say I like how python uses whitespace syntactically. The whitespace is consistent, makes programs readable and much more compact.

make seems to be less consistent. I think it distinguishes between a space and a tab, which isn't clear without editor help.


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.

Make's whitespace is unnecessarily clever.


This ("the conceptual model is sound but the implementation could be improved") is pretty much the basis for build2: https://build2.org/build2/doc/build2-build-system-manual.xht...


File names with spaces is a sign of lousy developers and IT technicians. If you have file names with spaces you have already lost.


Bwahahahahahaha! Good one!


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.


> the GUI should encode the space as a non-breaking space character

At this rate, why can't the tool itself escape the spaces from the filenames into non-breaking-spaces before processing?


Ambiguity. Two file names with the single difference that one has a breaking space and another a non- breaking space.


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.


You're over 20 years too late to propose this.


We can move gradually towards this, not that there's anything lost besides a lot of time writing absurd quotes so that your script "supports spaces"


I can't tell if you are being sarcastic.


i am dead serious about that. Allowing the separator character in filenames is a nightmarish error.


Only for tools that are stupid for not being able to handle any kind of filename.


Yes, like filenames with multiple dots, for example.

I agree that filesystems must allow almost arbitrary filenames. But some characters should definitely be forbidden, like '/', '\n' and ' '.


The vast majority of users never even see the command line - why should they be dealing with the limitations imposed by it?


These users would never notice if their filenames are encoded using one type of space or the other inside the filesystem. That's a win-win!


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.


my point exactly!


And are we gonna talk about case-insensitive filesystems?

cringe


The thing I cringe at is the notion that it is ever helpful to manage files with names that differ only in case. Who does this? Why?


It's not always intentional. Make itself, for example, allows Makefile and makefile. What if you've got both in a project you unpack on OSX. Uhoh.

https://www.gnu.org/software/make/manual/html_node/Makefile-...


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.


I can't imagine why. I run make on case-insensitive-but-case-preserving HFS+ and APFS-formatted disks all the time.


Good thing! Make serves as a gatekeeper from stupid spaces in paths from creeping into a project at the very source code level.

Let the users of the software do that at run-time, if they are so inclined.


This is why I find detox to be such a handy tool:

http://detox.sourceforge.net/

Detox has solved endless amounts of hassle...


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?


Huh? If you can rename the files why keep any kind of whitespace in them at all?




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: