# include "jam.h"
# include "lists.h"
# include "parse.h"
# include "variable.h"
# include "rules.h"
# include "search.h"
# include "newstr.h"
# include "make.h"
# include "headers.h"
# include "command.h"
static void make0();
# ifndef max
# define max( a,b ) ((a)>(b)?(a):(b))
# endif
typedef struct {
int temp;
int updating;
int cantfind;
int cantmake;
int targets;
int made;
} COUNTS ;
static char *target_fate[] =
{
"init",
"making",
"stable",
"newer",
"temp",
"touched",
"missing",
"old",
"update",
"nofind",
"nomake"
} ;
static char *target_bind[] =
{
"unbound",
"missing",
"parents",
"exists",
} ;
# define spaces(x) ( " " + 16 - ( x > 16 ? 16 : x ) )
int
make( n_targets, targets, anyhow )
int n_targets;
char **targets;
int anyhow;
{
int i;
COUNTS counts[1];
int status = 0;
memset( (char *)counts, 0, sizeof( *counts ) );
for( i = 0; i < n_targets; i++ )
{
TARGET *t = bindtarget( targets[i] );
make0( t, T_BIND_UNBOUND, (time_t)0, 0, counts, anyhow );
}
#ifdef APPLE_EXTENSIONS
if( globs.enable_timings )
{
printf( " headers scanned: %d time spent scanning: %.2f\n",
globs.headers_scanned, globs.header_scanning_time );
append_timing_entry( globs.timing_entry, 0, "jam internals: dependency analysis -- make0()", NULL, NULL);
globs.timing_entry = create_timing_entry();
append_timing_entry( globs.timing_entry, 0, "BuildPhase", NULL, "<jam setup>" );
}
#endif
#ifdef APPLE_EXTENSIONS
if( PARSABLE_OUTPUT )
pbx_printf( "JBGN", "%i %i %i\n", counts->updating, counts->cantfind, counts->cantmake );
globs.num_targets_to_update = counts->updating;
#endif
#ifndef APPLE_EXTENSIONS
if( DEBUG_MAKE )
{
if( counts->targets )
printf( "...found %d target(s)...\n", counts->targets );
if( counts->temp )
printf( "...using %d temp target(s)...\n", counts->temp );
if( counts->updating )
printf( "...updating %d target(s)...\n", counts->updating );
if( counts->cantfind )
printf( "...can't find %d target(s)...\n", counts->cantfind );
if( counts->cantmake )
printf( "...can't make %d target(s)...\n", counts->cantmake );
}
#endif
#ifdef APPLE_EXTENSIONS
if (counts->cantfind != 0 && !globs.ignore) {
exit(EXITBAD);
}
#endif
status = counts->cantfind || counts->cantmake;
for( i = 0; i < n_targets; i++ )
status |= make1( bindtarget( targets[i] ) );
return status;
}
static void
make0( t, pbinding, ptime, depth, counts, anyhow )
TARGET *t;
int pbinding;
time_t ptime;
int depth;
COUNTS *counts;
int anyhow;
{
TARGETS *c;
int fate, hfate;
time_t last, leaf, hlast, hleaf;
char *flag = "";
if( DEBUG_MAKEPROG )
printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
switch( t->fate )
{
case T_FATE_MAKING:
printf( "warning: %s depends on itself\n", t->name );
return;
default:
return;
case T_FATE_INIT:
break;
}
t->fate = T_FATE_MAKING;
pushsettings( t->settings );
if( t->binding == T_BIND_UNBOUND && !( t->flags & T_FLAG_NOTFILE ) )
{
t->boundname = search( t->name, &t->time );
t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
}
if( t->binding == T_BIND_MISSING && t->flags & T_FLAG_TEMP && ptime )
{
t->time = ptime;
t->binding = t->time ? T_BIND_PARENTS : T_BIND_MISSING;
}
if( t->binding == T_BIND_EXISTS )
headers( t );
popsettings( t->settings );
if( DEBUG_BIND )
{
if( strcmp( t->name, t->boundname ) )
{
printf( "bind\t--\t%s%s: %s\n",
spaces( depth ), t->name, t->boundname );
}
switch( t->binding )
{
case T_BIND_UNBOUND:
case T_BIND_MISSING:
case T_BIND_PARENTS:
printf( "time\t--\t%s%s: %s\n",
spaces( depth ), t->name, target_bind[ (int) t->binding ] );
break;
case T_BIND_EXISTS:
printf( "time\t--\t%s%s: %s",
spaces( depth ), t->name, ctime( &t->time ) );
break;
}
}
last = 0;
leaf = 0;
fate = T_FATE_STABLE;
for( c = t->deps[ T_DEPS_DEPENDS ]; c; c = c->next )
{
make0( c->target, t->binding, t->time, depth + 1, counts, anyhow );
leaf = max( leaf, c->target->leaf );
leaf = max( leaf, c->target->hleaf );
if( t->flags & T_FLAG_LEAVES )
{
last = leaf;
continue;
}
last = max( last, c->target->time );
last = max( last, c->target->htime );
fate = max( fate, c->target->fate );
fate = max( fate, c->target->hfate );
}
if( t->flags & T_FLAG_NOUPDATE )
{
last = 0;
t->time = 0;
}
if( fate >= T_FATE_BROKEN )
{
fate = T_FATE_CANTMAKE;
}
else if( t->binding == T_BIND_MISSING )
{
fate = T_FATE_MISSING;
}
else if ( fate >= T_FATE_SPOIL && (t->flags & T_FLAG_NOUPDATE) )
{
fate = T_FATE_STABLE;
}
else if ( fate >= T_FATE_SPOIL )
{
fate = T_FATE_UPDATE;
}
else if( t->binding == T_BIND_EXISTS && last > t->time )
{
fate = T_FATE_OUTDATED;
}
else if( t->binding == T_BIND_PARENTS && last > t->time )
{
fate = T_FATE_OUTDATED;
}
else if( t->flags & T_FLAG_TOUCHED )
{
fate = T_FATE_TOUCHED;
}
else if( anyhow && !( t->flags & T_FLAG_NOUPDATE ) )
{
fate = T_FATE_TOUCHED;
}
else if( t->binding == T_BIND_EXISTS && t->flags & T_FLAG_TEMP )
{
fate = T_FATE_ISTMP;
}
else if( t->binding == T_BIND_EXISTS && pbinding == T_BIND_MISSING )
{
fate = T_FATE_NEWER;
}
else if( t->binding == T_BIND_EXISTS && ptime && t->time > ptime )
{
fate = T_FATE_NEWER;
}
else if( fate == T_FATE_NEWER )
{
fate = T_FATE_STABLE;
}
if( fate == T_FATE_MISSING &&
!t->actions &&
!t->deps[ T_DEPS_DEPENDS ] )
{
if( t->flags & T_FLAG_NOCARE )
{
fate = T_FATE_STABLE;
}
else
{
#ifdef APPLE_EXTENSIONS
if (PARSABLE_OUTPUT) {
pbx_printf( "JERR", "Missing file or directory: %s\n", t->name );
}
else {
printf( "Missing file or directory: %s\n", t->name );
}
#else
printf( "don't know how to make %s\n", t->name );
#endif
fate = T_FATE_CANTFIND;
}
}
t->time = max( t->time, last );
t->leaf = leaf ? leaf : t->time ;
t->fate = fate;
hlast = 0;
hleaf = 0;
hfate = T_FATE_STABLE;
for( c = t->deps[ T_DEPS_INCLUDES ]; c; c = c->next )
{
make0( c->target, pbinding, ptime, depth + 1, counts, anyhow );
hlast = max( hlast, c->target->time );
hlast = max( hlast, c->target->htime );
hleaf = max( hleaf, c->target->leaf );
hleaf = max( hleaf, c->target->hleaf );
hfate = max( hfate, c->target->fate );
hfate = max( hfate, c->target->hfate );
}
t->htime = hlast;
t->hleaf = hleaf ? hleaf : t->htime;
t->hfate = hfate;
#ifndef APPLE_EXTENSIONS
if( !( ++counts->targets % 1000 ) && DEBUG_MAKE )
printf( "...patience...\n" );
#endif
if( fate == T_FATE_ISTMP )
counts->temp++;
else if( fate == T_FATE_CANTFIND )
counts->cantfind++;
else if( fate == T_FATE_CANTMAKE && t->actions )
counts->cantmake++;
else if( fate >= T_FATE_BUILD && fate < T_FATE_BROKEN && t->actions )
counts->updating++;
if( !( t->flags & T_FLAG_NOTFILE ) && fate >= T_FATE_SPOIL )
flag = "+";
else if( t->binding == T_BIND_EXISTS && ptime && t->time > ptime )
flag = "*";
if( DEBUG_MAKEPROG )
printf( "made%s\t%s\t%s%s\n",
flag, target_fate[ (int) t->fate ],
spaces( depth ), t->name );
}