/* * /+\ * +\ Copyright 1993, 2000 Christopher Seiwald. * \+/ * * This file is part of jam. * * License is hereby granted to use this software and distribute it * freely, as long as this copyright notice is retained and modifications * are clearly marked. * * ALL WARRANTIES ARE HEREBY DISCLAIMED. */ /* * jam.c - make redux * * See Jam.html and Jamlang.html for usage information. * * These comments document the code. * * The top half of the code is structured such: * * jam * / | \ * +---+ | \ * / | \ * jamgram option \ * / | \ \ * / | \ \ * / | \ | * scan | compile make * | | / \ / | \ * | | / \ / | \ * | | / \ / | \ * jambase parse rules search make1 * | | \ * | | \ * | | \ * timestamp command execute * * * The support routines are called by all of the above, but themselves * are layered thus: * * variable|expand * / | | | * / | | | * / | | | * lists | | filesys * \ | | * \ | | * \ | | * newstr | * \ | * \ | * \ | * hash * * Roughly, the modules are: * * command.c - maintain lists of commands * compile.c - compile parsed jam statements * execunix.c - execute a shell script on UNIX * execvms.c - execute a shell script, ala VMS * expand.c - expand a buffer, given variable values * fileunix.c - manipulate file names and scan directories on UNIX * filevms.c - manipulate file names and scan directories on VMS * hash.c - simple in-memory hashing routines * headers.c - handle #includes in source files * jambase.c - compilable copy of Jambase * jamgram.y - jam grammar * lists.c - maintain lists of strings * make.c - bring a target up to date, once rules are in place * make1.c - execute command to bring targets up to date * newstr.c - string manipulation routines * option.c - command line option processing * parse.c - make and destroy parse trees as driven by the parser * regexp.c - Henry Spencer's regexp * rules.c - access to RULEs, TARGETs, and ACTIONs * scan.c - the jam yacc scanner * search.c - find a target along $(SEARCH) or $(LOCATE) * timestamp.c - get the timestamp of a file or archive member * variable.c - handle jam multi-element variables * * 05/04/94 (seiwald) - async multiprocess (-j) support * 02/08/95 (seiwald) - -n implies -d2. * 02/22/95 (seiwald) - -v for version info. * 09/11/00 (seiwald) - PATCHLEVEL folded into VERSION. */ # include "jam.h" # include "option.h" # include "patchlevel.h" /* These get various function declarations. */ # include "lists.h" # include "parse.h" # include "variable.h" # include "compile.h" # include "rules.h" # include "newstr.h" # include "scan.h" # include "timestamp.h" # include "make.h" /* Macintosh is "special" */ # ifdef OS_MAC # include <QuickDraw.h> # endif /* And UNIX for this */ # ifdef unix # include <sys/utsname.h> # endif struct globs globs = { 0, /* noexec */ 1, /* jobs */ # ifdef OS_MAC { 0, 0 }, /* debug - suppress tracing output */ # else { 0, 1 }, /* debug ... */ # endif 0, /* output commands, not run them */ 1 /* CWM. Always scanheaders by default */ } ; /* Symbols to be defined as true for use in Jambase */ static char *othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 } ; /* Known for sure: * mac needs arg_enviro * OS2 needs extern environ */ # ifdef OS_MAC # define use_environ arg_environ # ifdef MPW QDGlobals qd; # endif # endif # ifndef use_environ # define use_environ environ # if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT ) extern char **environ; # endif # endif main( int argc, char **argv, char **arg_environ ) { int n; char *s; struct option optv[N_OPTS]; char *all = "all"; int anyhow = 0; int status; # ifdef OS_MAC InitGraf(&qd.thePort); # endif argc--, argv++; #ifndef OPT_HEADER_OPTION_EXT if( ( n = getoptions( argc, argv, "d:j:f:s:t:ano:v", optv ) ) < 0 ) #else if( ( n = getoptions( argc, argv, "d:j:f:s:t:ano:vp", optv ) ) < 0 ) #endif { printf( "\nusage: jam [ options ] targets...\n\n" ); printf( "-a Build all targets, even if they are current.\n" ); printf( "-dx Set the debug level to x (0-9).\n" ); printf( "-fx Read x instead of Jambase.\n" ); printf( "-jx Run up to x shell commands concurrently.\n" ); printf( "-n Don't actually execute the updating actions.\n" ); printf( "-ox Write the updating actions to file x.\n" ); #ifdef OPT_HEADER_OPTION_EXT printf( "-p Partial build. Ignore header dependencies\n"); #endif printf( "-sx=y Set variable x=y, overriding environment.\n" ); printf( "-tx Rebuild x, even if it is up-to-date.\n" ); printf( "-v Print the version of jam and exit.\n\n" ); printf( "\n" ); /* CWM - Added help on debug levels */ printf( "The debug levels are:\n" ); printf( " 1 - show make actions when executed\n" ); printf( " 2 - show text of actions\n" ); printf( " 3 - show progress of make. Show files when bound\n" ); printf( " 4 - show execcmds()'s work\n" ); printf( " 5 - show rule invocations\n" ); printf( " 6 - show header scan, dir scan, attempts at binding\n" ); printf( " 7 - show variable setting\n" ); printf( " 8 - show variable fetches and expansions. " "show 'if' calculations\n" ); printf( " 9 - show scanner tokens. Show memory use\n" ); #ifdef OPT_GRAPH_DEBUG_EXT printf( " 10 - dump dependency graph before starting build\n" ); printf( " 11 - show changes to a targets fate in make0()\n" ); #endif printf( "\n" ); printf( " To select individual debug levels, try: -d+n -d+n...\n" ); exit( EXITBAD ); } argc -= n, argv += n; /* Version info. */ if( ( s = getoptval( optv, 'v', 0 ) ) ) { printf( "Jam/MR " ); printf( "Version %s. ", VERSION ); printf( "Copyright 1993, 2000 Christopher Seiwald. " ); printf( "%s.\n", OSMINOR ); return EXITOK; } /* Pick up interesting options */ if( ( s = getoptval( optv, 'n', 0 ) ) ) globs.noexec++, globs.debug[2] = 1; if( ( s = getoptval( optv, 'a', 0 ) ) ) anyhow++; #ifdef OPT_HEADER_OPTION_EXT if( ( s = getoptval( optv, 'p', 0 ) ) ) globs.scanheaders = 0; #endif if( ( s = getoptval( optv, 'j', 0 ) ) ) globs.jobs = atoi( s ); /* Turn on/off debugging */ for( n = 0; s = getoptval( optv, 'd', n ); n++ ) { int i; /* First -d, turn off defaults. */ if( !n ) for( i = 0; i < DEBUG_MAX; i++ ) globs.debug[i] = 0; i = atoi( s ); if( i < 0 || i >= DEBUG_MAX ) { printf( "Invalid debug level '%s'.\n", s ); continue; } /* n turns on levels 1-n */ /* +n turns on level n */ if( *s == '+' ) globs.debug[i] = 1; else while( i ) globs.debug[i--] = 1; } /* Set JAMDATE first */ { char *date; time_t clock; time( &clock ); date = newstr( ctime( &clock ) ); /* Trim newline from date */ if( strlen( date ) == 25 ) date[ 24 ] = 0; var_set( "JAMDATE", list_new( L0, newstr( date ) ), VAR_SET ); #ifdef OPT_TIME_STAMP_OUTPUT_EXT printf( "...starting...%s", ctime ( &clock ) ); #endif } /* And JAMUNAME */ # ifdef unix { struct utsname u; if( uname( &u ) >= 0 ) { var_set( "JAMUNAME", list_new( list_new( list_new( list_new( list_new( L0, newstr( u.sysname ) ), newstr( u.nodename ) ), newstr( u.release ) ), newstr( u.version ) ), newstr( u.machine ) ), VAR_SET ); } } # endif /* unix */ /* * Jam defined variables OS, OSPLAT */ var_defines( othersyms ); /* load up environment variables */ var_defines( use_environ ); /* Load up variables set on command line. */ for( n = 0; s = getoptval( optv, 's', n ); n++ ) { char *symv[2]; symv[0] = s; symv[1] = 0; var_defines( symv ); } /* Initialize builtins */ compile_builtins(); #ifdef OPT_JOB_SLOT_EXT /* Silently enforce maximum to be two digits */ /* Test against 99 rather than MAXJOBS, as the intent of */ /* this is to protect the fixed size buffers. MAXJOBS is */ /* enforced elsewhere. */ if( globs.jobs > 99 ) globs.jobs = 99; #endif #ifdef OPT_EXPORT_JOBNUM_EXT { LIST *l = 0; int i; char num[3]; /* The number could be negative if the user is trying to be nasty */ if( globs.jobs < 1 ) globs.jobs = 1; /* How many jobs are we allowed to spawn? */ sprintf( num, "%d", globs.jobs ); var_set( "JAM_NUM_JOBS", list_new( 0, newstr( num )), VAR_SET ); /* An easy test to see if there are multiple jobs */ if( globs.jobs > 1 ) var_set( "JAM_MULTI_JOBS", list_new( 0, newstr( num )), VAR_SET ); /* Create a list of the job nums. ie, -j4 -> 0 1 2 3 */ for( i = 0; i < globs.jobs; ++i ) { sprintf( num, "%d", i ); l = list_new( l, newstr( num ) ); } var_set( "JAM_JOB_LIST", l, VAR_SET ); } #endif /* Parse ruleset */ for( n = 0; s = getoptval( optv, 'f', n ); n++ ) parse_file( s ); if( !n ) parse_file( "+" ); status = yyanyerrors(); /* Manually touch -t targets */ for( n = 0; s = getoptval( optv, 't', n ); n++ ) touchtarget( s ); /* If an output file is specified, set globs.cmdout to that */ if( s = getoptval( optv, 'o', 0 ) ) { if( !( globs.cmdout = fopen( s, "w" ) ) ) { printf( "Failed to write to '%s'\n", s ); exit( EXITBAD ); } globs.noexec++; } /* Now make target */ if( !argc ) status |= make( 1, &all, anyhow ); else status |= make( argc, argv, anyhow ); /* Widely scattered cleanup */ var_done(); donerules(); donestamps(); donestr(); /* close cmdout */ if( globs.cmdout ) fclose( globs.cmdout ); #ifdef OPT_TIME_STAMP_OUTPUT_EXT { time_t clock; time( &clock ); printf( "...finished...%s", ctime ( &clock ) ); } #endif return status ? EXITBAD : EXITOK; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 1226 | Craig Mcpheeters |
Created a branch which will be used to integrate changes from Matt Armstrong's copy of Jam. |
||
//guest/craig_mcpheeters/jam/src/jam.c | |||||
#6 | 1190 | Craig Mcpheeters | Oops, the list is 0 based | ||
#5 | 1189 | Craig Mcpheeters |
Integration of changes from my A|W work branch. Added a -d11 debug mode, which outputs information on fate changes Create jam variables to show job (-jn) information, such as the number of jobs requested, whether or not there is more than one job, and a list of the job slot numbers. These can be used in a variety of ways in supporting multi-job builds Added jobs slot expansion to the action blocks, the sequence !! is replaced by the job slot the action is running in. Modified the special shell handling to include unix. It used to be that on Unix, you could create an action block which exceeded the size that execvp() could handle (perhaps only when the DynamicCommandSize option is enabled.) On NT, all non-default shells are invoked through a intermediate file. This modification does the same for unix shells. Improved the -d+10 debug level, the dependency graph. It now shows the flags on the node as well (NOUPDATE, NOTFILE, etc.) Only issue the '...skipped' messages for nodes which would have been built |
||
#4 | 1023 | Craig Mcpheeters |
Integration from //guest/craig_mcpheeters/work/jam/src/... This return incorporates all of the Alias|Wavefront extensions to Jam, into an area which is a proper branch of the Jam mainline. An integration of these files into the Jam mainline will show all of the differences. There are several extensions to Jam in this return. Look at the new file Jamfile.config for an explanation of the extensions, and how to compile them into your own copy of Jam. If you want to build a copy of Jam with all of the extensions, do this: jam -sAllOptions=1 Read the config file for more info. The extensions range from minor output tweaks and simple fixes to more major things like a header cache, serialization of output from multiple jobs, dynamic command block sizing These are all offered without warranty, etc. |
||
#3 | 784 | Craig Mcpheeters | Integration from Jam mainline | ||
#2 | 617 | Craig Mcpheeters | Integration from mainline as of @3 | ||
#1 | 616 | Craig Mcpheeters | Integration from Jam mainline, as of @2 |