http://invisible-island.net/make-tools/
Copyright © 2014,2019 by Thomas E. Dickey
Here are some files from ded in the mid-1990s illustrating how I used the archive rules to keep the makefiles simple.
Most of this makefile is lists: CSRC
and
OBJS
. The latter is used for archive rules;
the $Z
symbol is the name of the archive, while the
parentheses around the object filenames tells the make
program that those refer to files stored within the archive.
The makefile uses the include
feature introduced
by augmake,
first widely used in AT&T's SVr2 make program in
1984.
The library which I wrote for ded
and related programs has several subdirectories containing
sources. This particular file is used for the
cm_funcs
subdirectory.
# $Id: Makefile,v 12.1 1994/07/02 12:56:29 tom Exp $
# MAKE-file for miscellaneous library routines
####### (Environment) ##########################################################
include ../td_defns.mk
####### (Standard Lists) #######################################################
CSRC =\
cutoff.c \
newzone.c \
next_ver.c \
packdate.c \
rcs_dir.c \
rcsargpr.c \
rcsdebug.c \
rcsedit.c \
rcskeys.c \
rcslast.c \
rcsload.c \
rcslocks.c \
rcsname.c \
rcspath.c \
rcsperm.c \
rcssymbs.c \
rcstemp.c \
rcstime.c \
samebr.c \
sccs_dir.c \
sccsdbug.c \
sccslast.c \
sccsname.c \
vcs_file.c \
vercmp.c
SOURCES = Makefile descrip.mms $(CSRC)
OBJS =\
$Z(cutoff.o) \
$Z(newzone.o) \
$Z(next_ver.o) \
$Z(packdate.o) \
$Z(rcs_dir.o) \
$Z(rcsargpr.o) \
$Z(rcsdebug.o) \
$Z(rcsedit.o) \
$Z(rcskeys.o) \
$Z(rcslast.o) \
$Z(rcsload.o) \
$Z(rcslocks.o) \
$Z(rcsname.o) \
$Z(rcspath.o) \
$Z(rcsperm.o) \
$Z(rcssymbs.o) \
$Z(rcstemp.o) \
$Z(rcstime.o) \
$Z(samebr.o) \
$Z(sccs_dir.o) \
$Z(sccsdbug.o) \
$Z(sccslast.o) \
$Z(sccsname.o) \
$Z(vcs_file.o) \
$Z(vercmp.o)
ALL = $Z
####### (Standard Productions) #################################################
include ../td_rules.mk
####### (Details of Productions) ###############################################
$Z(rcsargpr.o)\
$Z(rcsedit.o)\
$Z(rcskeys.o)\
$Z(rcslast.o)\
$Z(rcsload.o)\
$Z(rcslocks.o)\
$Z(rcsname.o)\
$Z(rcspath.o)\
$Z(rcsperm.o)\
$Z(rcssymbs.o)\
$Z(rcstime.o)\
$Z(samebr.o)\
$Z(vcs_file.o): $(RCSDEFS_H)
$Z(sccsdbug.o)\
$Z(sccslast.o)\
$Z(sccsname.o): $(SCCSDEFS_H)
The top-most “include” file contains the suffix
rule .c.a
, which (because of the way the targets are
expressed) is treated as an archive rule. It cleans up
after the compile, leaving only an updated archive file.
# $Id: td_lib.mk,v 12.1 1993/09/22 13:33:35 dickey Exp $
# common definitions for makefiles built over TD_LIB library.
####### (Environment) ##########################################################
TD_LIB = td_lib
# TOP = ../../.. -- must define
B = ../bin
I = $(TOP)/$(TD_LIB)/include
L = $(TOP)/$(TD_LIB)/lib
GET = checkout
COPY = cp -p
PUT = rm -f $@; $(COPY) $? $@
MAKE = make $(MFLAGS) -k$(MAKEFLAGS) CFLAGS="$(CFLAGS)" COPY="$(COPY)"
#CC = gcc -g -O -Wall -Wshadow -Wconversion -Wstrict-prototypes -Wmissing-prototypes
#LINK = purify $(CC)
LINK = $(CC)
INSTALL_BIN = $(TOP)/install_bin
INSTALL_LIB = $(TOP)/install_lib
INSTALL_MAN = $(TOP)/install_man
####### (Command-line Options) #################################################
INCLUDES= -I. -I$I
CPP_OPTS= $(DEFINES) $(INCLUDES)
LIBS = $L/$(TD_LIB).a
DATE = echo '** '`date` >> $@
LINTLIBS= -ltd
LINTOPTS= $(CPP_OPTS) $(LINTLIBS)
####### (Standard Lists) #######################################################
# don't put .a into CLEAN, because VERDIX-ADA uses that for source!
CLEAN = *.[oi] *.lint *.bak *.log *.out *.tst .nfs* core
DESTROY =sh -c 'for i in *;do case $$i in RCS);; *) rm -f $$i;;esac;done;exit 0'
RUN_TESTS=sh -c '$@.sh 2>&1 | tee -a $@.out'
PTYPES_H = $I/ptypes.h $I/td_lib.h
CURSES_H = $(PTYPES_H) $I/td_curse.h
QSORT_H = $(PTYPES_H) $I/td_qsort.h
RCSDEFS_H = $(PTYPES_H) $I/rcsdefs.h $I/deltree.h
SCCSDEFS_H = $(PTYPES_H) $I/sccsdefs.h
####### (Development) ##########################################################
CPROTO = cproto -e -i -fo'\\n\\t\\t' -fp'\\n\\t\\t'
LINT_EACH = sh -c 'for i in $?;do echo $$i:; tdlint $(LINTOPTS) $$i >>$@;done'
.SUFFIXES: .c .o .a
.c.o: ; $(CC) $(CPP_OPTS) $(CFLAGS) -c $<
.c.a:
@echo compile $<
@$(CC) $(CFLAGS) $(CPP_OPTS) -c $*.c
@ar rv $@ $*.o
@rm -f $*.o
.SUFFIXES: .i .proto .lint .tst
.c.i: ; $(CC) $(CPP_OPTS) -E -C $< >$@
.c.proto: ; $(CPROTO) $(CPP_OPTS) $< >$@
.c.lint: ; tdlint $(LINTOPTS) $< >$@
.c.tst: ; $(CC) -o $@ -DTEST $(CFLAGS) $(CPP_OPTS) $< $Z $(LIBS)
.SUFFIXES: .man .cat
.man.cat:
rm -f $@
nroff -man $? >$@
To keep the leaf-directories makefiles simple, they first include this file:
# $Id: td_defns.mk,v 12.1 1994/07/02 12:56:39 tom Exp $
# Common make-definitions for TD_LIB
.SUFFIXES:
.SUFFIXES: .c .o .a
####### (Environment) ##########################################################
TOP = ../../..
include ../../support/td_lib.mk
LINTLIBS = -ltd -lcurses -ltermcap
Z = $L/$(TD_LIB).a
SOURCES = Makefile descrip.mms $(CSRC)
ALL = $Z
The actual makefile targets are in this complementary file:
# $Id: td_rules.mk,v 12.1 1994/07/02 12:53:57 tom Exp $
# Common make-rules for TD_LIB
####### (Standard Productions) #################################################
all\
run_test\
install: $(SOURCES) $(ALL)
clean: ; rm -f $(CLEAN)
clobber: clean ; rm -f $(ALL)
destroy: ; $(DESTROY)
sources: $(SOURCES)
####### (Details of Productions) ###############################################
$Z: $(OBJS)
ranlib $Z
.PRECIOUS: $Z
$(OBJS): $(PTYPES_H)
####### (Development) ##########################################################
$(SOURCES): ; $(GET) $@
lint.out: $(CSRC) ; $(DATE); $(LINT_EACH)
lincnt.out: $(CSRC) ; $(DATE); lincnt $(CSRC) >>$@
tags: $(CSRC) ; dotags $(CSRC)