doc: Complex Makefile Example

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

doc: Complex Makefile Example

Kaz Kylheku
Hi all,

The Complex Makefile Example given in Appendix C of the GNU Make
manual seems quite dated. It does some things that are not
best practices, or not today.

Maybe that appendix should just be removed.

For instance, it "hijacks" the CFLAGS variable in order to specify
local definitions without which the program will not build.

      CFLAGS = $(CDEBUG) -I. -I$(srcdir) $(DEFS) \
              -DDEF_AR_FILE=\"$(DEF_AR_FILE)\" \

If this practice is followed, the distro package maintainer
has to reproduce all of this content in order to add a compiler
option to CFLAGS, or else patch the Makefile.

Another problem: it needlessly specifies a recipe for
building a file from .o files, instead of just letting the
built-in rule handle it, and gets it wrong:

      tar:    $(OBJS)
              $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)

The built-in rule is very similar, but refers to $(LDLIBS).

The built-in could be used because one of $(OBJS) has a stem
which matches the target: there is a tar.o.

Quote: "An interesting feature of this makefile is that
'testpad.h' is a source file automatically created by the
'testpad' program, itself compiled from 'testpad.c'."

This "interesting" thing is done wrong. Because ./testpad
is required when the program is being built for generating
a header file, it has to be compiled with the build machine's
native compiler, not with $(CC). A distro will set CC to the
target CC, which could be an armv7 compiler, running on
an Intel machine.

Fixing that issue will get ./testpad to run; but not
necessarily correctly.

If ./testpad generates values that reflect features of the
target machine environment, a host-compiled ./testpad may
not generate them correctly.

Makefiles which pull stunts like that are why people have
given up and switched to doing distro builds inside
QEMU chroot environments.

Does anyone really make executable Makefiles with
#!/usr/bin/make -f? It seems like that is being recommended,
since it is in a documented example.