📄 make.c
字号:
/* If LEAVES has been applied, we only heed the timestamps of */
/* the leaf source nodes. */
leaf = max( leaf, c->target->leaf );
if( t->flags & T_FLAG_LEAVES )
{
last = leaf;
continue;
}
last = max( last, c->target->time );
fate = max( fate, c->target->fate );
#ifdef OPT_GRAPH_DEBUG_EXT
if( DEBUG_FATE )
if( fate < c->target->fate )
printf( "fate change %s from %s to %s by dependency %s\n",
t->name,
target_fate[fate], target_fate[c->target->fate],
c->target->name);
#endif
}
/* Step 4b: pick up included headers time */
/*
* If a header is newer than a temp source that includes it,
* the temp source will need building.
*/
hlast = t->includes ? t->includes->time : 0;
/* Step 4c: handle NOUPDATE oddity */
/*
* If a NOUPDATE file exists, make dependents eternally old.
* Don't inherit our fate from our dependents. Decide fate
* based only upon other flags and our binding (done later).
*/
if( t->flags & T_FLAG_NOUPDATE )
{
#ifdef OPT_GRAPH_DEBUG_EXT
if( DEBUG_FATE )
if( fate != T_FATE_STABLE )
printf( "fate change %s back to stable, NOUPDATE.\n",
t->name);
#endif
last = 0;
t->time = 0;
/*
* Don't inherit our fate from our dependents. Decide fate
* based only upon other flags and our binding (done later).
*/
fate = T_FATE_STABLE;
}
/* Step 4d: determine fate: rebuild target or what? */
/*
In English:
If can't find or make child, can't make target.
If children changed, make target.
If target missing, make it.
If children newer, make target.
If temp's children newer than parent, make temp.
If temp's headers newer than parent, make temp.
If deliberately touched, make it.
If up-to-date temp file present, use it.
If target newer than non-notfile parent, mark target newer.
Otherwise, stable!
Note this block runs from least to most stable:
as we make it further down the list, the target's
fate is getting stabler.
*/
#ifdef OPT_GRAPH_DEBUG_EXT
savedFate = fate;
oldTimeStamp = 0;
#endif
if( fate >= T_FATE_BROKEN )
{
fate = T_FATE_CANTMAKE;
}
else if( fate >= T_FATE_SPOIL )
{
fate = T_FATE_UPDATE;
}
else if( t->binding == T_BIND_MISSING )
{
fate = T_FATE_MISSING;
}
else if( t->binding == T_BIND_EXISTS && last > t->time )
{
#ifdef OPT_GRAPH_DEBUG_EXT
oldTimeStamp = 1;
#endif
fate = T_FATE_OUTDATED;
}
else if( t->binding == T_BIND_PARENTS && last > p->time )
{
#ifdef OPT_GRAPH_DEBUG_EXT
oldTimeStamp = 1;
#endif
fate = T_FATE_NEEDTMP;
}
else if( t->binding == T_BIND_PARENTS && hlast > p->time )
{
fate = T_FATE_NEEDTMP;
}
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 && p &&
p->binding != T_BIND_UNBOUND && t->time > p->time )
{
#ifdef OPT_GRAPH_DEBUG_EXT
oldTimeStamp = 1;
#endif
fate = T_FATE_NEWER;
}
else
{
fate = T_FATE_STABLE;
}
#ifdef OPT_GRAPH_DEBUG_EXT
if( DEBUG_FATE && fate != savedFate )
if( savedFate == T_FATE_STABLE )
printf( "fate change %s set to %s%s\n",
t->name, target_fate[fate],
oldTimeStamp ? " (by timestamp)" : "" );
else
printf( "fate change %s from %s to %s%s\n",
t->name, target_fate[savedFate], target_fate[fate],
oldTimeStamp ? " (by timestamp)" : "" );
#endif
/* Step 4e: handle missing files */
/* If it's missing and there are no actions to create it, boom. */
/* If we can't make a target we don't care about, 'sokay */
/* We could insist that there are updating actions for all missing */
/* files, but if they have dependents we just pretend it's NOTFILE. */
if( fate == T_FATE_MISSING && !t->actions && !t->depends )
{
if( t->flags & T_FLAG_NOCARE )
{
#ifdef OPT_GRAPH_DEBUG_EXT
if( DEBUG_FATE )
printf( "fate change %s to STABLE from %s, "
"no actions, no dependents and don't care\n",
t->name, target_fate[fate]);
#endif
fate = T_FATE_STABLE;
}
else
{
printf( "don't know how to make %s\n", t->name );
fate = T_FATE_CANTFIND;
}
}
/* Step 4f: propagate dependents' time & fate. */
/* Set leaf time to be our time only if this is a leaf. */
t->time = max( t->time, last );
t->leaf = leaf ? leaf : t->time ;
/* This target's fate may have been updated by virtue of following
* some target's rebuilds list, so only allow it to be increased
* to the fate we've calculated. Otherwise, grab its new fate.
*/
if (fate > t->fate)
t->fate = fate;
else
fate = t->fate;
/* Step 4g: if this target needs to be built, force rebuild
* everything in this target's rebuilds list */
if (fate >= T_FATE_BUILD && fate < T_FATE_BROKEN)
force_rebuilds(t);
/*
* Step 5: sort dependents by their update time.
*/
if( globs.newestfirst )
t->depends = make0sort( t->depends );
/*
* Step 6: a little harmless tabulating for tracing purposes
*/
/* Don't count or report interal includes nodes. */
if( t->flags & T_FLAG_INTERNAL )
return;
if (counts) {
#ifdef OPT_IMPROVED_PATIENCE_EXT
++counts->targets;
#else
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 && p && t->time > p->time )
flag = "*";
if( DEBUG_MAKEPROG )
printf( "made%s\t%s\t%s%s\n",
flag, target_fate[ t->fate ],
spaces( depth ), t->name );
/* We don't have DEBUG_CAUSES.
if( DEBUG_CAUSES &&
t->fate >= T_FATE_NEWER &&
t->fate <= T_FATE_MISSING )
printf( "%s %s\n", target_fate[ t->fate ], t->name );
*/
}
#ifdef OPT_GRAPH_DEBUG_EXT
static const char* target_name( TARGET* t )
{
static char buf[1000];
if (t->flags & T_FLAG_INTERNAL) {
sprintf(buf, "%s (internal node)", t->name);
return buf;
} else {
return t->name;
}
}
/*
* dependGraphOutput() - output the DG after make0 has run
*/
static void
dependGraphOutput( TARGET *t, int depth )
{
TARGETS *c;
if ( (t->flags & T_FLAG_VISITED) != 0
|| !t->name
|| !t->boundname)
return;
t->flags |= T_FLAG_VISITED;
switch (t->fate)
{
case T_FATE_TOUCHED:
case T_FATE_MISSING:
case T_FATE_OUTDATED:
case T_FATE_UPDATE:
printf( "->%s%2d Name: %s\n", spaces(depth), depth, target_name(t) );
break;
default:
printf( " %s%2d Name: %s\n", spaces(depth), depth, target_name(t) );
break;
}
if( strcmp (t->name, t->boundname) )
{
printf( " %s Loc: %s\n", spaces(depth), t->boundname );
}
switch( t->fate )
{
case T_FATE_STABLE:
printf( " %s : Stable\n", spaces(depth) );
break;
case T_FATE_NEWER:
printf( " %s : Newer\n", spaces(depth) );
break;
case T_FATE_ISTMP:
printf( " %s : Up to date temp file\n", spaces(depth) );
case T_FATE_NEEDTMP:
printf( " %s : Temporary file, to be updated\n", spaces(depth) );
break;
case T_FATE_TOUCHED:
printf( " %s : Been touched, updating it\n", spaces(depth) );
break;
case T_FATE_MISSING:
printf( " %s : Missing, creating it\n", spaces(depth) );
break;
case T_FATE_OUTDATED:
printf( " %s : Outdated, updating it\n", spaces(depth) );
break;
case T_FATE_REBUILD:
printf( " %s : Rebuild, Updating it\n", spaces(depth) );
break;
case T_FATE_UPDATE:
printf( " %s : Updating it\n", spaces(depth) );
break;
case T_FATE_CANTFIND:
printf( " %s : Can't find it\n", spaces(depth) );
break;
case T_FATE_CANTMAKE:
printf( " %s : Can't make it\n", spaces(depth) );
break;
}
if( t->flags & ~T_FLAG_VISITED )
{
printf( " %s : ", spaces(depth) );
if( t->flags & T_FLAG_TEMP ) printf ("TEMPORARY ");
if( t->flags & T_FLAG_NOCARE ) printf ("NOCARE ");
if( t->flags & T_FLAG_NOTFILE ) printf ("NOTFILE ");
if( t->flags & T_FLAG_TOUCHED ) printf ("TOUCHED ");
if( t->flags & T_FLAG_LEAVES ) printf ("LEAVES ");
if( t->flags & T_FLAG_NOUPDATE ) printf ("NOUPDATE ");
printf( "\n" );
}
for( c = t->depends; c; c = c->next )
{
printf( " %s : Depends on %s (%s)", spaces(depth),
target_name(c->target), target_fate[ c->target->fate ] );
if (c->target->time == t->time)
printf( " (max time)");
printf("\n");
}
for( c = t->depends; c; c = c->next )
{
dependGraphOutput( c->target, depth + 1 );
}
}
#endif
/*
* make0sort() - reorder TARGETS chain by their time (newest to oldest)
*/
static TARGETS *
make0sort( TARGETS *chain )
{
TARGETS *result = 0;
/* We walk chain, taking each item and inserting it on the */
/* sorted result, with newest items at the front. This involves */
/* updating each TARGETS' c->next and c->tail. Note that we */
/* make c->tail a valid prev pointer for every entry. Normally, */
/* it is only valid at the head, where prev == tail. Note also */
/* that while tail is a loop, next ends at the end of the chain. */
/* Walk current target list */
while( chain )
{
TARGETS *c = chain;
TARGETS *s = result;
chain = chain->next;
/* Find point s in result for c */
while( s && s->target->time > c->target->time )
s = s->next;
/* Insert c in front of s (might be 0). */
/* Don't even think of deciphering this. */
c->next = s; /* good even if s = 0 */
if( result == s ) result = c; /* new head of chain? */
if( !s ) s = result; /* wrap to ensure a next */
if( result != c ) s->tail->next = c; /* not head? be prev's next */
c->tail = s->tail; /* take on next's prev */
s->tail = c; /* make next's prev us */
}
return result;
}
static LIST *targets_to_update_ = 0;
void mark_target_for_updating(char *target)
{
targets_to_update_ = list_new( targets_to_update_, target );
}
LIST *targets_to_update()
{
return targets_to_update_;
}
void clear_targets_to_update()
{
list_free(targets_to_update_);
targets_to_update_ = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -