(this FAQ should cover Borland and GNU MAKE, maybe others)

================================================================
"Why should I use MAKE? My IDE has a project manager."
================================================================
- If you change compilers, your old project files become useless.
  Well-written makefiles (and well-written versions of Make)
  are more portable.

xxx - other reasons?

================================================================
"Is there a 'standard' MAKE?"
================================================================
xxx - I'm not sure. POSIX?

================================================================
"Show me an example makefile"
================================================================
Here is a working DJGPP makefile, with annotation:

# As you may have guessed, comments in makefiles start with #
# so the line below has been commented out. (See: "Should the
# makefile itself be a dependent?")
#MAKEFILE=dj.mak

# Define a macro with name "DEBUG" and value "-g -Wall".
DEBUG	=-g -Wall

# After defining a macro, you'll want to use it. Do this by
# surrounding the macro name with ( and ) and prefixing
# it with $. This declaration sets CFLAGS to "-g -Wall -O2"
CFLAGS	=$(DEBUG) -O2
NFLAGS	=-f coff
LFLAGS	=$(DEBUG)

FAR	=main.o  dj.o  font.o  lf32_8.o
NEAR	=main.o  dj2.o  font.o  ln_8.o

# The line below has a colon in it, so it's a rule or dependency
# or both (a dependency, in this case). The first explicit
# rule or dependency of the makefile is the default target;
# the action that MAKE takes when you just type "make" with
# nothing after it. Here, MAKE will attempt to build the
# files "near.exe" and "far.exe".
#
# The rule to build all targets has the traditional name
# "all". If the default target is not "all", then the
# traditional name "dummy" is used for the default target.
all:	near.exe  far.exe

# Two "implicit rules". These tell MAKE how to convert ".c"
# files into ".o" files (i.e. how to compile), and how to
# convert ".asm" files into ".o" files (i.e. how to assemble).
#
# The whitespace before "gcc" and "nasm" MUST be a tab
# (see: "What does 'missing separator' mean?").
.c.o:
	gcc $(CFLAGS) -c -o$@ $<

.asm.o:
	nasm $(NFLAGS) -o$@ $<

# An "explicit rule". This tells MAKE how to build the
# executable file "far.exe" from the object files listed
# in $(FAR).
#
# Note $(MAKEFILE) in the top line but not the bottom. The
# makefile is not incorporated into "far.exe", but it is
# a dependent, i.e. "far.exe" should be re-built if the file
# named by $(MAKEFILE) changes.
far.exe: $(FAR) $(MAKEFILE)
	gcc $(LFLAGS) -o$@ $(FAR)

near.exe: $(NEAR) $(MAKEFILE)
	gcc $(LFLAGS) -o$@ $(NEAR)

# This is a dependency. It relies on an implicit rule defined
# elsewhere (in this case, the ".c.o" rule). It translates as
#    "If any of the files main.c, defs.h, or dj.mak are
#    changed, then main.o should be re-compiled."
main.o:	main.c	defs.h	$(MAKEFILE)

# "dj2.o" and "dj.o" are both built from file "dj.c". The C
# macro "NEARPTR" is defined when compiling "dj2.o". This is
# not the default behavior of the ".c.o" implicit rule above,
# so "dj2.o" needs an explicit rule.
#
# "defs.h" is #include'd by "dj.c". It is treated the same
# way as $(MAKEFILE): though not mentioned on the "gcc"
# command line, it is a dependent.
dj.o:	dj.c	defs.h	$(MAKEFILE)

dj2.o:	dj.c	defs.h	$(MAKEFILE)
	gcc -DNEARPTR=1 $(CFLAGS) -c -o$@ dj.c

font.o:	font.c	defs.h	$(MAKEFILE)

lf32_8.o:lf32_8.c defs.h $(MAKEFILE)	depth8.c

ln_8.o:	ln_8.c	defs.h	$(MAKEFILE)	depth8.c

# "clean" is the traditional name of the target which deletes
# temporary and/or intermediate files. You invoke this target
# by typing "make clean".
clean:
	del *.o
	del *.obj
	del *.exe

