Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/build/jam_src/jam.c @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 13.0 KB
Line 
1/*
2 * /+\
3 * +\   Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * \+/
5 *
6 * This file is part of jam.
7 *
8 * License is hereby granted to use this software and distribute it
9 * freely, as long as this copyright notice is retained and modifications
10 * are clearly marked.
11 *
12 * ALL WARRANTIES ARE HEREBY DISCLAIMED.
13 */
14
15/*  This file is ALSO:
16 *  Copyright 2001-2004 David Abrahams.
17 *  Distributed under the Boost Software License, Version 1.0.
18 *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
19 */
20
21/*
22 * jam.c - make redux
23 *
24 * See Jam.html for usage information.
25 *
26 * These comments document the code.
27 *
28 * The top half of the code is structured such:
29 *
30 *                       jam
31 *                      / | \
32 *                 +---+  |  \
33 *                /       |   \
34 *         jamgram     option  \
35 *        /  |   \              \
36 *       /   |    \              \
37 *      /    |     \             |
38 *  scan     |     compile      make
39 *   |       |    /  | \       / |  \
40 *   |       |   /   |  \     /  |   \
41 *   |       |  /    |   \   /   |    \
42 * jambase parse     |   rules  search make1
43 *                   |           |      |   \
44 *                   |           |      |    \
45 *                   |           |      |     \
46 *               builtins    timestamp command execute
47 *                               |
48 *                               |
49 *                               |
50 *                             filesys
51 *
52 *
53 * The support routines are called by all of the above, but themselves
54 * are layered thus:
55 *
56 *                     variable|expand
57 *                      /  |   |   |
58 *                     /   |   |   |
59 *                    /    |   |   |
60 *                 lists   |   |   pathsys
61 *                    \    |   |
62 *                     \   |   |
63 *                      \  |   |
64 *                     newstr  |
65 *                        \    |
66 *                         \   |
67 *                          \  |
68 *                          hash
69 *
70 * Roughly, the modules are:
71 *
72 *      builtins.c - jam's built-in rules
73 *      command.c - maintain lists of commands
74 *      compile.c - compile parsed jam statements
75 *      execunix.c - execute a shell script on UNIX
76 *      execvms.c - execute a shell script, ala VMS
77 *      expand.c - expand a buffer, given variable values
78 *      file*.c - scan directories and archives on *
79 *      hash.c - simple in-memory hashing routines
80 *  hdrmacro.c - handle header file parsing for filename macro definitions
81 *      headers.c - handle #includes in source files
82 *      jambase.c - compilable copy of Jambase
83 *      jamgram.y - jam grammar
84 *      lists.c - maintain lists of strings
85 *      make.c - bring a target up to date, once rules are in place
86 *      make1.c - execute command to bring targets up to date
87 *      newstr.c - string manipulation routines
88 *      option.c - command line option processing
89 *      parse.c - make and destroy parse trees as driven by the parser
90 *      path*.c - manipulate file names on *
91 *      hash.c - simple in-memory hashing routines
92 *      regexp.c - Henry Spencer's regexp
93 *      rules.c - access to RULEs, TARGETs, and ACTIONs
94 *      scan.c - the jam yacc scanner
95 *      search.c - find a target along $(SEARCH) or $(LOCATE)
96 *      timestamp.c - get the timestamp of a file or archive member
97 *      variable.c - handle jam multi-element variables
98 *
99 * 05/04/94 (seiwald) - async multiprocess (-j) support
100 * 02/08/95 (seiwald) - -n implies -d2.
101 * 02/22/95 (seiwald) - -v for version info.
102 * 09/11/00 (seiwald) - PATCHLEVEL folded into VERSION.
103 * 01/10/01 (seiwald) - pathsys.h split from filesys.h
104 */
105
106# include "jam.h"
107# include "option.h"
108# include "patchlevel.h"
109
110/* These get various function declarations. */
111
112# include "lists.h"
113# include "parse.h"
114# include "variable.h"
115# include "compile.h"
116# include "builtins.h"
117# include "rules.h"
118# include "newstr.h"
119# include "scan.h"
120# include "timestamp.h"
121# include "make.h"
122# include "strings.h"
123# include "expand.h"
124
125/* Macintosh is "special" */
126
127# ifdef OS_MAC
128# include <QuickDraw.h>
129# endif
130
131/* And UNIX for this */
132
133# ifdef unix
134# include <sys/utsname.h>
135# endif
136
137struct globs globs = {
138        0,                      /* noexec */
139        1,                      /* jobs */
140        0,                      /* quitquick */
141        0,                      /* newestfirst */
142# ifdef OS_MAC
143        { 0, 0 },               /* debug - suppress tracing output */
144# else
145        { 0, 1 },               /* debug ... */
146# endif
147        0                       /* output commands, not run them */
148} ;
149
150/* Symbols to be defined as true for use in Jambase */
151
152static char *othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 } ;
153
154/* Known for sure:
155 *      mac needs arg_enviro
156 *      OS2 needs extern environ
157 */
158
159# ifdef OS_MAC
160# define use_environ arg_environ
161# ifdef MPW
162QDGlobals qd;
163# endif
164# endif
165
166/* on Win32-LCC */
167# if defined( OS_NT ) && defined( __LCC__ )
168#   define  use_environ _environ
169# endif
170
171# if defined( __MWERKS__)
172# define use_environ _environ
173extern char **_environ;
174#endif
175
176# ifndef use_environ
177# define use_environ environ
178# if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT )
179extern char **environ;
180# endif
181# endif
182
183# if YYDEBUG != 0
184extern int yydebug;
185# endif
186
187#ifndef NDEBUG
188static void run_unit_tests()
189{
190# if defined( USE_EXECNT )
191    extern void execnt_unit_test();
192    execnt_unit_test();
193# endif
194    string_unit_test();
195    var_expand_unit_test();
196}
197#endif
198
199#ifdef HAVE_PYTHON
200    extern PyObject*
201    bjam_call(PyObject *self, PyObject *args);
202 
203    extern PyObject*
204    bjam_import_rule(PyObject* self, PyObject* args);
205#endif
206
207int  main( int argc, char **argv, char **arg_environ )
208{
209    int         n;
210    char                *s;
211    struct option       optv[N_OPTS];
212    const char  *all = "all";
213    int         anyhow = 0;
214    int         status;
215    int arg_c = argc;
216    char ** arg_v = argv;
217    const char *progname = argv[0];
218
219# ifdef OS_MAC
220    InitGraf(&qd.thePort);
221# endif
222
223#ifdef HAVE_PYTHON
224    Py_Initialize();
225
226    {
227        static PyMethodDef BjamMethods[] = {
228            {"call", bjam_call, METH_VARARGS,
229             "Call the specified bjam rule."},
230            {"import_rule", bjam_import_rule, METH_VARARGS,
231             "Imports Python callable to bjam."},
232            {NULL, NULL, 0, NULL}
233        };
234
235        Py_InitModule("bjam", BjamMethods);
236    }
237
238#endif
239
240    argc--, argv++;
241
242        if( getoptions( argc, argv, "-:d:j:f:gs:t:ano:qv", optv ) < 0 )
243    {
244        printf( "\nusage: %s [ options ] targets...\n\n", progname );
245
246        printf( "-a      Build all targets, even if they are current.\n" );
247        printf( "-dx     Set the debug level to x (0-9).\n" );
248        printf( "-fx     Read x instead of Jambase.\n" );
249            /* printf( "-g      Build from newest sources first.\n" ); */
250        printf( "-jx     Run up to x shell commands concurrently.\n" );
251        printf( "-n      Don't actually execute the updating actions.\n" );
252        printf( "-ox     Write the updating actions to file x.\n" );
253                printf( "-q      Quit quickly as soon as a target fails.\n" );
254        printf( "-sx=y   Set variable x=y, overriding environment.\n" );
255        printf( "-tx     Rebuild x, even if it is up-to-date.\n" );
256        printf( "-v      Print the version of jam and exit.\n" );
257        printf( "--x     Option is ignored.\n\n" );
258
259        exit( EXITBAD );
260    }
261
262    /* Version info. */
263
264    if( ( s = getoptval( optv, 'v', 0 ) ) )
265    {
266        printf( "Boost.Jam  " );
267        printf( "Version %s. %s.\n", VERSION, OSMINOR );
268           printf( "   Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.  \n" );
269        printf( "   Copyright 2001 David Turner.\n" );
270        printf( "   Copyright 2001-2004 David Abrahams.\n" );
271        printf( "   Copyright 2002-2005 Rene Rivera.\n" );
272        printf( "   Copyright 2003-2005 Vladimir Prus.\n" );
273
274        return EXITOK;
275    }
276
277    /* Pick up interesting options */
278
279    if( ( s = getoptval( optv, 'n', 0 ) ) )
280        globs.noexec++, globs.debug[2] = 1;
281
282        if( ( s = getoptval( optv, 'q', 0 ) ) )
283            globs.quitquick = 1;
284    if( ( s = getoptval( optv, 'a', 0 ) ) )
285        anyhow++;
286
287    if( ( s = getoptval( optv, 'j', 0 ) ) )
288        globs.jobs = atoi( s );
289
290        if( ( s = getoptval( optv, 'g', 0 ) ) )
291            globs.newestfirst = 1;
292
293    /* Turn on/off debugging */
294
295    for( n = 0; s = getoptval( optv, 'd', n ); n++ )
296    {
297        int i;
298
299        /* First -d, turn off defaults. */
300
301        if( !n )
302            for( i = 0; i < DEBUG_MAX; i++ )
303                globs.debug[i] = 0;
304
305        i = atoi( s );
306
307        if( i < 0 || i >= DEBUG_MAX )
308        {
309            printf( "Invalid debug level '%s'.\n", s );
310            continue;
311        }
312
313        /* n turns on levels 1-n */
314        /* +n turns on level n */
315
316        if( *s == '+' )
317            globs.debug[i] = 1;
318        else while( i )
319            globs.debug[i--] = 1;
320    }
321
322#ifndef NDEBUG
323    run_unit_tests();
324#endif
325#if YYDEBUG != 0
326    if ( DEBUG_PARSE )
327        yydebug = 1;
328#endif
329
330    /* Set JAMDATE first */
331
332    {
333        char *date;
334        time_t clock;
335        time( &clock );
336        date = newstr( ctime( &clock ) );
337
338        /* Trim newline from date */
339
340        if( strlen( date ) == 25 )
341            date[ 24 ] = 0;
342
343        var_set( "JAMDATE", list_new( L0, newstr( date ) ), VAR_SET );
344    }
345
346 
347    {
348   /* Pleace don't change the following line. The 'bump_version.py' script
349       expect a specific format of it. */
350    char  *major_version = "03", *minor_version = "01", *changenum = "11";
351    var_set( "JAM_VERSION",
352             list_new( list_new( list_new( L0, newstr( major_version ) ), 
353                                 newstr( minor_version ) ), 
354                       newstr( changenum ) ),
355             VAR_SET );
356    }
357
358    /* And JAMUNAME */
359# ifdef unix
360    {
361        struct utsname u;
362
363        if( uname( &u ) >= 0 )
364        {
365            var_set( "JAMUNAME", 
366                     list_new( 
367                         list_new(
368                             list_new(
369                                 list_new(
370                                     list_new( L0, 
371                                               newstr( u.sysname ) ),
372                                     newstr( u.nodename ) ),
373                                 newstr( u.release ) ),
374                             newstr( u.version ) ),
375                         newstr( u.machine ) ), VAR_SET );
376        }
377    }
378# endif /* unix */
379
380    /* load up environment variables */
381
382    /* first into global module, with splitting, for backward compatibility */
383    var_defines( use_environ, 1 );
384   
385    /* then into .ENVIRON, without splitting */
386    enter_module( bindmodule(".ENVIRON") );
387    var_defines( use_environ, 0 );
388    exit_module( bindmodule(".ENVIRON") );
389
390        /*
391         * Jam defined variables OS, OSPLAT
392     * We load them after environment, so that
393     * setting OS in environment does not
394     * change Jam notion of the current platform.
395         */
396
397    var_defines( othersyms, 1 );
398
399
400    /* Load up variables set on command line. */
401
402    for( n = 0; s = getoptval( optv, 's', n ); n++ )
403    {
404        char *symv[2];
405        symv[0] = s;
406        symv[1] = 0;
407        var_defines( symv, 1 );
408    }
409
410    /* Set the ARGV to reflect the complete list of arguments of invocation. */
411
412    for ( n = 0; n < arg_c; ++n )
413    {
414        var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
415    }
416
417        /* Initialize built-in rules */
418
419        load_builtins();
420
421    /* Add the targets in the command line to update list */
422
423    for ( n = 1; n < arg_c; ++n )
424    {
425        if ( arg_v[n][0] == '-' )
426        {
427            char *f = "-:d:j:f:gs:t:ano:qv";
428            for( ; *f; f++ ) if( *f == arg_v[n][1] ) break;
429            if ( f[1] == ':' && arg_v[n][2] == '\0' ) { ++n; }
430        }
431        else
432        {
433            mark_target_for_updating(arg_v[n]);
434        }
435    }
436
437    /* Parse ruleset */
438
439    {
440        FRAME frame[1];
441        frame_init( frame );
442        for( n = 0; s = getoptval( optv, 'f', n ); n++ )
443            parse_file( s, frame );
444
445        if( !n )
446            parse_file( "+", frame );
447    }
448
449    status = yyanyerrors();
450
451    /* Manually touch -t targets */
452
453    for( n = 0; s = getoptval( optv, 't', n ); n++ )
454        touchtarget( s );
455
456    /* If an output file is specified, set globs.cmdout to that */
457
458    if( s = getoptval( optv, 'o', 0 ) )
459    {
460        if( !( globs.cmdout = fopen( s, "w" ) ) )
461        {
462            printf( "Failed to write to '%s'\n", s );
463            exit( EXITBAD );
464        }
465        globs.noexec++;
466    }
467
468    /* Now make target */
469
470    {
471        LIST* targets = targets_to_update();
472        if ( !targets )
473        {
474            status |= make( 1, &all, anyhow );
475        }
476        else 
477        {
478            int targets_count = list_length(targets);
479            const char **targets2 = (const char **)malloc(targets_count * sizeof(char *));
480            int n = 0;
481            for ( ; targets; targets = list_next(targets) )
482            {
483                targets2[n++] = targets->string;
484            }
485            status |= make( targets_count, targets2, anyhow );       
486            free(targets);
487        }
488    }
489
490
491    if ( DEBUG_PROFILE )
492        profile_dump();
493
494    /* Widely scattered cleanup */
495
496    var_done();
497    donerules();
498    donestamps();
499    donestr();
500
501    /* close cmdout */
502
503    if( globs.cmdout )
504        fclose( globs.cmdout );
505
506#ifdef HAVE_PYTHON
507    Py_Finalize();
508#endif
509
510
511    return status ? EXITBAD : EXITOK;
512}
Note: See TracBrowser for help on using the repository browser.