commit 308efab69a5d70ba9753eb2b724c6f1eb1361e57
parent fd454a3956626cfbd0b7f267f89b6cdbe5a44cdc
Author: lostd <lostd@2f30.org>
Date: Wed, 19 Nov 2014 02:05:49 +0200
Macro assignment and precedence plus links and fixes
Diffstat:
M | guides/make.md | | | 62 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- |
1 file changed, 57 insertions(+), 5 deletions(-)
diff --git a/guides/make.md b/guides/make.md
@@ -27,7 +27,8 @@ More flags or libs can be inserted like this:
The reason these work is that most `make` implementations have inference
rules and default variable values, so they know how to build binaries
from certain files using the source file extension. To see the list of
-inference rules do this on a Makefile-less directory:
+inference rules (also known as implicit rules or suffix rules) do this
+on a Makefile-less directory:
$ make -p
@@ -45,10 +46,12 @@ For C++ you also have:
CXX -- Compiler
CXXFLAGS -- Compile flags
+Not all `make` implementations pre-define all of the above variables;
+you should check with the systems you want to support first.
On the previous command line examples we define those as shell
environment variables and they are instantiated as make variables as
-well. We could also provide them as command line arguments to the
-`make` command:
+well (macros). We could also provide them as command line arguments to
+the `make` command:
$ make CPPFLAGS=-DDEBUG LDLIBS=-lpcap test
cc -O2 -pipe -DDEBUG -o test test.c -lpcap
@@ -58,7 +61,7 @@ And double quotes also work there:
$ make CPPFLAGS=-DDEBUG LDLIBS="-lpcap -lm" test
cc -O2 -pipe -DDEBUG -o test test.c -lpcap -lm
-Now instead of writing all these variables every time you may create a
+Now instead of writing all these macros every time you may create a
simple Makefile to handle that part, but still rely on inference rules:
CPPFLAGS = -DDEBUG
@@ -98,6 +101,55 @@ so the `rm` command will always run:
That is true unless a file named `clean` appears in the filesystem. If
you want to ensure that such rules are not affected by this artifact you
can declare that they are special rules that are always evaluated.
-Simple add:
+Simply add:
.PHONY: all clean
+
+Now that we have a Makefile let's run this command:
+
+ $ CPPFLAGS=-DPIC make
+ cc -O2 -pipe -DDEBUG -o test test.c -lpcap -lm
+
+And the same with the macro as argument:
+
+ $ make CPPFLAGS=-DPIC
+ cc -O2 -pipe -DPIC -o test test.c -lpcap -lm
+
+We see that the macro assignment in the Makefile overrides the shell
+environment variable and the command line argument overrides the
+Makefile! By now we have a simple Makefile with one target. How about
+a Makefile with multiple targets? We would have to alter the `all:`
+target and the `clean:` shell command because they deal with the same
+stuff. Here we can use a macro assignment to hold the list of targets
+like that:
+
+ BIN = bin1 bin2
+
+ all: $(BIN)
+
+ clean:
+ rm -f $(BIN)
+
+And this way all we have to ever touch to add `bin3` is the `BIN`
+variable. We get:
+
+ $ make && make clean
+ cc -O2 -pipe -DDEBUG -o bin1 bin1.c -lpcap -lm
+ cc -O2 -pipe -DDEBUG -o bin2 bin2.c -lpcap -lm
+ rm -f bin1 bin2
+
+
+#### More reading on portability
+
+ * [OpenBSD make(1)](
+ http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/make.1)
+ * [NetBSD make(1)](
+ http://netbsd.gw.com/cgi-bin/man-cgi?make+1)
+ * [Solaris make(1S)](
+ https://docs.oracle.com/cd/E36784_01/html/E36870/make-1s.html)
+ * [System V make(1)](
+ https://docs.oracle.com/cd/E36784_01/html/E36870/sysv-make-1.html)
+ * [IRIX 6.5 make(1)](
+ http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650&db=man&fname=/usr/share/catman/u_man/cat1/make.z)
+ * [Autoconf manual](
+ https://www.gnu.org/software/autoconf/manual/autoconf.html#Portable-Make)