Live data from Hacker News

A Tutorial on Portable Makefiles

nullprogram.com

31–40 of 114 posts

Re: A Tutorial on Portable Makefiles

#31

An issue I have with make is that it can not handle non-existence dependencies. DJB noted this in 2003 [1]. To quote myself on this [2]: > Especially when using C or C++, often target files depend on nonexistent files as well, meaning that a target file should be rebuilt when a previosly nonexistent file is created: If the preprocessor includes /usr/include/stdio.h because it could not find /usr/local/include/stdio.h…

I personally use scons instead of Makefiles. Its dependency analysis is amazing, I haven't seen it fail a single time.

Did scons finally get a little less opinionated?

It used to be that scons really forced you to use subsidiary SConscript child files for anything more complicated than a couple files in a single directory instead of being able to lump it all into a single SConstruct.

Re: A Tutorial on Portable Makefiles

#33
> Microsoft has an implementation of make called Nmake, which comes with Visual Studio. It’s nearly a POSIX-compatible make, but necessarily breaks [...] Windows also lacks a Bourne shell and the standard unix tools, so all of the commands will necessarily be different.

What I've been mulling over is an implementation of make that accepts only a restricted subset of the make syntax, eliding the extensions found in either BSD and GNU make, and disallowing use of non-standard extensions to the commands themselves (and maybe even further restricted still). In theory, a make that does this wouldn't even need to depend on a POSIX environment—it could treat the recipes not as commands but instead as a language. It wouldn't even take much to bootstrap this; you could use something like BusyBox as your interpreter. Call it `bake`.

Crucially, this is not another alternative to make: every bake script is a valid Makefile, which means it is make (albeit a restricted subset).

Re: A Tutorial on Portable Makefiles

#34
post #15
post #6

Wait... "%.o: %.c" is nonstandard?!?

Yes, base Make is almost useless for anything larger than a utility.

According to the POSIX make manpage [1], the following double-suffix rule is part of the defaults:

    .c.o:
        $(CC) $(CFLAGS) -c $
[1]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ma...

Re: A Tutorial on Portable Makefiles

#35

Earlier quoted context omitted.

Is this a common problem? I can't think of any project that does this, and there's a simple solution as well: don't shadow system headers. That's just asking for pain, regardless of how well make handles it.

I don't think this problem is limited to system headers. Something as innocent as #include "foo/bar.h" can be affected by this if you pass -I with at least two unique paths to the compiler.

ok, sure, I revise my answer to don't shadow any header.

Re: A Tutorial on Portable Makefiles

#36
More nifty portable Make facts:

- For portable recursive make(1) calls, use $(MAKE). This has the added advantage of BSD systems which can electively install GNU Make as gmake being able to pass in the path to gmake to run GNU Makefiles [1]

- BSD's don't include GNU Make in base system. BSD's port and build system uses Make extensively, and has a different dialect [2]

- In addition to that, you will likely choose to invoke system commands in your Makefile. These also have the same GNU-specific features that won't work on BSD's. So keep your commands like find, ls, etc. POSIX-compliant [3]

- Part of the reasons tools like CMake exist is to abstract not only library/header paths and compiler extensions, but also the fact POSIX shell scripting and Makefile's are quite limited.

- Not only is there a necessity to use POSIX commands and POSIX compatible Make language, but the shell scripting must also not use Bash-isms and such, since there's no guarantee the system will have Bash.

- POSIX Makefiles have no conditionals as of 2017. Here's a ticket from the issue tracker suggesting it in 2013: http://austingroupbugs.net/view.php?id=805.

- You can do nifty tricks with portable Makefile's to get around limitations. For instance, major dialects can still use commands to grab piped information and put it into a variable. For instance, you may not have double globs across all systems, but you can use POSIX find(1) to store them in a variable:

    FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]go$$' 2> /dev/null
Then access the variable:

    if command -v entr > /dev/null; then ${WATCH_FILES} | entr -c $(MAKE) test; else $(MAKE) test entr_warn; fi
I cover this in detail in my book The Tao of tmux, available for free to read online. [4]

- MacOS comes with Bash, and if I remember correctly, GNU Make comes with the developer CLI tools as make.

- For file watching across platforms (including with respect for kqueue), I use entr(1) [5]. This can plop right into a Makefile. I use it to automatically rerun testsuites and rebuild docs/projeocts. For instance https://github.com/cihai/cihai/blob/cebc197/Makefile#L16 (feel free to copy/paste, it's permissively licensed).

[1] https://www.gnu.org/software/make/manual/html_node/MAKE-Vari...

[2] https://www.freebsd.org/cgi/man.cgi?query=make&apropos=0&sek...

[3] http://pubs.opengroup.org/onlinepubs/9699919799/utilities/fi...

[4] https://leanpub.com/the-tao-of-tmux/read#tips-and-tricks

[5] http://entrproject.org

Re: A Tutorial on Portable Makefiles

#38

More nifty portable Make facts: - For portable recursive make(1) calls, use $(MAKE). This has the added advantage of BSD systems which can electively install GNU Make as gmake being able to pass in the path to gmake to run GNU Makefiles [1] - BSD's don't include GNU Make in base system. BSD's port and build system uses Make extensively, and has a different dialect [2] - In addition to that, you will likely choose to…

But there's no way in POSIX make itself to assign a value to FILES dynamically - you have to assign the FILES environment var or supply via command line args. POSIX make will expand ${FILES} by the replacement value in commands (and prerequisites but not targets). It then merely happens to be interpreted as part of the command it's placed into.

Re: A Tutorial on Portable Makefiles

#39
post #17

Earlier quoted context omitted.

> it's not perfect I used to be so hopeful for cmake, but just grew to be sort of annoyed by it. Build systems are, however, perennial like the grass, so we'll see more.

I just wish it would work with relative paths. It shouldn't break your build to move a folder around.

AFAIK cmake works perfectly fine with relative paths; what breaks?

Re: A Tutorial on Portable Makefiles

#40

Earlier quoted context omitted.

I just wish it would work with relative paths. It shouldn't break your build to move a folder around.

AFAIK cmake works perfectly fine with relative paths; what breaks?

I don't think it works: https://ofekshilon.com/2016/08/30/cmake-rants/
Post reply on HN