-
Notifications
You must be signed in to change notification settings - Fork 9
/
mmk_doc.sdml
2141 lines (1995 loc) · 78.8 KB
/
mmk_doc.sdml
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
<COMMENT>
Abstract: VAX DOCUMENT source for _MMK User's Guide_
Authors: Matt Madison
Copyright (c) 2008, Matthew Madison.
Copyright (c) 2014, Endless Software Solutions.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the copyright owner nor the names of any
other contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Modified by:
03-Aug-2012 Sneddon Initial commenting (plus other
rearrangments.
15-Feb-2013 Sneddon Updated for V5.0.
06-Mar-2013 Sneddon Document '~=' assignment.
09-Apr-2013 Sneddon INCLUDE does not require leading '.'.
01-May-2013 Sneddon #68: change '!=' to '|='.
30-May-2014 Sneddon Replace | with <vbar>.
13-JUN-2014 Sneddon Add .SUFFIXES_* directives.
<ENDCOMMENT>
<INCLUDE>(ETC_DIR:DYNAMIC_SYMBOLS.SDML)
<FRONT_MATTER>(MMK_DOC_1)
<TITLE_PAGE>
<TITLE>(Guide to the MMK Make Utility)
<ABSTRACT>(<REFERENCE>(RELMONTH))
<P>This manual describes the MMK Make Utility, a <quote>(make)
utility for VMS systems.
<ENDABSTRACT>
<REVISION_INFO>(This is a revised manual.)
<REVISION_INFO>(Operating System and Version:\VAX/VMS V5.2 or later;
OpenVMS Alpha V1.5 or later; OpenVMS IA64 V8.2 or later)
<REVISION_INFO>(Software Version:\MMK <REFERENCE>(VER))
<ENDTITLE_PAGE>(Endless Software Solutions<LINE>Perth, Western Australia)
<INCLUDE>(SRC_DIR:COPYRIGHT.SDML)
<CONTENTS_FILE>
<PREFACE>(7\MMK_DOC_2)
<P>This guide explains how to install and use MMK.
<head1>(Intended Audience\MMK_DOC_3)
<p>This manual is intended for all MMK users, primarily programmers who
need to build software systems.
<p>MMK is patterned after VAX DEC/Module Management System (DEC/MMS), which
is in turn based on the UNIX <emphasis>(make) utility.
The reader is assumed to have at least cursory knowledge of <emphasis>(make)
or DEC/MMS.
<p>
Further information regarding MMK, including release details and support
agreements can be found at the Endless Software Solutions website:
<code_example>
http://www.endlesssoftware.com.au
<endcode_example>
<NOTE>
This document does not provide a general tutorial on <emphasis>(make) utilities.
New users are advised to learn more about description files (makefiles) by reviewing
either DEC/MMS documentation or books on the UNIX <emphasis>(make)
utility.
<ENDNOTE>
<head1>(Document Structure\MMK_DOC_4)
<p>tbs
<head1>(Related Documents\MMK_DOC_5)
<p>
The following documents might also be helpful when using MMK:
<list>(unnumbered)
<le>The <emphasis>(MMK Release Notes) contain further information related to
new and deprecated features of MMK.
<le>The <emphasis>(Guide to the Module Management System)
(order number: <keep>(AA-P119J-TE)) contains further information related to DEC/MMS
and can be found at
<keep>(<emphasis>(http://h71000.www7.hp.com/doc/decset.html)).
<le>The <emphasis>(GNU Make Manual) contains information related to
<emphasis>(make) and can be found at
<keep>(<emphasis>(http://www.gnu.org/software/make/manual/)).
<endlist>
<head1>(Conventions\MMK_DOC_6)
<p>In this document, the following convention will be used for the names
of the three similar utilities:
<list>(unnumbered)
<le><emphasis>(MMK\BOLD) refers to the package
described in this document.
<le><emphasis>(DEC/MMS\BOLD) refers to DEC/Module Management System,
a product of Digital Equipment Corporation.
<le><emphasis>(<emphasis>(make\ITALIC)\BOLD) refers to the UNIX <emphasis>(make) utility.
<endlist>
<ENDPREFACE>
<ENDFRONT_MATTER>
<chapter>(Introduction\MMK_DOC_7)
<p>This chapter describes MMK. It includes an
overview of MMK and basic information on its use.
<head1>(Overview\MMK_DOC_8)
<p>MMK is a tool for building a <quote>(software system;) that is, a collection
of one or more executable images or other types of files that are related to a
particular project. Building a complex system by hand can be a difficult
and time-consuming task; using command procedures can make the task easier,
but it may still be time-consuming.
<p>With MMK, you create a file called a <emphasis>(Makefile) or
<emphasis>(MMS description file) to describe your software system: the
<newterm>(objects) (i.e., source files, object files, etc.) that comprise the
system, the <newterm>(dependencies) between those objects, and the commands
used to build the system. When you
invoke MMK, it performs the following steps:
<list>(numbered)
<le>MMK reads and parses the description file, constructing a tree from
the objects and dependencies listed in the file.
<le>It then identifies the object to be built (called the <emphasis>(target)).
<le>The tree of dependencies is traced from the target, and the revision dates
for the files in that path are compared. If an object doesn't exist or is
older than the object it depends on, the commands to
build the object are executed in a subprocess. This continues until all
objects along the dependency path have been checked and the target
has been brought completely up-to-date.
<endlist>
<p>In this way, MMK can execute the commands to rebuild only those pieces of your
software system that need rebuilding due to a change that you have made.
This can drastically reduce development time for a project.
<head1>(Invoking MMK\MMK_DOC_9)
<p>Provided that MMK has been installed using the steps laid out in
the installation instructions (file AAAREADME.INSTALL in the kit), you can
invoke MMK from DCL as a foreign command:
<interactive>
<S>($)<u>(MMK)
<endinteractive>
<p>Full command syntax is given in <reference>(mmk_syntax). By default,
MMK looks for a description file called DESCRIP.MMS in the current directory;
if that file does not exist, it then looks for a file called MAKEFILE. If
it cannot find that file, an error is signaled. You can use the /DESCRIPTION
qualifier to specify a different name for your description file, if needed.
<p>MMK starts by reading the description file and constructing a tree
from the <newterm>(objects) listed in the description file
(e.g., source files, include files,
object files, etc.) and a tree of <newterm>(dependencies) between those
objects. It then identifies the <newterm>(target) object to be built,
and traverses the dependency tree to identify those objects that need to
be built (called <emphasis>(intermediate targets)) in order to build the target.
<p>MMK compares each target's revision date/time against the objects on which
it depends and executes the actions for that building the target only if needed.
You can force a complete
rebuild by using the /FROM_SOURCES qualifier on the MMK command.
<chapter>(Description Files\MMK_DOC_10)
<p>The key to successfully building your software system with MMK is
the creation of
a complete and accurate description file. This chapter describes the format
for a description file and its components.
<head1>(Description File Components\MMK_DOC_11)
<p>A description file is a collection of the following components:
<list>(unnumbered)
<le><emphasis>(Dependencies\bold), which describe how one object depends
on one or more other objects.
<le><emphasis>(Actions\bold), which are commands to be executed when an object
needs to be built.
<le><emphasis>(Macro definitions\bold), for defining symbols that may be
used in rules or actions.
<le><emphasis>(Inference rule definitions\bold), which are rules based on
suffixes (and possibly directories as well), from which MMK can infer
dependencies and actions without you having to list them explicitly in
your makefile.
<le><emphasis>(MMK directives\bold), which provide a means for adding
commands to be executed before or after all other actions, provide a simple
conditional-build mechanism, and other directives for modifying MMK's behavior.
<endlist>
<p>Here is an example of a simple description file:
<interactive>
PROGRAM.EXE : MAIN.OBJ,SUBROUTINES.OBJ
LINK/EXEC=PROGRAM.EXE MAIN.OBJ,SUBROUTINES.OBJ
MAIN.OBJ : MAIN.FOR
FORTRAN MAIN
SUBROUTINES.OBJ : SUBROUTINES.MAR
MACRO SUBROUTINES
<endinteractive>
<p>This is a simple collection of dependencies and actions for building
an image called PROGRAM.EXE. PROGRAM.EXE depends on two object files,
called MAIN.OBJ and SUBROUTINES.OBJ; MAIN is a FORTRAN module and
SUBROUTINES is a MACRO module.
<p>MMK accepts either a colon or the DEC/MMS DEPENDS_ON keyword to separate
a target object from its sources. In either case, the separator must be
surrounded by blanks -- this differs from <emphasis>(make), but is consistent
with DEC/MMS syntax.
<head1>(Using Inference Rules\MMK_DOC_12)
<p>MMK includes a collection of built-in inference rules and actions
for most VMS programming languages. The rules are driven by the file type
suffix attached to the object name; you must use the default file types
in order to make use of the default rules.
<p>For example, the description file in the last section could be simplified
to just:
<interactive>
PROGRAM.EXE : MAIN.OBJ,SUBROUTINES.OBJ
LINK/EXEC=PROGRAM.EXE MAIN.OBJ,SUBROUTINES.OBJ
MAIN.OBJ : MAIN.FOR
SUBROUTINES.OBJ : SUBROUTINES.MAR
<endinteractive>
<p>MMK's built-in inference rules automatically define the actions for
building a .OBJ file from a .FOR (using the FORTRAN command) and for building
a .OBJ file from a .MAR file (using the MACRO command).
<P>The description file could even be simplified further, to just:
<interactive>
PROGRAM.EXE : MAIN.OBJ,SUBROUTINES.OBJ
LINK/EXEC=PROGRAM.EXE MAIN.OBJ,SUBROUTINES.OBJ
<endinteractive>
<p>MMK automatically searches the <emphasis>(suffixes list) when
constructing the dependency tree and locates inference rules for
the .OBJ files automatically. This illustrates the second use
for inference rules: they are used not only for inferring actions
for a dependency that omits them, but they may also be used for
inferring dependencies themselves based on a combination of
source and target suffixes. This second purpose can greatly simplify
your makefiles, and makes the build process more automatic.
<head1>(Defining Inference Rules\infrules)
<P>
You can define your own inference rules, either to extend or replace the
ones built into MMK. You may include these rule definitions in your
makefile, or in a separate file called a <emphasis>(rules file). Rules
files can be included by the use of a logical name or through the /RULES
qualifier on the MMK command; see the <reference>(mmk_syntax) for further
information.
<P>
MMK supports two types of inference rules: <emphasis>(generic) and
<emphasis>(prefixed). Generic rules are based solely on suffixes (file types),
as in:
<interactive>
.C.OBJ :
CC/OBJECT=$(MMS$TARGET) $(MMS$SOURCE)
<endinteractive>
<cp>
which says, <quote>(to build <emphasis>(filename).OBJ from an existing file
called <emphasis>(filename).C, use the <emphasis>(CC\bold) command.) In
general, generic rules work best when the source and target files reside
in the same directory.
<P>
<emphasis>(Prefixed) inference rules are based on both suffixes and
<quote>(prefixes) -- device and directory specifications. This provides
a way to have MMK automatically infer dependenices between files that
reside in different directories. For example:
For example, the prefixed rule:
<interactive>
{SRC$:}.C{OBJ$:}.OBJ :
CC/OBJECT=$(MMS$TARGET) $(MMS$SOURCE)
<endinteractive>
<P>
tells MMK, <quote>(to build OBJ$:<emphasis>(filename).OBJ from an existing
file called SRC$:<emphasis>(filename).C, use the <emphasis>(CC\bold) command.)
This works like the generic rule above, but with the additional provision
of having the source and target reside in different locations.
<p>
You can have more than one prefixed rule for a particular pair of suffixes;
you may also mix generic rules and prefixed rules for a pair of suffixes.
When attempting to infer a dependency, MMK will first use the prefixed
rules, then fall back to using the generic rule.
<P>
In prefixed rules, the curly braces (<quote>({) and <quote>(})) are required.
One of the two prefixes may be null, but specifying two null prefixes is
equivalent to defining a generic rule.
<P>
In order to match a prefixed rule, file specification <emphasis>(as
it exists in the description file) must match the prefix in the rule; MMK
performs no logical name translation on prefixes, nor can it identify
equivalencies between two prefixes that reference the same directory using
different syntax.
<P>
The first inference rule for a pair of suffixes, whether it is generic
or prefixed, must specify an action list; subsequent rules for the same
pair of suffixes (with different prefixes) may have the action list omitted,
in which case MMK will use the action list from the first rule. For example,
MMK already has a built-in generic rule for .C.OBJ, which is:
<interactive>
.C.OBJ :
$(CC)$(CFLAGS) $(MMS$SOURCE)
<endinteractive>
<p>
If you are simply adding a set of prefixed rules for the .C.OBJ suffix pair,
you do not need to specify an action list on those rules; MMK will use the
action list from the built-in generic rule.
<head1>(Forced Setup/Teardown Actions in Inference Rules\forcedST)
<P>
MMK recognizes two special modifiers on action lines specified for inference
rules. The <emphasis>(setup) modifier, <quote>(<), forces the execution
of an action prior to any unmodified action. The <emphasis>(teardown)
modifier, <quote>(>), forces the execution of an action after all other
actions. Setup and teardown actions are performed for all dependencies
matching the inference rule, even if a dependency includes explicit
actions.
<p>For example, the inference rule
<interactive>
.C.OBJ :
< DEFINE/USER DECC$SHR V6_ROOT:[SYSLIB]DECC$SHR
$(CC)$(CFLAGS) $(MMS$SOURCE)
<endinteractive>
<P>
would cause the logical name DECC$SHR to be defined prior to the invocation
of the C compiler for all compilations into .OBJ files. This would apply
even on dependencies containing explicit actions, such as
<interactive>
FRED.OBJ : FRED.C
$(CC)$(CFLAGS)/DEFINE=FRED $(MMS$SOURCE)
<endinteractive>
<head1>(Modifying the Suffix List\MMK_DOC_13)
<P>
MMK uses a <emphasis>(suffix list) to determine the inference rules it
should search for inferring a dependency. MMK has a built-in suffix
list which goes with its list of built-in inference rules; see
<reference>(default_rules) for more information on the built-in rules
and suffix list.
<P>You can augment or replace the built-in suffix list
with your own suffixes by using the directives listed in <reference>(sfxdir)
in a rules file or a makefile.
<table>(Suffix List Directives\sfxdir)
<table_setup>(2\10)
<table_heads>(Directive\Description)
<table_row>(.SUFFIXES\Specify no file types to clear the list or append file
types to the end of the suffix list)
<table_row>(.SUFFIXES_BEFORE\Inserts a list of file types in the suffixes
precedence list before the specified first
file type)
<table_row>(.SUFFIXES_AFTER\Inserts a list of file types in the suffixes
precedence list after the specified first
file type.)
<table_row>(.SUFFIXES_DELETE\Removes a list of files types from the suffix
precedence list.)
<endtable>
<P>For example, let's say you have a Modula-2 compiler on your system, whose
source files have a file type (suffix) of .MOD. MMK has no built-in inference
rules for this file type; you could add one with the following sequence:
<interactive>
.SUFFIXES : .MOD
.MOD.OBJ :
MODULA2/OBJECT=$(MMS$TARGET) $(MMS$SOURCE)
<endinteractive>
<P>
The .SUFFIXES directive above adds the .MOD suffix to the end of the
suffix list. This is followed by the inference rule for creating an
object file from a Modula-2 source file.
<P>
Specifying the .SUFFIXES directive with nothing to the right of the colon
clears the current suffix list. You can do this to prevent MMK from
using any inference rules for the current build, or to follow it with
another .SUFFIXES directive that specifies only those suffixes for which you
want inference rules to be enabled.
<P>
It is also possible to determine the current active .SUFFIXES list by
using the builtin macro MMSSUFFIXES.
<head1>(Using Conditionals\using_cond)
<p>
MMK provides several directives that can be used to modify the build sequence
based on conditions. These directives are .IF, .IFDEF, .IFNDEF, .ELSE,
.ELSIF and .ENDIF. The .IFDEF directive checks if the specified macro is
defined and .IFNDEF is the logical inverse, the syntax of which is:
<interactive>
.IFDEF VEGETABLE
...
.ENDIF
<endinteractive>
<p>or,
<interactive>
.IFNDEF VEGETABLE
...
.ENDIF
<endinteractive>
<p>The .IF directive supports more general comparison (and thus greater
power) by allowing the specification of a boolean expression, like so:
<interactive>
.IF expression
...
[.ELSEIF expression]
[...]
[.ELSE]
[...]
.ENDIF
<endinteractive>
<p>In the example above, <emphasis>(expression) can be replaced by any
operations consisting of the operators (both MMS and MMK operators are
listed) listed in <reference>(boolop).
<table>(Conditional Expression Operators\boolop)
<table_setup>(3\10\10)
<table_heads>(MMS Syntax\MMK Syntax\Example)
<table_unit>
<table_unit_heads>(<span>(3)Boolean Operators)
<table_row>(.AND\AND\expression .AND expression)
<table_row>(.NOT\NOT\.NOT expression)
<table_row>(.OR\OR\expression .OR expression)
<endtable_unit>
<table_unit>
<table_unit_heads>(<span>(3)Comparison Operators)
<table_row>(.EQ\EQL\expression .EQ expression)
<table_row>(.GE\GEQ\expression .GE expression)
<table_row>(.GT\GTR\expression .GT expression)
<table_row>(.LE\LEQ\expression .LE expression)
<table_row>(.LT\LSS\expression .LT expression)
<table_row>(.NE\NEQ\expression .NE expression)
<endtable_unit>
<endtable>
<p>All expressions evaluate to a boolean result. After all macro substitution
is performed and the the operand is not an empty string it is the equivalent
of a boolean TRUE. All comparisons are performed without regard to
upper/lower case.
<head2>(GNU Make Conditionals\gnucond)
<p>
Supplemental to the MMS/MMK conditionals, MMK also supports the specification
of the GNU Make-style conditionals <emphasis>(ifeq), <emphasis>(ifneq),
<emphasis>(ifdef), <emphasis>(ifndef), <emphasis>(else) and <emphasis>(endif).
The ifdef and ifndef conditionals behave exactly as their MMS/MMK
counter-parts. However, ifeq and ifneq have a slightly different syntax:
<interactive>
ifeq (arg1, arg2)
ifeq 'arg1' 'arg2'
ifeq "arg1" "arg2"
ifeq "arg1" 'arg2'
ifeq 'arg1' "arg2"
<endinteractive>
<p>Although the example lists ifeq, it can be replaced with its logical
inverse, ifneq. These two directives simply compare their arguments
(ignoring case) and test for equality. The following is an example adapted
from the GNU Make manual:
<interactive>
ifeq ($(strip $(foo)),)
# Come in here if foo is an empty string
...
endif
<endinteractive>
<p>In order to use the conditionals it is necessary to first enable them.
This can be done from the command line with the specification of the
/EXTENDED_SYNTAX=GNU_SYNTAX qualifier or with the .GNU_SYNTAX directive in
the description file.
<head1>(Macro Definitions\macrodef)
<p>
MMK supports a range of operators for assigning values to macros. To simplyfy
description files it is possible to concatenate and test before assignment.
<reference>(macops) defines the available assignment operators.
<table>(Macro Assignment Operator\macops)
<table_setup>(3\8\20)
<table_heads>(Operator\Description\Example)
<table_row>(<emphasis>(=\bold)\Assign value.\<interactive>(FOO = BAR))
<table_row>(<emphasis>(+=\bold)\Concatenate to existing value.\<interactive>(FOR += ,NEXT))
<table_row>(<emphasis>(?=\bold)\Assign if macro is undefined.\<interactive>(FOO ?= FIRST))
<table_row>(<emphasis>(<vbar>=\bold)\Assign command results.\<interactive>(FOO <vbar>= DIRECTORY))
<table_row>(<emphasis>(~=\bold)\Completely evaluate value before assignment\)
<endtable>
<P>
Two of these assignment operators behave a little differently than the others.
They are both described in more detail below.
<head2>(Command Assignment)
<p>Command assignment is the <emphasis>(<vbar>=\bold) operator. The assigned
value is taken as a command and executed, with the results being assigned
to the macro. Using this mechanism it would be possible to determine
some details of the running system, like so:
<interactive>
FOO <vbar>= SHOW SYSTEM/NOPROCESS
ALL :
@ WRITE SYS$OUTPUT "$(FOO)"
<endinteractive>
<p>the results of which might look something like:
<interactive>
$ MMK
OpenVMS V7.3 on node BENDER 15-FEB-2013 16:05:10.03 Uptime 37 15:54:40
<endinteractive>
<note>
<p>
The '!' character is already a comment delimiter in MMK. To resolve this,
the MMK description file parser now tests for a '=' character immediately
following a '!'. Usually when detecting a '!' character the remainder of the
line (including the comment delimiter) will be stripped from the output.
However, in this special case the delimiter and the following characters will
not be stripped and instead parsed as an assignment. This may create issues
for existing procedures that contain comments that match this pattern.
<P>
However, it is worth noting that this restriction only applies to the
'!' comment delimiter. It is still possible to use '#' in any place
and achieve the desired result.
<endnote>
<head2>(Evaluated Assignment)
<p>
Evaluated assignment is the <emphasis>(~=\bold) operator. This assignment
operator is special in that it completely evaluated the value before
assigning it to the macro.
<p>
All records in the description file are evaluated and an attempt is made to
resolve all macros as they are read in to the parser. However, if an
unresolved macro, or a builtin function call is found it is not
evaluated to the empty string, rather it is retained for a time when those
macros are available. An example from the default definitions within MMK
is:
<code_example>
BASIC = BASIC
BASFLAGS = /NOLIST/OBJECT=$(MMS$TARGET_NAME)$(OBJ)
<endcode_example>
The definition of BASFLAGS will not be evaluated fully as the description
file is processed, leaving MMS$TARGET_NAME and OBJ unresolved until BASFLAGS
is resolved as a part of executing the build actions that include this
definition (shown below).
<code_example>
.BAS$(OBJ) :
$(BASIC)$(BASFLAGS) $(MMS$SOURCE)
<endcode_example>
<P>
Sometimes this is not what is wanted and it is necessary to evaluate the
definition completely. The following is an excert from the procedure
that builds MMK's PCSI Product Definition File.
<code_example>
DOCUMENTATION ~= $(ADDPREFIX $(KITDIR),$(WILDCARD $(KITDIR)*.HTML)) -
$(ADDPREFIX $(KITDIR),$(WILDCARD $(KITDIR)*.PDF)) -
$(ADDPREFIX $(KITDIR),$(WILDCARD $(KITDIR)*.PS)) -
$(ADDPREFIX $(KITDIR),$(WILDCARD $(KITDIR)*.TXT))
<endcode_example>
Without being able to evaluate the macro definition for DOCUMENTATION
the list documentation files would actually evaluate to the function
calls, not the results of the builtin function calls.
<head1>(Deferring Macro Substitution\deferring)
<p>
MMK provides a way to defer the resolution of a macro that is referenced
in the right-hand side of a macro definition, as an extension to MMS.
Macros are normally referenced using the $(<emphasis>(name)) syntax,
which causes the value of the macro to be substituted immediately when
a line is parsed (except for MMK's <quote>(special) macros, such as
MMS$SOURCE and MMS$TARGET).
<P>
You can defer this substitution in MMK by using the syntax ${<emphasis>(name)}
instead. However, this syntax is only recognized on the right-hand side
of a macro definition. This can be useful when defining macros in a rules
file that rely on macros that do not get defined until another rules file
or a description file gets processed. For example, you might have the
following definition in a rules file:
<interactive>
CFLAGS = /OBJECT=$(MMS$TARGET)/NOLIST/DEFINE=(VMS_BUILD,${MOREDEFINES})
<endinteractive>
<cp>then in your description file, you can define the MOREDEFINES macro:
<interactive>
MOREDEFINES = ANOTHER_C_DEFINE
<endinteractive>
<cp>This will complete the CFLAGS macro value when it is referenced later
in the description file.
<head1>(Macro String Substitution\macrosubst)
<p>
MMK provides two mechanisms for causing string substitution to occur when
resolving a macro reference: suffix substitution and general string substitution.
<HEAD2>(Suffix Substitution\suffixsubst)
<P>
When a string contains a list of file specifications, you can replace the file
type suffixes on each file specification with a different suffix. The general
form of this type of substitution is:
<SYNTAX>
<EMPHASIS>($<OPAREN>\BOLD)<EMPHASIS>(macro-name)<EMPHASIS>(:\BOLD)<EMPHASIS>(old-sfx)<EMPHASIS>(=\BOLD)<EMPHASIS>(new-sfx)<EMPHASIS>(<CPAREN>\BOLD)
<ENDSYNTAX>
<CP>which causes the replacement of all occurences of the file type suffix <EMPHASIS>(old-sfx) with <EMPHASIS>(new-sfx).
Both suffixes must begin with a dot.
<P>For example,
in these macro definitions:
<INTERACTIVE>
SOURCES = FIRST.C, SECOND.C, THIRD.C
OBJECTS = $(SOURCES:.C=.OBJ)
<ENDINTERACTIVE>
<CP>the OBJECTS macro would have the value <QUOTE>(FIRST.OBJ, SECOND.OBJ, THIRD.OBJ).
This form of substitution works with file specification lists separated by either
blanks, commas, or both. The substitution rule following the colon may also contain
blanks, which are ignored. Substitutions are case-insensitive.
<HEAD2>(General String Substitution\stringsubst)
<P>
General string substitution in macro references is an extended feature of MMK. It
looks very similar to suffix substitution, but uses a double colon (<quote>(::))
instead of a single colon and allows the substitution to occur anywhere within
the string. The syntax is:
<SYNTAX>
<EMPHASIS>($<OPAREN>\BOLD)<EMPHASIS>(macro-name)<EMPHASIS>(::\BOLD)<EMPHASIS>(old-str)<EMPHASIS>(=\BOLD)<EMPHASIS>(new-str)<EMPHASIS>(<CPAREN>\BOLD)
<ENDSYNTAX>
<CP>which causes the replacement of all occurences of the string <EMPHASIS>(old-str) with <EMPHASIS>(new-str).
You may use a backslash <QUOTE>(<BACKSLASH>) as a <quote>(literal-next) escape when one of the strings contains
an equals sign. Neither string may contain a right parenthesis character (<QUOTE>(<CPAREN>)), even quoted with a backslash,
although this restriction will be lifted in a future release of MMK.
For example, the following macro definitions:
<INTERACTIVE>
SOURCES = FIRST.C,SECOND.C,THIRD.C
SOURCEPLUS = $(SOURCES::,=+)
<ENDINTERACTIVE>
<CP>would cause SOURCEPLUS to contain the list of filenames separated with plus
signs (<QUOTE>(+)) rather than commas.
<P>General string substitutions in macro references are case-insensitive, but
<emphasis>(do not) ignore blanks in the macro value or in the substitution rule.
For example, in the following definitions:
<INTERACTIVE>
TEST = Xyz xYz xyZ
REPLACED = $(TEST::YZ =YZ,)
<ENDINTERACTIVE>
<CP>the REPLACED macro would have the value <QUOTE>(XYZ,xYZ,xyZ), due to the
case-blind comparisons and the inclusion of the space in the <EMPHASIS>(old-str)
specification.
<head1>(Builtin Functions\builtins)
<p>
As well as symbol substituion it is also possible to call a number of
builtin functions that can process text to automate and simplify build
definitions. The following reference describes what each of these functions
does, with examples.
<ROUTINE_SECTION>(\\NONEWPAGE)
<ROUTINE>(ADDPREFIX\Prefix List Elements\\func_addprefix)
<SYNTAX>
$(ADDPREFIX prefix,text[ ...])
<ENDSYNTAX>
<DESCRIPTION>
<P>
ADDPREFIX treats <argument>(text) as a whitespace delimited list of words.
Each word is prefixed with <argument>(prefix) and returned in a space
delimited list.
<ENDDESCRIPTION>
<EXAMPLE_SEQUENCE>(EXAMPLE)
<EXAMPLES_INTRO>
The following examples show how to call the <reference>(func_addprefix)
builtin function and demonstrate the expected output.
<EXC>
LIST = CAT, DOG, SECRET, HEAVY
ALL :
@ WRITE SYS$OUTPUT "Unprefixed = $(LIST)"
@ WRITE SYS$OUTPUT "Prefixed = $(ADDPREFIX TOP ,$(LIST))"
<EXTEXT>
Description file to demonstrate the <reference>(func_addprefix) function.
<EXI>
Unprefixed = CAT, DOG, SECRET, HEAVY
Prefixed = TOP CAT, TOP DOG, TOP SECRET, TOP HEAVY
<EXTEXT>
The output the above description file would generate.
<ENDEXAMPLE_SEQUENCE>
<ROUTINE>(ADDSUFFIX\Suffix List Elements\\func_addsuffix)
<SYNTAX>
$(ADDSUFFIX suffix,text[ ...])
<ENDSYNTAX>
<DESCRIPTION>
<P>
ADDSUFFIX treats <argument>(text) as a whitespace delimited list of words.
Each word is suffixed with <argument>(suffix) and returned in a space
delimited list.
<ENDDESCRIPTION>
<EXAMPLE_SEQUENCE>(EXAMPLE)
<EXAMPLES_INTRO>
The following examples show how to call the <reference>(func_addsuffix)
builtin function and demonstrate the expected output.
<EXC>
LIST = OX VAX
SUFFIX = EN,
ALL :
@ WRITE SYS$OUTPUT "Unsuffixed = $(LIST)"
@ WRITE SYS$OUTPUT "Suffixed = $(ADDSUFFIX $(SUFFIX),$(LIST))"
<EXTEXT>
Description file to demonstrate the <reference>(func_addsuffix) function.
Notice that the suffix to be appended to each word is a symbol. This is
so that the text <interactive>(EN,) will recognize the '<s>(,)' character
as part of the suffix and not an argument delimiter in the builtin function.
<EXI>
Unsuffixed = OX VAX QUICK LENGTH STRENGTH
Suffixed = OXEN, VAXEN, QUICKEN, LENGTHEN, STRENGTHEN,
<EXTEXT>
The output the above description file would generate.
<ENDEXAMPLE_SEQUENCE>
<ROUTINE>(AND\Logical And\\func_and)
<SYNTAX>
$(AND condition[,condition[,...]])
<ENDSYNTAX>
<DESCRIPTION>
<P>
The AND function provides a logical and operation. Each of the
<argument>(condition) arguments are expanded until one evaluates to the
empty string. The arguments are evaluated individually and consecutively,
so if one should fail (evaluate to an empty string) then the remaining
conditions will <emphasis>(not\bold) be evaluated.
<P>
If all conditions evaluate to a non-empty string, then the result of this
function is the expansion of the final condition. Otherwise this function
will return the empty string.
<ENDDESCRIPTION>
<EXAMPLE_SEQUENCE>(EXAMPLE)
<EXAMPLES_INTRO>
The following examples show how to call the <reference>(func_and)
builtin function and demonstrate the expected output.
<EXC>
A = A
B = B
C = C
D =
FOO = $(AND $(A),$(B),$(C))
BAR = $(AND $(A),$(B),$(C),$(D))
ALL :
@ WRITE SYS$OUTPUT "FOO = $(FOO)"
@ WRITE SYS$OUTPUT "BAR = $(BAR)"
<EXTEXT>
Description file to demonstrate the <reference>(func_and) function.
<EXI>
FOO = C
BAR =
<EXTEXT>
The output the above description file would generate.
<ENDEXAMPLE_SEQUENCE>
<ROUTINE>(BASENAME\Get File Specification Without Type\\func_basename)
<SYNTAX>
$(BASENAME text[ ...])
<ENDSYNTAX>
<DESCRIPTION>
<P>
BASENAME returns the device, directory and file name portions of the
specifications found in <argument>(text). The result does not include
the file type. If multiple specifications are supplied, they will each
be evaluated and returned in a space delimited list.
<ENDDESCRIPTION>
<EXAMPLE_SEQUENCE>(EXAMPLE)
<EXAMPLES_INTRO>
The following examples show how to call the <reference>(func_basename)
builtin function and demonstrate the expected output.
<EXC>
FOO = $(BASENAME SYS$LOGIN:LOGIN.COM)
ALL :
@ WRITE SYS$OUTPUT "FOO = $(FOO)"
<EXTEXT>
Description file to demonstrate the <reference>(func_basename) function.
<EXI>
FOO = USER$:[FLYNN]LOGIN
<EXTEXT>
The output the above description file would generate.
<ENDEXAMPLE_SEQUENCE>
<ROUTINE>(CALL\Call User-defined Function\\func_call)
<SYNTAX>
$(CALL macro[,param[,...]])
<ENDSYNTAX>
<DESCRIPTION>
<P>
The CALL function makes it possible for a user to develop their own macro
functions. To call a macro function, specify the name in <argument>(macro),
not the substitution, and pass up to 31 arguments in <argument>(param).
<P>
Before <argument>(macro) is call (looked up and resolved) the arguments
passed in <argument>(param) are resolved and defined as symbols $(1)-$(31),
with $(0) being <argument>(macro).
<P>
It is important to remember certain escaping rules when defining
callable macros. MMK supports the concept of deferred substitution (see
<reference>(deferring) by using <S>(${) and <S>(}) as the substitution
delimiters. It is necessary to use this method of substitution when
specifying the macro arguments outside of any builtin function call, for
example:
<CODE_EXAMPLE>
REVERSE = ${2} ${1}
FOO = $(CALL REVERSE,A,B)
<ENDCODE_EXAMPLE>
<ENDDESCRIPTION>
<EXAMPLE_SEQUENCE>(EXAMPLE)
<EXAMPLES_INTRO>
The following examples show how to call the <reference>(func_call)
builtin function and demonstrate the expected output. Another example can
be found under the documentation for <reference>(func_findstring).
<EXC>
ORIGINS = $(FOREACH VAR,$(1),$(ORIGIN $(VAR)))
ECHO = WRITE SYS$OUTPUT
ALL :
@ $(ECHO) "$(CALL ORIGINS,MMSALPHA MMSIA64 MMSVAX)"
<EXTEXT>
This description file shows the definition of the user defined function
<emphasis>(ORIGINS\bold), which is a multi-argument version of the
<reference>(func_origin) builtin.
<P>
This example also demonstrates that because the $(1) substitution is
made within the <reference>(func_foreach) call, there is no need to use
deferred substitution.
<EXI>
UNDEFINED UNDEFINED SPECIAL
<EXTEXT>
The output the above description file would generate when run on a VAX system.
<ENDEXAMPLE_SEQUENCE>
<ROUTINE>(COLLAPSE\Collapse Whitespace\\func_collapse)
<SYNTAX>
$(COLLAPSE text)
<ENDSYNTAX>
<DESCRIPTION>
<P>
The COLLAPSE function removes all whitespace fomr <argument>(text).
<ENDDESCRIPTION>
<EXAMPLE_SEQUENCE>(EXAMPLE)
<EXAMPLES_INTRO>
The following examples show how to call the <reference>(func_collapse)
builtin function and demonstrate the expected output.
<EXC>
FOO = $(COLLAPSE 1 2 3 4 5 6 7) 8 9 10
ECHO = WRITE SYS$OUTPUT
ALL :
@ $(ECHO) "FOO = $(FOO)"
<EXTEXT>
Description file to demonstrate the <reference>(func_collapse) function.
<EXI>
FOO = 1234567 8 9 10
<EXTEXT>
The output the above description file would generate.
<ENDEXAMPLE_SEQUENCE>
<ROUTINE>(DIR\Get Device and Directory\\func_dir)
<SYNTAX>
$(DIR text[ ...])
<ENDSYNTAX>
<DESCRIPTION>
<P>
DIR returns the device and directory portion of the specifications found in
<argument>(text). If multiple specifications are supplied, they will each
be evaluated and returned in a space delimited list.
<P>
To retrieve only the directory, please see <reference>(func_directory).
<ENDDESCRIPTION>
<EXAMPLE_SEQUENCE>(EXAMPLE)
<EXAMPLES_INTRO>
The following examples show how to call the <reference>(func_dir)
builtin function and demonstrate the expected output.
<EXC>
FOO = $(DIR SYS$LOGIN)
ECHO = WRITE SYS$OUTPUT
ALL :
@ $(ECHO) "FOO = $(FOO)"
<EXTEXT>
Description file to demonstrate the <reference>(func_dir) function.
<EXI>
FOO = USER$:[FLYNN]
<EXTEXT>
The output the above description file would generate.
<ENDEXAMPLE_SEQUENCE>
<ROUTINE>(DIRECTORY\Get Directory\\func_directory)
<SYNTAX>
$(DIRECTORY text[ ...])
<ENDSYNTAX>
<DESCRIPTION>
<P>
DIRECTORY returns only the directory portion of the specifications found in
<argument>(text). This is different to <reference>(func_dir) which returns
both the device and directory.
<P>
If multiple specifications are supplied, they will each be evaluated and
returned in a space delimited list.
<ENDDESCRIPTION>
<EXAMPLE_SEQUENCE>(EXAMPLE)
<EXAMPLES_INTRO>
The following examples show how to call the <reference>(func_directory)
builtin function and demonstrate the expected output.
<EXC>
FOO = $(DIRECTORY SYS$LOGIN)
ECHO = WRITE SYS$OUTPUT
ALL :
@ $(ECHO) "FOO = $(FOO)"
<EXTEXT>
Description file to demonstrate the <reference>(func_directory) function.
<EXI>
FOO = [FLYNN]
<EXTEXT>
The output the above description file would generate.
<ENDEXAMPLE_SEQUENCE>
<ROUTINE>(FILENAME\Get Filename\\func_filename)
<SYNTAX>
$(FILENAME text[ ...])
<ENDSYNTAX>
<DESCRIPTION>
<P>
FILENAME returns only the file name portion of the specifications found in
<argument>(text). If multiple specifications are supplied, they will each
be evaluated and returned in a space delimited list.
<ENDDESCRIPTION>
<EXAMPLE_SEQUENCE>(EXAMPLE)
<EXAMPLES_INTRO>
The following examples show how to call the <reference>(func_filename)
builtin function and demonstrate the expected output.
<EXC>
FOO = $(FILENAME SYS$LOGIN:LOGIN.COM)
ECHO = WRITE SYS$OUTPUT
ALL :
@ $(ECHO) "FOO = $(FOO)"
<EXTEXT>
Description file to demonstrate the <reference>(func_filename) function.
<EXI>
FOO = LOGIN
<EXTEXT>
The output the above description file would generate.
<ENDEXAMPLE_SEQUENCE>
<ROUTINE>(FILETYPE\Get File Type\\func_filetype)
<SYNTAX>
$(FILETYPE text[ ...])
<ENDSYNTAX>
<DESCRIPTION>
<P>
FILETYPE returns only the file type portion of the specifications found in
<argument>(text). If multiple specifications are supplied, they will each
be evaluated and returned in a space delimited list.
<ENDDESCRIPTION>
<EXAMPLE_SEQUENCE>(EXAMPLE)
<EXAMPLES_INTRO>
The following examples show how to call the <reference>(func_filetype)
builtin function and demonstrate the expected output.
<EXC>
FOO = $(FILENAME SYS$LOGIN:LOGIN.COM)
ECHO = WRITE SYS$OUTPUT
ALL :
@ $(ECHO) "FOO = $(FOO)"
<EXTEXT>
Description file to demonstrate the <reference>(func_filetype) function.
<EXI>
FOO = .COM
<EXTEXT>
The output the above description file would generate.
<ENDEXAMPLE_SEQUENCE>
<ROUTINE>(FILEVERSION\Get File Version\\func_fileversion)
<SYNTAX>
$(FILEVERSION text[ ...])
<ENDSYNTAX>
<DESCRIPTION>
<P>
FILEVERSION returns only the file version portion of the specifications found
in <argument>(text). If multiple specifications are supplied, they will each
be evaluated and returned in a space delimited list.
<P>
FILEVERSION retrieves the version information calling the $PARSE and then
the $SEARCH system services. In the event that the file does not exist,
the version number is returned as ";" so that a missing element does not
disrupt the list.
<ENDDESCRIPTION>