summaryrefslogtreecommitdiff
path: root/jmake/NOTES
blob: a11618d8cdf0c6afd7fd91e70fb57ea9770e2737 (plain)
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
The syntax in Jmake.rules is not elegant at all, but:

	- It is easy to parse (like sendmail.cf or troff files).
	- The rules are not supposed to change very often.
	- It is simple enough to be mastered in five minutes. :-)

Here is a small description:

o To deal with various cpp implementations:

Final @!\ means: end of line, next line starts at the left margin.
Final @@\ means: end of line, next line is to be indented by one tab.

The conversion occurs during Pass1.


o Symbol definitions

>SYMBOL: defines the symbol (Pass 1).
?SYMBOL:<text>: keeps <text> iff SYMBOL is defined (Pass 2).
%SYMBOL:<text>: keeps <text> iff SYMBOL is not defined (Pass 2).

The ?SYM can be nested (logical AND), as in:

	?SYMBOL:%TOKEN:text		/* Keeps text if SYMBOL and not TOKEN */

To implement a logical OR, see below.


o Commands

Commands can be passed to 'jmake'. They start with a leading '|'.

Available commands are:

|suffix <sx>: adds <sx> to the .SUFFIXES: list in the makefile (Pass 1 & 2).
|rule:<text>: adds <text> to the building rule section (Pass 1 & 2).
|rule: <text>: same as before, with a leading tab.
|skip: skips text until a line starting with '-skip' is found (Pass 2).
|expand <pattern>: expand lines until '-expand' with <pattern> (Pass 2).
|once <symbol>: text up to '-once' appears only the first time (Pass 1).

Thus, a way to implement a logical OR could be:

	/* Implements SYMBOL or not TOKEN */
	?SYMBOL:text			/* Keeps text if SYMBOL */
	%SYMBOL:|skip
		%TOKEN:text			/* Keeps text if not TOKEN */
	-skip

Actually, this is ugly, because the text has to appear twice.
Fortunately, I did not use it. :-)

The '|' commands cannot be nested. In particular, due to the simple
implementation of '|skip', it is impossible to put '|skip' inside
a skipped part. However, a '|once' section may have '|skip' sections.

But actually, as you have surely already guessed, the best way to
implement a logical OR is to use De Morgan's Law:

	not (p or q) <=> not p and not q

	/* Implements SYMBOL or not TOKEN (attempt #2) */
	%SYMBOL:?TOKEN:|skip
	text					/* If SYMBOL or not TOKEN */
	-skip

Who said they don't care ? ;-)

o Expansion

Expansion is done with the 'expand' command.  It has been provided to
avoid some cumbersome writings in makefiles when you have to repeat some
silly lines that only differ in file names, for instance.  Let's look at
an example first:

	|expand a!foo bar! b!yes no!
	!a::
		echo !a, !b
	-expand

Then two rules will be printed, and the values of (a,b) for the first
will be (foo, yes), for the second (bar, no).  Substitution is controled
by the '!' character.  If the word to be substituted is part of another
one, detach with the ^^ construct as in:  !b^^c.  It is possible to
use Makefile macros in the <pattern>, and they will be expanded by
jmake.  If this is not what you want, escape the first '$' sign (this is
a Makefile escape, i.e. you must double the '$', not precede it with a
backslash). A // stands for the null substitution value.

Here is another example which shows how the macro Expand can be used.
It is defined in Jmake.rules as:

	#define Expand(rule, pattern) @!\
	|expand pattern @!\
	rule @!\
	-expand

So we can write in the Jmakefile:

	|skip
	A = foo bar
	-skip

	#define Rule @!\
	$(DIR)/!a^^.o: !a^^.o @@\
		$(CC) -c !a^^.c @@\
		$(MV) !a^^.o $(DIR)
	
	Expand(Rule, a!$(A)!)

which will generate in Makefile.SH:

	$(DIR)/foo.o: foo.o
		$(CC) -c foo.c
		$(MV) foo.o $(DIR)

	$(DIR)/bar.o: bar.o
		$(CC) -c bar.c
		$(MV) bar.o $$(DIR)

The 'A' declaration has been surrounded by skip, so that it does
not appear in the generated Makefile.SH, but it will be taken into
account by jmake for the substitution in the pattern.

The number of expansions is determined by the number of possible
values for the _first_ parameter. If other parameters have less
substitution values, they will get void ones.

It is possible to add a regular expression at the end of '-expand'.
This regular expression will be removed from the final set of expansion
at the end of each line.  It is also possible to do substitutions in the
expanded item, by using the syntax (if 'f' is the expanded variable)
!f:<p>=<q> where <p> and <q> are two regular expressions (without
spaces).  The pattern <p> will be replaced by pattern <q> (only the
first occurrence will be replaced).

Finally, you may refer in the expanded section to variables whose value
is computed via another expansion, which makes it easy to define generic
Jmakefiles.

Example:

	SRC = foo.c bar.c
	OBJ = \
	|expand f!$(SRC)!
		!f:\.c=\.o \
	-expand \\
	INC = \
	|expand f!$(OBJ)!
		!f:\.o=\.h \
	-expand \\

which will generate in Makefile.SH:

	SRC = foo.c bar.c
	OBJ = \
		foo.o \
		bar.o
	INC = \
		foo.h \
		bar.h

Do not forget to protect special characters in your regular expressions such
as backslash, point, etc...

o Once

The once command is tagged with a name. The first time the name appears,
the once construct is ignored and the text up to '-once' will be copied
in the generated Makefile.SH.  However, future occurences of the same
name will be ignored (once will behave like skip).

Example:

	|once this_is_a_name
	<text>
	-once

o Initializations

+<line>: Puts the whole line in the initialization section (Pass 1 & 2).
++SYMBOL <value>: Adds <value> to the SYMBOL macro (Pass 1 and 2).

o User-defined variables

CFLAGS: added flags to C compiler
DPFLAGS: cpp flags to be added to mkdep for dependency
LDFLAGS: flags/libraries to be added at linking stage