home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d1xx
/
d179
/
dmake
/
dmake.doc
< prev
next >
Wrap
Text File
|
1989-02-25
|
11KB
|
326 lines
DMAKE.DOC
BETA RELEASE V0.5 6-Jan-1989
*BETA* *BETA* *BETA*
DMake (c)Copyright 1989 by Matthew Dillon, All Rights Reserved
NOTE!! This is an beta version. I have yet to add all the features
I will eventually want (like \ line continuation). In fact, that's
the whole point of saying 'beta' above ... only people interesting
in exploring and testing the radical features of DMake should be
using this release.
You MUST be familar with 'make' to understand these instructions.
Please read the bug list at the end.
The default file is 'DMakefile'. Options are:
-a force all time comparisons to fail
-f filename use this instead of DMakefile
-n don't actually execute the lines
-v (debugging, have fun)
-d (debugging, have lots of fun)
-s silent .. don't display startup copyright notice
RADICAL FEATURES
We are all familar with the UNIX make utility. We all hate it.
This program is the beginnings of my solution to the problem.
(1) Multiple dependancies on the left:
ram:a.o ram:b.o ram:c.o : a.c b.c c.c
cc %(right) -o %(left)
(2) Wildcards with virtual reverse mapping (I just made that word
up). In the example below, a directory search is used to
resolve the *.c wildcard in the line "ram:*.o : *.c". The left
side is then replaced with the resolved list changing the order
according to the wildcard specification ( *.c -> ram:*.o ).
NOTE that the two wildcard specifications have to contain the
same wildcards in the same order. NO directory search is made
for the objects ... the names are generated from the source.
Finally, note the line 'ram:*.o : *.asm'... note that this
combined with 'ram:*.o : *.c' specifies a joinin of the two
specs ... the 'ram:*.o' spec in the linker line will contain
ALL the objects.
$(EXE) : ram:symbols.m ram:*.o
ln +Q %(ram:*.o) -o $(EXE)
ram:*.o : *.c
cc +Iram:symbols.m %(right) -o %(left)
ram:*.o : *.asm
as %(right) -o %(left)
ram:symbols.m : include:symbols.m
copy %(right) %(left)
(3) $ and % variables. $(SYMBOL) is the standard way to specify
a symbol name. %(symbol) is used to macro-insert wildcard
symbols that appear on the right. Two special %
symbols exist: %(left) contains the stuff on the left and
%(right) contains the stuff on the right.
Note the difference between these two lines:
all: ram:*.o
ln %(ram:*.o) -o c:blah
ram:*.o : *.c
cc %(*.c) -o %(left)
The difference is that the symbol in the linker line contains
ALL the objects while the symbol in the compiler line contains
only the CURRENT .c file being compiled. The reason is explained
below, but it ought to be obvious.
Note that only variables on the right of the ':' may be
specified via their name in a %() macro. You can refer to
the left side with %(left), or the entire right side with
%(right).
(4) Another form that might be useful is this:
ram:*.o : *.c *.h
cc %(*.c) -o %(left)
Carefully now: Each .O file is dependant on its .C file.
Each .O file depends on ALL OF THE .H FILES. Note that here
we cannot say cc %(right) because that would include all the
.h files.
SPECIFICATION OF DEPENDANCIES
The specification of dependancies might seem a bit confusing to
you. Lets take a general example:
a b c d : r s t u
WARNING: If more than one argument exists on the left, the colon
usually must be delimited by spaces on both sides a : b instead of a: b
The rule is as follows: UNTIL one side is exhausted, one item on
the left is dependant on one item on the right. That is, a : r,
b : s, c : t etc....
If there are EXTRA arguments on the right, each argument is applied
to ALL THE ARGUMENTS ON THE LEFT. If I had a 'v' above it would be
equivalent to a : v, b : v, c : v, d : v.
EXTRA arguments on the left are disalloweds except for two cases:
blah : - blah depends on nothing
a b c d e : x - a : x, b : x, c : x , d : x, etc....
*.c : *.h - WRONG THIS DOES NOT SPECIFY ALL THE
.C FILES DEPENDANT ON THE .H FILES!!!
*.o : *.c *.h - This does, as well as saying that each
object depends on its associated .C file
Everything is eventually broken down into four types of dependancies:
wild : wild the wild on the right is directory searched (unless
already resolved previously) and a new set of
dependancies are created matching a single resolved
file name on the right with its equivalent on the
left.
wild : single The wild on the left is directory searched (unless
already resolved previously) and a new set of
dependancies are created matching a single resolved
file name on the left with the single specification
on the right.
single : wild The wild on the right is directory searched (unless
already resolved previously) and a new set of
dependancies are created matching the single item
on the left with each resolved name on the right.
NOTE: ALL of the generated dependancies will be
resolved before the associated command is run. The
associated command is run just once with the
conglomerate right side stuck together in one line
(see a sample linker line)
single : single obvious
Common problems:
ram:*.o ram:*.o : /dir2/*.c *.c RIGHT
cc %(right) -o %(left)
ram:*.o ram:library.o : /dir2/*.c library.c RIGHT
cc %(right) -o %(left)
ram:*.o ram:*.o : /dir2/*.c library.c WRONG
cc %(right) -o %(left)
Specifically, a wild : wild dependancy is broken down into many
single_file : single_file dependancies (after directory searching the
right hand side), while a wild : nonwild dependancy means "each of the
left hand sides depend on the right hand side".. the left hand sides
will be directory searched and expanded, which is NOT what you want
here.
EXECUTION ORDER & VARIABLES
Whenever possible, a depth first execution order will be taken:
all: ram:symbols.m $(OBJS)
ln "%(OBJS)" -o c:blah
$(OBJS): *.c
cc +Iram:symbols.m %(right) -o %(left)
ram:symbols.m : include:symbols.m
copy %(right) %(left)
Here, the symbols are guarenteed to be copied before the objects
are compiled. Variables work somewhat like the normal make. You
can create variables with '=':
SRCS = a.c b.c c.c
OBJS = $(SRCS:"*.c":"ram:*.o") (i.e. ram:a.o, ram:b.o ...)
When used in the Makefile, use $(SYMBOL) to get an exact replacement,
%(SYMBOL) to get an indirect replacement. $(ENVIROMENTVAR) may be
used to retrieve an enviroment variable, %(ENVIROMENTVAR) an indirect
replacement via in enviroment variable:
OBJS = ram:*.o
all: $(OBJS)
ln %(OBJS) ...
Here, %(OBJS) finds "ram:*.o" then re-applies it to %, giving you
the object list. That is: $(OBJS) -> %(ram:*.o) -> "ram:a.o ram:b.o ..."
The other little item you just saw is global name replacement on
symbol inclusion:
$(SYMNAME:"oldwild":"newwild") -if the symbol is a list of
files and not a wildcard
%(SYMNAME:"oldwild":"newwild") -if the symbol is a wildcard
on the righthand side of
the dependancy.
Causes the symbol to be parsed (space delimits) and each filename
rung through the grinder. Each filename is matched with the left
wildcard and then modified according to the right wildcard. Here
are two common DMakefiles:
SRCS = a.c b.c c.c d.c e.c
OBJS = $(SRCS:"*.c":"ram:*.o")
all: $(OBJS)
ln $(OBJS) -o c:blah
$(OBJS) : $(SRCS)
cc %(right) -o %(left)
---
SRCS = *.c
OBJS = ram:*.o
# note, in the line below you must specify $(SRCS) on the right
# hand side of you want %(SRCS) to expand properly
all: $(OBJS) $(SRCS)
ln %(OBJS) -o c:blah
Echo "%(SRCS)"
$(OBJS) : $(SRCS)
cc %(right) -o %(left)
arc: $(SRCS) c:blah
-delete ram:x.arc
arc a ram:x %(right)
Referencing multiple segments separately is relatively easy. In some
cases you cannot use the %(right) symbol because it contains too much:
all: symbols *.o *.lib libraries blah
ln %(*.o) -l %(*.lib)
Here, %(right) would be "symbols a.o b.o ... x.lib y.lib ... libraries blah"
To access just the .o's you may specify a % variable containing the
EXACT wildcard on the right hand side of the dependancy.
ALPHA 'TO-DO'
There are probably lots of bugs. The bigest one now is the lack
of error detection in dependancies and other sequences ... like
referencing variables which do not exist. It won't kill you but
it might make a mess.
You *can* ^C dmake though ... no problem (I hope), though the
current directory might change.
DMake is currently somewhat slow due to the amount of computation
it must do. You will notice the slowness for a large number of
sources. I am not releasing source yet (cause it's a mess and
might have some commercial value). You just wouldn't BELIEVE what
I had to go through!
DMake currently uses Execute() to run commands. Error codes are
ignored. However, you *can* 'cd' ... this is handled internally.
The original directory can be returned to via 'cd' with no argument.
Since Execute() is used, command lines that are too long get
chopped. Eventually there will be no limit (for non BCPL program).
But, since 'cd' is internal, you can sometimes shorten the link
line. In the example below we use the wildcard modification
feature to modify ram:*.o to just *.o in the link line after having
CD'd to ram:
OBJS = ram:*.o
SRCS = *.c
$(EXE): $(OBJS)
cd ram:
ln %(right:"ram:*":"*") -lc32 -o $(EXE)
cd
$(OBJS): $(SRCS)
cc %(right) -o %(left)
** TOO LONG LINES: DMake internally has a limit of 4K for an
internally generated line (for example, the linker line after
all the variables have been expanded). Each file name may be
up to 128 chars long. Note that Execute() cannot handle such
huge lines so if your linker line (the one that is liable to be
too big) becomes too large, I suggest you generate a link file
from DMakefile somehow (I usually shell -c echo *.o >blah or use
various features of LIST .. .giving them an (unexpanded) wildcard
and letting them do a directory scan to create a file full of
arguments. You must be careful in this case of leaving other
unrelated object modules lying around in your temporary directory.
I suggest you make a special purpose directory to hold the objects
(in ram:blah or whereever) to prevent the shell/LIST from picking
up unwanted files when they do a directory scan.
This solves a basic problem in many make files. (1) getting back
to your original directory, (2) putting sources and objects wherever
you want to without creating a mess of the makefile.