1/*
2 * aegis - project change supervisor
3 * Copyright (C) 1991-2008, 2011, 2012 Peter Miller
4 * Copyright (C) 2007, 2008 Walter Franzini
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or (at
9 * your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/*
21 * By default, only a short summary is prointed for each rule.  If you
22 * want to see the whole command (e.g. debugging the build) then put
23 * verbose=1 on the aeb command line.
24 */
25if [not [defined verbose]] then
26    verbose = 0;
27quiet = [not [verbose]];
28if [quiet] then
29    set silent;
30else
31    set star tell-position;
32
33function defined-or-null =
34{
35    if [defined [@1]] then
36        return [[@1]];
37    return;
38}
39
40/*
41 * The build_include_search_path function is used to build an include
42 * search path based on the directories passed in as arguments, and the
43 * special Cook [search_list] variable.
44 *
45 * It returns a list of strings formed by every combination of these two
46 * lists.  Importantly, all of the "." paths are searched first, then
47 * all of the "bl" paths, then "blbl" and so on.  This means that moving
48 * include files between directories is less of a drama than the naive
49 * [prepost -I %1 [search_list]] approach.
50 */
51function build_include_search_path =
52{
53    local result = ;
54    local dir = ;
55    local dir2 = ;
56    loop dir = [search_list]
57    {
58        loop dir2 = [arg]
59        {
60            if [in [dir] .] then
61                result += [dir2];
62            else
63            {
64                if [in [dir2] . ] then
65                    result += [dir];
66                else
67                    result += [dir]/[dir2];
68            }
69        }
70    }
71    return [result];
72}
73
74/*
75 * Turn on updating to ensure mod-time
76 * consistency on fast machines.
77 */
78set time-adjust;
79
80/*
81 * make sure targets are removed before the recipe body is run,
82 * and make sure that directories are created then too.
83 */
84set unlink mkdir;
85
86/*
87 * You may want to change some of these options.
88 * ([debug] must be defined, even if empty, use comments.)
89 *
90 * Change "main.h" to add the DEBUG define.
91 * All files reference this file, so this will cause recompilation
92 * of all files, both in the change and in the baseline.
93 */
94debug = -g /* -pg */ ;
95
96/*
97 * Make sure the [project], [change], [version] and [arch] variables are set.
98 */
99#ifndef project
100echo "The [project] variable was not set from the command line." set silent;
101echo "If you want to do a build which is not a development build" set silent;
102echo "or an integration build, use the make command, not cook." set silent;
103fail;
104#endif
105#ifndef change
106echo "The [change] variable was not set from the command line." set silent;
107echo "If you want to do a build which is not a development build" set silent;
108echo "or an integration build, use the make command, not cook." set silent;
109fail;
110#endif
111#ifndef version
112echo "The [version] variable was not set from the command line." set silent;
113echo "If you want to do a build which is not a development build" set silent;
114echo "or an integration build, use the make command, not cook." set silent;
115fail;
116#endif
117#ifndef arch
118echo "The [arch] variable was not set from the command line." set silent;
119echo "If you want to do a build which is not a development build" set silent;
120echo "or an integration build, use the make command, not cook." set silent;
121fail;
122#endif
123#ifndef search_path
124echo "The [search_path] variable was not set from the command line." set silent;
125echo "If you want to do a build which is not a development build" set silent;
126echo "or an integration build, use the make command, not cook." set silent;
127fail;
128#endif
129
130/*
131 * The first item in search list should be the absolute path of the
132 * current directory.  Assume that it is.
133 */
134search_list = .;
135search_tmp = [tail [split ':' [search_path]]];
136
137/*
138 * Try to shorten the search path in command lines, too.
139 *
140 * This takes a little getting used to....
141 * 1. For development builds, the search path is dev dir, then branch bl,
142 *    then ... project bl.  Thus, bl in a dev dir winds up pointing to
143 *    the branch repository.
144 * 2. For integration builds, aegis deliberately omits the branch
145 *    baseline from the path, but include's the branch's parents and
146 *    ancestors.  Thus, bl in an int dir winds up pointing to the
147 *    branch's parent's repository.
148 * The idea is that integration builds in a branch are like a
149 * development build of the branch's dev dir.
150 */
151search_name = bl;
152loop
153{
154    search_dir = [head [search_tmp]];
155    if [not [search_dir]] then
156        loopstop;
157    search_tmp = [tail [search_tmp]];
158
159    if [not [exists [search_name]]] then
160        ln -s [search_dir] [search_name]
161            set clearstat;
162    search_list = [search_list] [search_name];
163    search_name = [search_name]bl;
164}
165
166/*
167 * If this is a development build, the version will be x.y.Czzz,
168 * so look to see if there is a C in the version string.
169 */
170if [match_mask %1C%2 [version]] then
171{
172    /*
173     * The develop_begin_command in the config file
174     * always creates the "bl" symbolic link.
175     */
176    baseline = bl;
177
178    /*
179     * Supplement file modification times with fingerprints.
180     * Only do this for development builds.
181     */
182    set fingerprint;
183}
184
185if [not [defined baseline]] then
186{
187    /*
188     * Turn on aggressive updating to ensure the smallest possible
189     * range of mod times at aeipass.  This also ensures mod time
190     * consistency on fast machines.
191     */
192    set time-adjust-back;
193}
194
195/*
196 * determine the short version:
197 * no change or delta number
198 */
199version_short = [fromto %1.C%2 %1 [subst D C [version]]];
200
201version_shorter = [split "." [version_short]] _ _;
202version_shorter = [unsplit "." [word 1 [version_shorter]]
203    [word 2 [version_shorter]]];
204project_short = [fromto %.[version_short] % [project]];
205project_minus = [project_short]-[version_short];
206
207/*
208 * use GNU awk if present
209 */
210awk = [find_command gawk];
211/* fall back to nawk */
212if [not [awk]] then
213    awk = [find_command nawk];
214/* finally use plain awk - which might work */
215if [not [awk]] then
216    awk = awk;
217
218/*
219 * This file is generated by autoconf.
220 * It is architecture specific.
221 * If it is not found (not cooked yet) the following
222 * symbols will be undefined.
223 *
224 *      Must be included *after* the search_list is defined.
225 */
226#include-cooked-nowarn [arch]/etc/howto.conf
227if [not [defined prefix]] then
228    prefix = /usr/local;
229if [not [defined exec_prefix]] then
230    exec_prefix = [prefix];
231if [not [defined yacc]] then
232    yacc = yacc;
233if [not [defined libs]] then
234    libs = ;
235
236if [defined [arch]_c++] then
237    c++ = [[arch]_c++];
238
239if [not [defined-or-null c++]] then
240    c++ = ['if' [find_command g++] 'then' g++ 'else' c++];
241
242c++_path = [find_command [c++]];
243
244if [not [defined primary_arch]] then
245    primary_arch = ;
246if [not [count [primary_arch]]] then
247    primary_arch = linux-x86_64;
248
249/*
250 * To turn on the dmalloccxx library you need these two lines
251 *
252c++_flags += -DDMALLOC -DDMALLOC_FUNC_CHECK;
253libs += -ldmalloccxx;
254 *
255 * and the dmalloc library itself, of course.
256 *
257 * WARNING:  The dmalloc library can be instructed to log to a file,
258 * circumventing the Aegis I/O layer, thus it's possible to create file
259 * owned by root.  The dmalloc library should only ever be used as a
260 * debugging tool, and NEVER be used in a production build of Aegis.
261 */
262
263/*
264 * To turn on the Electric Fence malloc debugging library
265 *
266libs += -lefence;
267 *
268 * and the Electic Fence library itself, of course.
269 */
270
271/*
272 * The default recipe
273 */
274all =
275    [arch]/bin/test_funcs
276    configured_files
277    ;
278integration-build-targets = ;
279integration-build-targets: [integration-build-targets]
280    set nodefault;
281
282/*
283 * Integration builds also make the shar files for distribution,
284 * but only on the primary architecture.
285 */
286if [defined change] then
287if [not [defined baseline]] then
288if [in [arch] [primary_arch]] then
289    all += integration-build-targets ;
290
291all: [all]
292    set default
293{
294    if [not [defined baseline]] then
295    {
296        if [in [resolve etc/set-uid-root] etc/set-uid-root] then
297            chmod a+rx etc/set-uid-root;
298        set silent;
299        echo\;ls -l [addprefix [arch]/bin/ [set-uid-root-commands]];
300        echo "Integrator: please do the following:";
301        echo "\"  sudo" [pathname [resolve etc/set-uid-root]] [arch]
302            [set-uid-root-commands]'"';
303        echo "\"if they aren't set-uid-root already.  See the comments\"";
304        echo "\"in the etc/set-uid-root file for instructions for how to set\"";
305        echo "\"up your /etc/sudoers file.\"";
306    }
307}
308
309/*
310 * The source files.
311 * This is given to us by aegis.
312 */
313vs_file = common/patchlevel.h;
314change_files_removed = ;
315change_files = ;
316change_files_build = ;
317#include-cooked-nowarn etc/cook/change_files.[version]
318etc/cook/change_files.[version]: : etc/quote_strin.awk
319    set shallow nodefault
320{
321    if [quiet] then
322        function print Generate [target];
323    echo "removed_files = "
324         `aelcf -p [project] -c [change] -action remove | wc -l `
325         \"\;\" > [target];
326    echo >> [target];
327
328    echo "change_files_build =" >> [target];
329    aelcf -usage build -p [project] -c [change]
330          | awk -f [resolve etc/quote_strin.awk] >> [target];
331    echo \"\;\" >> [target];
332    echo >> [target];
333
334    echo "change_files =" >> [target];
335    aelcf -p [project] -c [change]
336          | awk -f [resolve etc/quote_strin.awk] >> [target];
337    echo \"\;\" >> [target];
338    echo >> [target];
339}
340project_files = ;
341project_files_build = ;
342#include-cooked-nowarn etc/cook/project_files.[version]
343etc/cook/project_files.[version]: : etc/quote_strin.awk
344    set shallow nodefault
345{
346    if [quiet] then
347        function print Generate [target];
348    echo "project_files =" >> [target];
349    aelpf -p [project] -c [change]
350          | awk -f [resolve etc/quote_strin.awk] >> [target];
351    echo \"\;\" >> [target];
352    echo >> [target];
353
354    echo "project_files_build =" >> [target];
355    aelpf -usage build -p [project] -c [change]
356          | awk -f [resolve etc/quote_strin.awk] >> [target];
357    echo \"\;\" >> [target];
358    echo >> [target];
359}
360
361/*
362 * Speed up graph building by stating the leaves explictly.
363 * This also gives more useful error messages.
364 */
365if [not [change_files_removed]] then
366if [count [project_files]] then
367if [count [change_files]] then
368{
369    graph_leaf_file = [project_files] [change_files];
370    graph_leaf_pattern = /%0%;
371}
372
373source_files =
374    [sort [stringset [project_files] [change_files]]]
375    ;
376
377
378version_obj = [arch]/common/version_stmp.o;
379common_obj = [arch]/common/common.a [version_obj];
380common_lib =
381    [stringset
382        [fromto
383            common/%0%.y
384            [arch]/common/%0%.yacc.o
385            [match_mask common/%0%.y [source_files]]
386        ]
387        [fromto
388            common/%0%.cc
389            [arch]/common/%0%.o
390            [match_mask common/%0%.cc [source_files]]
391        ]
392        [fromto
393            common/%0%.cc.in
394            [arch]/common/%0%.o
395            [match_mask common/%0%.cc.in [source_files]]
396        ]
397    -
398        [version_obj]
399    ];
400
401libaegis_obj = [arch]/libaegis/libaegis.a [version_obj];
402libaegis_lib =
403    [fromto
404        libaegis/%0%.y
405        [arch]/libaegis/%0%.yacc.o
406        [match_mask libaegis/%0%.y [source_files]]
407    ]
408    [fromto
409        libaegis/%0%.cc
410        [arch]/libaegis/%0%.o
411        [match_mask libaegis/%0%.cc [source_files]]
412    ]
413    [fromto
414        libaegis/%0%.def
415        [arch]/libaegis/%0%.fmtgen.o
416        [match_mask libaegis/%0%.def [source_files]]
417    ]
418    [common_lib]
419    ;
420
421/*
422 * There is a special list of files you must use, in preference to the
423 * standard C files.  This ensures appropriate operating system insulation
424 * is always in place.
425 */
426c_incl_excludes =
427    [fromto common/ac/%0%.h -ex\=%0%.h
428        [match_mask common/ac/%0%.h [source_files]]
429    ]
430    ;
431
432/*
433 * determine the list of commands
434 * (to be installed)
435 */
436
437commands =
438    [stringset
439        [fromto %1/%0%2 %1 [match_mask %/main.cc [source_files]]]
440    -
441        fmtgen
442        aefp
443        aemakefile
444    ];
445
446/*
447 * Add the commands to the list of top-level targets.
448 */
449all_commands:
450    [arch]/bin/aefp
451    [arch]/bin/aemakefile
452    [addprefix [arch]/bin/ [commands]]
453    [arch]/bin/xaegis
454    ;
455all = [all]
456    all_commands
457    ;
458
459/*
460 * determine the object files for each command
461 */
462cmd_list = [commands];
463loop
464{
465    cmd = [head [cmd_list]];
466    if [not [cmd]] then
467        loopstop;
468    cmd_list = [tail [cmd_list]];
469
470    [cmd]_obj =
471        [fromto [cmd]/%0%.y [arch]/[cmd]/%0%.yacc.o
472            [match_mask [cmd]/%0%.y [source_files]]
473        ]
474        [fromto [cmd]/%0%.def [arch]/[cmd]/%0%.fmtgen.o
475            [match_mask [cmd]/%0%.def [source_files]]
476        ]
477        [fromto [cmd]/%0%.cc [arch]/[cmd]/%0%.o
478            [match_mask [cmd]/%0%.cc [source_files]]
479        ]
480        [libaegis_obj]
481        ;
482    [cmd],I =
483        [fromto [cmd]/%0%.y [cmd]/%0%.yacc.cc,I
484            [match_mask [cmd]/%0%.y [source_files]]
485        ]
486        [fromto [cmd]/%0%.def [arch]/[cmd]/%0%.fmtgen.cc,I
487            [match_mask [cmd]/%0%.def [source_files]]
488        ]
489        [fromto [cmd]/%0%.cc [cmd]/%0%.cc,I
490            [match_mask [cmd]/%0%.cc [source_files]]
491        ]
492        ;
493}
494
495aefp_obj =
496    [arch]/aefp/main.o
497    [libaegis_obj]
498    ;
499
500aemeasure_obj =
501    [fromto %0%.cc [arch]/%0%.o
502        [match_mask aemeasure/%0%.cc [source_files]]
503    ]
504    [arch]/common/common.a
505    ;
506
507aemakefile_obj =
508    [fromto %0%.cc [arch]/%0%.o
509        [match_mask aemakefile/%0%.cc [source_files]]
510    ]
511    [arch]/common/common.a
512    ;
513
514fmtgen_obj =
515    [fromto
516        fmtgen/%0%.y
517        [arch]/fmtgen/%0%.yacc.o
518        [match_mask fmtgen/%0%.y [source_files]]
519    ]
520    [fromto
521        fmtgen/%0%.cc
522        [arch]/fmtgen/%0%.o
523        [match_mask fmtgen/%0%.cc [source_files]]
524    ]
525    [arch]/common/common.a
526    ;
527
528source_files_build =
529    [change_files_build] [project_files_build];
530source_files_non_build =
531    [stringset [source_files] - [source_files_build]];
532
533/*
534 * how to compile C sources
535 */
536if [defined [arch]_c++_flags] then
537    c++_flags = [split "%" [[arch]_c++_flags]];
538
539if [not [defined c++_flags]] then
540    c++_flags = -O2;
541c++_flags = [stringset [c++_flags] [debug]];
542
543if [defined [arch]_cc_include_flags] then
544    cc_include_flags = [split "%" [[arch]_cc_include_flags]];
545
546if [not [defined cc_include_flags]] then
547    cc_include_flags = ;
548cc_include_flags += [match_mask -I%0% [collect xml2-config --cflags]];
549
550/*
551 * we need to say -I. -I./[arch]
552 *                -Ibl -Ibl/[arch]
553 *                -Iblbl -Iblbl/[arch]
554 * etc, etc.
555 */
556c_incl_include_flags = [addprefix -I [build_include_search_path . [arch]]];
557cc_include_flags += [c_incl_include_flags];
558
559
560if [not [defined ld_flags]] then
561    ld_flags = ;
562if [defined [arch]_ld_flags] then
563    ld_flags += [split "%" [[arch]_ld_flags]];
564ld_flags += [debug];
565
566/*
567 * this next section is for g++
568 *
569 * The g++ include files MUST be first.
570 */
571g++_modern = 0;;
572#if [in [substring 1 3 [entryname [c++]]] g++]
573
574[arch]/etc/gxx_flags.cook: etc/gxx_flags.pl
575{
576    perl [resolve etc/gxx_flags.pl] > [target];
577}
578;;
579#include-cooked-nowarn [arch]/etc/gxx_flags.cook
580
581c++_flags =
582    [stringset
583        -ansi -Wall -Werror
584        [c++_flags]
585        [debug]
586        -Wshadow -Wpointer-arith -Wwrite-strings
587        -Wextra -Wunused
588
589        /*
590         * If known, tune optimizer for the CPU being used to compile.
591         * This only affects you iff you are an Aegis develeoper.
592         * The debian-packages are unaffected, the rpm packages are
593         * unaffected (their builds do not use this option).
594         */
595        -mtune\=native
596
597        /*
598         * If known, generate code for the CPU being used to compile.
599         * This only affects you iff you are an Aegis develeoper.
600         * The debian-packages are unaffected, the rpm packages are
601         * unaffected (their builds do not use this option).
602         *
603         * There is a risk that code will fail to execute on you next
604         * machine if you upgrade to a newlaptop and copy your old
605         * filesystem across.
606         */
607        -march\=native
608
609        /* check even more printf-like stuff */
610        -Wformat\=2
611
612        /*
613         * The g++ command doesn't have the -Wmissing-declarations
614         * -Wstrict-prototypes -Wmissing-prototypes options, even though
615         * gcc does.  I've registered a bug, maybe they will put it
616         * back.  But, don't hold your breath, they can't seem to
617         * understand just how useful they are.
618         */
619    ];
620if [g++_modern] then
621{
622    c++_flags =
623        [stringset
624            [c++_flags]
625            -fmessage-length\=0 /* this makes vim -q work better */
626        ];
627}
628#endif
629
630/*
631 *  Support for compiling with the Intel C++ Compiler.
632 *
633 *  The icc seems to catch different problem from gcc, thus compiling
634 *  Aegis with icc from time to time may help improve the quality of
635 *  the code.
636 *
637 *  To enable that compiler you need to modify the
638 *  aegis.conf.d/site.conf file setting the compiler and options value
639 *  most appropriate for you platform.
640 *
641 *  Example:
642 *  ------------------------------------------------------------------------
643 *  {
644 *      name = "linux-i486_c++";
645 *      value = "/opt/intel/cc/10.1.008/bin/icpc";
646 *  },
647 *  {
648 *      name = "linux-i486_c++_flags";
649 *      value = "-gxx-name=c++%-cxxlib";
650 *  },
651 *  ------------------------------------------------------------------------
652 *
653 *  Note the % sign in the example above (separating the -gxx-name and
654 *  -cxxlib options).  It's not an error and you should use it to
655 *  separate additional options you may need.
656 *
657 *  To be able to test the suid binary (at least on Linux) you must
658 *  modify the /etc/ld.so.conf file adding the directory name where to
659 *  find icc specific libraries.
660 *
661 */
662#if [in [notdir [c++]] icpc]
663
664/*
665 * The order of the -W* options must be preserved otherwise the
666 * -Werror option became unhelpful.  It seems that:
667 *
668 * 1) -Wall selects the warning to be raised
669 * 2) -Werror mark the selected warning to be reported as errors.
670 *
671 * Thus reverting the order shows a different behavior.
672 *
673 * The following diagnostic messages are disabled because they give
674 * too much warnings or because a "fix" is not evident:
675 *
676 * #111: statement is unreachable
677 * #181: argument is incompatible with corresponding format string conversion
678 * #193: (preprocessor) zero used for undefined preprocessing identifier
679 * #383: value copied to temporary, reference to temporary used
680 * #593: variable "__d0" was set but never used (FD_SET related)
681 * #810: suppress int to char warning
682 * #981: operands are evaluated in unspecified order
683 * #1418: external function definition with no prior declaration
684 * #1419: external declaration in primary source file
685 * #1572: floating-point equality and inequality comparisons are unreliable
686 */
687c++_flags =
688    [stringset
689     -ansi -Wall -Wbrief -Werror
690     -wd111,181,193,383,593,810,981,1418,1419,1572
691     [c++_flags]
692    ];
693#endif
694
695
696/*
697 * include files from common
698 */
699include_search_list =
700    [arch]/common
701    common
702    [arch]/libaegis
703    libaegis
704    ;
705
706/*
707 *  The gcc compiler and the icc compiler both supports -o in
708 *  combination with -c.
709 */
710cxx_c_o = [or
711    [in g++ [substring 1 3 [entryname [c++]]]]
712    [in [notdir [c++]] icpc]];
713
714/*
715 * Build %1/%2.o from %1/%2.cc
716 */
717[arch]/%1/%0%2.o: %1/%0%2.cc [c++_path]
718{
719    if [quiet] then
720        function print Compile [target];
721    extra = [c++_flags];
722    if [defined %2_flags] then
723        extra = [extra] [%2_flags];
724    if [in %2 mprintf sprintf] then
725        extra  += -Wno-format-nonliteral;
726
727    if [match %%.yacc %2] then
728    {
729        /*
730         * Generated files may have warnings, because we have no
731         * control over the quality of generated code (usually
732         * warnings about missing prototypes or unreferenced
733         * labels).
734         */
735        extra = [stringset [extra] - -Werror];
736
737        if [in [substring 1 3 [entryname [c++]]] g++] then
738        {
739            /*
740             * Generated files may have warnings, because we have no
741             * control over the quality of generated code (usually
742             * warnings about missing prototypes or unreferenced
743             * labels).
744             */
745            if [g++_modern] then
746                extra += -Wno-unused-function -Wno-unused-label;
747        }
748    }
749
750    local post =;
751    if [cxx_c_o]
752        then post = -o [target];
753    else
754        post = "&&" mv %2.o [target];
755
756    [c++] [extra]
757        [cc_include_flags]
758        -c [resolve %1/%0%2.cc]
759        [post];
760}
761
762[arch]/%1/%0%2.o: [arch]/%1/%0%2.cc [c++_path]
763{
764    if [quiet] then
765        function print Compile [target];
766    extra = [c++_flags];
767    if [defined %2_flags] then
768        extra = [extra] [%2_flags];
769
770    if [match %%.yacc %2] then
771    {
772        /*
773         * Generated files may have warnings, because we have no
774         * control over the quality of generated code (usually
775         * warnings about missing prototypes or unreferenced
776         * labels).
777         */
778        extra = [stringset [extra] - -Werror];
779    }
780
781    [c++] [extra]
782        [cc_include_flags]
783        -c [resolve [arch]/%1/%0%2.cc]
784        ['if' [cxx_c_o] 'then' -o [target]];
785    if [not [cxx_c_o]] then
786        mv %2.o [target];
787}
788
789%1/%0%2.cc.d: %1/%0%2.cc
790    set no-cascade
791{
792    if [quiet] then
793        function print Depends [target];
794    c_incl -nc -ns -eia -nrec
795        [c_incl_include_flags]
796        -prefix "'cascade %1/%0%2.cc ='"
797        -suffix "';'"
798        [resolve %1/%0%2.cc]
799        [addprefix -rlp\= [search_list]]
800        -slp [arch] "'[arch]'"
801        -nsri
802        /*
803         * Generated files may use excluded headers, because we
804         * have no control over the quality of generated code.
805         */
806        ['if' [not [match %%.yacc %2]] 'then'
807            ['if' [not [filter common/ac/%%0%% %1/%0%2.cc]]
808                'then' [c_incl_excludes]]]
809        -o [target];
810}
811
812%1/%0%2.h.d: %1/%0%2.h
813    set no-cascade
814{
815    if [quiet] then
816        function print Depends [target];
817    c_incl -nc -ns -eia -nrec
818        [c_incl_include_flags]
819        -prefix "'cascade %1/%0%2.h ='"
820        -suffix "';'"
821        [resolve %1/%0%2.h]
822        [addprefix -rlp\= [search_list]]
823        -slp [arch] "'[arch]'"
824        -nsri
825        ['if' [not [filter common/ac/%%0%% %1/%0%2.h]]
826            'then' [c_incl_excludes]]
827        -o [target];
828}
829
830%1/%0%2.cc.d: [arch]/%1/%0%2.cc
831    set no-cascade
832{
833    if [quiet] then
834        function print Depends [target];
835    c_incl -nc -ns -eia -nrec
836        [c_incl_include_flags]
837        -prefix "'cascade [arch]/%1/%0%2.cc ='"
838        -suffix "';'"
839        [resolve [arch]/%1/%0%2.cc]
840        [addprefix -rlp\= [search_list]]
841        -slp [arch] "'[arch]'"
842        -nsri
843        ['if' [not [filter common/ac/%%0%% %1/%0%2.h]]
844            'then' [c_incl_excludes]]
845        -o [target];
846}
847
848c-dep-files =
849    [fromto %1/%0%2.cc %1/%0%2.cc.d
850        [match_mask %1/%0%2.cc [source_files]]]
851    [fromto %1/%0%2.h %1/%0%2.h.d
852        [match_mask %1/%0%2.h [source_files]]]
853    [fromto %1/%0%2.y %1/%0%2.yacc.cc.d
854        [match_mask %1/%0%2.y [source_files]]]
855    [fromto %1/%0%2.y %1/%0%2.yacc.h.d
856        [match_mask %1/%0%2.y [source_files]]]
857    [fromto %1/%0%2.def %1/%0%2.fmtgen.cc.d
858        [match_mask %1/%0%2.def [source_files]]]
859    [fromto %1/%0%2.def %1/%0%2.fmtgen.h.d
860        [match_mask %1/%0%2.def [source_files]]]
861    ;
862
863#if [count [c-dep-files]]
864#include-cooked-nowarn [c-dep-files]
865#endif
866
867/*
868 * Catch 22: you need the include files to be there, to work out that
869 * you need to construct them.  This is the minimum set of dependencies
870 * to bootstrap the dependency process.  Sigh.
871 */
872
873cascade aeannotate/annotate.cc = libaegis/fstate.fmtgen.h;
874cascade aecomplete/command/ae_c.cc = libaegis/cstate.fmtgen.h;
875cascade aecomplete/command/aechown.cc = libaegis/cstate.fmtgen.h;
876cascade aecomplete/command/aecpu.cc = libaegis/cstate.fmtgen.h;
877cascade aecomplete/command/aedb.cc = libaegis/cstate.fmtgen.h;
878cascade aecomplete/command/aedbu.cc = libaegis/cstate.fmtgen.h;
879cascade aecomplete/command/aede.cc = libaegis/cstate.fmtgen.h;
880cascade aecomplete/command/aedeu.cc = libaegis/cstate.fmtgen.h;
881cascade aecomplete/command/aeib.cc = libaegis/cstate.fmtgen.h;
882cascade aecomplete/command/aeibu.cc = libaegis/cstate.fmtgen.h;
883cascade aecomplete/command/aeifail.cc = libaegis/cstate.fmtgen.h;
884cascade aecomplete/command/aeipass.cc = libaegis/cstate.fmtgen.h;
885cascade aecomplete/command/aemtu.cc = libaegis/cstate.fmtgen.h;
886cascade aecomplete/command/aencu.cc = libaegis/cstate.fmtgen.h;
887cascade aecomplete/command/aenfu.cc = libaegis/cstate.fmtgen.h;
888cascade aecomplete/command/aentu.cc = libaegis/cstate.fmtgen.h;
889cascade aecomplete/command/aerb.cc = libaegis/cstate.fmtgen.h;
890cascade aecomplete/command/aerbu.cc = libaegis/cstate.fmtgen.h;
891cascade aecomplete/command/aerfail.cc = libaegis/cstate.fmtgen.h;
892cascade aecomplete/command/aerm.cc = libaegis/cstate.fmtgen.h;
893cascade aecomplete/command/aermu.cc = libaegis/cstate.fmtgen.h;
894cascade aecomplete/command/aerpass.cc = libaegis/cstate.fmtgen.h;
895cascade aecomplete/command/aerpu.cc = libaegis/cstate.fmtgen.h;
896cascade aecomplete/command/aet.cc = libaegis/cstate.fmtgen.h;
897cascade aecomplete/complete/change/number.cc = libaegis/cstate.fmtgen.h;
898cascade aedist/list.cc = libaegis/cstate.fmtgen.h;
899cascade aedist/receive.cc = libaegis/cattr.fmtgen.h;
900cascade aefind/function/stat.cc = [arch]/common/config.h;
901cascade aefind/lex.cc = aefind/cmdline.yacc.h;
902cascade aeget/get/change/aetar.cc = libaegis/cstate.fmtgen.h;
903cascade aeget/get/change/download.cc = libaegis/cstate.fmtgen.h;
904cascade aeget/get/change/list.cc = libaegis/cstate.fmtgen.h;
905cascade aeget/get/change/menu.cc = libaegis/cstate.fmtgen.h;
906cascade aeget/get/file/activity.cc = libaegis/cstate.fmtgen.h;
907cascade aeget/get/file/history.cc = libaegis/cstate.fmtgen.h;
908cascade aeget/get/file/menu.cc = libaegis/fstate.fmtgen.h;
909cascade aeget/get/project/menu.cc = libaegis/cstate.fmtgen.h;
910cascade aeget/get/project/statistics.cc = libaegis/cstate.fmtgen.h;
911cascade aeget/get/project/statistics.cc = libaegis/fstate.fmtgen.h;
912cascade aegis/aeca.cc = libaegis/cattr.fmtgen.h;
913cascade aegis/aeca.h = libaegis/cattr.fmtgen.h;
914cascade aegis/aechown.cc = libaegis/cstate.fmtgen.h;
915cascade aegis/aechown.cc = libaegis/pstate.fmtgen.h;
916cascade aegis/aedb.cc = libaegis/common.fmtgen.h;
917cascade aegis/aedbu.cc = libaegis/common.fmtgen.h;
918cascade aegis/aede.cc = libaegis/common.fmtgen.h;
919cascade aegis/aedeu.cc = libaegis/common.fmtgen.h;
920cascade aegis/aedn.cc = libaegis/pconf.fmtgen.h;
921cascade aegis/aeib.cc = libaegis/common.fmtgen.h;
922cascade aegis/aeibu.cc = libaegis/common.fmtgen.h;
923cascade aegis/ael.cc = libaegis/fstate.fmtgen.h;
924cascade aegis/aemvu.cc = libaegis/pconf.fmtgen.h;
925cascade aegis/aenc.cc = libaegis/cattr.fmtgen.h;
926cascade aegis/aenc.cc = libaegis/common.fmtgen.h;
927cascade aegis/aencu.cc = libaegis/cattr.fmtgen.h;
928cascade aegis/aencu.cc = libaegis/common.fmtgen.h;
929cascade aegis/aenf.cc = libaegis/pconf.fmtgen.h;
930cascade aegis/aepa.cc = libaegis/pattr.fmtgen.h;
931cascade aegis/aerb.cc = libaegis/pattr.fmtgen.h;
932cascade aegis/aerf.cc = libaegis/pattr.fmtgen.h;
933cascade aegis/aerp.cc = libaegis/pattr.fmtgen.h;
934cascade aeimport/config_file.cc = libaegis/cstate.fmtgen.h;
935cascade aeimport/config_file.cc = libaegis/pconf.fmtgen.h;
936cascade aeimport/format/rcs/lex.cc = aeimport/format/rcs/gram.yacc.h;
937cascade aeimport/format/sccs/lex.cc = aeimport/format/sccs/gram.yacc.h;
938cascade aeimport/reconstruct.cc = libaegis/fstate.fmtgen.h;
939cascade aeimport/synthesize.cc = libaegis/cstate.fmtgen.h;
940cascade aeimport/synthesize.cc = libaegis/fstate.fmtgen.h;
941cascade aels/list.cc = libaegis/fstate.fmtgen.h;
942cascade aels/stack.cc = libaegis/cstate.fmtgen.h;
943cascade aepatch/receive.cc = libaegis/cattr.fmtgen.h;
944cascade aepatch/receive.cc = libaegis/pconf.fmtgen.h;
945cascade aexml/xml/change/cstate.cc = libaegis/cstate.fmtgen.h;
946cascade aexml/xml/change/fstate.cc = libaegis/fstate.fmtgen.h;
947cascade aexml/xml/change/pconf.cc = libaegis/cstate.fmtgen.h;
948cascade aexml/xml/project/cstate.cc = libaegis/cstate.fmtgen.h;
949cascade aexml/xml/project/fstate.cc = libaegis/fstate.fmtgen.h;
950cascade common/ac/ctype.h = [arch]/common/config.h;
951cascade common/ac/curl/curl.h = [arch]/common/config.h;
952cascade common/ac/dce/rpc.h = [arch]/common/config.h;
953cascade common/ac/errno.h = [arch]/common/config.h;
954cascade common/ac/fcntl.h = [arch]/common/config.h;
955cascade common/ac/libintl.h = [arch]/common/config.h;
956cascade common/ac/limits.h = [arch]/common/config.h;
957cascade common/ac/locale.h = [arch]/common/config.h;
958cascade common/ac/magic.h = [arch]/common/config.h;
959cascade common/ac/math.h = [arch]/common/config.h;
960cascade common/ac/mntent.h = [arch]/common/config.h;
961cascade common/ac/regex.h = [arch]/common/config.h;
962cascade common/ac/shadow.h = [arch]/common/config.h;
963cascade common/ac/signal.h = [arch]/common/config.h;
964cascade common/ac/stdarg.h = [arch]/common/config.h;
965cascade common/ac/stddef.h = [arch]/common/config.h;
966cascade common/ac/stdio.h = [arch]/common/config.h;
967cascade common/ac/stdlib.h = [arch]/common/config.h;
968cascade common/ac/string.h = [arch]/common/config.h;
969cascade common/ac/sys/clu.h = [arch]/common/config.h;
970cascade common/ac/sys/ioctl.h = [arch]/common/config.h;
971cascade common/ac/sys/prctl.h = [arch]/common/config.h;
972cascade common/ac/termios.h = [arch]/common/config.h;
973cascade common/ac/time.h = [arch]/common/config.h;
974cascade common/ac/unistd.h = [arch]/common/config.h;
975cascade common/ac/uuid.h = [arch]/common/config.h;
976cascade common/ac/wchar.h = [arch]/common/config.h;
977cascade common/ac/zlib.h = [arch]/common/config.h;
978cascade common/version_stmp.cc = common/patchlevel.h;
979cascade etc/aegis.html = etc/version.so;
980cascade fmtgen/lex.cc = fmtgen/parse.yacc.h;
981cascade lib/en/aoss4/main.mm = etc/version.so(exists);
982cascade lib/en/auug93/main.mm = etc/version.so(exists);
983cascade lib/en/building/main.man = etc/version.so(exists);
984cascade lib/en/cvs-comparison/main.ms = [arch]/etc/libdir.so;
985cascade lib/en/cvs-comparison/main.ms = etc/version.so(exists);
986cascade lib/en/faq/main.roff = etc/version.so(exists) lib/en/faq/toc.so;
987cascade lib/en/howto/introductio.so = [arch]/etc/libdir.so;
988cascade lib/en/howto/introductio.so = etc/version.so(exists);
989cascade lib/en/lsm/main.roff = etc/version.so;
990cascade lib/en/man1/aegis.cgi.1 = [arch]/etc/libdir.so;
991cascade lib/en/man1/aeintegratq.1 = [arch]/etc/libdir.so etc/version.so(exists);
992cascade lib/en/man1/aenpr.1 = [arch]/etc/libdir.so;
993cascade lib/en/man1/aenrls.1 = [arch]/etc/libdir.so;
994cascade lib/en/man1/aer.1 = [arch]/etc/libdir.so;
995cascade lib/en/man1/tkaegis.1 = etc/version.so(exists);
996cascade lib/en/man1/z_cr.so = etc/version.so(exists);
997cascade lib/en/man5/aegstate.5 = [arch]/etc/libdir.so;
998cascade lib/en/man5/aer.5 = [arch]/etc/libdir.so;
999cascade lib/en/man5/aerptidx.5 = [arch]/etc/libdir.so;
1000cascade lib/en/man5/aeustate.5 = [arch]/etc/libdir.so;
1001cascade lib/en/readme/main.man = etc/version.so(exists);
1002cascade lib/en/readme/main.man = lib/en/readme/new.so;
1003cascade lib/en/refman/main.man = lib/en/refman/index.so;
1004cascade lib/en/refman/main.man = lib/en/refman/parts.so;
1005cascade lib/en/user-guide/c1.0.so = [arch]/etc/libdir.so;
1006cascade lib/en/user-guide/c1.0.so = etc/version.so(exists);
1007cascade libaegis/ael/change/incomplete.cc = libaegis/cstate.fmtgen.h;
1008cascade libaegis/ael/change/outstanding.cc = libaegis/cstate.fmtgen.h;
1009cascade libaegis/ael/formeditnum.cc = libaegis/fstate.fmtgen.h;
1010cascade libaegis/ael/formeditnum.h = libaegis/fstate.fmtgen.h;
1011cascade libaegis/ael/project/history.cc = libaegis/cstate.fmtgen.h;
1012cascade libaegis/aer/expr/name.cc = libaegis/aer/value/gstate.h;
1013cascade libaegis/aer/expr/name.cc = libaegis/cattr.fmtgen.h;
1014cascade libaegis/aer/expr/name.cc = libaegis/common.fmtgen.h;
1015cascade libaegis/aer/expr/name.cc = libaegis/cstate.fmtgen.h;
1016cascade libaegis/aer/expr/name.cc = libaegis/fstate.fmtgen.h;
1017cascade libaegis/aer/expr/name.cc = libaegis/pattr.fmtgen.h;
1018cascade libaegis/aer/expr/name.cc = libaegis/pconf.fmtgen.h;
1019cascade libaegis/aer/expr/name.cc = libaegis/pstate.fmtgen.h;
1020cascade libaegis/aer/expr/name.cc = libaegis/uconf.fmtgen.h;
1021cascade libaegis/aer/expr/name.cc = libaegis/ustate.fmtgen.h;
1022cascade libaegis/aer/lex.cc = libaegis/aer/report.yacc.h;
1023cascade libaegis/aer/list.cc = libaegis/rptidx.fmtgen.h;
1024cascade libaegis/aer/parse.cc = libaegis/rptidx.fmtgen.h;
1025cascade libaegis/aer/value/cstate.cc = libaegis/aer/value/cstate.h;
1026cascade libaegis/aer/value/cstate.cc = libaegis/aer/value/fstate.h;
1027cascade libaegis/aer/value/fstate.cc = libaegis/aer/value/fstate.h;
1028cascade libaegis/aer/value/gstate.cc = libaegis/aer/value/gstate.h;
1029cascade libaegis/aer/value/gstate.cc = libaegis/aer/value/pstate.h;
1030cascade libaegis/aer/value/pstate.cc = libaegis/aer/value/cstate.h;
1031cascade libaegis/aer/value/pstate.cc = libaegis/aer/value/fstate.h;
1032cascade libaegis/aer/value/pstate.cc = libaegis/aer/value/pstate.h;
1033cascade libaegis/change.h = libaegis/cstate.fmtgen.h;
1034cascade libaegis/change.h = libaegis/fstate.fmtgen.h;
1035cascade libaegis/change.h = libaegis/pconf.fmtgen.h;
1036cascade libaegis/change/architecture/check.cc = libaegis/cstate.fmtgen.h;
1037cascade libaegis/change/architecture/check.cc = libaegis/pconf.fmtgen.h;
1038cascade libaegis/change/architecture/find_variant.h = libaegis/cstate.fmtgen.h;
1039cascade libaegis/change/architecture/run_disc_cmd.cc = libaegis/pconf.fmtgen.h;
1040cascade libaegis/change/attributes/copy.cc = libaegis/cattr.fmtgen.h;
1041cascade libaegis/change/attributes/copy.cc = libaegis/cstate.fmtgen.h;
1042cascade libaegis/change/attributes/default.cc = libaegis/cattr.fmtgen.h;
1043cascade libaegis/change/attributes/default.cc = libaegis/pconf.fmtgen.h;
1044cascade libaegis/change/attributes/edit.cc = libaegis/cattr.fmtgen.h;
1045cascade libaegis/change/attributes/verify.cc = libaegis/cattr.fmtgen.h;
1046cascade libaegis/change/build/run_int_com.cc = libaegis/pconf.fmtgen.h;
1047cascade libaegis/change/cstate/improve.cc = libaegis/cstate.fmtgen.h;
1048cascade libaegis/change/cstate/improve.h = libaegis/cstate.fmtgen.h;
1049cascade libaegis/change/develop_direct/read_write.cc = libaegis/cstate.fmtgen.h;
1050cascade libaegis/change/file/is_config.cc = libaegis/pconf.fmtgen.h;
1051cascade libaegis/change/file/metrics/get.cc = libaegis/metric_file.fmtgen.h;
1052cascade libaegis/change/is_completed.cc = libaegis/cstate.fmtgen.h;
1053cascade libaegis/change/pconf/get.cc = libaegis/fstate.fmtgen.h;
1054cascade libaegis/change/test/batch.cc = libaegis/fstate.fmtgen.h;
1055cascade libaegis/change/test/batch.cc = libaegis/pconf.fmtgen.h;
1056cascade libaegis/change/test/batch.cc = libaegis/tstrslt.fmtgen.h;
1057cascade libaegis/change/test/batch_fake.cc = libaegis/fstate.fmtgen.h;
1058cascade libaegis/change/test/batch_fake.cc = libaegis/tstrslt.fmtgen.h;
1059cascade libaegis/change/test/run_list.cc = libaegis/pconf.fmtgen.h;
1060cascade libaegis/common.cc = libaegis/common.fmtgen.h;
1061cascade libaegis/glue.h = [arch]/common/config.h;
1062cascade libaegis/gonzo.cc = libaegis/gstate.fmtgen.h;
1063cascade libaegis/gonzo.cc = libaegis/ustate.fmtgen.h;
1064cascade libaegis/gonzo.h = libaegis/gstate.fmtgen.h;
1065cascade libaegis/lex.cc = libaegis/gram.yacc.h;
1066cascade libaegis/metrics.cc = libaegis/metrics.fmtgen.h;
1067cascade libaegis/os/interrupt.h = [arch]/common/config.h;
1068cascade libaegis/patch/read.cc = libaegis/common.fmtgen.h;
1069cascade libaegis/project.cc = libaegis/pstate.fmtgen.h;
1070cascade libaegis/project.h = libaegis/pattr.fmtgen.h;
1071cascade libaegis/project.h = libaegis/pstate.fmtgen.h;
1072cascade libaegis/project/delta2change.cc = libaegis/cstate.fmtgen.h;
1073cascade libaegis/project/file.h = libaegis/fstate.fmtgen.h;
1074cascade libaegis/project/file/directory/conflict.cc = libaegis/fstate.fmtgen.h;
1075cascade libaegis/project/file/find_fuzzy.cc = libaegis/fstate.fmtgen.h;
1076cascade libaegis/project/file/nth.cc = libaegis/fstate.fmtgen.h;
1077cascade libaegis/project/file/roll_forward.cc = libaegis/cstate.fmtgen.h;
1078cascade libaegis/project/file/roll_forward.h = libaegis/fstate.fmtgen.h;
1079cascade libaegis/project/file/trojan.cc = libaegis/pconf.fmtgen.h;
1080cascade libaegis/project/file/version_path.cc = libaegis/fstate.fmtgen.h;
1081cascade libaegis/project/new_branch.cc = libaegis/cstate.fmtgen.h;
1082cascade libaegis/project/new_branch.cc = libaegis/pconf.fmtgen.h;
1083cascade libaegis/project/pattr/edit.cc = libaegis/pattr.fmtgen.h;
1084cascade libaegis/project/pattr/get.cc = libaegis/pattr.fmtgen.h;
1085cascade libaegis/project/pattr/set.cc = libaegis/pattr.fmtgen.h;
1086cascade libaegis/project/pconf/get.cc = libaegis/pconf.fmtgen.h;
1087cascade libaegis/project/sch_path_get.cc = libaegis/cstate.fmtgen.h;
1088cascade libaegis/project/sch_path_get.cc = libaegis/fstate.fmtgen.h;
1089cascade libaegis/sub.cc = libaegis/sub/change/state.h;
1090cascade libaegis/sub/base_relativ.cc = libaegis/cstate.fmtgen.h;
1091cascade libaegis/sub/change/delta.cc = libaegis/cstate.fmtgen.h;
1092cascade libaegis/sub/change/number.cc = libaegis/cstate.fmtgen.h;
1093cascade libaegis/sub/change/state.cc = libaegis/sub/change/state.h;
1094cascade libaegis/sub/delta.cc = libaegis/cstate.fmtgen.h;
1095cascade libaegis/sub/expr_lex.cc = libaegis/sub/expr_gram.yacc.h;
1096cascade libaegis/sub/plural_lex.cc = libaegis/sub/plural_gram.yacc.h;
1097cascade libaegis/sub/project/specific.cc = libaegis/pconf.fmtgen.h;
1098cascade libaegis/sub/source.cc = libaegis/cstate.fmtgen.h;
1099cascade libaegis/tstrslt.cc = libaegis/tstrslt.fmtgen.h;
1100cascade libaegis/user.h = libaegis/uconf.fmtgen.h;
1101cascade libaegis/user.h = libaegis/ustate.fmtgen.h;
1102/* cascade lib/en/readme/main.man = etc/proj_metric.so; */
1103
1104if [count [common_lib]] then
1105[common_lib]: [arch]/common/config.h;
1106
1107if [count [match_mask %0%.o [fmtgen_obj]]] then
1108[match_mask %0%.o [fmtgen_obj]]: [arch]/common/config.h;
1109
1110/*
1111 * How to use yacc sources.
1112 */
1113
1114yacc_cmd_flags = -v;
1115
1116%1/%0%2.gen.h
1117%1/%0%2.yacc.cc %1/%0%2.yacc.h: %1/%0%2.y
1118    single-thread y.tab.c y.tab.h
1119{
1120    if [quiet] then
1121        function print Yacc [target];
1122    rm -f %1/%0%2.list y.output
1123        set silent;
1124    [yacc] -d [yacc_cmd_flags] [resolve %1/%0%2.y];
1125    yy = [collect echo %0%2 | sed -e "'s|[^a-zA-Z0-9]|_|g'"];
1126    sed     -e "'s/[yY][yY]/"[yy]"_/g'"
1127        -e "'s|y\.tab\.c|%1/%0%2.yacc.cc|g'"
1128        -e "'/<stdio.h>/d'"
1129        -e "'/<stdlib.h>/d'"
1130        -e "'/<stddef.h>/d'"
1131        < y.tab.c > %1/%0%2.yacc.cc;
1132    rm y.tab.c;
1133    sed -e "'s/[yY][yY]/"[yy]"_/g'" -e "'s/Y_TAB_H/"[yy]"_TAB_H/g'"
1134        < y.tab.h > %1/%0%2.yacc.h;
1135    rm y.tab.h;
1136    if [exists y.output] then
1137        mv y.output %1/%0%2.list
1138            set clearstat;
1139    echo "'#error'" > %1/%0%2.gen.h;
1140}
1141
1142[arch]/bin/%: script/%.tcl
1143{
1144    if [quiet] then
1145        function print Copy [target];
1146    cp [resolve [need]] [target];
1147    chmod 755 [target];
1148}
1149
1150/*
1151 * Or from a .sh script
1152 * Use bash to check syntax.
1153 * Or fall back to ksh if there
1154 * This avoids linux ksh that gripes about obsolete back-tic usage
1155 */
1156check_sh = [find_command bash];
1157if [not [check_sh]] then
1158    check_sh = [find_command ksh];
1159if [not [check_sh]] then
1160    check_sh = sh;
1161
1162[arch]/bin/%: etc/%.sh
1163{
1164    if [quiet] then
1165        function print Link [target];
1166    cat [resolve etc/%.sh] > [target];
1167    [check_sh] -n [target];
1168    chmod 755 [target];
1169}
1170
1171/*
1172 * How to automatically configure things to cope with the environment
1173 * we find ourselves in.
1174 */
1175#include-cooked etc/autoconf.cook
1176
1177
1178ranlib = [find_command ranlib];
1179
1180[arch]/%/%.a: [%_lib]
1181    set meter
1182{
1183    if [quiet] then
1184        function print Link [target];
1185    ar qc [target] [resolve [%_lib]];
1186    if [ranlib] then
1187        [ranlib] [target];
1188}
1189
1190set-uid-root-commands = aegis aeimport aelock;
1191
1192/*
1193 * build the programs from their objects
1194 */
1195
1196[arch]/bin/%: [%_obj]
1197{
1198    if [quiet] then
1199        function print Link [target];
1200    sh [resolve etc/rsrvd_syms.sh] `cat`;
1201data
1202[unsplit "\n" [resolve [%_obj]]]
1203dataend
1204
1205    [c++] -o [target]
1206        [stringset [ld_flags] [debug]]
1207        [resolve [%_obj]] [libs]
1208            set meter;
1209
1210    chmod 755 [target];
1211
1212    /*
1213     * aegis itself must be set-uid-root
1214     */
1215    if [in [target] [addprefix [arch]/bin/ [set-uid-root-commands]]] then
1216    {
1217        if [in [resolve etc/set-uid-root] etc/set-uid-root] then
1218            chmod a+rx etc/set-uid-root;
1219        sudo [pathname [resolve etc/set-uid-root]]
1220            [arch] [entryname [target]]
1221                set errok;
1222    }
1223}
1224
1225
1226/*
1227 * building things which require fmtgen to build
1228 *
1229 * Build %.fmtgen.cc and %.fmtgen.h from %.def
1230 *
1231 * A host binding here can help a great deal; otherwise you need to
1232 * construct exactly the same files for each architecture.
1233 */
1234
1235%1/%0%2.fmtgen.cc %1/%0%2.fmtgen.h: %1/%0%2.def: [arch]/bin/fmtgen
1236    /* host-binding [[generate-arch]-hosts] */
1237{
1238    if [quiet] then
1239        function print 'Format generate' [target];
1240    /*
1241     * We don't resolve the path of the .def file, because fmtgen can
1242     * do it itself, and because this allows the unresolved source
1243     * file name to be inserted into the comment at the top of the
1244     * output files.
1245     *
1246     * We insert the unresolved file name because (a) it's less
1247     * confusing, and (b) it doesn't needlessly change the fingerprint
1248     * just because of the search path.  This, in turn, means that
1249     * cook doesn't rebuild a couple of hundred files which don't
1250     * need to be recompiled.
1251     */
1252    [resolve [arch]/bin/fmtgen]
1253        [addprefix "-I" [search_list]]
1254        %1/%0%2.def %1/%0%2.fmtgen.cc %1/%0%2.fmtgen.h
1255        ;
1256}
1257
1258%0%.fmtgen.cc: %0%.def: [arch]/bin/fmtgen
1259    /* host-binding [[generate-arch]-hosts] */
1260{
1261    if [quiet] then
1262        function print Fmtgen [target];
1263    [resolve [arch]/bin/fmtgen]
1264        [addprefix "-I" [search_list]]
1265        -ic %0%.fmtgen.cc
1266        %0%.def
1267        ;
1268}
1269
1270%0%.fmtgen.h: %0%.def: [arch]/bin/fmtgen
1271    /* host-binding [[generate-arch]-hosts] */
1272{
1273    if [quiet] then
1274        function print Fmtgen [target];
1275    [resolve [arch]/bin/fmtgen]
1276        [addprefix "-I" [search_list]]
1277        -ii %0%.fmtgen.h
1278        %0%.def
1279        ;
1280}
1281
1282%1/%0%2.def.d: %1/%0%2.def
1283    set no-cascade
1284{
1285    if [quiet] then
1286        function print Depends [target];
1287    c_incl -nc -ns -eia -nrec
1288        [c_incl_include_flags]
1289        -prefix "'cascade %1/%0%2.def ='"
1290        -suffix "';'"
1291        [resolve %1/%0%2.def]
1292        [addprefix -rlp\= [search_list]]
1293        -slp [arch] "'[arch]'"
1294        -nsri
1295        -o [target];
1296}
1297
1298def-dep-files =
1299    [fromto %1/%0%2.def %1/%0%2.def.d
1300        [match_mask %1/%0%2.def [source_files]]
1301    ];
1302
1303#if [count [def-dep-files]]
1304#include-cooked-nowarn [def-dep-files]
1305#endif
1306
1307/*
1308 * The version stamp is to be updated for every
1309 * integration and development build.
1310 */
1311
1312[vs_file]:
1313    set shallow
1314{
1315    echo "'#define PATCHLEVEL \""[version]"\"'" > [target];
1316    aegis -list version -p [project] -c [change]
1317    | [awk] "-F'[[\\\\]]'"
1318"'/^copyright_years/{print \"#define COPYRIGHT_YEARS \\\"\" $2 \"\\\"\" }'"
1319    >> [target];
1320}
1321
1322[arch]/lib/report.index : lib/report.index
1323    set shallow
1324{
1325    if [quiet] then
1326        function print Copy [target];
1327    cat [resolve [need]] > [target];
1328}
1329
1330
1331etc/version.so:
1332    set ['if' [or [not [defined baseline] ] [not [exists bl/etc/version.so
1333        ] ] ] 'then' shallow]
1334{
1335    if [quiet] then
1336        function print Generate [target];
1337    echo \".ds v) [version_short]\" > [target];
1338    echo \".ds V) [version]\" >> [target];
1339    echo [version]
1340        | [awk] -F.  "'{o=$2%2; print\".ds o) \"o;"
1341            "print \".ds p) \" $1 \".\" (o ? ($2 - 1) : ($2 + 1)) }'"
1342        >> [target];
1343    echo [version]
1344        | [awk] -F. "'{print \".ds u) \"$1\".\"$2}'"
1345        >> [target];
1346    aegis -list version -p [project] -c [change]
1347        | [awk] -F'\'"\'' "'/previous/{print $2}'"
1348        | [awk] -F. "'{print \".ds w) \"$1\".\"$2}'"
1349        >> [target];
1350    aegis -list version -p [project] -c [change]
1351    | [awk] "-F'[[\\\\]]'" "'/^copyright_years/{print \".ds Y) \" $2}'"
1352    >> [target];
1353}
1354
1355
1356/*
1357 * These recipes build a Makefile for a user.  They do not build a
1358 * Makefile useful for a development build, because no arch
1359 * information is included in the Makefile.
1360 */
1361
1362Makefile.in: [arch]/bin/aemakegen [arch]/bin/aemakefile [vs_file]
1363    [stringset [source_file_order] - [targets]]
1364{
1365    if [quiet] then
1366        function print Generate [target];
1367    [resolve [arch]/bin/aemakegen] --debug
1368        --target\=makefile --flavour\=aegis
1369        --project\=[project] --change\=[change]
1370
1371        /* also tell it about the extra files in the tarball */
1372        [stringset [source_file_order] - [source_files] [targets]]
1373
1374        > [target];
1375    [resolve [arch]/bin/aemakefile] [vs_file] [source_files] > [target].old;
1376    /* tkdiff [target].old [target] set errok; */
1377}
1378
1379etc/CHANGES: [arch]/bin/aereport lib/report/proj_detai.rpt [vs_file]
1380{
1381    if [quiet] then
1382        function print Generate [target];
1383    [resolve [arch]/bin/aereport]
1384        -f [resolve lib/report/proj_detai.rpt]
1385        -o [target]
1386        -p [project_short]
1387        -pw\=80 -pl\=66
1388                                      set meter;
1389}
1390
1391/*
1392 * How to cook documents.
1393 */
1394#include-cooked etc/documents.cook
1395
1396/*
1397 * Internationalization recipes
1398 */
1399#include-cooked etc/i18n.cook
1400
1401/*
1402 * Archive directory for integration builds
1403 * (Must come after i18n.cook)
1404 */
1405#include-cooked etc/archive.cook
1406
1407/*
1408 * Source file metrics
1409 */
1410#include-cooked etc/metrics.cook
1411
1412/*
1413 * C formatting checking.
1414 */
1415#include-cooked etc/cfmt.cook
1416
1417/*
1418 * Symbols cross references for editing.
1419 */
1420#include-cooked etc/tags.cook
1421
1422/*
1423 * Generate documentation out of the header files.
1424 */
1425#include-cooked etc/doxygen.cook
1426#include-cooked etc/apt-get-d.cook
1427
1428/*
1429 * Assorted other cookbooks, proximal to their subjects.
1430 */
1431module.cook = [match_mask "%0module.cook" [source_files]];
1432#if [count [module.cook]]
1433#include [resolve [module.cook]]
1434#endif
1435
1436
1437/* vim: set ts=8 sw=4 et : */
1438