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- 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—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—which files (targets) need to
be created from which files (sources)—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 – 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) < <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>@^&$%$</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—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. <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. 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. 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. 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. 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 –, 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–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
<<replaceable>filename</replaceable>> 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. 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>
|