Makefile
Recently, I had to build some project involving a lot of files. Two choices were possible:
- use a script to build
- use a Makefile
I ended up with a Makefile, which is the best solution I think. As the script has to generate a bunch of files from “source” files. (I have to confess also, I have been a bit influenced by jessfraz with those tweets: here and here)
This project also learned me some tricks which can be reused, here is a little list
Default variable
You can set a default value to an internal variable of a makefile. Those variables
can be set up at the make
command run i.e: make ARCH=i686
or ARCH=i686 make
SERVER_PORT ?= 5050
ARCH ?= amd64
Watch all files from a directory to change
This is perfectly correct and usable in a Makefile
archive.tgz: $(shell find root -type f | sed 's/ /\\ /g')
@tar cvzf $@ $^
Note: $@
represent the target and $^
all the file dependencies
Define and use a command
You can define a command as a parameter and use it in a target, this is really convenient and a huge plus against a shell script (which will require an eval statement). You can nest variable inside your commands, this gives a lot of flexibility.
WGET = wget -d -o logfile
archive.tgz:
$(WGET) -O "$@" "https://ftp.gnu.org/gnu/coreutils/coreutils-5.0.tar.gz"
Use another makefile
We can use the makefile from another project within the current makefile, with
the -C
option. In this example $(MAKE)
is setup by default to make
command.
The $(dir ...)
part is a make
internal command
(see here)
vendor/darkhttpd/darkhttpd_:
$(MAKE) -C $(dir $@)
Escape variable
Sometimes you need to escape the variable character, this can be done by doubling
it: $$
. In the following example, the $$2
will represent the $2
from awk
and not a variable from make
clean.virsh:
virsh list | awk '$$2 ~ /ipxe/ {system("virsh destroy " $$2)}'
virsh list --all | awk '$$2 ~ /ipxe/ {system("virsh undefine " $$2)}'
Debug your targets
In order to debug your targets you can run a simple command which is not too verbose, but display enough information though (got from the documentation here)
# Replace the <target> by the one you want to debug
make --debug=basic -n <target>
That’s all folks
I will try to improve this article over the time as I find new tips from make
.