|
|
1.1 root 1: .nr PS 12
2: .NH
3: Software Management
4: .nr PS 10
5: .XS
6: \*(SN Software Management
7: .XE
8: .PP
9: Although the
10: .UX
11: operating system offers a rich variety of programming tools, a frequent
12: complaint is that there are too few guidelines showing how to use them
13: in a coherent way. SPMS provides the `glue' for coordinating the use
14: of these tools and this section describes the techniques which have been
15: devised for the development and maintenance of software packages.
16: .NH 2
17: Program Development Techniques
18: .XS
19: \*(SN Program Development Techniques
20: .XE
21: .PP
22: Before discussing the maintenance of complete software packages, it is
23: worthwhile to review the basic commands for managing individual programs
24: and libraries. The commands are summarized in table 2 and explained below
25: in more detail.
26: .KF
27:
28: .SM
29: .ce
30: \fITable 2.\fR Program development commands
31: .NL
32:
33: .so develop.tbl
34: .KE
35: .NH 3
36: \fIProgram compilation\fR
37: .XS
38: \*(SN Program compilation
39: .XE
40: .PP
41: The command
42: .ID
43: % \fBmake\fR
44: .DE
45: compiles source files into object files and loads them together
46: to produce an executable program. Although
47: .I make
48: uses built-in information for generating the object files
49: from the source files, the decision on how to load the program is
50: left to the user. By default, the program makefiles produced by
51: .I mkmf
52: use the C compiler for this purpose. However, if the programming
53: language is not C, the LINKER macro definition in the makefile should
54: be altered accordingly. For Fortran this can be done by typing the command
55: .ID
56: % \fBmkmf LINKER=f77\fR
57: .DE
58: and for Pascal
59: .ID
60: % \fBmkmf LINKER=pc\fR
61: .DE
62: .PP
63: Compiler options can be specified by adding certain macros to a
64: makefile. For example, the macro
65: .ID
66: CFLAGS = \-O
67: .DE
68: causes a C program to be compiled with optimization, and the macro
69: .ID
70: CFLAGS = \-I../../include \-g
71: .DE
72: tells the C compiler to search for header files in the directory
73: `../../include' as well as in the current directory (see \(sc\|2.9.1),
74: and to compile the program with debugging information. FFLAGS and
75: PFLAGS can be used similarly to set options for the Fortran and Pascal
76: compilers respectively.
77: .NH 3
78: \fIInstallation\fR
79: .XS
80: \*(SN Installation
81: .XE
82: .PP
83: The command
84: .ID
85: % \fBmake install\fR
86: .DE
87: installs a program or library (see \(sc\|2.9.3). If any source code
88: files are newer than their corresponding object files they are
89: recompiled and the program or library reformed. Even if the object
90: files are up-to-date, a program may still be relinked if the libraries
91: on which it depends are newer than the program itself.
92: .PP
93: Normally a program is stripped of its symbol table and relocation
94: bits when it is installed, to save space. This can be avoided
95: if the
96: .B \-s
97: option is removed from the
98: .I install
99: command line in the makefile.
100: .NH 3
101: \fIUpdating\fR
102: .XS
103: \*(SN Updating
104: .XE
105: .PP
106: If a program or library is out-of-date \- that is, some of the source
107: code files are newer than the installed version \- the command
108: .ID
109: \fBmake update\fR
110: .DE
111: recompiles and reinstalls the program or library. This command is more
112: powerful than \fImake install\fR because it is not affected by the
113: absence of the object files. In the case of an out-of-date library, all
114: the object files are extracted from the library before any
115: recompilation takes place, and removed once the library has been
116: reinstalled.
117: .NH 3
118: \fIDependency analysis\fR
119: .XS
120: \*(SN Dependency analysis
121: .XE
122: .PP
123: Although the
124: .I make
125: program has a set of built-in rules for recompiling a program if any of
126: the files on which it depends have changed since the last time it was
127: constructed, these rules do not extend to included files. It is
128: necessary to add explicit dependency rules to a makefile so that if
129: a header file is changed, the affected source files will be recompiled
130: and a new program produced. For instance, if the rule
131: .ID
132: vs.o: vs.h hash.h list.h
133: .DE
134: is added to the makefile for the `vs' program, the file `vs.c' will be
135: recompiled if any of the included files (see \(sc\|2.9.1) have changed
136: since the last time it was compiled. The command
137: .ID
138: % \fBmake depend\fR
139: .DE
140: calls on the
141: .I mkmf
142: makefile editor to insert header file dependencies into a makefile.
143: .NH 3
144: \fIProgram checking\fR
145: .XS
146: \*(SN Program checking
147: .XE
148: .PP
149: Programs written in C can be checked for bugs, obscurities, wasteful
150: or error prone constructions, type and function usage, and portability
151: by the
152: .I lint
153: program\|[4]. If a makefile contains the line
154: .ID
155: lint:; @lint $(LINTFLAGS) $(SRCS) $(LINTLIST)
156: .DE
157: where the LINTFLAGS macro definition specifies
158: .I lint
159: options, SRCS represents the source files making up the program or library,
160: and LINTLIST is a list of lint libraries (see below), the command
161: .ID
162: % \fBmake lint\fR
163: .DE
164: will check that the program or library is consistent.
165: .PP
166: To set up the `vs' program might be set up for ``linting'', the macro
167: definitions would be
168: .DS
169: LINTFLAGS \kx= \-I../../include
170:
171: SRCS\h'|\nxu'= vs.c
172:
173: LINTLIST\h'|\nxu'= \ky../../lib/llib-lhash.ln \\\\
174: \h'|\nyu'\&../../lib/llib-llist.ln \\\\
175: \h'|\nyu'\-lc
176: .DE
177: .PP
178: Just as program libraries share functions among different programs,
179: lint libraries can be used to check that those functions have been used
180: correctly. Lint libraries are created by \fIlint \-C\fR as shown by the
181: following entry in the makefile belonging to the `hash' library
182: .DS
183: $(LINTLIB): \kx$(SRCS) $(HDRS) $(EXTHDRS)
184: \h'|\nxu'@echo "Loading $(LINTLIB) . . ."
185: \h'|\nxu'@lint $(LINTFLAGS) \-C$(LIBNAME) $(SRCS)
186: \h'|\nxu'@echo done
187: .DE
188: where LIBNAME is defined in the makefile as `hash', and LINTLIB is defined
189: as `llib-l$(LIBNAME).ln' in accordance with standard lint library naming
190: conventions.
191: .NH 3
192: \fIVersion control and releases\fR
193: .XS
194: \*(SN Version control and releases
195: .XE
196: .PP
197: During the time that a program is being developed it is quite likely
198: that it will undergo several revisions. Features are added and
199: algorithms are improved. Often changes are made which are later found
200: not to work and need to be undone. One way to handle these changes is
201: to save a copy of each file before it is revised. However, this quickly
202: becomes expensive in terms of space. A better solution is to use a
203: version control system like
204: .I SCCS
205: (Source Code Control System)\|[6] or
206: .I RCS
207: (Revision Control System)\|[10] which stores only the changes made to the
208: source code together with details such as when each change was made,
209: why it was made, and who made it.
210: .PP
211: Once a program is ready for release, all of the source files should be
212: stamped with a common version name or number so that it can be recreated
213: at any time regardless of any subsequent changes.
214: .I RCS
215: has the advantage over
216: .I SCCS
217: in this respect because it enables the user to stamp each release with a
218: unique name. For example, if the makefile and all the source files in
219: release 2 of the `list' library are stamped `V2', the command sequence
220: .ID
221: % \fBco \-rV2 Makefile\fR
222: % \fBmake VERSION=V2 co\fR
223: .DE
224: will create that release
225: by extracting or ``checking out'' the Makefile and the source files from the
226: .I RCS
227: system
228: using the
229: .I co
230: command.
231: .NH 3
232: \fIFunction tagging\fR
233: .XS
234: \*(SN Function tagging
235: .XE
236: .PP
237: By creating a database of function names\**
238: .FS
239: For C, Fortran, and Pascal programs only.
240: .FE
241: with the command
242: .ID
243: % \fBmake tags\fR
244: .DE
245: it is possible for the user to find and edit a function without having
246: to remember the name of the file in which the function is located. For
247: example, in the `src' directory of the `libhash' subproject, the
248: command
249: .ID
250: % \fBvi \-t htinit\fR
251: .DE
252: invokes the
253: .I vi
254: editor on the file `htinit.c' and positions the cursor at the beginning of the
255: `htinit' hash table initialization function.
256: .PP
257: A list of functions which make up the program or library,
258: together with the line number and file in which each is defined, can be
259: obtained by the command
260: .ID
261: % \fBmake index\fR
262: .DE
263: .NH 3
264: \fIPrinting\fR
265: .XS
266: \*(SN Printing
267: .XE
268: .PP
269: To print all of the program source and header files on the line printer
270: .I lpr,
271: type
272: .ID
273: % \fBmake print | lpr\fR
274: .DE
275: By default the files are formatted by
276: .I pr
277: so that the output is separated into pages headed by a date, the name of
278: the file, and a page number. Another format can be specified by changing
279: the PRINT macro definition in the makefile.
280: .NH 3
281: \fICleaning up\fR
282: .XS
283: \*(SN Cleaning up
284: .XE
285: .PP
286: To save space once a program has been completed, the command
287: .ID
288: % \fBmake clean\fR
289: .DE
290: removes object files plus any other files which can be regenerated easily.
291: .NH 3
292: \fITesting\fR
293: .XS
294: \*(SN Testing
295: .XE
296: .PP
297: Using the test cases prepared previously (see \(sc\|3.4), it is possible
298: to test an entire program or library by typing the command
299: .ID
300: % \fBptest\fR
301: .DE
302: .I Ptest
303: reports the outcome of each test \- i.e. whether it passes or fails \- and if
304: it fails, saves the error diagnostics in a file called E\fItest\fR where
305: .I test
306: is the name of the test.
307: .PP
308: Because
309: .I ptest
310: uses a number of temporary working files for each test and creates an error
311: diagnostic file for each test that fails, it is a good idea not to clutter up
312: the directories that contain source code or test cases, but instead perform
313: the testing in another directory such as `work' (see \(sc\|4.3.5).
314: .NH 3
315: \fICompound commands\fR
316: .XS
317: \*(SN Compound commands
318: .XE
319: .PP
320: The
321: .I make
322: program can process multiple requests. For example,
323: .ID
324: % \fBmake install tags clean\fR
325: .DE
326: installs a program or library, creates function tags, and removes
327: any unneeded files. The only operation which may cause problems
328: if it is used in conjunction with
329: .I install
330: or
331: .I update
332: is \fImake depend\fR because it recreates the include file dependencies
333: .B after
334: the
335: .I make
336: command has already read the makefile.
337: .NH 3
338: \fIUser-defined commands\fR
339: .XS
340: \*(SN User-defined commands
341: .XE
342: .PP
343: Most of the tasks described above are handled by the
344: .I make
345: command. More complex programming tasks can also be defined by adding
346: extra instructions to each makefile. However, rather than modify every
347: program and library makefile in a project individually, the user can
348: get
349: .I mkmf
350: to use alternative `p.Makefile' and `l.Makefile' makefile templates when
351: creating program and library makefiles respectively, if these templates
352: exist in the project `lib' directory (see fig. 3). The templates for
353: project `vs' include directives for type checking and version control (see
354: appendix B). It is a worthwhile exercise to compare them against the
355: standard templates shown in appendix A.
356: .NH 2
357: Layered Construction of Software Packages
358: .XS
359: \*(SN Layered Construction of Software Packages
360: .XE
361: .PP
362: A complex software package may be built and installed in \fIlayers\fR\|[2]
363: as shown in table 3.
364: .KF
365:
366: .SM
367: .ce
368: \fITable 3.\fR Layers of software
369: .NL
370:
371: .so layer.tbl
372: .KE
373: .PP
374: Each layer is assigned a specific label so that it can be built individually,
375: as well as a priority level so that the complete software package can be
376: constructed in a predetermined sequence. Layers are implemented by attaching
377: type labels to the directories which are part of the building process.
378: Table 4 suggests a set of type labels for each layer. By convention, type
379: label `update' is used for the construction of the entire software package.
380: .KF
381:
382: .SM
383: .ce
384: \fITable 4.\fR Layer type labels and priority levels
385: .NL
386:
387: .so construct.tbl
388: .KE
389: .PP
390: If the project `vs' is organized into layers in the manner shown in figure 11,
391: .KF
392: .sp 34
393: .SM
394: .ce
395: \fIFigure 11. \fRLayers of project `vs'
396:
397: .NL
398: .KE
399: then the command
400: .ID
401: % \fBpexec \-T\|libsrc make update\fR
402: .DE
403: brings the program libraries up-to-date, while the command
404: .ID
405: % \fBpexec \-T\|cmdsrc make update\fR
406: .DE
407: does the same for the programs
408: .I vs
409: and
410: .I vstutor.
411: By typing
412: .ID
413: % \fBpexec \-T\|update make update\fR
414: .DE
415: the entire software package can be updated.
416: .NH 2
417: Maintenance of Software Packages
418: .XS
419: \*(SN Maintenance of Software Packages
420: .XE
421: .PP
422: Having established the conventions for maintaining the individual components
423: of a software package, global tasks such as printing,
424: testing, cleaning, etc., can now be described in more detail. The type
425: labels that provide the means for coordinating these tasks are
426: summarized in table 5. Some of the labels have the letter
427: .I n
428: to indicate priority because the directories to which they are attached
429: must be processed in a particular order (see \(sc\|2.10.2).
430: .KF
431:
432: .SM
433: .ce
434: \fITable 5.\fR Type label conventions
435: .NL
436:
437: .so label.tbl
438: .KE
439: .NH 3
440: \fICounting of source lines\fR
441: .XS
442: \*(SN Counting of source lines
443: .XE
444: .PP
445: The total number of lines of source code in a software package can be counted
446: by concatenating the source files in each `src' directory and piping them
447: to the word count program as
448: .ID
449: % \fBpexec \-q \-T\|src make PRINT=cat print | wc \-l\fR
450: .DE
451: where
452: .B \-q
453: suppresses the printing of project directory titles, and
454: .B \-l
455: tells
456: .I wc
457: to count lines only.
458: .NH 3
459: \fICataloging of functions\fR
460: .XS
461: \*(SN Cataloging of functions
462: .XE
463: .PP
464: A list of functions, together with the line number and file in which
465: each is defined, may be obtained\** for each program in a software package
466: .FS
467: For C, Fortran, and Pascal programs only.
468: .FE
469: by the command
470: .ID
471: % \fBpexec \-T\|cmdsrc make index\fR
472: .DE
473: .PP
474: A comprehensive index of all the library functions can be generated by
475: outputting the function definitions in each library (e.g. `libhash' and
476: `liblist') to the
477: .I sort
478: program by
479: .ID
480: % \fBpexec \-q \-Tlibsrc make index | sort\fR
481: .DE
482: .NH 3
483: \fIPrinting\fR
484: .XS
485: \*(SN Printing
486: .XE
487: .PP
488: After printing all of the source code in a project by
489: .ID
490: % \fBpexec \-T\|print make print | lpr\fR
491: .DE
492: a table of contents can be produced by
493: .ID
494: % \fBpexec \-Tprint make \\\&"PRINT=ls \-C\^\\\&" print | lpr\fR
495: .DE
496: Backslash `\\' characters prevent the double quotes `"' from being stripped
497: from the PRINT macro definition by the shell before the
498: .I make
499: command is executed in each directory.
500: .NH 3
501: \fIProgram checking\fR
502: .XS
503: \*(SN Program checking
504: .XE
505: .PP
506: Software packages written in C can be cross-checked for function and type usage
507: by applying the
508: .I lint
509: command to the source code in each of the project directories containing a
510: program or library
511: .ID
512: % \fBpexec "\-T\|libsrc\||\|cmdsrc" make lint\fR
513: .DE
514: .NH 3
515: \fITesting\fR
516: .XS
517: \*(SN Testing
518: .XE
519: .PP
520: All of the tests previously prepared for a software package are exercised
521: by the command
522: .ID
523: % \fBpexec \-T\|test ptest > testlog\fR
524: .DE
525: in the directories labeled `test'. In the case of project `vs', the
526: following directories are labeled `test'
527: .DS
528: .so test.tbl
529: .DE
530: The outcome of each test \- i.e. whether it passes or fails \- is recorded
531: in the file called `testlog' in the current working directory. If a test
532: fails, the cause of the failure is recorded in a file bearing the
533: name `E\fItest\fR' where
534: .I test
535: is the name of the test, located in the directory where the test is
536: executed.
537: .NH 3
538: \fIComparing versions\fR
539: .XS
540: \*(SN Comparing versions
541: .XE
542: .PP
543: The method for comparing the source code in two different versions of a
544: project depends on the way in which the versions are stored. If they
545: are stored in separate projects the
546: .I pdiff
547: command can be used to compare the contents of the directories belonging
548: to each of the two projects. For example, if `nvs' is a new version of
549: the project `vs', then the command
550: .ID
551: % \fBpdiff \-T\|src ^vs ^nvs\fR
552: .DE
553: will produce a summary of the differences between them. However, if the
554: different versions are stored as deltas in a version control system such as
555: .I SCCS
556: or
557: .I RCS,
558: then either the
559: .I sccsdiff
560: command or the
561: .I rcsdiff
562: command must be used instead. To show how this is done with
563: .I RCS,
564: .ID
565: % \fBpexec \-T\|src make VERSION=V2 diff\fR
566: .DE
567: compares the current working version of the source code in the project
568: `vs' with a previous version labeled `V2'.
569: .NH 3
570: \fIReleases\fR
571: .XS
572: \*(SN Releases
573: .XE
574: .PP
575: If the source code for a software package is stored in a version control
576: system like
577: .I RCS,
578: it is possible to re-create any particular version of the package provided
579: that all the source files in that version have previously been stamped
580: with a symbolic version name\** (for example, `V2').
581: .FS
582: \fISCCS\fR does not have this feature.
583: .FE
584: The process is carried out in two stages. After removing the current version
585: of the source code (hopefully, it has already been stored in the version
586: control system) by the following command sequence,
587: .ID
588: % \fBpexec \-T\|src \'rm \`make PRINT=echo print\` Makefile\'\fR
589: .DE
590: the makefile and source files for the desired version (say `V2') are
591: checked out by
592: .ID
593: % \fBpexec \-T\|src \'co \-rV2 Makefile; make VERSION=V2 co\'\fR
594: .DE
595: .NH 3
596: \fICleaning up\fR
597: .XS
598: \*(SN Cleaning up
599: .XE
600: .PP
601: If a software package is in a stable state \- that is, it is not being
602: modified \- then, as an economy measure, the amount of space that it
603: takes up can be reduced by removing object files plus any other files
604: that can be regenerated easily. This task is implemented by
605: .ID
606: % \fBpexec \-T\|clean make clean\fR
607: .DE
608: assuming that the directories containing the files to be removed are
609: labeled `clean'.
610:
611:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.