⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tutorial.ms

📁 早期freebsd实现
💻 MS
📖 第 1 页 / 共 5 页
字号:
.Ix 0 def .PMAKE.Ix 0 def variable global MAKE.Ix 0 def MAKEThe name by which PMake was invoked is stored in this variable. Forcompatibility, the name is also stored in the MAKE variable..IP .MAKEFLAGS.Ix 0 def variable global .MAKEFLAGS.Ix 0 def .MAKEFLAGS variable.Ix 0 def variable global MFLAGS.Ix 0 def MFLAGSAll the relevant flags with which PMake was invoked. This does notinclude such things as.B \-for variable assignments. Again for compatibility, this value is storedin the MFLAGS variable as well..RE.LPTwo other variables, ``.INCLUDES'' and ``.LIBS,'' are covered in thesection on special targets in chapter 3..Ix 0 ref variable global .INCLUDES.Ix 0 ref variable global .LIBS.LPGlobal variables may be deleted using lines of the form:.Ix 0 def #undef.Ix 0 def variable deletion.DS#undef \fIvariable\fP.DEThe.CW # ' `must be the first character on the line. Note that this may only bedone on global variables..xH 3 Environment Variables.LP.Ix 0 def variable environmentEnvironment variables are passed by the shell that invoked PMake andare given by PMake to each shell it invokes. They are expanded likeany other variable, but they cannot be altered in any way..LPOne special environment variable,.CW PMAKE ,.Ix 0 def variable environment PMAKEis examined by PMake for command-line flags, variable assignments,etc., it should always use. This variable is examined before theactual arguments to PMake are. In addition, all flags given to PMake,either through the.CW PMAKEvariable or on the command line, are placed in this environmentvariable and exported to each shell PMake executes. Thus recursiveinvocations of PMake automatically receive the same flags as thetop-most one..LPUsing all these variables, you can compress the sample makefile even more:.DSOBJS            = a.o b.o c.oprogram         : $(OBJS)        cc $(.ALLSRC) \-o $(.TARGET)$(OBJS)         : defs.ha.o             : a.c        cc \-c a.cb.o             : b.c        cc \-c b.cc.o             : c.c        cc \-c c.c.DE.Ix 0 ref variable local .ALLSRC.Ix 0 ref .ALLSRC.Ix 0 ref variable local .TARGET.Ix 0 ref .TARGET.Rd 3.xH 2 Comments.LP.Ix 0 def commentsComments in a makefile start with a `#' character and extend to theend of the line. They may appearanywhere you want them, except in a shell command (though the shellwill treat it as a comment, too). If, for some reason, you need to use the `#'in a variable or on a dependency line, put a backslash in front of it.PMake will compress the two into a single `#' (Note: this isn't trueif PMake is operating in full-compatibility mode)..Ix 0 ref flags -M.Ix 0 ref compatibility.xH 2 Parallelism.No.LPPMake was specifically designed to re-create several targets at once,when possible. You do not have to do anything special to cause this tohappen (unless PMake was configured to not act in parallel, in whichcase you will have to make use of the.B \-Land.B \-Jflags (see below)),.Ix 0 ref flags -L.Ix 0 ref flags -Jbut you do have to be careful at times..LPThere are several problems you are likely to encounter. One isthat some makefiles (and programs) are written in such a way that it isimpossible for two targets to be made at once. The program.CW xstr ,for example,always modifies the files.CW stringsand.CW x.c .There is no way to change it. Thus you cannot run two of them at oncewithout something being trashed. Similarly, if you have commandsin the makefile that always send output to the same file, you will notbe able to make more than one target at once unless you change thefile you use. You can, for instance, add a.CW $$$$to the end of the file name to tack on the process ID of the shellexecuting the command (each.CW $$expands to a single.CW $ ,thus giving you the shell variable.CW $$ ).Since only one shell is used for all thecommands, you'll get the same file name for each command in thescript..LPThe other problem comes from improperly-specified dependencies thatworked in Make because of its sequential, depth-first way of examiningthem. While I don't want to go into depth on how PMakeworks (look in chapter 4 if you're interested), I will warn you thatfiles in two different ``levels'' of the dependency tree may beexamined in a different order in PMake than they were in Make. Forexample, given the makefile.DSa               : b cb               : d.DEPMake will examine the targets in the order.CW c ,.CW d ,.CW b ,.CW a .If the makefile's author expected PMake to abort before making.CW cif an error occurred while making.CW b ,or if.CW bneeded to exist before.CW cwas made,s/he will be sorely disappointed. The dependencies areincomplete, since in both these cases,.CW cwould depend on.CW b .So watch out..LPAnother problem you may face is that, while PMake is set up to handle theoutput from multiple jobs in a graceful fashion, the same is not so for input.It has no way to regulate input to different jobs,so if you use the redirection from.CW /dev/ttyI mentioned earlier, you must be careful not to run two of the jobs at once..xH 2 Writing and Debugging a Makefile.LPNow you know most of what's in a makefile, what do you do next? Thereare two choices: (1) use one of the uncommonly-available makefilegenerators or (2) write your own makefile (I leave out the third choice ofignoring PMake and doing everything by hand as being beyond the boundsof common sense)..LPWhen faced with the writing of a makefile, it is usually best to startfrom first principles: just what.I areyou trying to do? What do you want the makefile finally to produce?.LPTo begin with a somewhat traditional example, let's say you need towrite a makefile to create a program,.CW expr ,that takes standard infix expressions and converts them to prefix form (forno readily apparent reason). You've got three source files, in C, thatmake up the program:.CW main.c ,.CW parse.c ,and.CW output.c .Harking back to my pithy advice about dependency lines, you write thefirst line of the file:.DSexpr            : main.o parse.o output.o.DEbecause you remember.CW expris made from.CW .ofiles, not.CW .cfiles. Similarly for the.CW .ofiles you produce the lines:.DSmain.o          : main.cparse.o         : parse.coutput.o        : output.cmain.o parse.o output.o : defs.h.DE.LPGreat. You've now got the dependencies specified. What you need now iscommands. These commands, remember, must produce the target on thedependency line, usually by using the sources you've listed.You remember about local variables? Good, so it should cometo you as no surprise when you write.DSexpr            : main.o parse.o output.o        cc -o $(.TARGET) $(.ALLSRC).DEWhy use the variables? If your program grows to produce postfixexpressions too (which, of course, requires a name change or two), itis one fewer place you have to change the file. You cannot do this forthe object files, however, because they depend on their correspondingsource files.I and.CW defs.h ,thus if you said.DS	cc -c $(.ALLSRC).DEyou'd get (for.CW main.o ):.DS	cc -c main.c defs.h.DEwhich is wrong. So you round out the makefile with these lines:.DSmain.o          : main.c        cc -c main.cparse.o         : parse.c        cc -c parse.coutput.o        : output.c        cc -c output.c.DE.LPThe makefile is now complete and will, in fact, create the program youwant it to without unnecessary compilations or excessive typing onyour part. There are two things wrong with it, however (aside from itbeing altogether too long, something I'll address in chapter 3):.IP 1)The string.CW "main.o parse.o output.o" '' ``is repeated twice, necessitating two changes when you add postfix(you were planning on that, weren't you?). This is in direct violationof de Boor's First Rule of writing makefiles:.QP.IAnything that needs to be written more than onceshould be placed in a variable..IP "\&"I cannot emphasize this enough as being very important to themaintenance of a makefile and its program..IP 2)There is no way to alter the way compilations are performed short ofediting the makefile and making the change in all places. This is eviland violates de Boor's Second Rule, which follows directly from thefirst:.QP.IAny flags or programs used inside a makefile should be placed in a variable sothey may be changed, temporarily or permanently, with the greatest ease..LPThe makefile should more properly read:.DSOBJS            = main.o parse.o output.oexpr            : $(OBJS)        $(CC) $(CFLAGS) -o $(.TARGET) $(.ALLSRC)main.o          : main.c        $(CC) $(CFLAGS) -c main.cparse.o         : parse.c        $(CC) $(CFLAGS) -c parse.coutput.o        : output.c        $(CC) $(CFLAGS) -c output.c$(OBJS)         : defs.h.DEAlternatively, if you like the idea of dynamic sources mentioned insection 2.3.1,.Rm 0 2.3.1.Rd 4.Ix 0 ref "dynamic source".Ix 0 ref source dynamicyou could write it like this:.DSOBJS            = main.o parse.o output.oexpr            : $(OBJS)        $(CC) $(CFLAGS) -o $(.TARGET) $(.ALLSRC)$(OBJS)         : $(.PREFIX).c defs.h        $(CC) $(CFLAGS) -c $(.PREFIX).c.DEThese two rules and examples lead to de Boor's First Corollary:.QP.IVariables are your friends..LPOnce you've written the makefile comes the sometimes-difficult task of.Ix 0 ref debuggingmaking sure the darn thing works. Your most helpful tool to make surethe makefile is at least syntactically correct is the.B \-n.Ix 0 ref flags -nflag, which allows you to see if PMake will choke on the makefile. Thesecond thing the.B \-nflag lets you do is see what PMake would do without it actually doingit, thus you can make sure the right commands would be executed wereyou to give PMake its head..LPWhen you find your makefile isn't behaving as you hoped, the firstquestion that comes to mind (after ``What time is it, anyway?'') is``Why not?'' In answering this, two flags will serve you well:.CW "-d m" '' ``.Ix 0 ref flags -dand.CW "-p 2" .'' ``.Ix 0 ref flags -pThe first causes PMake to tell you as it examines each target in themakefile and indicate why it is deciding whatever it is deciding. Youcan then use the information printed for other targets to see whereyou went wrong. The.CW "-p 2" '' ``flag makes PMake print out its internal state when it is done,allowing you to see that you forgot to make that one chapter depend onthat file of macros you just got a new version of. The output from.CW "-p 2" '' ``is intended to resemble closely a real makefile, but with additionalinformation provided and with variables expanded in those commandsPMake actually printed or executed..LPSomething to be especially careful about is circular dependencies..Ix 0 def dependency circularE.g..DSa		: bb		: c dd		: a.DEIn this case, because of how PMake works,.CW cis the only thing PMake will examine, because.CW dand.CW awill effectively fall off the edge of the universe, making itimpossible to examine.CW b(or them, for that matter).PMake will tell you (if run in its normal mode) all the targetsinvolved in any cycle it looked at (i.e. if you have two cycles in thegraph (naughty, naughty), but only try to make a target in one ofthem, PMake will only tell you about that one. You'll have to try tomake the other to find the second cycle). When run as Make, it willonly print the first target in the cycle..xH 2 Invoking PMake.LP.Ix 0 ref flags.Ix 0 ref arguments.Ix 0 ref usagePMake comes with a wide variety of flags to choose from.They may appear in any order, interspersed with command-line variableassignments and targets to create.The flags are as follows:.IP "\fB\-d\fP \fIwhat\fP".Ix 0 def flags -d.Ix 0 ref debuggingThis causes PMake to spew out debugging information thatmay prove useful to you. If you can'tfigure out why PMake is doing what it's doing, you might try usingthis flag. The.I whatparameter is a string of single characters that tell PMake whataspects you are interested in. Most of what I describe will makelittle sense to you, unless you've dealt with Make before. Justremember where this table is and come back to it as you read on.The characters and the information they produce are as follows:.RS.IP aArchive searching and caching..IP cConditional evaluation..IP dThe searching and caching of directories..IP jVarious snippets of information related to the running of the multipleshells. Not particularly interesting..IP mThe making of each target: what target is being examined; when it waslast modified; whether it is out-of-date; etc..IP pMakefile parsing..IP rRemote execution..IP sThe application of suffix-transformation rules. (See chapter 3).IP tThe maintenance of the list of targets..IP v

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -