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

📄 ch55.htm

📁 linux-unix130.linux.and.unix.ebooks130 linux and unix ebookslinuxLearning Linux - Collection of 12 E
💻 HTM
📖 第 1 页 / 共 3 页
字号:


dothis.o: dothis.c



      cc -c dothis.c



dothat.o: dothat.c



      cc -c dothat.c



itquick.o: itquick.s



      as -o itquick.o itquick.s



fresh:



      rm *.o



maybe.h: yes.h no.h



      cp yes.h no.h /users/sue/



</FONT></PRE>



<P>Thus, your <TT>makefile</TT> is now equipped to build two variations of the same



program. Issue the command<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">$ make someonehappy1



</FONT></PRE>



<P>to build the version using the interface routines found in <TT>dothis.c</TT>.



Build your other program that uses the <TT>dothat.c</TT> interface routines with



the following command:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">$ make someonhappy2



</FONT></PRE>



<H4 ALIGN="CENTER"><A NAME="Heading9<FONT COLOR="#000077">Forcing Recompiles</FONT></H4>



<P>It is possible to trick <TT>make</TT> into doing (or not doing) recompiles. An



example of a situation in which you may not want <TT>make</TT> to recompile is when



you have copied files from another directory. This operation updates the modification



times of the files, though they may not need to be recompiled. You can use the <TT>touch</TT>



utility or <TT>make</TT> with the <TT>-t</TT> option to update the modification times



of all target files defined in the <TT>makefile</TT>.







<DL>



	<DT></DT>



</DL>











<DL>



	<DD>



<HR>



<A NAME="Heading10<FONT COLOR="#000077"><B>TIP: </B></FONT>Do you want to test



	your <TT>makefile</TT>? Use <TT>make</TT> with the <TT>-n</TT> option. It will echo



	the commands to you without actually executing them.



<HR>







</DL>







<H4 ALIGN="CENTER"><A NAME="Heading11<FONT COLOR="#000077">Macros</FONT></H4>



<P><TT>make</TT> lets you define macros within your <TT>makefile</TT>, which are



expanded by <TT>make</TT> before the program executes the commands found in your



<TT>makefile</TT>. Macros have the following format:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">macro identifier = text



</FONT></PRE>



<P>The text portion can be the name of a file, a directory, a program to execute,



or just about anything. Text can also be a list of files, or a literal text string



enclosed by double quotes. The following is an example of macros that you might use



in your <TT>someonehappy</TT> <TT>makefile</TT>:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">LIBFILES=/usr/happy/lib/likeatree.a



objects = main.o dothis.o



CC = /usr/bin/cc



1version=&quot;This is one version of someonehappy&quot;



OPTIONS =



</FONT></PRE>



<P>As a matter of convention, macros are usually in uppercase, but they can be typed



in lowercase as in the previous example. Notice that the <TT>OPTIONS</TT> macro defined



in the list has no text after the equal sign. This means that you have assigned the



<TT>OPTIONS</TT> macro to a null string. Whenever this macro is found in a command



list, <TT>make</TT> will generate the command as if there were no <TT>OPTIONS</TT>



macro at all. By the same token, if you try to refer to an undefined macro, <TT>make</TT>



will ignore it during command generation.</P>



<P>Macros can also include other macros, as in the following example:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">BOOK_DIR = /users/book/



MY_CHAPTERS = ${BOOK_DIR}/pete/book



</FONT></PRE>



<P>Macros must be defined before they are used on a dependency line, although they



can refer to each other in any order.</P>



<P><TT>make</TT> has internal macros that it recognizes for commonly used commands.



The C compiler is defined by the <TT>CC</TT> macro, and the flags that the C compiler



uses are stored in the <TT>CFLAGS</TT> macro.</P>



<P>Macros are referred to in the <TT>makefile</TT> by enclosing the macro name in



curly brackets and preceding the first bracket with a <TT>$</TT>. If you use macros



in the first <TT>someonehappy</TT> <TT>makefile</TT>, it might look like this:<FONT



COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF"># Time to exercise some macros



CC = /usr/bin/cc



AS = /usr/bin/as



OBJS = main.o dothis.o itquick.o



YN = yes.h no.h



# We could do the following if this part of the path might be used elsewhere



LIB_DIR = /usr/happy/lib



LIB_FILES = ${LIB_DIR}/likeatree.a



someonehappy:  ${OBJS} ${LIB_FILES}



      ${CC} -o someonehappy ${OBJS} ${LIB_FILES}



main.o: main.c



      cc -c main.c



dothis.o: dothis.c



      cc -c dothis.c



itquick.o: itquick.s



      ${AS} -o itquick.o itquick.s



fresh:



      rm *.o



maybe.h: ${YN}



      cp yes.h no.h /users/sue/



</FONT></PRE>



<P><TT>make</TT> also recognizes shell variables as macros if they are set in the



