|
CIRR.COMCompile TimeWriting Portable Makefiles |
So, what should a good Makefile look like? Here are some samples
from a current project. The project uses the System V make, and it's
associated include mechanism. This isn't an issue in this case, as it's
for a single customer who is unlikely to ever port this software off of
System V (Solaris.) The project is being developed using Informix's 4GL
database programming language.
The Makefiles are of two types. Listing 1 and Listing 2 are the common include files for all programs. These include build rules for the software (not covered by the default rules in make), and the build rules for objects common to most of the directories.
Listing 1,#---------------------------------------------------------------------------
# @(#) $ Id: rules.mk,v 1.12 2002/06/21 20:43:51 eric Exp $
#
# Common Makefile definitions needed to build the private billing
# system
#---------------------------------------------------------------------------
INSTALL_ROOT=${DESTDIR}/opt/privbill
BINDIR=${INSTALL_ROOT}/bin
SCREENDIR=${INSTALL_ROOT}/screens
# where to find interesting Informix bits
INFORMIXDIR=/opt/informix
INFORMIXLIB=$(INFORMIXDIR)/lib:$(INFORMIXDIR)/lib/tools
# needed to get c4gl to compile
INFORMIXSERVER=tahoe
DBPATH=/home/privbill
# set -fwritable-strings when using gcc, as
# 4gl likes to scribble into constant strings
CFLAGS= -I${INFORMIXDIR}/incl/tools -g -fwritable-strings
C4GLFLAGS= -anyerr -fwritable-strings -g
LDOPTS=-R$(INFORMIXLIB)
#
# 4gl "compilers" (with default arguments)
#
C4GL=c4gl
FORM4GL=form4gl -q
COMMON_OBJS= common.4go globals.4go
.SUFFIXES: .4go .4ge .4gl
.SUFFIXES: .frm .per
.4gl.4go:
${C4GL} ${C4GLFLAGS} -c -o $@ $<
.per.frm:
${FORM4GL} $*
Listing 1
Common/rules.mk defines a number of macros needed
through out the project. It also defines the rules needed to
convert source files into objects, and on screen form files into
their compiled editions.
Among the make variables defined are CFLAGS, to modify the C compilation environment; LDOPTS to include extra options to the linker (in this case, adding the Informix library directory to the run time loaders search path); C4GLFLAGS to modify the compilation environment for the C4GL compiler; and C4GL to define the compiler.
make's list of known suffixes is also augmented to include the suffixes used by Informix's c4gl source compiler, and Informix's form4gl form compiler.
This Makefile ends with suffix rules to compile
4GL source code into objects, and 4GL form source
into their compiled format.
Listing 2 defines the targets for the object files and source files that are included from a number of other program directories. In an ideal world, three of these object files,#---------------------------------------------------------------------------
# @(#) $ Id: sources.mk,v 1.8 2002/06/24 19:02:06 eric Exp $
# $ Source: /home/cvsrep/PrivBill/Common/sources.mk,v $
#
# Commonly used objects
#---------------------------------------------------------------------------
globals.4go: ../Common/globals.4gl
${C4GL} ${C4GLFLAGS} -c -o globals.4go ../Common/globals.4gl
common.4go: ../Common/common.4gl ../Common/globals.4gl
${C4GL} ${C4GLFLAGS} -c -o common.4go ../Common/common.4gl
version.4go: version.4gl
VSRCS=$(4GLSRCS) ../Common/common.4gl
version.4gl: $(VSRCS) ../Common/sources.mk
@echo "Generating version.4gl"
@rm -f version.4gl
@# long script to auto generate version.4gl deleted >version.4gl
usps.o: ../Common/usps.c
${CC} ${CFLAGS} -c -o usps.o ../Common/usps.c
${SCREENDIR}:
mkdir -p ${SCREENDIR}
${BINDIR}:
mkdir -p ${BINDIR}
Listing 2
globals.4go,
common.4go, and usps.o would be built into a
library to be linked with the programs in other directories. This
project isn't yet in the ideal world. :-)
A target is included to automatically generate a version information
function for every program that desires one. The in-line script,
which was removed for brevity, is about 60 lines long, and generates
a source file of valid code. The generated version.4gl source
is then compiled using an earlier dependency. The resulting file is
against the programs objects, and is made available via an
option in the program's menu.
Don't be afraid to include scripts in-line in the Makefile,
but do make them readable. In-lining the script in
the Makefile reduces the number of source files that
have to be provided as part of the distribution, hopefully keeping
things simpler.
The#---------------------------------------------------------------------------
# @(#) $ Id: Makefile,v 1.5 2002/06/20 16:48:28 eric Exp $
#
# Private Billing CSR user interface
#---------------------------------------------------------------------------
include ../Common/rules.mk
CSR_PERS= acct002.per acct003.per csrp001.per call001.per \
qacct.per query01.per usps001.per
CSR_FRMS=$(CSR_PERS:.per=.frm)
CSR02_4GE= csr02.4ge
all: $(CSR02_4GE) $(CSR_FRMS)
install: $(BINDIR) $(SCREENDIR) $(CSR02_4GE) $(CSR_FRMS)
for i in $(CSR_4GES); do \
cp $$i $(BINDIR) ; \
done
for i in $(CSR_FRMS) ; do \
cp $$i $(SCREENDIR) ; \
done
CSR02_SRCS=csr_addcl.4gl csr_main.4gl csr_query.4gl csr_updcl.4gl
CSR02_OBJS=$(CSR02_SRCS:.4gl=.4go) $(COMMON_OBJS) usps.o version.4go
$(CSR02_4GE): $(CSR02_OBJS)
${C4GL} -o $(CSR02_4GE) $(CSR02_OBJS) $(LDOPTS) -lnls
clean:
rm -f $(CSR_4GES)
rm -f $(CSR02_OBJS)
rm -f $(CSR02_SRCS:.4gl=.4ec)
rm -f $(CSR02_SRCS:.4gl=.ec)
rm -f $(CSR02_SRCS:.4gl=.c)
rm -f $(CSR_FRMS)
$(CSR02_OBJS): ../Common/globals.4gl
4GLSRCS=$(CSR02_SRCS)
# common sources/objects (../Common/globals.4gl, ../Common/common.4gl)
include ../Common/sources.mk
Listing 3
Makefile above builds the program csr02.
The file starts off with the projects standard header, which includes some edit history.
Then a number of macros are defined, allowing the rest of the
Makefile to be clearer, as well as reducing the
possibility of mistakes in references, etc.
The first real target defines what should happen if a bare make
is typed in the program directory. After that, the install
target is defined. The install target can really be defined
almost anywhere, the author finds it useful to define it early.
The next real target actually links the objects into the executable.
All of the objects are build using the rules defined by
../Common/rules.mk.
A clean target is defined, to remove the executables, and the
intermediate objects, and other cruft left around by the build process.
Finally, all the objects are explicitly declared as having a
dependency on .../Common/globals.4gl (which contains
a group of global type definitions and the like.)
Hopefully, this gives you a good idea of what a readable
Makefile should look like, and what targets should be
included.
| Copyright 2000,2001 Central Iowa (Model) Railroad | Contact Us |
Referral Program |
Support |
| $Id: 2002-10.html,v 1.1 2002/08/21 17:07:55 cirr Exp $ | Terms of Service | Privacy Information |