summaryrefslogtreecommitdiff
path: root/jmake/jmake.man
blob: 49c4b73b2fa648a75949d32fe5c10f058c25f88d (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
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
.\" $Id: jmake.man 47 2010-11-28 22:23:13Z rmanfredi $
.\"
.\"  Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi
.\"
.\"  You may redistribute only under the terms of the Artistic Licence,
.\"  as specified in the README file that comes with the distribution.
.\"  You may reuse parts of this distribution only within the terms of
.\"  that same Artistic Licence; a copy of which may be found at the root
.\"  of the source tree for dist 4.0.
.\"
.\" $Log: jmake.man,v $
.\" Revision 3.0.1.3  2004/08/22 09:01:55  ram
.\" patch71: renamed |test as |case as the construct has its syntax
.\" patch71: added |subst section to allow variable substitutions
.\"
.\" Revision 3.0.1.2  2004/08/21 23:19:52  ram
.\" patch71: added '|shell' section to emit verbatim code in Makefile.SH
.\" patch71: new '|test' to conditionally generate Makefile sections
.\"
.\" Revision 3.0.1.1  1995/05/12  11:57:58  ram
.\" patch54: updated my e-mail address
.\"
.\" Revision 3.0  1993/08/18  12:04:18  ram
.\" Baseline for dist 3.0 netwide release.
.\"
.TH JMAKE 1 ram
.SH NAME
jmake \- a generic makefile builder
.SH SYNOPSIS
.B jmake
[
.I cpp options
]
.SH DESCRIPTION
.I Jmake
builds a makefile out of a rather high level description held in a
.I Jmakefile
file. The generated file is a
.I Makefile.SH
rather than a simple makefile, which means it is ready to be used in
conjonction with
.I metaconfig.
In particular, parameters such as "where to install executables" will
be automatically determined by
.I Configure
and only the needed parameters will be taken into account.
.PP
To use
.I jmake
you have to write a
.I Jmakefile
first, which describes the way things are to be built. Your
.I Jmakefile
will be included inside a generic template through the C pre-processor.
This means you may use the usual C /**/ comments, but not the shell # comments.
The C comments will not appear in the generated
.I Makefile.SH
but lines starting with ;# will finally appear as shell comments. If you
have to write the string /* in the generated
.I Makefile.SH
then you have to escape it (otherwise
.I jmake
will think of it as the start of a C comment). Simply put a # in front
of the *, as in /#*.
.PP
You have a set of macros at your disposal, and all these macros are
listed in the Index file, along with the piece of code they will
expand to. Usually, a
.I Jmakefile
is fairly small and thus easier to maintain than a huge
.I Makefile.
Some internal powerful commands allow you to write
portable makefiles easily, without having to spend many efforts, because
someone else already did the job for you :-).
.PP
When you want to generate your makefile, you usually do not run
.I jmake
but use the
.I jmkmf
script which is a wrapper and will invoke
.I jmake
with the correct options.
.PP
All the knowledge of
.I jmake
is held in two files: the template
.I Jmake.tmpl
and the macro definition file
.I Jmake.rules.
The first file includes the second, along with the
.I Jmakefile.
It is sometimes necessary to know how things works to be able to correctly
use all the features provided. For instance, you may have to write your
own rules for a specific project. Although you cannot overwrite the
predefined rules, you can extent the
.I Jmake.rules
file or simply add your macros in your
.I Jmakefile.
You may also use
.I #include
statements when you want to share these macros and do not want to duplicate
the code.
.PP
The syntax in Jmake.rules is not elegant at all, but:
.sp
.PD 0
.IP -
It is easy to parse (like sendmail.cf or troff files).
.IP -
The rules are not supposed to change very often.
.IP -
It is simple enough to be mastered in five minutes. :-)
.sp
Here is a small description:
.sp
.IP 1)
To deal with various \fIcpp\fR implementations:
.sp
.RS
.IP \(bu
Final @!\\ means: end of line, next line starts at the left margin.
.IP \(bu
Final @@\\ means: end of line, next line is to be indented by one tab.
.sp
.PP
There should always be one of @!\\ or @@\\ at the end of each line.
The only exception is for macros that are to be used as part of a
rule body (e.g. \fIRemoveTargetProgram\fR). In that case, the first
line (which holds the \fI#define\fR) should end with a single backslash.
.RE
.sp
.IP 2)
Symbol definitions:
.sp
.RS
.IP \(bu
>SYMBOL: defines the symbol.
.IP \(bu
?SYMBOL:<text>: keeps <text> iff SYMBOL is defined.
.IP \(bu
%SYMBOL:<text>: keeps <text> iff SYMBOL is not defined.
.sp
.PP
The ?SYM can be nested (logical AND), as in:
.sp
.in +5
?SYMBOL:%TOKEN:text
.in -5
.sp
which will keep text if SYMBOL is defined and TOKEN undefined.
To implement a logical OR, see below.
.RE
.sp
.IP 3)
Makefile target tests:
.sp
.RS
.IP \(bu
?\fItarget\fR?:<text>: keeps <test> iff \fItarget\fR is defined.
.IP \(bu
%\fItarget\fR%:<text>: keeps <test> iff \fItarget\fR is not defined.
.sp
A makefile \fItarget\fR is defined as a standalone target, for instance
the
.B depend.local
target, which would be defined as:
.sp
.in +5
.nf
depend.local:
.sp
.in -5
.fi
Also note that it is only valid for targets defined
.I so far
in the generated makefile.  It is not a predicate that can be used
to test for targets that will eventually be defined later on in the
generation.
.RE
.sp
.IP 4)
Commands:
.sp
.RS
Commands can be passed to \fIjmake\fR. They start with a leading '|'.
Available commands are:
.sp
.IP \(bu
|suffix <sx>: adds <sx> to the .SUFFIXES: list in the makefile.
.sp
.IP \(bu
|rule:<text>: adds <text> to the building rule section.
.sp
.IP \(bu
|rule: <text>: same as before, with a leading tab.
.sp
.IP \(bu
|skip: skips text until a line starting with '-skip' is found.
.sp
.IP \(bu
|subst: begins section where lines will be subject to variable substitution,
until '-subst' is found.  This means that when the Makefile.SH is run, all
instances of $var within the \fIsubst\fR section will be substituted by the
shell.
.sp
.IP \(bu
|shell: emits section until matching '-shell' as-is in the generated
Makefile.SH.  This can be useful to prepare \fI|case\fR sections.  It is
not allowed to nest \fIshell\fR sections.
.sp
.IP \(bu
|case: this command must be followed by a shell variable name (without
its leading '$' sign) and a case-style pattern, for instance the string
"var in f*".  It will generate the corresponding "case" test in the
Makefile.SH on the "$var" value and only if this test is true will the
section until the matching '-case' be generated in the Makefile when
Makefile.SH is run.  It is possible to nest \fIcase\fR sections freely.
.sp
.IP \(bu
|expand <pattern>: expand lines until '-expand' with <pattern>. A
complete example is shown below.
.sp
.IP \(bu
|once <symbol>: text up to '-once' appears only the first time.
.sp
.PP
The '|' commands cannot be nested, unless otherwise noted.
In particular, due to the simple
implementation of \fI|skip\fR, it is impossible to put \fI|skip\fR inside
a skipped part. However, a \fI|once\fR section may have \fI|skip\fR sections.
It is allowed to nest \fI|case\fR sections at will.
.sp
.PP
Here is a way to implement a logical OR:
.sp
.in +5
.nf
/* Implements SYMBOL or not TOKEN */
?SYMBOL:text		/* Keeps text if SYMBOL */
%SYMBOL:|skip
	%TOKEN:text		/* Keeps text if not TOKEN */
-skip
.fi
.in -5
.sp
Actually, this is ugly, because the text has to appear twice.
Fortunately, I did not use that construct. :-)
.sp
Indeed, as you have surely already guessed, the best way to
implement a logical OR is to use De Morgan's Law:
.sp
.in +5
.nf
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
.sp
.in -5
.fi
Who said they didn't care about logic? ;-)
.sp
.PP
Expansion is done with the \fIexpand\fR 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:
.sp
.in +5
.nf
|expand a!foo bar! b!yes no!
!a::
	echo !a, !b
