
Makefile hacks: print the value of any variable (2010) - Tomte
https://blog.melski.net/2010/11/30/makefile-hacks-print-the-value-of-any-variable/
======
jgrahamc
Eric (who wrote TFA) and I worked together at Electric Cloud on GNU make
stuff. He took over from me writing a column called "Ask Mr. Make".

The columns I wrote are all available here:
[http://blog.jgc.org/2013/02/updated-list-of-my-gnu-make-
arti...](http://blog.jgc.org/2013/02/updated-list-of-my-gnu-make-
articles.html)

Or, if you like, there's a book version:
[https://www.nostarch.com/gnumake](https://www.nostarch.com/gnumake)

~~~
rurban
I started with your first article which begins with "There aren't any
debuggers for Make" Actually Rocky's remake existed in June 2004 already. Bad,
very bad...

    
    
        commit 60f9a6ab18f12802c79a977d1b6b65b106355c10
        Author: R. Bernstein <rocky@gnu.org>
        Date:   Sun Apr 4 01:38:36 2004 +0000
    
        Initial revision

~~~
jgrahamc
Hmm. "Bad, very bad..." seems like an exaggeration. I wrote that article in
June 2004. Although the initial commit for remake (which I covered in 2007)
was in April 2004 the initial release was... at the same time as my article.

My article was published on June 27, 2004: [https://web-
beta.archive.org/web/20080202093023/http://www.c...](https://web-
beta.archive.org/web/20080202093023/http://www.cmcrossroads.com/articles/ask-
mr.-make/printing-the-value-of-a-makefile-variable.html)

remake preparing for first release on June 12, 2004:
[https://github.com/rocky/remake/commit/f9ad86874dae33ea89485...](https://github.com/rocky/remake/commit/f9ad86874dae33ea894853f48e87aeae6743bd1b)

------
paulddraper
OT but make (GNU make specifically) is an amazing piece of software.

It seems every build tool since then has intentionally disregarded the file-
based dependency graph that is the elegance of make. Crazy.

(There are modern Blaze-clones which continue the spirit, but with a steeper
learning-curve.)

~~~
pg314
Make has some serious shortcomings though. Some that I can think of: it relies
on timestamps instead of content hashes, it doesn't rebuild things when e.g.
compiler flags change, its approach to header dependencies in C/C++ is clumsy,
it needs to parse the Makefile each time (which for large projects takes non-
negligible time), it doesn't have an integration with inotify (which means it
needs to stat() every file to check its timestamp).

~~~
spc476
> it relies on timestamps instead of content hashes

If it relied upon content hashes, then make would have to hash the files each
time it ran (taking time---checking the timestamp is faster). For a large
project, this might be too excessive.

> it doesn't rebuild things when e.g. compiler flags change

Just make the Makefile a dependency on each target. That problem solved.

> it needs to parse the Makefile each time

Um ... of course. The only way around this is for make to compile into some
easier format to read or some database type thing (perhaps a .makefile?) and
it would need to track changes to Makefile to update the database type thing
(well, make does dependency tracking so that shouldn't be too hard).

Just a question---do you have a project where reading the Makefile takes a
non-negligible time?

> it doesn't have an integration with inotify

inotify is a) Linux only (make, and specifically GNU Make, runs on nearly
everything) and b) it's an API, not a service that can be queried. Doing this
implies that make will have to always be running checking all files for a
project. Which project? All projects that have a makefile on my system? After
a certain number of files being tracked, I'm certain that checking "inotify"
(a daemon perhaps?) is the same as checking "stat()" for file metadata.

~~~
paulddraper
These are solvable approaches, though it's easy to see why make did what it
did.

> hash the files each time it ran

Bazel & co relies on file hashes, but only checks then when the timestamp
changes.

Downside: now you have to keep hashes as metadata somewhere.

> it needs to parse the Makefile each time

Many build tools run a long running process either in the foreground (SBT, new
Maven) or in the background (Gradle).

Downside: Now you have to run a long running process...

> it doesn't have an integration with inotify

It could.

Downside: Not universal, uses memory, more complex.

------
js2
Does this count as a make hack? I have (or had, can't seem to find it right
now) a script to generate a makefile from a list of URLs of files to be
downloaded. In this case, it was for when I needed to download hundreds or
thousands of files. The makefile just called curl to do the downloading. But
the beauty of using make was that I could easily control the download
concurrency with -j, and of course that it would skip already downloaded
files. I think I may have even made it properly resume partial downloads by
checking for the temporary target file and using its size to send the right
range request.

Anyway, it's been a few years, but I thought it was pretty clever at the time.

~~~
dahart
Yeah, I think it counts, though make was designed for general purpose jobs and
not just compilation, so it gets a lot of credit for being a solid and general
tool. Being able to resume jobs is awesome, and free concurrency is too. I've
done the same thing and used make for batch downloads and batch image resizing
and batch frame rendering, etc. etc. I did it enough times that I generalized
my makefile so I could easily schedule resumeable parallel command line
batches. I called it "mbatch" and was getting ready to publish it... but then
I discovered gnu parallel. :P

------
jnwatson
Most folks don't use it as such, but make is a logic programming language, ala
Prolog. It can use a long chain of translations without you telling it the
sequence. For example, I could #include "foo.pdu.der.h" in a C file, and make
figured out that it needed to find foo.pdu.xer, translate it from XER to DER
as a "pdu" PDU, then hexlify it as an char array into foo.pdu.der.h.

It is a very flexible tool if you can get past the syntax (and always use
--warn-undefined-variables).

------
ksherlock
I had a similar need except I didn't which variable I was looking for. I think
I found this on stack overflow:

    
    
        .PHONY: variables
        variables :
            $(foreach v, $(.VARIABLES), $(info $(v) = $($(v))))
            @echo
    

which prints all variables and their respective values.

------
zzzcpan
Here's a similar "hack", but it is not limited to gnu make:

    
    
      printvar:
              @echo $(VAR)
    

You can execute it like this:

    
    
      make printvar VAR='$(PWD)'

