aboutsummaryrefslogtreecommitdiff
path: root/en_US.ISO8859-1/books/pmake/basics/chapter.xml
blob: 4ae0a8b7992e2222b14642747238ae8fc4b6ac8b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
<?xml version="1.0" encoding="iso-8859-1"?>
<!--
     $FreeBSD$
-->

<chapter id="basics">
  <title>The Basics of PMake</title>

  <para><application>PMake</application> takes as input a file that
    tells which files depend on which other files to be complete and
    what to do about files that are <quote>out-of-date</quote>.
    This file is known as a <quote>makefile</quote> and is usually
    kept in the top-most directory of the system to be built.
    While you can call the makefile anything you want,
    <application>PMake</application> will look for
    <filename>Makefile</filename> and <filename>makefile</filename>
    (in that order) in the current directory if you do not tell it
    otherwise.  To specify a different makefile, use the
    <option>-f</option> flag, e.g.</para>

  <screen>&prompt.user; <userinput>pmake <option>-f</option> <replaceable>program.mk</replaceable></userinput></screen>

  <para>A makefile has four different types of lines in it:</para>

  <itemizedlist>
    <listitem>
      <para>File dependency specifications</para>
    </listitem>

    <listitem>
      <para>Creation commands</para>
    </listitem>

    <listitem>
      <para>Variable assignments</para>
    </listitem>

    <listitem>
      <para>Comments, include statements and conditional directives</para>
    </listitem>
  </itemizedlist>

  <para>Any line may be continued over multiple lines by ending it
    with a backslash.  The backslash, following newline and any
    initial whitespace on the following line are compressed into a
    single space before the input line is examined by
    <application>PMake</application>.</para>

  <section id="deplines">
    <title>Dependency Lines</title>

    <para>As mentioned in the introduction, in any system, there are
      dependencies between the files that make up the system.
      For instance, in a program made up of several C source files and
      one header file, the C files will need to be re-compiled should
      the header file be changed.  For a document of several chapters
      and one macro file, the chapters will need to be reprocessed if
      any of the macros changes.  These are dependencies and are
      specified by means of dependency lines in the makefile.</para>

    <para>On a dependency line, there are targets and sources,
      separated by a one-&nbsp;or two-character operator.  The targets
      <quote>depend</quote> on the sources and are usually created
      from them.  Any number of targets and sources may be specified
      on a dependency line.  All the targets in the line are made to
      depend on all the sources.  Targets and sources need not be
      actual files, but every source must be either an actual file or
      another target in the makefile.  If you run out of room, use a
      backslash at the end of the line to continue onto the next
      one.</para>

    <para>Any file may be a target and any file may be a source, but
      the relationship between the two (or however many) is determined
      by the <quote>operator</quote> that separates them.  Three types
      of operators exist: one specifies that the datedness of a target
      is determined by the state of its sources, while another
      specifies other files (the sources) that need to be dealt with
      before the target can be re-created.  The third operator is very
      similar to the first, with the additional condition that the
      target is out-of-date if it has no sources.  These operations
      are represented by the colon, the exclamation point and the
      double-colon, respectively, and are mutually exclusive.
      Their exact semantics are as follows:</para>

    <informaltable frame="none">
      <tgroup cols="2">
	<tbody>
	  <row valign="top">
	    <entry><literal>:</literal></entry>

	    <entry>If a colon is used, a target on the line is
	      considered to be <quote>out-of-date</quote> (and in need
	      of creation) if any of the sources has been modified
	      more recently than the target, or the target does not
	      exist.  Under this operation, steps will be taken to
	      re-create the target only if it is found to be
	      out-of-date by using these two rules.</entry>
	  </row>

	  <row valign="top">
	    <entry><literal>!</literal></entry>

	    <entry>If an exclamation point is used, the target will
	      always be re-created, but this will not happen until all
	      of its sources have been examined and re-created, if
	      necessary.</entry>
	  </row>

	  <row valign="top">
	    <entry><literal>::</literal></entry>

	    <entry>If a double-colon is used, a target is
	      <quote>out-of-date</quote> if any of the sources has
	      been modified more recently than the target, or the
	      target does not exist, or the target has no sources.
	      If the target is out-of-date according to these rules,
	      it will be re-created.  This operator also does
	      something else to the targets, but I will go into that
	      in the next section
	      (see <xref linkend="shellcmds"/>).</entry>
	  </row>
	</tbody>
      </tgroup>
    </informaltable>

    <para>Enough words, now for an example.  Take that C program I
      mentioned earlier.  Say there are three C files
      (<filename>a.c</filename>, <filename>b.c</filename> and
      <filename>c.c</filename>) each of which includes the file
      <filename>defs.h</filename>.  The dependencies between the files
      could then be expressed as follows:</para>

    <programlisting>program         : a.o b.o c.o

a.o b.o c.o     : defs.h

a.o             : a.c

b.o             : b.c

c.o             : c.c</programlisting>

    <para>You may be wondering at this point, where
      <filename>a.o</filename>, <filename>b.o</filename> and
      <filename>c.o</filename> came in and why they depend on
      <filename>defs.h</filename> and the C files do not.
      The reason is quite simple: <maketarget>program</maketarget>
      cannot be made by linking together <filename>.c</filename>
      files&mdash;it must be made from <filename>.o</filename> files.
      Likewise, if you change <filename>defs.h</filename>, it is not
      the <filename>.c</filename> files that need to be re-created,
      it is the <filename>.o</filename> files.  If you think of
      dependencies in these terms&mdash;which files (targets) need to
      be created from which files (sources)&mdash;you should have no
      problems.</para>

    <para>An important thing to notice about the above example, is
      that all the <filename>.o</filename> files appear as targets on
      more than one line.  This is perfectly all right: the target is
      made to depend on all the sources mentioned on all the
      dependency lines.  For example, <filename>a.o</filename> depends
      on both <filename>defs.h</filename> and <filename>a.c</filename>.</para>

    <para>The order of the dependency lines in the makefile is
      important: the first target on the first dependency line in the
      makefile will be the one that gets made if you do not say
      otherwise.  That is why program comes first in the example
      makefile, above.</para>

    <para>Both targets and sources may contain the standard C-Shell wildcard
      characters (<literal>{</literal>, <literal>}</literal>,
      <literal>*</literal>, <literal>?</literal>, <literal>[</literal>, and
      <literal>]</literal>), but the non-curly-brace ones may only appear in
      the final component (the file portion) of the target or source.
      The characters mean the following things:</para>

    <informaltable frame="none">
      <tgroup cols="2">
	<tbody>
	  <row valign="top">
	    <entry><literal>{}</literal></entry>

	    <entry>These enclose a comma-separated list of options and
	      cause the pattern to be expanded once for each element
	      of the list.  Each expansion contains a different
	      element.  For example,
	      <filename>src/{whiffle,beep,fish}.c</filename> expands
	      to the three words <filename>src/whiffle.c</filename>,
	      <filename>src/beep.c</filename>, and
	      <filename>src/fish.c</filename>.  These braces may be
	      nested and, unlike the other wildcard characters, the
	      resulting words need not be actual files.  All other
	      wildcard characters are expanded using the files that
	      exist when <application>PMake</application> is
	      started.</entry> </row>

	  <row valign="top">
	    <entry><literal>*</literal></entry>

	    <entry>This matches zero or more characters of any sort.
	      <filename>src/*.c</filename> will expand to the same
	      three words as above as long as src contains those three
	      files  (and  no other files that end in
	      <filename>.c</filename>).></entry>
	  </row>

	  <row valign="top">
	    <entry><literal>?</literal></entry>

	    <entry>Matches any single character.</entry>
	  </row>

	  <row valign="top">
	    <entry><literal>[]</literal></entry>

	    <entry>This is known as a character class and contains
	      either a list of single characters, or a series of
	      character ranges (<literal>a-z</literal>, for example
	      means all characters between <literal>a</literal> and
	      <literal>z</literal>), or both.  It matches any single
	      character contained in the list.  For example,
	      <literal>[A-Za-z]</literal> will match all letters,
	      while <literal>[0123456789]</literal> will match all
	      numbers.</entry>
	  </row>
	</tbody>
      </tgroup>
    </informaltable>
  </section>

  <section id="shellcmds" xreflabel="Shell Commands">
    <title>Shell Commands</title>

    <para><quote>Is not that nice,</quote> you say to yourself,
      <quote>but how are files actually ``re-created'', as he likes to
	spell it?</quote>
      The re-creation is accomplished by commands you place in the
      makefile.  These commands are passed to the Bourne shell (better
      known as <filename>/bin/sh</filename>) to be executed and are
      expected to do what is necessary to update the target file
      (<application>PMake</application> does not actually check to see
      if the target was created.  It just assumes it is there).</para>

    <para>Shell commands in a makefile look a lot like shell commands
      you would type at a terminal, with one important exception: each
      command in a makefile must be preceded by at least one
      tab.</para>

    <para>Each target has associated with it a shell script made up of
      one or more of these shell commands.  The creation script for a
      target should immediately follow the dependency line for that
      target.  While any given target may appear on more than one
      dependency line, only one of these dependency lines  may be
      followed  by a creation script, unless the <literal>::</literal>
      operator was used on the dependency line.</para>

    <para>If the double-colon was used, each dependency line for the
      target may be followed by a shell script.  That script will only
      be executed if the target on the associated dependency line is
      out-of-date with respect to the sources on that line, according
      to the rules I gave earlier.  I'll give you a good example of
      this later on.</para>

    <para>To expand on the earlier makefile, you might add commands
      as follows:</para>

    <programlisting>program         : a.o b.o c.o
        cc a.o b.o c.o -o program

a.o b.o c.o     : defs.h
a.o             : a.c
       cc -c a.c

b.o             : b.c
       cc -c b.c

c.o             : c.c
       cc -c c.c</programlisting>

    <para>Something you should remember when writing a makefile is,
      the commands will be executed if the target on the dependency
      line is out-of-date, not the sources.  In this example, the
      command <command>cc -c a.c</command> will be executed if
      <filename>a.o</filename> is out-of-date.  Because of the
      <literal>:</literal> operator, this means that should
      <filename>a.c</filename> or <filename>defs.h</filename> have
      been modified more recently than <filename>a.o</filename>, the
      command will be executed (<filename>a.o</filename> will be
      considered out-of-date).</para>

    <para>Remember how I said the only difference between a makefile
      shell command and a regular shell command was the leading tab?
      I lied.  There is another way in which makefile commands differ
      from regular ones.  The first two characters after the initial
      whitespace are treated specially.  If they are any combination
      of <filename>@</filename> and <literal>-</literal>, they cause
      <application>PMake</application> to do different things.</para>

    <para>In most cases, shell commands are printed before they are
      actually executed.  This is to keep you informed of what is
      going on.  If an <literal>@</literal> appears, however, this
      echoing is suppressed.  In the case of an echo command,
      say</para>

    <programlisting>echo Linking index</programlisting>

    <para>it would be rather silly to see</para>

    <screen>echo Linking index
Linking index</screen>

    <para>so <application>PMake</application> allows you to place an
      <literal>@</literal> before the command to prevent the command
      from being printed:</para>

    <programlisting>@echo Linking index</programlisting>

    <para>The other special character is the <literal>-</literal>.
      In case you did not know, shell commands finish with a certain
      <quote>exit status</quote>.  This status is made available by
      the operating system to whatever program invoked the command.
      Normally this status will be <literal>0</literal> if everything
      went ok and non-zero if something went wrong.  For this reason,
      <application>PMake</application> will consider an error to have
      occurred if one of the shells it invokes returns a non-zero
      status.  When it detects an error,
      <application>PMake</application>'s usual action is to abort
      whatever it is doing and exit with a non-zero status itself (any
      other targets that were being created will continue being made,
      but nothing new will be started.
      <application>PMake</application> will exit after the last job
      finishes).  This behavior can be altered, however, by placing a
      <literal>-</literal> at the front of a command
      (e.g. <command>-mv index index.old</command>), certain
      command-line arguments, or doing other things, to be detailed
      later.  In such a case, the non-zero status is simply ignored
      and <application>PMake</application> keeps chugging
      along.</para>

    <para>Because all the commands are given to a single shell to
      execute, such things as setting shell variables, changing
      directories, etc., last beyond the command in which they are
      found.  This also allows shell compound commands (like for
      loops) to be entered in a natural manner.  Since this could
      cause problems for some makefiles that depend on each command
      being executed by a single shell,
      <application>PMake</application> has a <option>-B</option> flag
      (it stands for backwards-compatible) that forces each command to
      be given to a separate shell.  It also does several other
      things, all of which I discourage since they are now
      old-fashioned.</para>

    <para>A target's shell script is fed to the shell on its (the
      shell's) input stream. This means that any commands, such as
      <application>ci</application> that need to get input from the
      terminal will not work right &ndash; they will get the shell's
      input, something they probably will not find to their liking.
      A simple way around this is to give a command like this:</para>

    <screen><command>ci $(SRCS) &lt; <devicename>/dev/tty</devicename></command></screen>

    <para>This would force the program's input to come from the
      terminal.  If you cannot do this for some reason, your only
      other alternative is to use <application>PMake</application> in
      its fullest compatibility mode.
      See <quote>Compatibility</quote> in <xref linkend="gods"/>.</para>
  </section>


  <section id="variables">
    <title>Variables</title>

    <para><application>PMake</application>, like
      <application>Make</application> before it, has the ability to
      save text in variables to be recalled later at your convenience.
      Variables in <application>PMake</application> are used much like
      variables in the shell and, by tradition, consist of all
      upper-case letters (you do not have to use all upper-case
      letters.  In fact there is nothing to stop you from calling a
      variable <literal>@^&amp;$%$</literal>.  Just tradition).  Variables
      are assigned-to using lines of the form:</para>

    <programlisting>VARIABLE = value</programlisting>

    <para>appended-to by:</para>

    <programlisting>VARIABLE += value</programlisting>

    <para>conditionally assigned-to (if the variable is not already
      defined) by:</para>

    <programlisting>VARIABLE ?= value</programlisting>

    <para>and assigned-to with expansion (i.e. the value is expanded
      (see below) before being assigned to the variable&mdash;useful
      for placing a value at the beginning of a variable, or other
      things) by:</para>

    <programlisting>VARIABLE := value</programlisting>

    <para>Any whitespace before value is stripped off.  When
      appending, a space is placed between the old value and the stuff
      being appended.</para>

    <para>The final way a variable may be assigned to is using:</para>

    <programlisting>VARIABLE != shell-command</programlisting>

    <para>In this case, shell-command has all its variables expanded
      (see below) and is passed off to a shell to execute.  The output
      of the shell is then placed in the variable.  Any newlines
      (other than the final one) are replaced by spaces before the
      assignment is made.  This is typically used to find the current
      directory via a line like:</para>

    <programlisting>CWD             != pwd</programlisting>

    <note>
      <para>This is intended to be used to execute commands that
	produce small amounts of output
	(e.g.&nbsp;<application>pwd</application>).
	The implementation is less than intelligent and will likely
	freeze if you execute something that produces thousands of
	bytes of output (8 Kb is the limit on many &unix; systems).
	The value of a variable may be retrieved by enclosing the
	variable name in parentheses or curly braces and preceding the
	whole thing with a dollar sign.</para>
    </note>

    <para>For example, to set the variable <envar>CFLAGS</envar> to
      the string <literal>-I/sprite/src/lib/libc -O,</literal> you
      would place a line:</para>

    <programlisting>CFLAGS = -I/sprite/src/lib/libc -O</programlisting>

    <para>in the makefile and use the word
      <literal>$(CFLAGS)</literal> wherever you would like the string
      <literal>-I/sprite/src/lib/libc -O</literal> to appear.  This is
      called variable expansion.</para>

    <note>
      <para>Unlike <application>Make</application>,
	<application>PMake</application> will not expand a variable
	unless it knows the variable exists.  E.g.&nbsp;if you have a
	<literal>${i}</literal> in a shell command and you have not
	assigned a value to the variable <varname>i</varname> (the
	empty string is considered a value, by the way), where
	<application>Make</application> would have substituted the
	empty string, <application>PMake</application> will leave the
	<literal>${i}</literal> alone.
	To keep <application>PMake</application> from substituting for
	a variable it knows, precede the dollar sign with another
	dollar sign (e.g.&nbsp;to pass <literal>${HOME}</literal> to
	the shell, use <literal>$${HOME}</literal>).  This causes
	<application>PMake</application>, in effect, to expand the
	<literal>$</literal> macro, which expands to a single
	<literal>$</literal>.</para>
    </note>

    <para>For compatibility, <application>Make</application>'s style
      of variable expansion will be used if you invoke
      <application>PMake</application> with any of the compatibility
      flags (<option>-V</option>, <option>-B</option> or
      <option>-M</option>.  The <option>-V</option> flag alters just
      the variable expansion).  There are two different times at which
      variable expansion occurs: when parsing a dependency line, the
      expansion occurs immediately upon reading the line.  If any
      variable used on a dependency line is undefined,
      <application>PMake</application> will print a message and exit.
      Variables in shell commands are expanded when the command is
      executed.  Variables used inside another variable are expanded
      whenever the outer variable is expanded (the expansion of an
      inner variable has no effect on the outer variable.  For
      example, if the outer variable is used on a dependency line and
      in a shell command, and the inner variable changes value between
      when the dependency line is read and the shell command is
      executed, two different values will be substituted for the outer
      variable).</para>

    <para>Variables come in four flavors, though they are all expanded
      the same and all look about the same.  They are (in order of
      expanding scope):</para>

    <itemizedlist>
      <listitem>
	<para>Local variables.</para>
      </listitem>

      <listitem>
	<para>Command-line variables.</para>
      </listitem>

      <listitem>
	<para>Global variables.</para>
      </listitem>

      <listitem>
	<para>Environment variables.</para>
      </listitem>
    </itemizedlist>

    <para>The classification of variables does not matter much, except
      that the classes are searched from the top (local) to the bottom
      (environment) when looking up a variable.  The first one found
      wins.</para>

    <section id="localvariables">
      <title>Local Variables</title>

      <para>Each target can have as many as seven local variables.
	These are variables that are only <quote>visible</quote>
	within that target's shell script and contain such things as
	the target's name, all of its sources (from all its dependency
	lines), those sources that were out-of-date, etc.  Four local
	variables are defined for all targets.  They are:</para>

      <variablelist>
	<varlistentry>
	  <term><makevar>.TARGET</makevar></term>

	  <listitem>
	    <para>The name of the target.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><makevar>.OODATE</makevar></term>

	  <listitem>
	    <para>The 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 in which the
	      dependencies were given.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><makevar>.ALLSRC</makevar></term>

	  <listitem>
	    <para>The list of all sources for this target in the order
	      in which they were given.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><makevar>.PREFIX</makevar></term>

	  <listitem>
	    <para>The target without its suffix and without any
	      leading path.  E.g.&nbsp;for the target
	      <filename>../../lib/compat/fsRead.c</filename>, this
	      variable would contain <literal>fsRead</literal>.</para>
	  </listitem>
	</varlistentry>
      </variablelist>

      <para>Three other local variables are set only for certain
	targets under special circumstances.  These are the
	<makevar>.IMPSRC,</makevar> <makevar>.ARCHIVE,</makevar> and
	<makevar>.MEMBER</makevar> variables.  When they are set and
	how they are used is described later.</para>

      <para>Four of these variables may be used in sources as well as
	in shell scripts.  These are <makevar>.TARGET</makevar>,
	<makevar>.PREFIX</makevar>, <makevar>.ARCHIVE</makevar> and
	<makevar>.MEMBER</makevar>.  The variables in the sources are
	expanded once for each target on the dependency line,
	providing what is known as a <quote>dynamic source,</quote>
	allowing  you to specify several dependency lines at once.
	For example:</para>

      <programlisting>$(OBJS)         : $(.PREFIX).c</programlisting>

      <para>will create a dependency between each object file and its
	corresponding C source file.</para>
    </section>

    <section id="cmdvars">
      <title>Command-line Variables</title>

      <para>Command-line variables are set when
	<application>PMake</application> is first invoked by giving a
	variable assignment as one of the arguments.
	For example:</para>

      <screen>pmake "CFLAGS = -I/sprite/src/lib/libc -O"</screen>

      <para>would make <envar>CFLAGS</envar> be a command-line
	variable with the given value.  Any assignments to
	<envar>CFLAGS</envar> in the makefile will have no effect,
	because once it is set, there is (almost) nothing you can do
	to change a command-line variable (the search order, you see).
	Command-line variables may be set using any of the four
	assignment operators, though only <literal>=</literal> and
	<literal>?=</literal> behave as you would expect them to,
	mostly because assignments to command-line variables are
	performed before the makefile is read, thus the values set in
	the makefile are unavailable at the time.
	<literal>+=</literal> is the same as <literal>=</literal>,
	because the old value of the variable is sought only in the
	scope in which the assignment is taking place (for reasons of
	efficiency that I will not get into here).  <literal>:=</literal>
	and <literal>?=</literal> will work if the  only variables
	used are in the environment.  <literal>!=</literal> is sort of
	pointless to use from the command line, since the same effect
	can no doubt be accomplished using the shell's own command
	substitution mechanisms (backquotes and all that).</para>
    </section>

    <section id="globalvariables">
      <title>Global Variables</title>

      <para>Global variables are those set or appended-to in the
	makefile.  There are two classes of global variables: those
	you set and those <application>PMake</application> 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 <application>PMake</application> sets (almost)
	always begin with a period and always contain upper-case
	letters, only.  The variables are as follows:</para>

      <variablelist>
	<varlistentry>
	  <term><makevar>.PMAKE</makevar></term>

	  <listitem>
	    <para>The name by which <application>PMake</application>
	      was invoked is stored in this variable.  For
	      compatibility, the name is also stored in the
	      <makevar>MAKE</makevar> variable.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><makevar>.MAKEFLAGS</makevar></term>

	  <listitem>
	    <para>All the relevant flags with which
	      <application>PMake</application> was invoked.
	      This does not include such things as <option>-f</option>
	      or variable assignments. Again for compatibility, this
	      value is stored in the <makevar>MFLAGS</makevar>
	      variable as well.</para>
	  </listitem>
	</varlistentry>
      </variablelist>

      <para>Two other variables, <makevar>.INCLUDES</makevar> and
	<makevar>.LIBS,</makevar> are covered in the section on
	special targets in <xref linkend="shortcuts"/>.</para>

      <para>Global variables may be deleted using lines of the
	form:</para>

      <programlisting>#undef variable</programlisting>

      <para>The <literal>#</literal> must be the first character on
	the line.  Note that this may only be done on global
	variables.</para>
    </section>

    <section id="envvars">
      <title>Environment Variables</title>

      <para>Environment variables are passed by the shell that invoked
	<application>PMake</application> and are given by
	<application>PMake</application> to each shell it invokes.
	They are expanded like any other variable, but they cannot be
	altered in any way.</para>

      <para>One special environment variable, <envar>PMAKE</envar>, is
	examined by <application>PMake</application> for command-line
	flags, variable assignments, etc., it should always use.  This
	variable is examined before the actual arguments to
	<application>PMake</application> are.  In addition, all flags
	given to <application>PMake</application>, either through the
	<envar>PMAKE</envar> variable or on the command line, are
	placed in this environment variable and exported to each shell
	<application>PMake</application> executes.  Thus recursive
	invocations of <application>PMake</application> automatically
	receive the same flags as the top-most one.</para>

      <para>Using all these variables, you can compress the sample
	makefile even more:</para>

      <programlisting>OBJS            = a.o b.o c.o

program         : $(OBJS)
        cc $(.ALLSRC) -o $(.TARGET)

$(OBJS)         : defs.h

a.o             : a.c
        cc -c a.c

b.o             : b.c
        cc -c b.c

c.o             : c.c
        cc -c c.c</programlisting>
    </section>
  </section>

  <section id="comments">
    <title>Comments</title>

    <para>Comments in a makefile start with a <literal>#</literal>
      character and extend to the end of the line.  They may appear
      anywhere you want them, except in a shell command (though the
      shell will treat it as a comment, too).  If, for some reason,
      you need to use the <literal>#</literal> in a variable or on a
      dependency line, put a backslash in front of it.
      <application>PMake</application> will compress the two into a
      single <literal>#</literal>.</para>

    <note>
      <para>This is not true if <application>PMake</application> is
	operating in full-compatibility mode).</para>
    </note>
  </section>

  <section id="parellelism">
    <title>Parallelism</title>

    <para><application>PMake</application> was specifically designed
      to re-create several targets at once, when possible. You do not
      have to do anything special to cause this to happen (unless
      <application>PMake</application> was configured to not act in
      parallel, in which case you will have to make use of the
      <option>-L</option> and <option>-J</option> flags (see below)),
      but you do have to be careful at times.</para>

    <para>There are several problems you are likely to encounter.  One
      is that some makefiles (and programs) are written in such a way
      that it is impossible for two targets to be made at once.  The
      program <application>xstr</application>, for example, always
      modifies the files <filename>strings</filename> and
      <filename>x.c</filename>.  There is no way to change it.  Thus
      you cannot run two of them at once without something being
      trashed.  Similarly, if you have commands in the makefile that
      always send output to the same file, you will not be able to
      make more than one target at once unless you change the file you
      use.  You can, for instance, add a <literal>$$$$</literal> to
      the end of the file name to tack on the process ID of the shell
      executing the command (each <literal>$$</literal> expands to a
      single <literal>$</literal>, thus giving you the shell variable
      <literal>$$</literal>).  Since only one shell is used for all
      the commands, you will get the same file name for each command
      in the script.</para>

    <para>The other problem comes from improperly-specified
      dependencies that worked in <application>Make</application>
      because of its sequential, depth-first way of examining them.
      While I do not want to go into depth on how
      <application>PMake</application> works (look in <xref
      linkend="gods"/> if you are interested), I will warn you that
      files in two different levels of the dependency tree may be
      examined in a different order in
      <application>PMake</application> than they were in
      <application>Make</application>.
      For example, given the makefile:</para>

    <programlisting>a               :

b c b           : d</programlisting>

    <para><application>PMake</application> will examine the targets in
      the order <maketarget>c</maketarget>,
      <maketarget>d</maketarget>, <maketarget>b</maketarget>,
      <maketarget>a</maketarget>.  If the makefile's author expected
      <application>PMake</application> to abort before making
      <maketarget>c</maketarget> if an error occurred while making
      <maketarget>b</maketarget>, or if <maketarget>b</maketarget>
      needed to exist before <maketarget>c</maketarget> was made,
      (s)he will be sorely disappointed.  The dependencies are
      incomplete, since in both these cases,
      <maketarget>c</maketarget> would depend on
      <maketarget>b</maketarget>.  So watch out.</para>

    <para>Another problem you may face is that, while
      <application>PMake</application> is set up to handle the output
      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 <devicename>/dev/tty</devicename> I
      mentioned earlier, you must be careful not to run two of the
      jobs at once.</para>
  </section>

  <section id="writeanddebug">
    <title>Writing and Debugging a Makefile</title>

    <para>Now you know most of what is in a
      <filename>Makefile</filename>, what do you do next?  There are
      two choices: use one of the uncommonly-available makefile
      generators or write your own makefile (I leave out the third
      choice of ignoring <application>PMake</application> and doing
      everything by hand as being beyond the bounds of common
      sense).</para>

    <para>When faced with the writing of a makefile, it is usually
      best to start from first principles: just what are you trying to
      do?  What do you want the makefile finally to produce?  To begin
      with a somewhat traditional example, let's say you need to write
      a makefile to create a program, <command>expr</command>, that
      takes standard infix expressions and converts them to prefix
      form (for no readily apparent reason).  You have got three
      source files, in C, that make up the program:
      <filename>main.c</filename>, <filename>parse.c</filename>, and
      <filename>output.c</filename>.  Harking back to my pithy advice
      about dependency lines, you write the first line of the
      file:</para>

    <programlisting>expr            : main.o parse.o output.o</programlisting>

    <para>because you remember <filename>expr</filename> is made from
      <filename>.o</filename> files, not <filename>.c</filename>
      files.  Similarly for the <filename>.o</filename> files you
      produce the lines:</para>

    <programlisting>main.o          : main.c

parse.o         : parse.c

output.o        : output.c

main.o parse.o output.o : defs.h</programlisting>

    <para>Great.  You have now got the dependencies specified.  What
      you need now is commands.  These commands, remember, must
      produce the target on the dependency line, usually by using the
      sources you have listed.  You remember about local variables?
      Good, so it should come to you as no surprise when you
      write:</para>

    <programlisting>expr            : main.o parse.o output.o
	cc -o $(.TARGET) $(.ALLSRC)</programlisting>

    <para>Why use the variables?  If your program grows to produce
      postfix expressions too (which, of course, requires a name
      change or two), it is one fewer place you have to change the
      file. You cannot do this for the object files, however, because
      they depend on their corresponding source files and
      <filename>defs.h</filename>, thus if you said:</para>

    <programlisting>cc -c $(.ALLSRC)</programlisting>

    <para>you will get (for <filename>main.o</filename>):</para>

    <programlisting>cc -c main.c defs.h</programlisting>

    <para>which is wrong.  So you round out the makefile with these
      lines:</para>

    <programlisting>main.o          : main.c
	cc -c main.c

parse.o         : parse.c
	cc -c parse.c

output.o        : output.c
	cc -c output.c</programlisting>

    <para>The makefile is now complete and will, in fact, create the
      program you want it to without unnecessary compilations or
      excessive typing on your part.  There are two things wrong with
      it, however (aside from it being altogether too long, something
      I will address in <xref linkend="shortcuts"/>):</para>

    <orderedlist>
      <listitem>
	<para>The string <literal>main.o parse.o output.o</literal> is
	  repeated twice, necessitating two changes when you add
	  postfix (you were planning on that, were not you?).  This is
	  in direct violation of de Boor's First Rule of writing
	  makefiles:</para>

	<para>Anything that needs to be written more than once should
	  be placed in a variable.  I cannot emphasize this enough as
	  being very important to the maintenance of a makefile and
	  its program.</para>
      </listitem>

      <listitem>
	<para>There is no way to alter the way compilations are
	  performed short of editing the makefile and making the
	  change in all places.  This is evil and violates de Boor's
	  Second Rule, which follows directly from the first:</para>

	<para>Any flags or programs used inside a makefile should be
	  placed in a variable so they may be changed, temporarily or
	  permanently, with the greatest ease.</para>
      </listitem>
    </orderedlist>

    <para>The makefile should more properly read:</para>

    <programlisting>OBJS            = main.o parse.o output.o

expr            : $(OBJS)
	$(CC) $(CFLAGS) -o $(.TARGET) $(.ALLSRC)

main.o          : main.c
	$(CC) $(CFLAGS) -c main.c

parse.o         : parse.c
	$(CC) $(CFLAGS) -c parse.c

output.o        : output.c
	$(CC) $(CFLAGS) -c output.c

$(OBJS)         : defs.h</programlisting>

    <para>Alternatively, if you like the idea of dynamic sources
      mentioned in <xref linkend="localvariables"/>, you could write it
      like this:</para>

    <programlisting>OBJS            = main.o parse.o output.o

expr            : $(OBJS)
	$(CC) $(CFLAGS) -o $(.TARGET) $(.ALLSRC)

$(OBJS)         : $(.PREFIX).c defs.h
	$(CC) $(CFLAGS) -c $(.PREFIX).c</programlisting>

    <para>These two rules and examples lead to de Boor's First
      Corollary:
      <emphasis>Variables are your friends</emphasis>.</para>

    <para>Once you have written the makefile comes the
      sometimes-difficult task of making sure the darn thing works.
      Your most helpful tool to make sure the makefile is at least
      syntactically correct is the <option>-n</option> flag, which
      allows you to see if <application>PMake</application> will choke
      on the makefile.  The second thing the <option>-n</option> flag
      lets you do is see what <application>PMake</application> would
      do without it actually doing it, thus you can make sure the
      right commands would be executed were you to give
      <application>PMake</application> its head.</para>

    <para>When you find your makefile is not behaving as you hoped,
      the first question that comes to mind (after <quote>What time is
      it, anyway?</quote>) is <quote>Why not?</quote> In answering
      this, two flags will serve you well: <literal>-d m</literal> and
      <quote>-p 2</quote>.
      The first causes <application>PMake</application> to tell you as
      it examines each target in the makefile and indicate why it is
      deciding whatever it is deciding.  You can then use the
      information printed for other targets to see where you went
      wrong.  The <quote>-p 2</quote> flag makes
      <application>PMake</application> print out its internal state
      when it is done, allowing you to see that you forgot to make
      that one chapter depend on that file of macros you just got a
      new version of.  The output from <quote>-p 2</quote> is intended
      to resemble closely a real makefile, but with additional
      information provided and with variables expanded in those
      commands <application>PMake</application> actually printed or
      executed.</para>

    <para>Something to be especially careful about is circular
      dependencies.  For example:</para>

    <programlisting>a         : b

b         : c d

d         : a</programlisting>

    <para>In this case,
      because of how <application>PMake</application> works,
      <maketarget>c</maketarget> is the only thing
      <application>PMake</application> will examine, because
      <maketarget>d</maketarget> and <maketarget>a</maketarget> will
      effectively fall off the edge of the universe, making it
      impossible to examine <maketarget>b</maketarget> (or them, for
      that matter).  <application>PMake</application> will tell you
      (if run in its normal mode) all the targets involved in any
      cycle it looked at (i.e.&nbsp;if you have two cycles in the
      graph (naughty, naughty), but only try to make a target in one
      of them, <application>PMake</application> will only tell you
      about that one.  You will have to try to make the other to find
      the second cycle).  When run as <application>Make</application>,
      it will only print the first target in the cycle.</para>
  </section>

  <section id="invoking">
    <title>Invoking PMake</title>

    <para><application>PMake</application> comes with a wide variety
      of flags to choose from.  They may appear in any order,
      interspersed with command-line variable assignments and targets
      to create.  The flags are as follows:</para>

    <variablelist>
      <varlistentry>
	<term><option>-d <replaceable>what</replaceable></option></term>

	<listitem>
	  <para>This causes <application>PMake</application> to spew
	    out debugging information that may prove useful to you.
	    If you cannot figure out why
	    <application>PMake</application> is doing what it is
	    doing, you might try using this flag.
	    The <replaceable>what</replaceable> parameter is a string
	    of single characters that tell
	    <application>PMake</application> what aspects you are
	    interested in.  Most of what I describe will make little
	    sense to you, unless you have dealt with
	    <application>Make</application> before.  Just remember
	    where this table is and come back to it as you read on.
	    The characters and the information they produce are as
	    follows:</para>

	  <informaltable frame="none">
	    <tgroup cols="2">
	      <tbody>
		<row valign="top">
		  <entry><literal>a</literal></entry>

		  <entry>Archive searching and caching.</entry>
		</row>

		<row valign="top">
		  <entry><literal>c</literal></entry>

		  <entry>Conditional evaluation.</entry>
		</row>

		<row valign="top">
		  <entry><literal>d</literal></entry>

		  <entry>The searching and caching of
		    directories.</entry>
		</row>

		<row valign="top">
		  <entry><literal>j</literal></entry>

		  <entry>Various snippets of information related to
		    the running of the multiple shells.  Not
		    particularly interesting.</entry>
		</row>

		<row valign="top">
		  <entry><literal>m</literal></entry>

		  <entry>The making of each target: what target is
		    being examined; when it was last modified; whether
		    it is out-of-date; etc.</entry>
		</row>

		<row valign="top">
		  <entry><literal>p</literal></entry>

		  <entry>Makefile parsing.</entry>
		</row>

		<row valign="top">
		  <entry><literal>r</literal></entry>

		  <entry>Remote execution.</entry>
		</row>

		<row valign="top">
		  <entry><literal>s</literal></entry>

		  <entry>The application of suffix-transformation
		    rules.  (See <xref linkend="shortcuts"/>.)</entry>
		</row>

		<row valign="top">
		  <entry><literal>t</literal></entry>

		  <entry>The maintenance of the list of targets.</entry>
		</row>

		<row valign="top">
		  <entry><literal>v</literal></entry>

		  <entry>Variable assignment.</entry>
		</row>
	      </tbody>
	    </tgroup>
	  </informaltable>

	  <para>Of these all, the <literal>m</literal> and
	    <literal>s</literal> letters will be most useful to you.
	    If the <option>-d</option> is the final argument or the
	    argument from which it would get these key letters (see
	    below for a note about which argument would be used)
	    begins with a &ndash;, all of these debugging flags will
	    be set, resulting in massive amounts of output.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-f</option> makefile</term>

	<listitem>
	  <para>Specify a makefile to read different from the standard
	  makefiles (<filename>Makefile</filename> or
	  <filename>makefile</filename>).
	  If makefile is <literal>-</literal>,
	  <application>PMake</application> uses the standard input.
	  This is useful for making quick and dirty makefiles.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-h</option></term>

	<listitem>
	  <para>Prints out a summary of the various flags
	    <application>PMake</application> accepts.
	    It can also be used to find out what level of concurrency was
	    compiled into the version of <application>PMake</application> you
	    are using (look at <literal>-J</literal> and
	    <literal>-L</literal>) and various other information on how
	    <application>PMake</application> was configured.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-i</option></term>

	<listitem>
	  <para>If you give this flag, <application>PMake</application> will
	    ignore non-zero status returned by any of its shells.  It is like
	    placing a <literal>-</literal> before all the commands in the
	    makefile.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-k</option></term>

	<listitem>
	  <para>This is similar to <option>-i</option> in that it allows
	    <application>PMake</application> to continue when it sees an
	    error, but unlike <option>-i</option>, where
	    <application>PMake</application> continues blithely as if nothing
	    went wrong, <option>-k</option> causes it to recognize the error
	    and only continue work on those things that do not depend on the
	    target, either directly or indirectly (through depending on
	    something that depends on it), whose creation returned the error.
	    The <option>k</option> is for <quote>keep going</quote>.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-l</option></term>

	<listitem>
	  <para><application>PMake</application> has the ability to lock a
	    directory against other people executing it in the same directory
	    (by means of a file called <filename>LOCK.make</filename> that it
	    creates and checks for in the directory).  This is a Good Thing
	    because two people doing the same thing in the same place can be
	    disastrous for the final product (too many cooks and all that).
	    Whether this locking is the default is up to your system
	    administrator.  If locking is on, <option>-l</option> will turn it
	    off, and vice versa.
	    Note that this locking will not prevent you from invoking
	    <application>PMake</application> twice in the same place&ndash;if
	    you own the lock file, <application>PMake</application> will warn
	    you about it but continue to execute.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-m <replaceable>directory</replaceable></option></term>

	<listitem>
	  <para>Tells <application>PMake</application> another place to search
	    for included makefiles via the
	    &lt;<replaceable>filename</replaceable>&gt; style.
	    Several <filename>-m</filename> options can be given to form a
	    search path.  If this construct is used the default system
	    makefile search path is completely overridden.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-n</option></term>

	<listitem>
	  <para>This flag tells <application>PMake</application> not to
	    execute the commands needed to update the out-of-date targets in
	    the makefile.  Rather, <application>PMake</application> will
	    simply print the commands it would have executed and exit.
	    This is particularly useful for checking the correctness of a
	    makefile.  If <application>PMake</application> does not do what
	    you expect it to, it is a good chance the makefile is wrong.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-p number</option></term>

	<listitem>
	  <para>This causes <application>PMake</application> to print its
	    input in a reasonable form, though not necessarily one that would
	    make immediate sense to anyone but me.  The number is a bitwise OR
	    of 1 and 2, where 1 means it should print the input before doing
	    any processing and 2 says it should print it after everything has
	    been re-created.
	    Thus <option>-p 3</option> would print it twice-a-once before
	    processing and once after (you might find the difference between
	    the two interesting).  This is mostly useful to me, but you may
	    find it informative in some bizarre circumstances.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-q</option></term>

	<listitem>
	  <para>If you give <application>PMake</application> this flag, it
	    will not try to re-create anything.  It will just see if anything
	    is out-of-date and exit non-zero if so.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-r</option></term>

	<listitem>
	  <para>When <application>PMake</application> starts up, it reads a
	    default makefile that tells it what sort of system it is on and
	    gives it some idea of what to do if you do not tell it anything.
	    I will tell you about it in <xref linkend="shortcuts"/>.
	    If you give this flag, <application>PMake</application> will not
	    read the default makefile.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-s</option></term>

	<listitem>
	  <para>This causes <application>PMake</application> to not print
	    commands before they are executed.  It is the equivalent of
	    putting an <quote>@</quote> before every command in the
	    makefile.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-t</option></term>

	<listitem>
	  <para>Rather than try to re-create a target,
	    <application>PMake</application> will simply <quote>touch</quote>
	    it so as to make it appear up-to-date.
	    If the target did not exist before, it will when
	    <application>PMake</application> finishes, but if the target did
	    exist, it will appear to have been updated.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-v</option></term>

	<listitem>
	  <para>Targets can still be created in parallel, however.
	    This is the mode <application>PMake</application> will enter
	    if it is invoked either as <command>smake</command> or
	    <command>vmake</command>.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-x</option></term>

	<listitem>
	  <para>This tells <application>PMake</application> it is OK to export
	    jobs to other machines, if they are available.  It is used when
	    running in Make mode, as exporting in this mode tends to make
	    things run slower than if the commands were just executed
	    locally.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-B</option></term>

	<listitem>
	  <para>Forces <application>PMake</application> to be as
	    backwards-compatible with <application>Make</application> as
	    possible while still being itself.  This includes:</para>

	  <itemizedlist>
	    <listitem>
	      <para>Executing one shell per shell command</para>
	    </listitem>

	    <listitem>
	      <para>Expanding anything that looks even vaguely like a
		variable, with the empty string replacing any variable
		<application>PMake</application> does not know.</para>
	    </listitem>

	    <listitem>
	      <para>Refusing to allow you to escape a <literal>#</literal>
		with a backslash.</para>
	    </listitem>

	    <listitem>
	      <para>Permitting undefined variables on dependency lines and
		conditionals (see below).  Normally this causes
		<application>PMake</application> to abort.</para>
	    </listitem>
	  </itemizedlist>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-C</option></term>

	<listitem>
	  <para>This nullifies any and all compatibility mode flags you may
	    have given or implied up to the time the <option>-C</option> is
	    encountered.  It is useful mostly in a makefile that you wrote for
	    <application>PMake</application> to avoid bad things happening
	    when someone runs <application>PMake</application> as
	    <application>make</application> or has things set in the
	    environment that tell it to be compatible.
	    <option>-C</option> is not placed in the <envar>PMAKE</envar>
	    environment variable or the <makevar>.MAKEFLAGS</makevar> or
	    <envar>MFLAGS</envar> global variables.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-D <replaceable>variable</replaceable></option></term>

	<listitem>
	  <para>Allows you to define a variable to have <quote>1</quote> as
	    its value.  The variable is a global variable, not a command-line
	    variable.  This is useful mostly for people who are used to the C
	    compiler arguments and those using conditionals, which I will get
	    into in <xref linkend="condition"/>.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-I <replaceable>directory</replaceable></option></term>

	<listitem>
	  <para>Tells <application>PMake</application> another place to search
	    for included makefiles.  Yet another thing to be explained in
	    <xref linkend="shortcuts"/> (<xref linkend="including"/>, to be
	    precise).</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-J <replaceable>number</replaceable></option></term>

	<listitem>
	  <para>Gives the absolute maximum number of targets to create at once
	    on both local and remote machines.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-L <replaceable>number</replaceable></option></term>

	<listitem>
	  <para>This specifies the maximum number of targets to create on the
	    local machine at once.
	    This may be <literal>0</literal>, though you should be wary of
	    doing this, as <application>PMake</application> may hang until a
	    remote machine becomes available, if one is not available when it
	    is started.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-M</option></term>

	<listitem>
	  <para>This is the flag that provides absolute, complete, full
	    compatibility with <application>Make</application>.  It still
	    allows you to use all but a few of the features of
	    <application>PMake</application>, but it is non-parallel.
	    This is the mode <application>PMake</application> enters if you
	    call it <command>make</command>.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-P</option></term>

	<listitem>
	  <para>When creating targets in parallel, several shells are
	    executing at once, each wanting to write its own two cents'-worth
	    to the screen.
	    This output must be captured by <application>PMake</application>
	    in some way  in order to prevent the screen from being filled with
	    garbage even more indecipherable than you usually see.
	    <application>PMake</application> has two ways of doing this, one
	    of which provides for much cleaner output and a clear separation
	    between the output of different jobs, the other of which provides
	    a more immediate response so one can tell what is really
	    happening.  The former is done by notifying you when the creation
	    of a target starts, capturing the output and transferring it to
	    the screen all at once when the job finishes.  The latter is done
	    by catching the output of the shell (and its children) and
	    buffering it until an entire line is received, then printing that
	    line preceded by an indication of which job produced the output.
	    Since I prefer this second method, it is the one used by default.
	    The first method will be used if you give the <option>-P</option>
	    flag to <application>PMake</application>.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-V</option></term>

	<listitem>
	  <para>As mentioned before, the <option>-V</option> flag tells
	    <application>PMake</application> to use
	    <application>Make</application>'s style of expanding variables,
	    substituting the empty string for any variable it does not
	    know.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-W</option></term>

	<listitem>
	  <para>There are several times when <application>PMake</application>
	    will print a message at you that is only a warning, i.e.&nbsp;it
	    can continue to work in spite of your having done something silly
	    (such as forgotten a leading tab for a shell command).  Sometimes
	    you are well aware of silly things you have done and would like
	    <application>PMake</application> to stop bothering you.  This flag
	    tells it to shut up about anything non-fatal.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-X</option></term>

	<listitem>
	  <para>This flag causes <application>PMake</application> to not
	    attempt to export any jobs to another machine.</para>
	</listitem>
      </varlistentry>
    </variablelist>

    <para>Several flags may follow a single <literal>-</literal>.  Those flags
      that require arguments take them from successive parameters.
      For example:</para>

    <screen>pmake -fDnI server.mk DEBUG /chip2/X/server/include</screen>

    <para>will cause <application>PMake</application> to read
      <filename>server.mk</filename> as the input makefile,
      define the variable <makevar>DEBUG</makevar> as a global variable and
      look  for included makefiles in the directory
      <filename>/chip2/X/server/include</filename>.</para>
  </section>

  <section id="summary">
    <title>Summary</title>

    <para>A makefile is made of four types of lines:</para>

    <itemizedlist>
      <listitem>
	<para>Dependency lines</para>
      </listitem>

      <listitem>
	<para>Creation commands</para>
      </listitem>

      <listitem>
	<para>Variable assignments</para>
      </listitem>

      <listitem>
	<para>Comments, include statements and conditional directives</para>
      </listitem>
    </itemizedlist>

    <para>A dependency line is a list of one or more targets, an operator
      (<literal>:</literal>, <literal>::</literal>, or <literal>!</literal>),
      and a list of zero or more sources.  Sources may contain wildcards and
      certain local variables.</para>

    <para>A creation command is a regular shell command preceded by a tab.  In
      addition, if the first two characters after the tab
      (and other whitespace) are a combination of <literal>@</literal> or
      <literal>-</literal>, <application>PMake</application> will cause the
      command to not be printed (if the character is <literal>@</literal>) or
      errors from it to be ignored (if <literal>-</literal>).  A blank line,
      dependency line or variable assignment terminates a creation script.
      There may be only one creation script for each target with a
      <literal>:</literal> or <literal>!</literal> operator.</para>

    <para>Variables are places to store text.  They may be unconditionally
      assigned-to using the <literal>=</literal> operator, appended-to using
      the <literal>+=</literal> operator, conditionally (if the variable is
      undefined) assigned-to with the <literal>?=</literal> operator, and
      assigned-to with variable expansion with the <literal>:=</literal>
      operator.  The output of a shell command may be assigned to a variable
      using the <literal>!=</literal> operator.  Variables may be expanded
      (their value inserted) by enclosing their name in parentheses or curly
      braces, preceded by a dollar sign.  A dollar sign may be escaped with
      another dollar sign.  Variables are not expanded if
      <application>PMake</application> does not know about them.
      There are seven local variables: <makevar>.TARGET</makevar>,
      <makevar>.ALLSRC</makevar>, <makevar>.OODATE</makevar>,
      <makevar>.PREFIX</makevar>, <makevar>.IMPSRC</makevar>,
      <makevar>.ARCHIVE</makevar>, and <makevar>.MEMBER</makevar>.
      Four of them (<makevar>.TARGET</makevar>, <makevar>.PREFIX</makevar>,
      <makevar>.ARCHIVE</makevar>, and <makevar>.MEMBER</makevar>) may be used
      to specify <quote>dynamic sources</quote>.  Variables are good.  Know
      them.  Love them.  Live them.</para>

    <para>Debugging of makefiles is best accomplished using the
      <option>-n</option>, <option>-d m</option>, and
      <option>-p 2</option> flags.</para>
  </section>
</chapter>