-expand
.fi
.in -5
.sp
.PP
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.
.PP
The ^^^ construct behaves like ^^, i.e. it is stripped out, but it also
removes any following white space after the ^^^.  If you prepend something
to a macro argument, and that macro argument was written with spaces before
it, then this will let you concatenate something right before that argument's
final value.
.sp
.PP
Here is another example which shows how the macro Expand can be used.
It is defined in \fIJmake.rules\fR as:
.sp
.in +5
.nf
#define Expand(rule, pattern) @!\\
|expand pattern @!\\
rule @!\\
-expand
.sp
.in -5
.fi
So we can write in the \fIJmakefile\fR:
.sp
.in +5
.nf
|skip
A = foo bar
-skip

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

Expand(Rule, a!$(A)!)
.sp
.in -5
.fi
which will generate in \fIMakefile.SH\fR:
.sp
.in +5
.nf
$(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)
.sp
.in -5
.fi
.sp
.PP
The 'A' declaration has been surrounded by \fIskip\fR, so that it does
not appear in the generated Makefile.SH, but it will be taken into
account by \fIjmake\fR for the substitution in the pattern.
.sp
.PP
The number of expansions is determined by the number of possible
values for the \fBfirst\fR parameter. If other parameters have less
substitution values, they will get void ones.
.sp
.PP
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:\fI<p>\fR=\fI<q>\fR
where \fI<p>\fR and \fI<q>\fR are two regular expressions (without spaces).
The pattern \fI<p>\fR will be replaced by the pattern \fI<q>\fR (only the first
occurrence will be replaced).
.sp
.PP
Finally, you may refer in the expanded section to variables whose value is
computed via another expansion, which makes it easy to define generic
\fIJmakefiles\fR.
.sp
Example:
.sp
.in +5
.nf
SRC = foo.c bar.c
OBJ = \\
|expand f!$(SRC)!
	!f:\\.c=\\.o \\
