-
Notifications
You must be signed in to change notification settings - Fork 8
/
MANPAGE
1136 lines (888 loc) · 53.5 KB
/
MANPAGE
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
STU(1) STU STU(1)
NAME
stu - build automation
SYNOPSIS
stu [ -f FILENAME ] [ OPTION ]... [ TARGET ]...
DESCRIPTION
Stu is a tool for build automation. Like Make, it is used to call
other programs in order to build files. Stu has three features that
work in conjunction to allow contructs impossible to realize in Make:
(1) Dynamic dependencies: The dependencies of a target can be them‐
selves computed by a command. When '[FILENAME]' (a filename currounded
by angle brackets) is used as a dependency, Stu will build the file
FILENAME and read dependencies from it. (2) Parameters: Names of
files (and transient targets) can contain parameters written using dol‐
lar syntax. For example, a rule with a target filename 'list.$name'
will be used to build any file matching the pattern 'list.*', and the
parameter $name can be used in names of dependencies and in the build
command. Targets may contain any number of parameters. (3) Concatena‐
tion: Stu allows expressions such as list.[FILENAME] and list.(a b c)
to construct a list of files following a certain pattern.
At its core, Stu is very much like Make: Instead of a 'Makefile', one
uses a file named 'main.stu', which is read by Stu. Also like Make, Stu
will build the first target it finds, except if given an explicit tar‐
get to built. Stu is designed to follow the conventions of Make, of
the shell, and of Unix and POSIX in general. As an example, the op‐
tions -f and -k have the same meaning in Stu as they do in Make.
Rules for building files are read from the file 'main.stu', from a file
passed by the -f option, or using -F.
Names of targets to build passed on the command line outside of options
follow a simplified Stu syntax, in which the only special characters
are the transient target marker '@', brackets '[]', and flags starting
with a dash '-'. All other characters are interpreted as part of file‐
names; this includes all spaces. The parentheses '()' are not parsed
as Stu syntax, because the shell's braces '{}' can be used instead.
When -J is used, arguments passed on the command line are interpreted
as filenames without Stu syntax. The syntax of arguments outside of
options and without using the -J is subject to change with new features
in Stu -- to pass filenames portably, use the -c option when passing
individual filenames, or -J when passing multiple filenames, e.g. via
xargs(1). To pass targets in full stu syntax portably, use the -C op‐
tion.
OPTIONS
-0 FILENAME
Read targets from FILENAME, which must contain \0-separated
filenames. No Stu syntax is processed. This option is also
suitable in all cases where a file contains only the name of a
single file, since filenames do not contain the \0 character.
Using this option is equivalent to using the [-0 FILENAME] syn‐
tax.
-a Treat all trivial dependencies, which are declared with the -t
flag or option, as non-trivial.
-c FILENAME
Pass a target filename, without Stu syntax. This option only
allows file targets to be specified, not transient targets.
-C EXPRESSION
Pass a target using full Stu syntax. The given expression is
parsed as if it was given as one or more dependencies in a Stu
script. As a result, flags -p, -o and -t, brackets, parentheses
and other Stu syntax elements can be used, and spaces separate
filenames. This is not equivalent to passing a string as an ar‐
gument to Stu outside of options, because -C supports full Stu
syntax, while arguments supports only a reduced syntax (see
above).
-d Debug mode. Show internal information about the Stu algorithm
on standard error output. All printed output lines begin with
the string 'DEBUG ', i.e. the word DEBUG followed by two spa‐
ces. The output is otherwise not standardized and is subject to
change, in particular with internal changes to the algorithms
used.
-E Explain error messages. For certain errors, an additional ex‐
planation is written on standard error output. Only some error
messages have explanations.
-f FILENAME
Read the given file instead of the default 'main.stu'. If the
name of a directory is passed, the file 'main.stu' in the given
directory is read. If '-' is passed, read standard input. The
-f option can be used multiple times.
-F RULES
Pass rules in full Stu syntax.
-g Treat all optional dependencies (declared with the -o flag) as
non-optional.
-h, --help
Output a short help and exit.
-i Interactive mode. I.e., put the jobs run into the foreground.
Must not be used in conjunction with -j N when N > 1. Without
this option, jobs are run in the background, meaning they can't
read standard input (they get /dev/null instead), will not get
any terminal signals, and pressing Ctrl-C will stop Stu as a
whole. Using this option, each job is run in the foreground,
and therefore they can read standard input, will get terminal
signals such as SIGINT (after Ctrl-C) and end-of-stdin (after
Ctrl-D). Thus, when -i is used, pressing Ctrl-C will only in‐
terrupt the currently running job, and if the -k option is used,
Stu will continue with the next job. When Ctrl-Z is pressed,
Stu will interrupt the currently running job, and ask the user
to press ENTER to continue, or press Ctrl-C/Ctrl-Z to interrupt
or suspend Stu itself. When -i is used, Stu must be run in a
terminal.
-I Print a list of all buildable file targets and exit. Prints one
file pattern per line. The patterns are glob pattern suitable
for use in the shell. Use quoting for all characters that need
quoting in the shell. Can be used to populate files such as
".gitgignore", but care should be taken due to the quoting syn‐
tax and Git's special handling of names that start or end with a
slash.
-j K Run K jobs in parallel. K must be a positive integer. Without
this option, jobs are not run in parallel, which is equivalent
to using the -j 1 setting. When running jobs in parallel and
the -k option is not used, a single job that fails will make Stu
abort all other running jobs and terminate. Thus, the -j option
is often used in conjunction with the -k option. The parameter
K is mandatory. This option works like the corresponding option
in GNU Make, but note that in GNU Make, the argument is op‐
tional.
-J Parse all arguments to Stu as filenames, disabling all Stu syn‐
tax that is otherwise used. Intended when Stu is used with
tools such as xargs(1) or similar. The -J option itself does
not take an argument; it only changes the way arguments outside
of options are interpreted.
-k Keep going. Do not stop running when an error occurs. Instead,
try to build as much as possible. This option is equivalent to
that of Make.
-K Don't delete partially built files when a command fails or when
Stu is interrupted. By default, Stu will delete the target of a
command after the command fails or is interrupted, when the file
is newer than it was before starting the command. This option
disables that behavior. Note that with this option, a subse‐
quent invocation of Stu may lead to the partially built file be‐
ing erroneously considered up to date.
-m ORDER
Specify the order in which jobs are run. When ORDER is 'dfs'
(the default), Stu traverses the dependency graph in a depth-
first fashion, in a way similar to most Make implementations.
When ORDER is 'random', the order in which jobs are run is ran‐
domized within each target.
-M STRING
Run jobs in pseudorandom order, seeded by the given string.
-n FILENAME
Read targets from FILENAME, which must contain newline-separated
filenames. No Stu syntax is processed. Using this option is
equivalent to using the [-n FILENAME] syntax.
-o FILENAME
Pass the given file as an optional dependency, i.e., build it
only if it already exists and is out of date.
-p FILENAME
Pass the given file as a persistent dependency, i.e., build the
file but ignore its timestamp.
-P Print the set of rules and exit. Note that Make has a -p option
to print the rules, but does not exit. The output format is not
specified.
-q Question mode. Do not execute any commands. Instead, determine
whether the targets are up to date. The exit status is 0 when
all given targets (or the default target) are up to date, and 1
when not. The exit status may still be 2 or 4 on encountering
logical or fatal errors. The options -k and -j are ignored.
-s Silent mode. Suppress messages on standard output: messages
about which commands are run, a message when the build is suc‐
cessful, and a message when there is nothing to be done. Error
messages are not suppressed. This option is comparable to the
same option in Make.
-V, --version
Output the version number of Stu and exit.
-x Call the shell using the -x option, i.e., each individual shell
command is output to standard error output individually, instead
of outputting a full command at once on standard output. In the
output, each command is prefixed by the value of '$PS4'.
-y Disable color in output. By default, Stu checks whether error
output and standard error output are TTYs and whether $TERM is
defined and not 'dumb' and if they are, uses ANSI escape se‐
quences to color code messages.
-Y Enable color output.
-z Output runtime statistics about child processes on standard out‐
put when finished. Does not include the runtime of the Stu
process itself. Includes the runtime of all child and grand‐
child processes, and so on. Does not include the runtime of
children or grandchildren that have not been waited for (which
only happens when Stu is interrupted by a signal.)
Stu options are parsed with getopt(3) and therefore options must
precede arguments. Options following arguments may be supported
on some platforms.
OVERVIEW
A simple rule looks as follows:
results.txt: data.txt compute {
./compute --input data.txt --output results.txt
}
The colon may be omitted when there are no dependencies:
data.csv { ./generate --output data.csv }
Here is an example of a rule containing three parameters. Stu will use
pattern matching to match the target pattern to a given filename:
plot.$dataset.$method.$measure.eps:
data-$dataset.txt analyse-$method
{
./analyse-$method \
-m $measure \
-f data-$dataset.txt \
-o plot.$dataset.$method.$measure.eps
}
Here is an example of a dynamic dependency. The target 'compute' (a C
program) must be rebuild whenever its source code files are modified.
Since the set of source code files is large and may be changed by
changing the source code itself, we use the file 'compute.c.dep' to
contain the list of dependencies. The file 'compute.c.dep' will then
be built by Stu like any file, and its content parsed for the actual
dependencies:
compute: [compute.c.dep] {
gcc -c compute.c -o compute
}
$name.c.dep: $name.c compute-dep {
./compute-dep-c "$name.c" >"$name.c.dep"
}
Parameters can also use the syntax ${...}.
Syntax can be on multiple lines; whitespace is not significant. No
backslashes are needed at line ends:
output.txt:
a.data b.data c.data d.data e.data f.data g.data h.data i.data
j.data k.data l.data m.data
{
do-stuff >output.txt;
}
A rule may be entirely given on a single line:
system-info: { uname -a >system-info }
The following rule uses single quotes to declare filenames that include
parentheses and a colon:
'((': 'aaa:bbb' {
./bla -f
}
Multiple parametrized rules may match a target. In that case Stu uses
the one that is the least parametrized, as defined by the subset rela‐
tion on the set of characters that are in parameters. When building
'X.txt' in this example, only the second rule is called:
$name.txt: { echo "$name" is the best >"$name.txt" }
X.txt: { echo X sucks >X.txt }
Persistent dependencies: In the following example, the directory
'data' is a persistent dependency, i.e. 'data' is only built when it
does not exist, but it is never re-built. A persistent dependency is
indicated by the -p flag. This is useful for directories, whose time‐
stamps change when files are created/removed in them.
data/file: -p data {
echo Hello >data/file
}
data: { mkdir data }
Optional dependencies can be declared with the -o flag. An optional
dependency will never be built if it does not already exist. If it al‐
ready exists, then its own rule is used (and its date checked) to de‐
cide whether it should be rebuilt.
target: -o input {
if [ -r input ] ; then
cp input target
else
echo Hello >target
fi
}
Trivial dependencies are denoted with the -t flag. They denote a de‐
pendency that should never cause a target to be rebuilt, but if the
target is rebuilt for another reason, then they are treated like normal
dependencies. Trivial dependencies don't even cause a target to be re‐
built if they don't exist. Trivial dependencies are typically used for
configuration, i.e., for the setting up configuration of application.
Trivial dependencies are not allowed if the rule has no command.
target: -t input { ... }
Variable dependency: the content of variables can come from files. In
the following example, the C flags are stored in the file 'CFLAGS', and
used in the compilation command using the $[CFLAGS] dependency.
compute: compute.c $[CFLAGS]
{
gcc $CFLAGS compute -o compute.c
}
CFLAGS: { echo -Wall -Werror >CFLAGS }
Variable dependencies may be declared as persistent as in $[-p X] and
as trivial as in $[-t X] but not as optional using the -o flag. By de‐
fault, the name of the variable set is the same as the filename. An‐
other variable name can be used in the following way:
$[NAME = FILENAME]
If multiple variable dependencies have the same name, it is unspecified
which one is used. If a variable dependencies has the same name as a
parameter, it overrides the parameter.
Transient targets are marked with '@'. They are used for targets such
as '@clean' that do an action without building a file, and for lists of
files that depend on other targets, but don't have a command associated
with them. They are also used instead of variables that would other‐
wise contain a list of filenames.
Here is a transient target that cleans up the directory:
@clean: { rm -Rf *.o *~ }
Here a transient target is used as a shortcut to a longer name:
@build.$name: dat/build.$name.txt;
Here a transient target is used as a list of files. Multiple targets
can depend on it, to effectively depend on the individual files:
@headers: a.h b.h c.h;
x: x.c @headers {
cc x.c -o x
}
y: y.c @headers {
cc y.c -o y
}
FEATURES
Like a makefile, a Stu script consists of rules. In Stu, the order of
rules is not important, except for the fact that the first rule is used
by default if no rule is given explicitly. Comments are written with
'#' like in Make or in the shell.
The basic syntax is similar to that of make, but does not rely on
mandatory whitespace. Instead of tabs, the commands are enclosed in
curly braces.
Stu syntax supports two types of objects: file targets and transient
targets. Files are any file in the file system, and are always refer‐
enced by their filename. Transient targets have names beginning with
the '@' symbol and do not correspond to files, but can have dependen‐
cies and commands.
A rule for a file in Stu has the following syntax:
[>] TARGET [ : DEPENDENCY ... ] { COMMAND }
The target is a filename. DEPENDENCY ... are depencies. COMMAND is a
command which is passed to the shell for building. Stu will always ex‐
ecute the whole command block using a single call to the shell. This
is different than Make, which calls each line individually. This means
that you can for instance define a variable on one line and use it on
the next.
Stu uses the -e option when calling the shell; this means that any
failing command will make the whole target fail.
The standard input is redirected from /dev/null, except when an ex‐
plicit input redirection is specified using '<'. Thus, commands exe‐
cuted from within Stu cannot read from standard input, except when the
-i option is used. Stu starts each job in its own process group, whose
process group ID is equal to its process ID. This allows Stu to kill
all (direct and indirect) child processes of jobs, by using kill(2) to
terminate all processes in the corresponding process group.
When the command of a file is replaced by a semicolon, this means that
the file is always built together with its dependencies:
TARGET [ : DEPENDENCY ... ] ;
In this example, the file TARGET is assumed to be up to date whenever
all dependencies are up to date. This can be used when two files are
built by a single command. As a special case, writing the name of a
file followed by semicolon tells Stu that the file must always exist,
and is always up to date; Stu will then report an error if the file
does not exist:
TARGET ;
For a transient, the same syntax is used as for a file:
@TARGET [ : DEPENDENCY ... ] { COMMAND }
@TARGET [ : DEPENDENCY ... ] ;
If a transient target includes a command, Stu will have no way of re‐
membering that the command was executed, and the command will be exe‐
cuted again on the next invocation of Stu, even if the previous invoca‐
tion was successful. Therefore, commands for transient targets will
typically output build progress information, or perform actions that do
not fit well the build system paradigm, such as removing or deploying
built files.
Rules can have multiple targets, in which case the command must build
all the targets that are files. If one of the targets is a transient
target, this effectively creates an alias for the file targets.
TARGET... [ : DEPENDENCY ... ] { COMMAND }
TARGET... [ : DEPENDENCY ... ] ;
The operator '>' can be used in front of the target name to indicate
that the output of the command should be redirected into the target
file. As an example, the following rule creates the file 'HEADERS'
containing the output of the given 'echo' command:
>HEADERS { echo *.h }
For a file target, content can be specified directly using the '=' op‐
erator:
TARGET = { CONTENT ... }
The content is stripped of empty lines and common whitespace at the be‐
ginning of lines, and written into the file.
Using the equal sign with a file name creates a copy rule, i.e., the
given file is copied with the 'cp' command:
TARGET = [ -p | -o ] SOURCE;
By default, Stu will use '/bin/cp' to perform the copy. This can be
changed by setting the variable $STU_CP. If source ends in a slash
(outside of any parameter value), then Stu will look for a file with
the same basename as TARGET in the directory SOURCE. If the persistent
flag -p is used, the timestamp of the source file is not verified, only
its existence. If the optional flag -o is used, it is not an error if
the target exists and not the source: in that case the target is con‐
sidered up to date. Both flags must not be used simultaenously.
A dependency can be one of the following:
NAME A file dependency
The target depends on the file with the name NAME. Stu will make sure
that the file NAME is up to date before the target itself can be up to
date.
@NAME A transient dependency
A transient target. They represent a distinct namespace from files,
and thus their command do not create files.
-p NAME A persistent dependency
Stu will only check whether the dependency exists, but not its modifi‐
cation time. This is mostly useful for directories, as the modifica‐
tion time of directories is updated whenever files are added or removed
in the directory.
-o NAME An optional dependency
Optional dependencies are never built if they don't exist. If they ex‐
ist, they are treated like normal dependencies and their date is taken
into account for determining whether the target has to be rebuilt.
A dependency cannot be declared as persistent and optional at the same
time, as that would imply that its command is never executed.
-t NAME A trivial dependency
A trivial dependency will never cause the target to be rebuilt. How‐
ever, if the target is rebuilt for another reason, then the trivial de‐
pendency will be rebuilt itself. This is mostly useful for configura‐
tion files that are generated automatically, including the case of
files containing the flags used to invoke compilers and other programs.
'[' ['-n' | '-0' | '-C'] NAME ']' A dynamic dependency
Stu will ensure the file named NAME exists, and then parse it as con‐
taining further dependencies of the target. The fact that NAME needs
to be rebuild does not imply that the target has to be rebuilt. The
flag -n makes Stu interpret the content of the file as a newline-sepa‐
rated list of filenames. Analogously, the -0 flag can be used when the
file contains \0-separated filenames, or when the file contains the
name of exactly one file. If -C or no flag is used, the file is parsed
in full Stu syntax.
'[' @NAME ']' A dynamic transient target
Brackets can also be used around a transient dependency name. In that
case, all dependencies of the given transient targets will be consid‐
ered dynamic dependencies.
$[NAME] A variable dependency
The file NAME is ensured to be up to date, and the content of the file
NAME is used as the value of the variable $NAME when the target's com‐
mand is executed.
<NAME An input dependency
The dependency is a file which will be used as standard input for the
command.
( ... )
Groups of dependencies can be enclosed in parentheses. Parentheses may
not contain variable dependencies (i.e., something like The flags -p
and -o can be applied to a group of dependencies given in parentheses:
-p ( ... )
-o ( ... )
The flags -p and -o can be applied to dynamic dependencies:
-p [ ... ]
-o [ ... ]
in which case all resulting dynamic dependencies will be flagged as op‐
tional or persistent.
Both parentheses and brackets may be nested:
((A)) # Equivalent to A
[[A]] # Read out dependencies from all files given in the file 'A'.
CONCATENATION
In certain circumstances, two dependencies that are not separated by
spaces are said to be concatenated. Concatenation takes place in the
following cases:
A( A[ )A )( )[ ]A ]( ][
In this list, 'A' stands for any literal name, including one containing
parameters or quotes.
If two dependencies are concatenated, their concatenation is taken as
the dependency. Effectively this considers each side of the concatena‐
tion to be a list of names (after processing of dynamic dependencies),
and replaces the concatenation by the combination of all names in the
left groups concatenated textually with items in the right group.
PARAMETERS
Any file or transient target may include parameters. Parameters are
noted using the '$' character and are given a name. The syntax for pa‐
rameters is similar to that for variables in the shell. If the sign
'$' is followed by '{', then everything up to the corresponding '}' is
the parameter name. Otherwise, all alphanumeric characters and under‐
scores '_' following will be taken as the parameter name:
data/$name.png
data/${name}_2.png
Parameters cannot be contiguous. I.e., there must always be at least a
single character between two parameters. (The reason is that otherwise
it would be ambiguous how to match the two parameters.) Names of pa‐
rameters cannot be empty. Thus,
data/${part1}${part2}.png
data/${}.png
data/$
are errors.
Stu will match the pattern to any file or transient target it needs to
build. Parameters can appear in dependencies and in commands any num‐
ber of times (included not appearing in them). In a target name, a pa‐
rameter can only appear once. The following rule uses the single pa‐
rameter $name:
list.$name: data.$name ${name}.in
{
./compute-list -n "$name"
}
A target name may match more than one rule. If that is the case, Stu
will use the rule that dominates all other matching rules. A rule (x)
is defined to dominate another rule (y) for a given name if every char‐
acter in the name that is part of a matched parameter in rule (x) is
also inside a matched parameter in rule (y), and at least one character
of the name is part of a matched parameter in rule (y) but not in rule
(x). It is an error when there is no single matching rule that domi‐
nates all other matching rules.
In the following example, the first rule dominates the other rules for
the file named 'a.b.c':
a.$x.c: ... { ... }
a.$x: ... { ... }
$x.c: ... { ... }
In the following example, no rule dominates the others for the filename
'a.b.c', so Stu will report an error:
$x.b.c: ... { ... }
a.$x.c: ... { ... }
a.b.$x: ... { ... }
CANONICALIZATION
Stu canonicalizes names of files and transients. As an example, the
filenames 'aaa//bbb' and 'aaa/bbb' are considered to be the same by
Stu, and can be used interchangingly. Canonicalization concerns the
use of '/' (the directory separator) and '.' (the current directory).
The following rules are applied in order:
(1) All instances of multiple slashes ('/') are collapsed to a single
one, except when the name begins with exactly two slashes. Then, any
ending slash is removed, except if the name is '/' or '//'.
(2) If the name is '/.', it is changed to '/'. If the name is './', it
is changed to '.'. If the name begins with './' followed by a charac‐
ter that is not part of a parameter, the './' is removed (the rule is
applied repeatedly). Any number of ending '/.' components are removed.
Any number of '/./' is simplified to '/'.
Canonicalization does not involve any procedure that requires system
calls to be performed. Thus, symlinks are not resolved, and 'aaa/..'
is not simplified. Likewise, '/..' is not simplified to '/'.
The canonicalization rules apply not only to file targets, but also to
transient targets. Thus, @aaa//bbb and @aaa/bbb refer to the same tar‐
get. It is thus strongly suggested to use transient targets in a fash‐
ion that is consistent with the file system semantics of '/' and '.'.
Canonicalization is applied in the following fashion:
Phase 1: When rules are parsed, canonicalization is applied to all
target names. At this stage, parameters are not yet replaced by their
values, and thus the '/' and '.' components in parameter values are not
canonicalized in targets.
Phase 2: Second, When a dependency is matched to a rule, canonicaliza‐
tion is applied to the dependency name. At this stage, names do not
contain parameters and canonicalization is performed on the final file
or transient name.
Additionally, there are three special rules for canonicalization:
(a) There is a special rule concerning './': When a target to be
canonicalized in Phase 1 as described above starts with './' followed
immediately by a parameter, then this parameter will only match strings
that do not start with a slash. The './' is still removed. This makes
it possible to distinguish files with relative paths from files with
absolute paths. For instance, consider the following example:
A: ./list.B { ... }
$path.B { ... }
./$file { ... }
Here, the dependency './list.B' will match the third rule only. With‐
out the special rule, the dependency would match both the second and
third rule, and produce an error, because none of the two dominates the
other.
(b) Another special rule concerns the root directory '/': A pattern of
the form $A/xxx where $A is a parameter and xxx any string (which may
contain more parameters) will match the name '/xxx' by setting the pa‐
rameter $A to the value '/'. This special rule corresponds to the fact
that while the root directory is called '/', a file within it is called
'/xxx' rather than '//xxx'.
(c) If the target for a rule is '$x/AAA', where 'AAA' may contain other
parameters, then a dependency of 'AAA' will match that rule with $x set
to '.', as long as 'AAA' does not start with a slash.
DIRECTIVES
Directives in Stu are introduced by '%' and serve a similar purpose to
the C preprocessor, i.e., they are processed before the actual Stu
script is parsed and interpreted. (However, they are not used to im‐
plement a macro system.) The token '%' must be followed by the direc‐
tive name. There may be any amount of whitespace (including none) be‐
tween '%' and the name of the directive.
File inclusion is done using the '%include' directive. This can be put
at any place in the input file, and will temporarily continue tokeniza‐
tion in another file. The filename does not have to be quoted, except
if it contains special characters, just like any other filename in Stu.
If a directory is given after include (with or without an ending
slash), the file 'main.stu' within that directory is read.
% include a.stu
% include "b.stu"
% include 'c.stu'
% include data/
To declare which version of Stu a script is written for, use the '%ver‐
sion' directive:
% version 2.3
% version 2.3.4
Both variants will allow the script to be executed only with a version
of Stu of the correct major version number (2 in this example), and
whose minor version (and patch level) have at least the given values.
There may be multiple '%version' directives; each one is then checked
separately. In particular, it is possible to place a version directive
in each source file. This treatment of version numbers follows seman‐
tic versionning (semver.org). The version directive will not prevent
usage of Stu features that were not present in the specified version.
TOKENIZATION
Unquoted filenames in Stu may contain the following ASCII characters:
[a-z] [A-Z] [0-9] _ ^ ` + - . ~ /
and all non-ASCII characters. Filenames containing other characters
must be quoted by either single or double quotes, or by using back‐
slashes. The characters -, + and ~ are not allowed as the first char‐
acter of a name if they are not quoted.
The following characters have special meaning in Stu and cannot be used
in unquoted filenames:
# Comment (until the end of the line)
% Directive (followed by directive name and arguments)
\ Escape for characters and to ignore newlines
' Quote, without escape sequences
" Quote, with escape sequences
: Separator for rule definition
; In rules without command, end of dependency declaration
- Prefix character for flag, followed by a single character
$ Parameter
@ Transient target marker
> Output redirection
< Input redirection
= Assignment rule; copy rule; named variable
( ) List
[ ] Dynamic dependency
{ } Command
Comments introduced by '#' go until the end of the line. Commands
starting with '{' go until the matching '}', taking into account shell
syntax, i.e., the command itself may contain more braces. All other
characters are individual tokens and may or may not be separated from
other tokens by whitespace.
Quoting in Stu is similar to quoting in the shell. Quoted or unquoted
names which are not separated by whitespace are interpreted as a single
name. Outside of quotes, the backslash can be used to escape any char‐
acter. Backslash-newline sequences are ignored. All other characters
can be preceded by a backslash to retain their literal meaning as part
of a name.
Single quotes may contain any character except single quotes and the
NUL character '\0'. Backslashes and newline characters always have
their literal meaning inside single quotes.
Inside double quotes, backslashes, double quotes and the dollar sign
must be escaped by a backslash. Other C-like escape sequences are
supported, too. To be precise, the following escape sequences are pos‐
sible: \" \\ \$ \a \b \f \n \r \t \v. Dollars in double quotes intro‐
duce parameter names in the same way as outside quotes. Double quotes
may also contain unescaped newline characters. The NUL character '\0'
is not allowed inside double quotes. There is no \0 escape sequence,
as names of files and transients cannot contain the NUL byte.
Spacing rules: The lack of whitespace between tokens represents con‐
catenation under certain conditions. Specifically: To separate depen‐
dencies, whitespace must appear before opening parentheses and brack‐
ets, and after closing parenthesis and brackets, when the parenthesis
or bracket in question would otherwise be touching either a name token,
or another parenthesis or bracket "from outside". I.e., the following
combinations represent concatenation:
)( )[ ]( ][ )A ]A A( A[
In this list, 'A' stands for any name, including quoted names using
whitespace, except when this would create a new token, which is only
the case for name tokens.
The following characters are reserved for future extension:
* & | ! ? ,
SYNTAX
The syntax of a Stu script is given in the following Yacc-like nota‐
tion. This is the syntax after processing of directives, which are in‐
troduced with '%'.
rule_list: rule*
rule: ('@' NAME | ['>'] NAME)+ [':' expression_list]
('{' COMMAND '}' | ';')
NAME '=' '{' CONTENT '}'
NAME '=' ('-p' | '-o')* NAME ';'
expression_list: expression* {1}
expression: unit_expression* {2}
flag expression
variable_dep
unit_expression: '(' expression_list ')'
'[' expression_list ']'
redirect_dep
redirect_dep: ['<'] bare_dep
bare_dep: ['@'] NAME
variable_dep: '$' '[' flag* ['<'] NAME ']'
flag: '-p' | '-o' | '-t' | '-n' | '-0'
{1} with intervening whitespace {2} without intervening whitespace
Stu scripts read via the -f option or as the default Stu script
(main.stu), as well as the argument to the -F option must contain a
'rule_list'. A file included by brackets (a dynamic dependency) and
arguments to the -C option must contain an 'expression_list'. Argu‐
ments passed outside of options on the command line must contain an
'expression_list', but a simplified syntax is used in which only the
charaters '[]-@' are recognized, and that only in positions where they
make sense; in all other cases, characters are interpreted as part of
filenames -- this is also valid for whitespace.
SEMANTICS
Cycles in the dependency graph are not allowed. As an example, the fol‐
lowing results in an error:
A: B { ... }
B: A { ... }
Cycles are considered at the rule level, i.e., cycles such as the fol‐
lowing are also flagged as an error, even though there is no cycle on
the filename level. In the following example, it is not possible to
build the file 'a.gz.gz' from the file 'a', even though it would not
result in a cycle, but since both files 'a.gz' and 'a.gz.gz' use the
same parametrized rule, this is not allowed:
$name.gz: $name { gzip -k -- "$name" ; }
Cycles are possible in dynamic dependencies, where they are allowed and
ignored. For instance, the following examples will correctly build the
file 'A', after having built 'B' and 'C':
A: [B] { echo CORRECT >A ; }
B: { echo [C] >B ; }
C: { echo [B] >C ; }
Symlinks are treated transparently by Stu. In other words, Stu will
always consider the timestamp of the linked-to file. A symlink to a
non-existing file will be treated as a non-existing file.
Stu uses job control: Each job is put into its own process group. All
jobs are put into the background, except when the option -i is used.
When -i is not used, the standard input of all jobs is redirected from
/dev/null.
If a command fails, Stu will remove any of its target files, if they
have been already touched by the command. If the failing command did
not touch a target file, that existing target file is not removed.
This behavior is necessary to avoid the case that a commands partially
creates a target file, then fails, and then a subsequent invocation of
Stu sees the new file and considers it as up to date, even though it
was only partially created. Thus, commands in Stu do not need to make
sure they delete any output files when they fail. This behavior is
equivalent to that in Make.
EXIT STATUS
0 Success. Everything was built successfully, or was already up
to date.
1 Build error. This indicates errors in the commands invoked and
files read by Stu. Example: a child process produced an error,
or a dependency was not found and no rule was given for it.
When using the -q option, the exit status is 1 when the given
targets are not up to date.
2 Logical error. This indicates errors in the usage of Stu. Ex‐
amples are syntax errors in Stu scripts, cycles in the depen‐
dency graph and certain erroneous options on the command line.
3 Both build and logical errors were encountered (when using the
-k option).
4 Fatal error. An error occurred that made Stu abort execution
immediately, regardless of whether the -k option was used. This
includes system errors from which Stu cannot recover (such as
out-of-memory conditions), as well as errors on the Stu command
line that make Stu fail immediately.
ENVIRONMENT
STU_CP If set, Stu calls the 'cp' program from the given location in‐
stead of '/bin/cp'. The given version of 'cp' must support the
syntax 'cp -- "$fileA" "$fileB"'.
STU_OPTIONS
Contains options to be set on every run of Stu. Only the op‐
tions EQswxyYz can be set this way. The variable should contain
only these characters, dashes, and whitespace; other characters
produce an error. Options passed on the command line apply af‐
ter those passed using this variable.
STU_SHELL
If set, Stu calls the shell from the given location instead of
'/bin/sh'. The given shell must support the -e and -c options.
This is mainly useful on systems where '/bin/sh' is not a POSIX
shell. Stu ignores the $SHELL variable, like Make does, as that
variable is only intended to set the user's interactive shell.
STU_STATUS
Stu sets this variable to '1' in all child processes. In order
to avoid recursive invocation of Stu, Stu will fail with a fatal
error (exit status 4) on startup when the variable is set. To
circumvent this, unset the variable. Recursive Stu is as harm‐
ful as recursive Make.
TERM Used to determine whether to use color output. This variable
must be set to a value different from 'dumb', and isatty(3) must
return 1 for color to be enabled. (Alternatively, color can be
controlled by the -y and -Y options.)
SIGNALS
SIGUSR1
When received, Stu will output a list of currently running jobs
on standard output, and statistics about runtime, in a similar
way to the -z option. The reported runtimes include only jobs
that have already terminated, and exclude currently running
jobs. Multiple SIGUSR1 signals sent in rapid succession may re‐
sult in output only printed once.
CONFORMING TO
The Stu language is unique to this implementation, and the man page
serves as the reference for its syntax.
Stu follows Semantic Versioning (semver.org). The major version number
is increased when backward-incompatible changes are made. The minor
version number is increased when features are added. The patch level is
increased for other changes.
EXAMPLES
The basic example of a rule in Stu is:
program: program.c config.h
{
cc -c program.c -o program
}
The following declaration tells Stu that the file 'config.h' must ex‐
ist, and will allow Stu to give more meaningful error messages if the
file is not found.
config.h;
Input and output redirection can be used to write commands that invoke
a filter such as sed, awk or tr. The following example will build the
file 'A' containing the string 'HELLO':
>A: <B { tr a-z A-Z ; }
B = { hello }
Variable dependencies may be included indirectly through transient tar‐
gets without commands, and through dynamic dependencies. In the fol‐
lowing example, the variable $V will be passed through to the commands
for the targets A and B:
V: { echo Hello >V ; }
@x: $[V];
y: { echo '$[V]' >y ; }
A: @x { echo $V >A ; }
B: [y] { echo $V >B ; }
Trivial dependencies are often combined with variable dependencies to
implement flags, for instance to a compiler, as in the following exam‐
ple. This will make sure that a change in the file 'VERSION' will not
lead to a recompilation of the program, but if 'program.c' is modified
and 'program' is rebuilt, then 'CFLAGS' will also be rebuilt.
VERSION; # Contains the version number; updated by hand
>CFLAGS: $[VERSION] { echo -g -Wall -D VERSION=$VERSION ; }
program: program.c $[-t CFLAGS] { gcc $CFLAGS program.c -o program
; }
Copy rules are often used to copy a file from another directory into
the current directory. If both files have the same name, the name of
the source file can be omitted.