same shell in which <TT>make</TT> was invoked. For example, if a C shell variable



named <TT>BACKUP</TT> is defined by<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">$ setenv BACKUP /usr/happy/backup



</FONT></PRE>



<P>you can use it as a macro in your <TT>makefile</TT>. The macro definition<FONT



COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">OTHER_BACKUP = ${BACKUP}/last_week



</FONT></PRE>



<P>would be expanded by <TT>make</TT> to be<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">/usr/happy/backup/last_week



</FONT></PRE>



<P>You can reduce the size of your <TT>makefile</TT> even further. For starters,



you don't have to specify the executables for the C and assembler compilers because



these are known to <TT>make</TT>. You can also use two other internal macros, referred



to by the symbols <TT>$@</TT> and <TT>$?</TT>. The <TT>$@</TT> macro always denotes



the current target; the <TT>$?</TT> macro refers to all the dependents that are newer



than the current target. Both of these macros can only be used within command lines.



Thus, the <TT>makefile</TT> command<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">someonehappy: ${OBJS} ${LIB_FILES}



</FONT></PRE>







<PRE><FONT COLOR="#0066FF">      ${CC} -o $@ ${OBJS} ${LIB_FILES}



</FONT></PRE>



<P>will generate<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">/usr/bin/cc -o someonehappy main.o dothis.o itquick.o /usr/happy/lib/likeatree.a



</FONT></PRE>



<P>when using the following:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">$ make someonehappy



</FONT></PRE>



<P>The <TT>$?</TT> macro is a little trickier to use, but quite powerful. Use it



to copy the <TT>yes.h</TT> and <TT>no.h</TT> header files to Sue's home directory



whenever they are updated. The <TT>makefile</TT> command<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">maybe.h: ${YN}



</FONT></PRE>







<PRE><FONT COLOR="#0066FF">      cp $? /users/sue/



</FONT></PRE>



<P>evaluates to<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">cp no.h /users/sue/



</FONT></PRE>



<P>if only the <TT>no.h</TT> header file has been modified. It also evaluates to<FONT



COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">cp yes.h no.h /users/sue/



</FONT></PRE>



<P>if both header files have been updated since the last <TT>make</TT> of <TT>someonehappy</TT>.</P>



<P>So, with a little imagination, you can make use of some well-placed macros to



shrink your <TT>makefile</TT> further, and arrive at the following:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF"># Papa's got a brand new makefile



OBJS = main.o dothis.o itquick.o



YN = yes.h no.h



LIB_DIR = /usr/happy/lib



LIB_FILES = ${LIB_DIR}/likeatree.a



someonehappy:  ${OBJS} ${LIB_FILES}



      ${CC} -o $@ ${OBJS} ${LIB_FILES}



main.o: main.c



      cc -c $?



dothis.o: dothis.c



      cc -c $?



itquick.o: itquick.s



      ${AS} -o $@ $?



fresh:



      rm *.o



maybe.h: ${YN}







      cp $? /users/sue/



</FONT></PRE>



<H4 ALIGN="CENTER"><A NAME="Heading12<FONT COLOR="#000077">Suffix Rules</FONT></H4>



<P>As mentioned earlier in the &quot;Macros&quot; section, <TT>make</TT> does not



necessarily require everything to be spelled out for it in the <TT>makefile</TT>.



Because <TT>make</TT> was designed to enhance software development in Linux, it has



knowledge about how the compilers work, especially for C. For example, <TT>make</TT>



knows that the C compiler expects to compile source code files having a <TT>.c</TT>



suffix, and that it generates object files having an <TT>.o</TT> suffix. This knowledge



is encapsulated in a suffix rule: <TT>make</TT> examines the suffix of a target or



dependent to determine what it should do next.</P>



<P>There are many suffix rules that are internal to <TT>make</TT>, most of which



deal with the compilation of source and linking of object files. The default suffix



rules that are applicable in your <TT>makefile</TT> are shown here:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">.SUFFIXES: .o .c .s







.c.o:



      ${CC} ${CFLAGS} -c $&lt;







.s.o:







      ${AS} ${ASFLAGS} -o $@ $&lt;



</FONT></PRE>



<P>The first line is a dependency line stating the suffixes that <TT>make</TT> should



try to find rules for if none are explicitly written in the <TT>makefile</TT>. The



second dependency line is terse: Essentially, it tells <TT>make</TT> to execute the



associated C compile on any file with a <TT>.c</TT> suffix whose corresponding object



file (<TT>.o</TT>) is out of date. The third line is a similar directive for assembler



files. The new macro <TT>$&lt; </TT>has a similar role to that of the <TT>$?</TT>



directive, but can only be used in a suffix rule. It represents the dependency that



the rule is currently being applied to.</P>



<P>These default suffix rules are powerful in that all you really have to list in



your <TT>makefile</TT> are any relevant object files. <TT>make</TT> does the rest:



If<TT> main.o</TT> is out of date, <TT>make</TT> automatically searches for a <TT>main.c</TT>



file to compile. This also works for the <TT>itquick.o</TT> object file. After the



object files are updated, the compile of <TT>someonehappy</TT> can execute.</P>



<P>You can also specify your own suffix rules in order to have <TT>make</TT> perform



other operations. Say, for instance, that you want to copy object files to another



directory after they are compiled. You could explicitly write the appropriate suffix



rule in the following way:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">.c.o:



      ${CC} ${CFLAGS} -c $&lt;







      cp $@  backup



</FONT></PRE>



<P>The <TT>$@</TT> macro, as you know, refers to the current target. Thus, on the



dependency line shown, the target is a <TT>.o</TT> file, and the dependency is the



corresponding <TT>.c</TT> file.</P>



<P>Now that you know how to exploit the suffix rule feature of <TT>make</TT>, you



can rewrite your <TT>someonehappy</TT> <TT>makefile</TT> for the last time (I'll



bet you're glad to hear that news).<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF"># The final kick at the can



OBJS = main.o dothis.o itquick.o



YN = yes.h no.h



LIB_FILES = /usr/happy/lib/likeatree.a



someonehappy:  ${OBJS} ${LIB_FILES}



      ${CC} -o $@ ${OBJS} ${LIB_FILES}



fresh:



      rm *.o



maybe.h: ${YN}







      cp $? /users/sue/



</FONT></PRE>



<P>This <TT>makefile</TT> works as your first one did, and you can compile the entire



program using the following:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">$ make somonehappy



</FONT></PRE>



<P>Or, just compile one component of it as follows:<FONT COLOR="#0066FF"></FONT>



<PRE><FONT COLOR="#0066FF">$ make itquick.o



</FONT></PRE>



<P>This discussion only scratches the surface of <TT>make</TT>. You should refer



to the man page for <TT>make</TT> to further explore its many capabilities.



<H3 ALIGN="CENTER"><A NAME="Heading13<FONT COLOR="#000077">RCS</FONT></H3>



<P>One of the other important factors involved in software development is the management



of source code files as they evolve. On any type of software project, you might continuously



release newer versions of a program as features are added or bugs are fixed. Larger



projects usually involve several programmers, which can complicate versioning and



concurrency issues even further. In the absence of a system to manage the versioning



of source code on your behalf, it would be very easy to lose track of the versions



of files. This could lead to situations in which modifications are inadvertently



wiped out or redundantly coded by different programmers. Fortunately, Linux provides



just such a versioning system, called RCS (Revision Control System).</P>



<P>RCS can administer the versioning of files by controlling access to them. For



anyone to update a particular file, the person must record in RCS who she is and



why she is making the changes. RCS can then record this information along with the



updates in an RCS file separate from the original version. Because the updates are



kept independent from the original file, you can easily return to any previous version



if necessary. This can also have the benefit of conserving disk space because you



don't have to keep copies of the entire file around. This is certainly true for situations



in which versions differ only by a few lines; it is less useful if there are only



a few versions, each of which is largely different from the next.



<H4 ALIGN="CENTER"><A NAME="Heading14<FONT COLOR="#000077">Deltas</FONT></H4>



<P>The set of changes that RCS records for an RCS file is referred to as a delta.



The version number has two forms. The first form contains a release number and a



level number. The release number is normally used to reflect a significant change



to the code in the file. When you first create an RCS file, it is given a default



release of 1 and level of 1 (1.1). RCS automatically assigns incrementally higher



integers for the level number within a release (for example, 1.1, 1.2, 1.3, and so



on). RCS enables you to override this automatic incrementing whenever you want to



upgrade the version to a new release.</P>



<P>The second form of the version number also has the release and level components,



but adds a branch number followed by a sequence number. You might use this form if



you were developing a program for a client that required bug fixes, but you don't



want to place these fixes in the next &quot;official&quot; version. Although the



next version may include these fixes anyway, you may be in the process of adding



features that would delay its release. For this reason, you would add a branch to



your RCS file for this other development stream, which would then progress with sequence



increments. For example, imagine that you have a planned development stream of 3.1,



3.2, 3.3, 3.4, and so on. You realize that you need to introduce a bug fix stream



at 3.3, which will not include the functionality proposed for 3.4. This bug fix stream



would have a numbering sequence of 3.3.1.1, 3.3.1.2, 3.3.1.3, and so on.







<DL>



	<DT></DT>



</DL>











<DL>



	<DD>



<HR>



<A NAME="Heading15<FONT COLOR="#000077"><B>TIP: </B></FONT>As a matter of good



	development practice, each level or sequence should represent a complete set of changes.



	That implies that the code in each version is tested to be free of any obvious bugs.



<HR>







</DL>











<DL>



	<DT></DT>



</DL>

⌨️ 快捷键说明

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