================================================================
"What is all that punctuation? Is MAKE cursing back at me?"
================================================================
The two-character codes made of punctuation and starting with
$ are "automatic variables" (GNU Make terminology). Here are
some common ones:

    C:\PROJ\FOO.OUT  :   C:\PROJ\FOO.IN

Borland MAKE:
Variable    Implicit rule       Explicit rule

$*          path + root         path + root
            C:\PROJ\FOO         C:\PROJ\FOO

$?          path + infile       path + infile
            C:\PROJ\FOO.IN      C:\PROJ\FOO.IN

$@          path + outfile      path + outfile
            C:\PROJ\FOO.OUT     C:\PROJ\FOO.OUT

$<          path + infile       path + outfile
            C:\PROJ\FOO.IN      C:\PROJ\FOO.OUT

$&          root                root
            FOO                 FOO

$.          infile              outfile
            FOO.IN              FOO.OUT

$:          path (directory)    path (directory)
            C:\PROJ             C:\PROJ

GNU MAKE:
Variable    Implicit rule       Explicit rule

$*          path + root         path + root
            C:\PROJ\FOO         C:\PROJ\FOO

$?          path + infile       path + infile
            C:\PROJ\FOO.IN      C:\PROJ\FOO.IN

$@          path + outfile      path + outfile
            C:\PROJ\FOO.OUT     C:\PROJ\FOO.OUT

$<          path + infile       path + infile
            C:\PROJ\FOO.IN      C:\PROJ\FOO.IN

Watcom WMAKE:
xxx

================================================================
"Can I put more than one command in a rule?"
================================================================
Yes. Here is an example explicit rule with three commands:

        start32.obj: start32.asm  $(MAKEFILE)
                nasm -f win32 -ofoo start32.asm
		coff2omf foo start32.obj
		del foo

The rule ends with a blank line. Remember that each of the three
command lines here must be preceded with a tab, not spaces.

================================================================
"The lines in my makefile are too long to read!"
================================================================
You may end the line with \ as a "continuation character".
(See also: "I think the command line is too long.")
Example:

STRING	=string/stricmp.o string/strnset.o string/memcmp.o	\
	string/strcat.o string/strnicmp.o string/strncat.o	\
	string/strchr.o string/memicmp.o string/strcpy.o	\
	string/strlwr.o string/strncpy.o string/strcmp.o	\
	string/strupr.o string/strncmp.o string/strlen.o	\
	string/strstr.o string/strset.o string/memmove.o	\
	string/memset.o string/memset16.o string/memset32.o	\
	string/memchr.o string/memcpy.o

This is, syntactically, a single line. If you need \ at the end
of a line (e.g. as a DOS path separator) then escape the \ with
a second \

	# specify location of reentrant startup code and libs
	OBJDIR	=g:\locate\\
	LIBDIR	=g:\locate\\

================================================================
"What does 'missing separator' mean?"
================================================================
GNU MAKE produces this error when the first command after your
implicit or explicit rule is delimited with spaces instead of a
tab. (I believe the use of tab as a delimiter is a requirement
of the POSIX spec. Yes, this is stupid.)

You should avoid using DOS EDIT to create or edit makefiles,
as it often expands tabs as spaces.

================================================================
"What is .SUFFIXES: for?"
================================================================
You need one of the following to build a file:
- Explicit rule
- Implicit rule + dependency

In the second case, Make also needs to know about filename
extensions (suffixes). Some are built-in, others are not.
In general, when you use implicit rule + dependency to build
a file, and the source file has an "unusual" extension, you
should use .SUFFIXES.

Or, if you're feeling lazy or paranoid, just tell Make about
all the filename extensions you've known:
	.SUFFIXES: .c .cpp .asm .nsm .s .i .o .obj .a .lib
	.SUFFIXES: .elf .cof .exe .com .bin

xxx - not sure about this

================================================================
"Can I have multiple dependency lines for the same file?"
================================================================
xxx - I don't know.

    dj.o:	dj.c

    dj.o:	defs.h

    dj.o:	$(MAKEFILE)

================================================================
"Can I have a dependency in an implicit rule?"
================================================================
xxx - I don't know.

    # recompile all C files if the makefile changes???
    .c.o:       $(MAKEFILE)
	gcc $(CFLAGS) -c -o$@ $<

================================================================
"Can I have multiple files on the left side of a dependency?"
================================================================
This works:

    $(OBJS):	defs.h

xxx - but I don't know about this:

    # rebuild all object files if the makefile changes
    *.o:	$(MAKEFILE)

================================================================
"Can I chain dependencies?"
================================================================
xxx - I don't think so.

	dj.o:	dj.c		defs.h	$(MAKEFILE)	depth8.c

	cppdefs.h: defs.h

	# rebuild win.o if defs.h changes???
	win.o:	win.cpp	cppdefs.h	$(MAKEFILE)

================================================================
"Can I 'add on' to an implicit rule?"
================================================================
xxx - I don't know.

    .c.o:
	gcc $(CFLAGS) -c -o$@ $<

    # normal build
    foo.o:	foo.c

    # compile object file then strip it -- xxx -- doesn't work
    bar.o:	bar.c
	strip $@

================================================================
"MAKE stops when I say 'make clean' and the delete operation
fails because the file has already been deleted"
================================================================
Prefix the name of the delete command with a dash. This will
cause MAKE to assume the command is always successful:

clean:
        -rm krnl/*.o
        -rm boot/*.bin
        -rm lib/*.a lib/*.o

================================================================
"My IDE handles dependencies automatically; does MAKE?"
================================================================
It might. The GNU C preprocessor can examine C files for #include
statements, and generate an appropriate MAKE dependency:

    C:\TMP>cpp  -MM  ln_8.c
    ln_8.o: ln_8.c defs.h depth8.c

These automatically-generated dependencies could be directed
into files, and the files include'd in the makefile.

        CSRC    := $(wildcard *.c)
        DEPS    := $(CSRC:.c=.d)

        # how to use GCC to calculate dependencies
        CDEP    =gcc -M -nostdinc -I$(INCDIR) $< >$@

        %.d : %.c
                $(CDEP)

        # now, include those dependencies in this makefile:
        ifneq ($(MAKECMDGOALS),clean)
        -include $(DEPS)
        endif

xxx - exclude dependencies for 'clean' target, or else automatic
dependency (*.d) files will be built when you say 'make clean'

================================================================
"Should the makefile itself be a dependent?"
================================================================
Probably. If you change command-line options in the makefile (e.g.
turn source-level debugging information on or off, change the
memory model, or change the optimization level), then everything
should be rebuilt.

This can be tedious when you make large-scale changes in your
source code, or when debugging the makefile itself. You should
do something like this:

        #MAKEDEP=makefile

        main.o: main.c  defs.h  $(MAKEDEP)

Here, the declaration of MAKEDEP is commented out i.e.
$(MAKEDEP) is an empty string, and main.o does NOT depend
on it. Once your code is relatively stable and the makefile is
debugged, the definition of MAKEDEP should be un-commented.

================================================================
"Can I use $< in an explicit rule?"
================================================================
This is probably not a good idea. GNU MAKE appears to expand
this as the first file name in the dependency list, but other
MAKEs may not behave this way.

NO:
	fun.exe: sex.o  drugs.h  rock.h roll.h $(MAKEFILE)
		gcc $(LFLAGS) -o$@ $<

	krnl.exe: load.o krnl.o lib.o config.h $(MAKEFILE)
		gcc $(LFLAGS) -o$@ $<   # links only load.o

YES:
	fun.exe: sex.o  drugs.h  rock.h roll.h $(MAKEFILE)
		gcc $(LFLAGS) -o$@ sex.o

	OBJS=load.o krnl.o lib.o
	krnl.exe: $(OBJS) config.h $(MAKEFILE)
		gcc $(LFLAGS) -o$@ $(OBJS)

================================================================
(DOS) "I think the command line is too long."
================================================================
This is quite possible with DOS. There are several work-arounds.

1.  DJGPP supports several methods of dealing with this;
    consult the DJGPP FAQ if you are using that environment.

2.  "Response files". The better-quality DOS tools support this
    method. The long command lines are written to a temporary
    file, then the compiler, linker, or other tool reads the
    command lines from the file.

    Example: to invoke a long Turbo Link command line from within
    Borland MAKE, you can do this:

	main.exe: $(OBJS) $(MAKEFILE)
                tlink /x $(LFLAGS) @&&!
	c0$(MODEL).obj $(OBJS)
	$.
        # no map file (/x option)
	c$(MODEL).lib
	!

    The syntax shown here is specific to Borland MAKE. Check
    the documentation for your MAKE to see if it supports
    response files, and what their format should be.

3.  Chose shorter filenames, and/or shorter filename extensions.
    With care, you can create a Borland makefile that uses the
    extension ".o" instead of ".obj" for object files.

4.  Use wildcards:
        gcc $(LFLAGS) -o foo.exe *.o

================================================================
"What do these messages mean?"
	'Load error: can't switch mode'
	'DOS/16M error: [32]  DPMI host error'
================================================================
These are error messages from "DOS extenders"; programs that let
you run 32-bit code under DOS. These programs are not always
well-behaved.

Starting with Turbo/Borland C 3.0, Borland's DOS tools use a
16-bit DOS extender which is incompatible with the 32-bit DOS
extenders used by some other DOS compilers. If you want to use
Borland's MAKE with a non-Borland compiler, use real-mode
MAKER.EXE instead of MAKE.EXE

================================================================
"MAKE is trying to run 'rm'. This is not a DOS command!"
"I told MAKE to use '-O2' with GCC, but it's not."
================================================================
Some versions of MAKE, when faced with an incomplete makefile,
try to be helpful by using "built-in" rules. These are generally
NOT helpful.

Debug your makefile. GNU MAKE lets you disable the built-in
rules with the "-r" or "--no-builtin-rules" options. For Borland
make, find and delete (or rename) the file BUILTINS.MAK, usually
in the same directory as MAKE.EXE

================================================================
"'File format not recognized, treating as linker script'"
"'linker input file unused since linking not done'"
================================================================
Some compilers are collections of tools, with a "driver" program
that invokes the others as needed. GNU C falls into this
category. "gcc" is merely the driver; the actual work is done by
"cpp" (preprocessor), "cc1" (the compiler proper), "as"
(assembler), and "ld" (linker).

Sometimes the driver has to guess at what you are trying to do.
It does this by making assumptions about file contents based on
the extension of the filename. Unusual filename extensions
can confuse it. Consider: what is to be done here?

	gcc  -o homer.foo  homer.bar

MAKE will echo commands to the screen as it executes them. Study
this output to see if your makefile is buggy. Are you trying to
assemble a makefile? Link a .h file?

================================================================
"'Error: Undefined symbol FIWRQQ in module foo.cpp'"
"'Error: Undefined symbol FIDRQQ in module foo.cpp'"
"'Error: Undefined symbol N_FTOL@ in module foo.cpp'"
================================================================
Looks like you're trying to compile a program under Turbo or
Borland C; a program that uses floating-point math. You are
probably forgetting to link in the floating-point libraries.
One is named "maths.lib", "mathl.lib", "mathc.lib", etc.
depending on the memory model. The other is either "fp87.lib"
if your target system has an 80x87 math coprocessor, or
"emu.lib" if the target system has no 80x87.

    OBJS	=c0$(MODEL).obj  foo.o
    # emulated or hardware floating point?
    LIBS	=c$(MODEL).lib  math$(MODEL).lib  emu.lib
    #LIBS	=c$(MODEL).lib  math$(MODEL).lib  fp87.lib

    foo.exe: $(OBJS) $(MAKEFILE)
	tlink $(LFLAGS) $(OBJS), $.,,$(LIBS)

================================================================
"Are there any alternatives to MAKE?"
================================================================
Lots of them. But if you think Make sucks, wait until you see
the alternatives:

http://www.linuxlinks.com/Software/Programming/Development/Tools/Make_Tools/index.shtml
http://makepp.sourceforge.net/
http://www.trolltech.com/developer/download/tmake.html
http://www.tmk-site.org/
http://www.canb.auug.org.au/~millerp/cook/cook.html
http://www.gnu.org/software/cons/
http://www.scons.org/
http://jakarta.apache.org/ant/
ftp://ftp.cs.colorado.edu/pub/distribs/odin/
http://buildtool.sourceforge.net/
http://www.perforce.com/jam/jam.html




http://www.acm.uiuc.edu/sigops/rsrc/depend.html
"now a 'make depend' will calculate dependancies [automatically]"