-expand \\\\
INC = \\
|expand f!$(OBJ)!
	!f:\\.o=\\.h \\
-expand \\\\
.fi
.in -5
.sp
which will generate in \fIMakefile.SH\fR:
.sp
.in +5
.nf
SRC = foo.c bar.c
OBJ = \\
	foo.o \\
	bar.o
INC = \\
	foo.h \\
	bar.h
.in -5
.fi
.sp
Do not forget to protect special characters in your regular expressions such
as backslash, point, etc...
.sp
.PP
The \fIonce\fR 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 (\fIonce\fR will behave like \fIskip\fR).
.sp
Example:
.sp
.in +5
.nf
|once this_is_a_name
<text>
-once
.sp
.in -5
.fi
.sp
.PP
The \fIshell\fR command can be used to generate a shell fragment
in the Makefile.SH.  For instance, the following section in the Jmakefile:
.sp
.in +5
.nf
|shell
case "$d_usegtk1" in
define) glib=1; gtk=1;;
esac
-shell
.sp
.in -5
.fi
will cause the generation of the enclosed fragment in the Makefile.SH to
compute the values of the \fIglib\fR and \fIgtk\fR variables based on the
configuration variable \fId_usegtk1\fR set by running Configure.
.sp
.PP
In turn, this can be used in subsequent \fIcase\fR sections to activate
parts of the Makefile only when building for GTK1 using glib-1.x:
.sp
.in +5
.nf
|case glib in 1
display:
	echo "Building for glib-1.x"
-case
.sp
.in -5
.fi
This section will generate something like this in the Makefile.SH:
.sp
.in +5
.nf
!NO!SUBS!
case "$glib" in
1)
	$spitshell >>Makefile <<'!NO!SUBS!'
display:
	echo "Building for glib-1.x"
!NO!SUBS!
	;;
esac
$spitshell >>Makefile <<'!NO!SUBS!'
.sp
.in -5
.fi
And when running Makefile.SH, the "display" rule above will only appear
when building for glib-1.x.  The form of the final \fIMakefile\fR can
therefore depend on the configuration options chosen when \fIConfigure\fR
was run.
.RE
.sp
.IP 5)
Initializations:
.sp
.RS
.IP \(bu
+<line>: Puts the whole line in the initialization section.
.IP \(bu
++SYMBOL <value>: Adds <value> to the SYMBOL macro.
.RE
.sp
.IP 6)
User-defined variables:
.sp
The user may define CFLAGS, LDFLAGS or DPFLAGS as additional flags to be used
in C compilation, linking phase or depend target. It is thus possible to add
some extra flags such as -I or libraries for Makefiles in specific
sub-directories.
.sp
.PD
.SH AUTHOR
Raphael Manfredi <Raphael_Manfredi@pobox.com>
.SH FILES
.PD 0
.TP 20
Jmakefile
High level description of Makefile.SH
.TP
Jmake.rules
File holding the macro definitions
.TP
Jmake.tmpl
Template used to mould Makefile.SH
.PD
.SH BUGS
On systems whose
.I cpp
reduces multiple tabs and spaces to a single space,
.I jmake
attempts to put back any necessary tabs (which
.I make
expects in front of rules) but does not properly formats the
body of the rule itself.
.PP
There is a bootstraping problem when creating the first Makefile.SH, because
you cannot run it through a shell until there is a decent Configure
script, but you can't run \fImetaconfig\fR before there is a Makefile.SH
or some needed symbols will not be defined.
.SH "SEE ALSO"
jmkmf(1), metaconfig(1).