Live data from Hacker News

A Tutorial on Portable Makefiles

nullprogram.com

1–10 of 114 posts

Re: A Tutorial on Portable Makefiles

#2
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, the creation of the latter file should trigger a rebuild.

I did some research on the topic using the repository of the game Liberation Circuit [3] and my own redo implementation [4] … it turns out that a typical project in C or C++ has lots of non-existence dependencies. How do make users handle non-existence dependencies – except for always calling “make clean”?

[1] http://cr.yp.to/redo/honest-nonfile.html

[2] http://news.dieweltistgarnichtso.net/posts/redo-gcc-automati...

[3] https://github.com/linleyh/liberation-circuit

[4] http://news.dieweltistgarnichtso.net/bin/redo-sh.html (redo-dot gives a graph of dependencies and non-existence dependencies)

Re: A Tutorial on Portable Makefiles

#3
No one wants to manually do dependency management in even a moderately sized project. I really haven't found an ideal way to have these -MM -MT flags integrated into Makefiles; I've tried having an awk script automatically modify the Makefile as the build is happening, but of course the updated dependencies will only work for later builds, so it's only good for updating the dependencies. Any other approaches HNers used and really liked?

Re: A Tutorial on Portable Makefiles

#4
post #3

No one wants to manually do dependency management in even a moderately sized project. I really haven't found an ideal way to have these -MM -MT flags integrated into Makefiles; I've tried having an awk script automatically modify the Makefile as the build is happening, but of course the updated dependencies will only work for later builds, so it's only good for updating the dependencies. Any other approaches HNers us…

There exists DJB's redo approach [0], which i implemented [1], where dependencies and non-existence dependencies are only recorded after the build. A typical dofile is a shell script, so you do not need to learn another language. Targets also automatically depend on their own build rules (I have seen such a thing only in makefiles authored by DJB).

I wrote a blog post to show how to integrate dependency output for both dependency and non-existence dependency generation [2]. The game “Liberation Circuit” can be built with my redo implementation; you can output a dependency graph usable with Graphviz [4] using “redo-dot”.

There is only one other redo implementation that I would recommend, the one from Jonathan de Boyne Pollard [5], who rightly notices that compilers should output information about non-existence dependencies [6].

I would not recommend the redo implementation from Avery Pennarun [7], which is often referenced (and introduced me to the concept), mainly because it is not implemented well: It manages to be both larger and slower than my shell script implementation, yet the documentation says this about the sqlite dependency (classic case of premature optimization):

> I don't think we can reach the performance we want with dependency/build/lock information stored in plain text files

[0] http://cr.yp.to/redo.html

[1] http://news.dieweltistgarnichtso.net/bin/redo-sh.html

[2] http://news.dieweltistgarnichtso.net/posts/redo-gcc-automati...

[3] https://github.com/linleyh/liberation-circuit

[4] https://en.wikipedia.org/wiki/Graphviz

[5] http://jdebp.eu./Softwares/redo/

[6] http://jdebp.eu./FGA/introduction-to-redo.html#CompilerDefic...

[7] https://github.com/apenwarr/redo

Re: A Tutorial on Portable Makefiles

#5
post #3

No one wants to manually do dependency management in even a moderately sized project. I really haven't found an ideal way to have these -MM -MT flags integrated into Makefiles; I've tried having an awk script automatically modify the Makefile as the build is happening, but of course the updated dependencies will only work for later builds, so it's only good for updating the dependencies. Any other approaches HNers us…

Simply add:

  -include $(OBJS:%.o=%.d)
in your makefile (with -MMD in CFLAGS).

Re: A Tutorial on Portable Makefiles

#7
The problem comes in as soon as you need conditionals, which is likely when attempting to build something portably. There may be some gymnastics that can be done to write around the lack of their presence in standard make, but otherwise your options are:

- Supply multiple makefiles targeting different implementations

- Bring in autotools in all its glory (at this point you are depending on an external GNU package anyway)

- Or explicitly target GNU Make, which is the default make on Linux and macOS, is very commonly used on *BSD, and is almost certainly portable to every platform your software is going to be tested and run on. The downside being that BSD users need a heads up before typing "make" to build your software. But speaking as a former FreeBSD user, this is pretty easy to figure out after your first time seeing the flood of syntax errors.

Re: A Tutorial on Portable Makefiles

#8

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.

Re: A Tutorial on Portable Makefiles

#9

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.

Please elaborate: What do you find amazing about scons?

Also, how does scons handle non-existence dependencies?

What would be a scons dependency graph for this C code?

  #include
  main() {
   printf("hello, world\n");
   return 0;
  }
You can see a dependency graph I generated with redo here: http://news.dieweltistgarnichtso.net/posts/redo-gcc-automati...

Re: A Tutorial on Portable Makefiles

#10
post #7

The problem comes in as soon as you need conditionals, which is likely when attempting to build something portably. There may be some gymnastics that can be done to write around the lack of their presence in standard make, but otherwise your options are: - Supply multiple makefiles targeting different implementations - Bring in autotools in all its glory (at this point you are depending on an external GNU package any…

Another possibility is conditional compilation at the C level. thefile.c #includes thefile_unix.c or thefile_windows.c as appropriate.
Post reply on HN