Makefiles



It's a little difficult to fully explain Makefiles here, but here are some of the basic rules:

   * The make utility defaults to a certain set of rules; i.e., if you
     have a shell program source file, say prog.sh, and type "make
     prog" the make utility will automatically create "prog" and change
     the mode so it is executable. This also holds for C and other
     source files; make "knows" how to build an executable from a C
     source code file.
   * The make utility has never heard of Informix, so you need to
     provide a set of rules make can use to compile 4/GL, ESQL/C, forms
     and reports; you do this with a file, make.rules, that is included
     in the top of your Makefile (it's attached to this message).

A Makefile defines targets -- prog, for example, is the target of prog.sh -- and dependencies. A C program depends upon a object file, not the source file (because make knows that compiling a .c results in a .o which is then linked to produce an executable). So, you would define targets like this:

   MAKEFILE   =   Makefile

   MAINS   =   prog cprog

   OBJECTS   =   cprog.o

   ALL:   $(MAINS)

   cprog:   cprog.o
       $(CC) $(CFLAGS) -s -o cprog cprog.o $(LDFLAGS)

   cprog.o:

If you had prog.sh and cprog.c and Makefile in a directory, type make, hit the return, and you wind up with prog and cprog, both of which are executable.

Now, what if cprog has a couple of functions? OK, we add those like this:

   OBJECTS   =   cprog.o func01.o func02.o

   MAINS   =   cprog

   ALL:   $(MAINS)

   cprog:   cprog.o func01.o func02.o
       $(CC) $(CFLAGS) -s -o cprog cprog.o func01.o func02.o $(LDFLAGS)

   cprog.o:

   func01.o:

   func02.o:

and that's that.

CC, CFLAGS and LDFLAGS are tokens defined to mean something by make; MAINS and OBJECTS are tokens defined locally (you'll see why we use those later).

So, what about Informix stuff? Instead of saying that cprog above is eprog instead?

   MAKEFILE   =   Makefile

   MAINS   =   prog eprog

   OBJECTS   =   cprog.o func01.o func02.o

   ALL:   $(MAINS)

   include /usr/local/include/make.rules

   eprog:   eprog.o func01.o func02.o
       $(ESQL) $(ECFLAGS) -s -o eprog eprog.o func01.o func02.o $(LDFLAGS)

(the make.rules file below includes the instructions for make to use to build an ESQL/C program)

You're asking about 4-GL, though and fglpc and the like -- well, the make.rules file below includes the instructions for all of those, too; the instructions in make.rules default to sformbuild, so you just (1) change the FORM token in make.rules to

   FORM   =   ${INFORMIXDIR}/bin/form4gl

or include the line above in your Makefile (what's in the Makefile overrides what's in make.rules).

So your Makefile would look like:

   MAKEFILE   =   Makefile

   include /usr/local/include/make.rules

   FORM   =   ${INFORMIXDIR}/bin/form4gl

   FORMS   =   form1.frm form2.frm

   ALL:   $(FORMS)

and you'd get your forms built.

Notice something: there are blank lines between tokens and there are tabs between tokens, the equals sign and the definition; there is also a leading tab before $(CC) and $(ESQL) -- you separate with tabs and you must have a leading tab to indent.

We do reports the same way we do the forms; i.e.,

   REPORTS   =   rep01.arc rep02.arc

   ALL:   $(REPORTS)

You may want to change the definition of the report program in make.rules -- we use ACE reports and that's the default we use.

In practice you'll have a mixture of MAINS, FORMS, REPORTS and the like; use those tokens if you're going to use the make.rules file then tell make to build them with

   ALL:   $(MAINS) $(FORMS) $(REPORTS)

Also notice in the above (and below) that tokens (in the Makefile and in make.rules) are enclosed in parentheses and environment variables (like LOGNAME, GRPNAME) are enclosed in braces -- that's not a hard-and-fast rule, but it does help differentiate where some token definition comes from.

Hope this helps more than it hurts.

Here's a real Makefile that builds a couple of programs, junk, other, subtab and testit for testing the fglgets function that comes with Informix. It incorporates much of what's discussed above, plus a lot more that we consider "standard" when building Makefiles (CVS tokens, copyright notices, and a full set of definitions). Your mileage may vary.

   #ident  "$Id$"

   #
   #       Name:           $Source$
   #       Version:        $Revision$
   #       Modified:       $Date$
   #       Purpose:
   #       Author:         trona
   #       Date:           03/05/03
   #       $Log$
   #
   #       Generated by $Id$ Wed Mar 5 14:29:14 EST 2003

   MAKEFILE =      Makefile

   BASDIR  =       ${INSTALL_BASE}

   #       These are the rules for making Informix targets:
   include $(BASDIR)/include/make.rules
   #       Mess with them at your peril

   CFLAGS  =       -xarch=native64 -xO3 -xautopar -xbuiltin=%all
   -I${INFORMIXDIR}/incl/tools

   OWNER   =       ${LOGNAME}

   GROUP   =       ${GRPNAME}

   BINDIR  =       $(BASDIR)/bin

   BMASK   =       0755

   MAINS   =       junk other subtab testit

   OBJECTS =       fglgets.o junk.o other.o subtab.o tabfunc.o testit.o

   SOURCES =       fglgets.c other.4gl subtab.4gl tabfunc.c junk.4gl
   testit.4gl

   ALL:            $(MAINS)

   #       Uncomment these if you are using the GNU Project RCS software
   #SCCSDIR        =       fgl
   #$(SOURCES):
   #       co $@

   #       Uncomment these if you are using the Berkeley sccs front end
   software
   #SCCSDIR        =       fgl
   #$(SOURCES):
   #       sccs -d ${PROJECTDIR} -p $(SCCSDIR) get $(RELEASE) $@

   junk:           junk.o  $(LIBRARY)
           $(C4GL) $(C4FLAGS) -s -o junk junk.o $(LDFLAGS)

   other:          other.o fglgets.o $(LIBRARY)
           $(C4GL) $(C4FLAGS) -s -o other other.o fglgets.o $(LDFLAGS)

   subtab:         subtab.o tabfunc.o $(LIBRARY)
           $(C4GL) $(C4FLAGS) -s -o subtab subtab.o tabfunc.o $(LDFLAGS)

   testit:         testit.o fglgets.o $(LIBRARY)
           $(C4GL) $(C4FLAGS) -s -o testit testit.o fglgets.o $(LDFLAGS)


fglgets.o:

   tabfunc.o:

   junk.o:

   other.o:

subtab.o: testit.o:

   install:        $(MAINS)
           cp $(MAINS) $(BINDIR)
           cd $(BINDIR);\
           chown $(OWNER) $(MAINS);\
           chgrp $(GROUP) $(MAINS);\
           chmod $(BMASK) $(MAINS)

   remove:
           cd $(BINDIR);\
           rm -f $(MAINS)

   clean:
           rm -f $(OBJECTS)

   clobber:
           rm -f $(OBJECTS) $(MAINS)
   #       sccs -d ${PROJECTDIR} -p $(SCCSDIR) clean
   #       rcsclean

   newmakefile:
           makefile -m -f $(MAKEFILE) \
           'BASDIR =       ${INSTALL_BASE}'



#ident "$Id: make.rules,v 4.6 2002/09/10 16:20:40 trona Exp $"

# Note: CFLAGS, C4FLAGS and ECFLAGS default to GCC; whichever
# token is LAST in this file will be used; i.e., if
# you're using Solaris, make sure the Solars CFLAGS,
# C4FLAGS and ECFLAGS are last (just swap the lines).
#
# $Log: make.rules,v $
# Revision 4.6 2002/09/10 16:20:40 trona
# add xbuiltin flag for Solaris
#
# Revision 4.5 2002/08/28 15:41:05 trona
# add -xautopar compiler option for Solaris
#
# Revision 4.4 2002/07/23 20:55:22 trona
# add native64 for Solaris
#
# Revision 4.3 2002/07/23 17:28:56 trona
# remove native flag for Solaris
#
# Revision 4.2 1997/12/22 13:21:56 jwats
# Removed duplicate .ec~ target.
#
# Revision 4.1 1997/08/24 15:56:29 trona
# Initial installation
#

..SUFFIXES: .arc .arc~ .ace .ace~ .cbl .cbl~ .frm .frm~ .per .per~ .o .4gl .4gl~ .4go .ec .ec~ .c .c~ .y .y~ .l .l~ .s .s~ .sh .sh~ .h .h~

# C optimization flag
# these are for Solaris
CFLAGS = -xarch=native64 -xO3 -xautopar -xbuiltin=%all
# these are for GCC
CFLAGS = -O3

# ace section
..ace~.arc:
$(GET) $(GFLAGS) $<
${INFORMIXDIR}/bin/saceprep $<
rm -f $*.ace

..ace.arc:
${INFORMIXDIR}/bin/saceprep $<

# perform section
FORM = ${INFORMIXDIR}/bin/sformbld

..per~.frm:
$(GET) $(GFLAGS) $<
${FORM} $<
rm -f $*.per

..per.frm:
${FORM} $<

# cobol language section
COBOL = cobol

CBFLAGS = -dn -WC,NOTRUNC,MESSAGE,SOURCE,COPY,CHECK,STD1(ASCII),NOCODECHK,NOALPHA

..cbl~:
$(GET) $(GFLAGS) $<
$(COBOL) $(CBFLAGS) -s -o $@ $< $(LDFLAGS)
-rm -f $*.cbl $*.lst $*.int

..cbl:
$(COBOL) $(CBFLAGS) -s -o $@ $< $(LDFLAGS)
-rm -f $*.lst $*.int $*.o

..cbl~.o:
$(GET) $(GFLAGS) $<
$(COBOL) $(CBFLAGS) -c $<

..cbl.o:
$(COBOL) $(CBFLAGS) -c $<

# 4gl language section
C4GL = c4gl
# 4/GL optimization flag
# These are for Solaris
C4FLAGS = -xarch=native64 -xO3 -xautopar -xbuiltin=%all -w
# These are for GCC
C4FLAGS = -O3
FGL = fglpc

..4gl~:
$(GET) $(GFLAGS) $<
$(C4GL) $(C4FLAGS) -s -o $@ $< $(LDFLAGS)
-rm -f $*.4gl $*.4ec $*.ec $*.[co]

..4gl:
$(C4GL) $(C4FLAGS) -s -o $@ $< $(LDFLAGS)
-rm -f $*.4ec $*.[co]

..4gl~.4go:
$(GET) $(GFLAGS) $<
$(FGL) $*.4gl
-rm -f $*.4gl

..4gl.4go:
$(FGL) $*.4gl

..4gl~.o:
$(GET) $(GFLAGS) $<
$(C4GL) $(C4FLAGS) -e $<
$(CC) $(C4FLAGS) -I${INFORMIXDIR}/incl/tools -c $*.c
-rm -f $*.4gl $*.4ec $*.ec $*.c

..4gl.o:
$(C4GL) $(C4FLAGS) -e $<
$(CC) $(C4FLAGS) -I${INFORMIXDIR}/incl/tools -c $*.c
-rm -f $*.4ec $*.ec $*.c

..4gl~.a:
$(GET) $(GFLAGS) $<
$(C4GL) $(C4FLAGS) -e $<
$(CC) $(C4FLAGS) -I${INFORMIXDIR}/incl/tools -c $*.c
$(AR) $(ARFLAGS) $@ $*.o
-rm -f $*.4gl $*.4ec $*.ec $*.[co]

..4gl.a:
$(C4GL) $(C4FLAGS) -e $<
$(CC) $(C4FLAGS) -I${INFORMIXDIR}/incl/tools -c $*.c
$(AR) $(ARFLAGS) $@ $*.o
-rm -f $*.4ec $*.ec $*.[co]

# esql/c language section
ESQL = esql
# ESQL/C optimization flags
# These are for Solaris
ECFLAGS = -xarch=native64 -xO3 -xautopar -xbuiltin=%all
# These are for GCC
ECFLAGS = -O3

..ec~:
$(GET) $(GFLAGS) $<
$(ESQL) $(ECFLAGS) -s -o $@ $< $(LDFLAGS)
-rm -f $*.ec $*.[co]

..ec:
$(ESQL) $(ECFLAGS) -s -o $@ $< $(LDFLAGS)
-rm -f $*.[co]

..ec~.o:
$(GET) $(GFLAGS) $<
$(ESQL) $(ECFLAGS) -e $<
$(CC) -I${INFORMIXDIR}/incl/esql $(ECFLAGS) -c $*.c
-rm -f $*.ec $*.c

..ec.o:
$(ESQL) $(ECFLAGS) -e $<
$(CC) -I${INFORMIXDIR}/incl/esql $(ECFLAGS) -c $*.c
-rm -f $*.c

..ec~.a:
$(GET) $(GFLAGS) $<
$(ESQL) $(ECFLAGS) -e $<
$(CC) -I${INFORMIXDIR}/incl/esql $(ECFLAGS) -c $*.c
$(AR) $(ARFLAGS) $@ $*.o
-rm -f $*.ec $*.[co]

..ec.a:
$(ESQL) $(ECFLAGS) -e $<
$(CC) -I${INFORMIXDIR}/incl/esql $(ECFLAGS) -c $*.c
$(AR) $(ARFLAGS) $@ $*.o
-rm -f $*.[co]

..c~.c:
$(GET) $(GFLAGS) $<

..c~.o:
$(GET) $(GFLAGS) $<
$(CC) $(CFLAGS) -c $*.c
-rm -f $*.c

# RCS section
CO = co

..ace,v.arc:
$(CO) $<
$(INFORMIXDIR)/bin/saceprep $<

..per,v.frm:
$(CO) $<
$(FORM) $<

..ec,v.o:
$(CO) $<
$(ESQL) $(ECFLAGS) -c $*.o
-rm -f $*.c

..4gl,v.o:
$(CO) $<
$(C4GL) $(C4FLAGS) -c $*.o
-rm -f $*.c

..c,v.o:
$(CO) $<
$(CC) $(CFLAGS) -c $*.o
-rm -f $*.c

..ec,v.ec:
$(CO) $<

..4gl,v.4gl:
$(CO) $<

..c,v.c:
$(CO) $<


Relevant Pages

  • Re: properly accessing files > 2GB
    ... Makefile to detect 32 vs 64 bit OS and add or subtract 3? ... to opinions held by my employer, Sun Microsystems. ... LFS_CFLAGS = `getconf LFS_CFLAGS` ... prog: prog.c ...
    (comp.unix.programmer)
  • Re: properly accessing files > 2GB
    ... Makefile to detect 32 vs 64 bit OS and add or subtract 3? ... to opinions held by my employer, Sun Microsystems. ... LFS_CFLAGS = `getconf LFS_CFLAGS` ... prog: prog.c ...
    (comp.unix.programmer)
  • Re: properly accessing files > 2GB
    ... Makefile to detect 32 vs 64 bit OS and add or subtract 3? ... Expressed in this posting are my opinions. ... to opinions held by my employer, Sun Microsystems. ... prog: prog.c ...
    (comp.unix.programmer)
  • Re: Questions re C mode, ECB and some more
    ... Ah, I see, but that won't work when the Makefile is not in the same ... directory as the source file. ... but Makefile and objects are generated in a separate ...
    (comp.emacs)
  • Using make
    ... I have a source file called test.c. ... gcc test.c -o test ... I have both the sourcefile and the Makefile in the same ... mac2 c_assign> make ...
    (comp.lang.c)