|
|
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.