📄 tutorial.ms
字号:
be preceded by at least one tab..LPEach target has associated with it a shell script made up ofone or more of these shell commands. The creation script for a targetshould immediately follow the dependency line for that target. Whileany given target may appear on more than one dependency line, only oneof these dependency lines may be followed by a creation script, unlessthe `::' operator was used on the dependency line..Ix 0 ref operator double-colon.Ix 0 ref ::.No.LPIf the double-colon was used, each dependency line for the targetmay be followed by a shell script. That script will only be executedif the target on the associated dependency line is out-of-date withrespect to the sources on that line, according to the rules I gaveearlier.I'll give you a good example of this later on..LPTo expand on the earlier makefile, you might add commands as follows:.DSprogram : a.o b.o c.o cc a.o b.o c.o \-o programa.o b.o c.o : defs.ha.o : a.c cc \-c a.cb.o : b.c cc \-c b.cc.o : c.c cc \-c c.c.DE.LPSomething you should remember when writing a makefile is, thecommands will be executed if the.I targeton the dependency line is out-of-date, not the sources..Ix 0 ref target.Ix 0 ref source.Ix 0 ref out-of-dateIn this example, the command.CW "cc \-c a.c" '' ``will be executed if.CW a.ois out-of-date. Because of the `:' operator,.Ix 0 ref :.Ix 0 ref operator colonthis means that should.CW a.c.I or.CW defs.hhave been modified more recently than.CW a.o ,the command will be executed.CW a.o "\&" (will be considered out-of-date)..Ix 0 ref out-of-date.LPRemember how I said the only difference between a makefile shellcommand and a regular shell command was the leading tab? I lied. Thereis another way in which makefile commands differ from regular ones.The first two characters after the initial whitespace are treatedspecially.If they are any combination of `@' and `\-', they cause PMake to dodifferent things..LPIn most cases, shell commands are printed before they'reactually executed. This is to keep you informed of what's going on. Ifan `@' appears, however, this echoing is suppressed. In the case of an.CW echocommand, say.CW "echo Linking index" ,'' ``it would berather silly to see.DSecho Linking indexLinking index.DE.LPso PMake allows you to place an `@' before the command.CW "@echo Linking index" '') (``to prevent the command from being printed..LPThe other special character is the `\-'. In case you didn't know,shell commands finish with a certain ``exit status.'' This status ismade available by the operating system to whatever program invoked thecommand. Normally this status will be 0 if everything went ok andnon-zero if something went wrong. For this reason, PMake will consideran error to have occurred if one of the shells it invokes returns a non-zerostatus. When it detects an error, PMake's usual action is to abortwhatever it's doing and exit with a non-zero status itself (any othertargets that were being created will continue being made, but nothingnew will be started. PMake will exit after the last job finishes).This behavior can be altered, however, by placing a `\-' at the frontof a command.CW "\-mv index index.old" ''), (``certain command-line arguments,or doing other things, to be detailed later. In sucha case, the non-zero status is simply ignored and PMake keeps chuggingalong..No.LPBecause all the commands are given to a single shell to execute, suchthings as setting shell variables, changing directories, etc., lastbeyond the command in which they are found. This also allows shellcompound commands (like.CW forloops) to be entered in a natural manner.Since this could cause problems for some makefiles that depend oneach command being executed by a single shell, PMake has a.B \-B.Ix 0 ref compatibility.Ix 0 ref flags -Bflag (it stands for backwards-compatible) that forces each command tobe given to a separate shell. It also does several other things, allof which I discourage since they are now old-fashioned.\|.\|.\|..No.LPA target's shell script is fed to the shell on its (the shell's) input stream.This means that any commands, such as.CW cithat need to get input from the terminal won't work right \*- they'llget the shell's input, something they probably won't find to theirliking. A simple way around this is to give a command like this:.DSci $(SRCS) < /dev/tty.DEThis would force the program's input to come from the terminal. If youcan't do this for some reason, your only other alternative is to usePMake in its fullest compatibility mode. See .B Compatibilityin chapter 4..Ix 0 ref compatibility.LP.xH 2 Variables.LPPMake, like Make before it, has the ability to save text in variablesto be recalled later at your convenience. Variables in PMake are usedmuch like variables in the shell and, by tradition, consist ofall upper-case letters (you don't.I haveto use all upper-case letters.In fact there's nothing to stop you from calling a variable.CW @^&$%$ .Just tradition). Variables are assigned-to using lines of the form.Ix 0 def variable assignment.DSVARIABLE = value.DE.Ix 0 def variable assignmentappended-to by.DSVARIABLE += value.DE.Ix 0 def variable appending.Ix 0 def variable assignment appended.Ix 0 def +=conditionally assigned-to (if the variable isn't already defined) by.DSVARIABLE ?= value.DE.Ix 0 def variable assignment conditional.Ix 0 def ?=and assigned-to with expansion (i.e. the value is expanded (see below)before being assigned to the variable\*-useful for placing a value atthe beginning of a variable, or other things) by.DSVARIABLE := value.DE.Ix 0 def variable assignment expanded.Ix 0 def :=.LPAny whitespace before.I valueis stripped off. When appending, a space is placed between the oldvalue and the stuff being appended..LPThe final way a variable may be assigned to is using.DSVARIABLE != shell-command.DE.Ix 0 def variable assignment shell-output.Ix 0 def !=In this case, .I shell-commandhas all its variables expanded (see below) and is passed off to ashell to execute. The output of the shell is then placed in thevariable. Any newlines (other than the final one) are replaced byspaces before the assignment is made. This is typically used to findthe current directory via a line like:.DSCWD != pwd.DE.LP.B Note:this is intended to be used to execute commands that produce small amountsof output (e.g. ``pwd''). The implementation is less than intelligent and willlikely freeze if you execute something that produces thousands ofbytes of output (8 Kb is the limit on many UNIX systems)..LPThe value of a variable may be retrieved by enclosing the variablename in parentheses or curly braces and preceeding the whole thingwith a dollar sign..LPFor example, to set the variable CFLAGS to the string.CW "\-I/sprite/src/lib/libc \-O" ,'' ``you would place a line.DSCFLAGS = \-I/sprite/src/lib/libc \-O.DEin the makefile and use the word.CW "$(CFLAGS)"wherever you would like the string.CW "\-I/sprite/src/lib/libc \-O"to appear. This is called variable expansion..Ix 0 def variable expansion.No.LPUnlike Make, PMake will not expand a variable unless it knowsthe variable exists. E.g. if you have a.CW "${i}"in a shell command and you have not assigned a value to the variable.CW i (the empty string is considered a value, by the way), where Make would havesubstituted the empty string, PMake will leave the.CW "${i}"alone.To keep PMake from substituting for a variable it knows, precede thedollar sign with another dollar sign.(e.g. to pass.CW "${HOME}"to the shell, use.CW "$${HOME}" ).This causes PMake, in effect, to expand the.CW $macro, which expands to a single.CW $ .For compatibility, Make's style of variable expansion will be usedif you invoke PMake with any of the compatibility flags (\c.B \-V ,.B \-Bor.B \-M .The.B \-Vflag alters just the variable expansion)..Ix 0 ref flags -V.Ix 0 ref flags -B.Ix 0 ref flags -M.Ix 0 ref compatibility.LP.Ix 0 ref variable expansionThere are two different times at which variable expansion occurs:When parsing a dependency line, the expansion occurs immediatelyupon reading the line. If any variable used on a dependency line isundefined, PMake will print a message and exit.Variables in shell commands are expanded when the command isexecuted.Variables used inside another variable are expanded whenever the outervariable is expanded (the expansion of an inner variable has no effecton the outer variable. I.e. if the outer variable is used on a dependencyline and in a shell command, and the inner variable changes valuebetween when the dependency line is read and the shell command isexecuted, two different values will be substituted for the outervariable)..Ix 0 def variable types.LPVariables come in four flavors, though they are all expanded the sameand all look about the same. They are (in order of expanding scope):.RS.IP \(bu 2Local variables..Ix 0 ref variable local.IP \(bu 2Command-line variables..Ix 0 ref variable command-line.IP \(bu 2Global variables..Ix 0 ref variable global.IP \(bu 2Environment variables..Ix 0 ref variable environment.RE.LPThe classification of variables doesn't matter much, except that theclasses are searched from the top (local) to the bottom (environment)when looking up a variable. The first one found wins..xH 3 Local Variables.LP.Ix 0 def variable localEach target can have as many as seven local variables. These arevariables that are only ``visible'' within that target's shell scriptand contain such things as the target's name, all of its sources (fromall its dependency lines), those sources that were out-of-date, etc.Four local variables are defined for all targets. They are:.RS.IP ".TARGET".Ix 0 def variable local .TARGET.Ix 0 def .TARGETThe name of the target..IP ".OODATE".Ix 0 def variable local .OODATE.Ix 0 def .OODATEThe list of the sources for the target that were considered out-of-date.The order in the list is not guaranteed to be the same as the order inwhich the dependencies were given..IP ".ALLSRC".Ix 0 def variable local .ALLSRC.Ix 0 def .ALLSRCThe list of all sources for this target in the order in which theywere given..IP ".PREFIX".Ix 0 def variable local .PREFIX.Ix 0 def .PREFIXThe target without its suffix and without any leading path. E.g. forthe target.CW ../../lib/compat/fsRead.c ,this variable would contain.CW fsRead ..RE.LPThree other local variables are set only for certain targets underspecial circumstances. These are the ``.IMPSRC,''.Ix 0 ref variable local .IMPSRC.Ix 0 ref .IMPSRC``.ARCHIVE,''.Ix 0 ref variable local .ARCHIVE.Ix 0 ref .ARCHIVEand ``.MEMBER''.Ix 0 ref variable local .MEMBER.Ix 0 ref .MEMBERvariables. When they are set and how they are used is described later..LPFour of these variables may be used in sources as well as in shellscripts..Ix 0 def "dynamic source".Ix 0 def source dynamicThese are ``.TARGET'', ``.PREFIX'', ``.ARCHIVE'' and ``.MEMBER''. Thevariables in the sources are expanded once for each target on thedependency line, providing what is known as a ``dynamic source,''.Rd 0allowing you to specify several dependency lines at once. For example,.DS$(OBJS) : $(.PREFIX).c.DEwill create a dependency between each object file and itscorresponding C source file..xH 3 Command-line Variables.LP.Ix 0 def variable command-lineCommand-line variables are set when PMake is first invoked by giving avariable assignment as one of the arguments. For example,.DSpmake "CFLAGS = -I/sprite/src/lib/libc -O".DEwould make .CW CFLAGSbe a command-line variable with the given value. Any assignments to.CW CFLAGSin the makefile will have no effect, because once itis set, there is (almost) nothing you can do to change a command-linevariable (the search order, you see). Command-line variables may beset using any of the four assignment operators, though only.CW =and.CW ?=behave as you would expect them to, mostly because assignments tocommand-line variables are performed before the makefile is read, thusthe values set in the makefile are unavailable at the time..CW +=.Ix 0 ref +=.Ix 0 ref variable assignment appendedis the same as.CW = ,because the old value of the variable is sought only in the scope inwhich the assignment is taking place (for reasons of efficiency that Iwon't get into here)..CW :=and.CW ?=.Ix 0 ref :=.Ix 0 ref ?=.Ix 0 ref variable assignment expanded.Ix 0 ref variable assignment conditionalwill work if the only variables used are in the environment..CW !=is sort of pointless to use from the command line, since the sameeffect can no doubt be accomplished using the shell's own commandsubstitution mechanisms (backquotes and all that)..xH 3 Global Variables.LP.Ix 0 def variable globalGlobal variables are those set or appended-to in the makefile.There are two classes of global variables: those you set and those PMake sets.As I said before, the ones you set can have any name you want them to have,except they may not contain a colon or an exclamation point.The variables PMake sets (almost) always begin with aperiod and always contain upper-case letters, only. The variables areas follows:.RS.IP .PMAKE.Ix 0 def variable global .PMAKE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -