divzeroweb

2f30.org website
git clone git://git.2f30.org/divzeroweb
Log | Files | Refs | README | LICENSE

make.md (5469B)


      1 ### How to make and make clean
      2 
      3 Do you write Makefiles?  Do you want them to be fairly portable?  Then
      4 continue reading this.  Here are some things that I keep in mind when
      5 dealing with builds and `make`.  First of all, there are cases where you
      6 can use `make` without a Makefile.  For example, if you have a simple
      7 `test.c` just to quickly try something you can do:
      8 
      9     $ make test
     10     cc -O2 -pipe    -o test test.c
     11 
     12 And if you need some preprocessor flags:
     13 
     14     $ CPPFLAGS=-DDEBUG make test
     15     cc -O2 -pipe  -DDEBUG  -o test test.c
     16 
     17 And if you also need to link with a library:
     18 
     19     $ CPPFLAGS=-DDEBUG LDLIBS=-lpcap make test
     20     cc -O2 -pipe  -DDEBUG  -o test test.c -lpcap
     21 
     22 More flags or libs can be inserted like this:
     23 
     24     $ CPPFLAGS=-DDEBUG LDLIBS="-lpcap -lm" make test
     25     cc -O2 -pipe  -DDEBUG  -o test test.c -lpcap -lm
     26 
     27 The reason these work is that most `make` implementations have inference
     28 rules and default variable values, so they know how to build binaries
     29 from certain files using the source file extension.  To see the list of
     30 inference rules (also known as implicit rules or suffix rules) do this
     31 on a Makefile-less directory:
     32 
     33     $ make -p
     34 
     35 Now it should make more sense why and how the builds worked.  For
     36 development in C these are the important variables:
     37 
     38     CC       -- Compiler
     39     CPPFLAGS -- Preprocessor flags
     40     CFLAGS   -- Compile flags
     41     LDFLAGS  -- Link flags
     42     LDLIBS   -- Libraries to link with
     43 
     44 For C++ you also have:
     45 
     46     CXX      -- Compiler
     47     CXXFLAGS -- Compile flags
     48 
     49 Not all `make` implementations pre-define all of the above variables;
     50 you should check with the systems you want to support first.
     51 On the previous command line examples we define those as shell
     52 environment variables and they are instantiated as make variables as
     53 well (macros).  We could also provide them as command line arguments to
     54 the `make` command:
     55 
     56     $ make CPPFLAGS=-DDEBUG LDLIBS=-lpcap test
     57     cc -O2 -pipe  -DDEBUG  -o test test.c -lpcap
     58 
     59 And double quotes also work there:
     60 
     61     $ make CPPFLAGS=-DDEBUG LDLIBS="-lpcap -lm" test
     62     cc -O2 -pipe  -DDEBUG  -o test test.c -lpcap -lm
     63 
     64 Now instead of writing all these macros every time you may create a
     65 simple Makefile to handle that part, but still rely on inference rules:
     66 
     67     CPPFLAGS = -DDEBUG
     68     LDLIBS = -lpcap -lm
     69 
     70 Assuming the above Makefile, now type:
     71 
     72     $ make test
     73     cc -O2 -pipe  -DDEBUG  -o test test.c -lpcap -lm
     74 
     75 Now let's add a default target so that we also avoid typing that.  It is
     76 customary that this default target is named `all`.  Our Makefile now
     77 becomes:
     78 
     79     CPPFLAGS = -DDEBUG
     80     LDLIBS = -lpcap -lm
     81 
     82     all: test
     83 
     84 Just do:
     85 
     86     $ make
     87     cc -O2 -pipe  -DDEBUG  -o test test.c -lpcap -lm
     88 
     89 It is also common to have a `clean` target as well.  Add the following:
     90 
     91     clean:
     92             rm -f test
     93 
     94 Note that the shell command under the dependency line begins with a tab
     95 character.  The dependency here is empty and will always be unsatisfied,
     96 so the `rm` command will always run:
     97 
     98     $ make clean
     99     rm -f test
    100 
    101 That is true unless a file named `clean` appears in the filesystem.  If
    102 you want to ensure that such rules are not affected by this artifact you
    103 can declare that they are special rules that are always evaluated.
    104 Simply add:
    105 
    106     .PHONY: all clean
    107 
    108 Now that we have a Makefile let's run this command:
    109 
    110     $ CPPFLAGS=-DPIC make
    111     cc -O2 -pipe  -DDEBUG  -o test test.c -lpcap -lm
    112 
    113 And the same with the macro as argument:
    114 
    115     $ make CPPFLAGS=-DPIC
    116     cc -O2 -pipe  -DPIC  -o test test.c -lpcap -lm
    117 
    118 We see that the macro assignment in the Makefile overrides the shell
    119 environment variable and the command line argument overrides the
    120 Makefile!  By now we have a simple Makefile with one target.  How about
    121 a Makefile with multiple targets?  We would have to alter the `all:`
    122 target and the `clean:` shell command because they deal with the same
    123 stuff.  Here we can use a macro assignment to hold the list of targets
    124 like that:
    125 
    126     BIN = bin1 bin2
    127 
    128     all: $(BIN)
    129 
    130     clean:
    131             rm -f $(BIN)
    132 
    133 And this way all we have to ever touch to add `bin3` is the `BIN`
    134 variable.  We get:
    135 
    136     $ make && make clean
    137     cc -O2 -pipe  -DDEBUG  -o bin1 bin1.c -lpcap -lm
    138     cc -O2 -pipe  -DDEBUG  -o bin2 bin2.c -lpcap -lm
    139     rm -f bin1 bin2
    140 
    141 
    142 #### Notes on various make implementations
    143 
    144 Some `make` implementations such as the IRIX one do not use the LDLIBS
    145 variable in their default inference rules.  We could do something like:
    146 
    147     LDFLAGS = $(LDFLAGS) $(LDLIBS)
    148 
    149 The problem with this is that the libraries will possibly appear before
    150 the object files when linking and this may be a problem for some
    151 compilers.  The better solution is to rewrite the inference rules in a way
    152 that includes LDLIBS at the end.  For example:
    153 
    154     .c:
    155             $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
    156 
    157 
    158 #### More reading on portability
    159 
    160  * [OpenBSD make(1)](
    161      http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/make.1)
    162  * [NetBSD make(1)](
    163      http://netbsd.gw.com/cgi-bin/man-cgi?make+1)
    164  * [Solaris make(1S)](
    165      https://docs.oracle.com/cd/E36784_01/html/E36870/make-1s.html)
    166  * [System V make(1)](
    167      https://docs.oracle.com/cd/E36784_01/html/E36870/sysv-make-1.html)
    168  * [IRIX 6.5 make(1)](
    169      http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650&db=man&fname=/usr/share/catman/u_man/cat1/make.z)
    170  * [Autoconf manual](
    171      https://www.gnu.org/software/autoconf/manual/autoconf.html#Portable-Make)