⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 make1.c

📁 jam源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. * * This file is part of Jam - see jam.c for Copyright information. *//* * make1.c - execute command to bring targets up to date * * This module contains make1(), the entry point called by make() to  * recursively decend the dependency graph executing update actions as * marked by make0(). * * External routines: * *	make1() - execute commands to update a TARGET and all its dependents * * Internal routines, the recursive/asynchronous command executors: * *	make1a() - recursively traverse target tree, calling make1b() *	make1b() - dependents of target built, now build target with make1c() *	make1c() - launch target's next command, call make1b() when done *	make1d() - handle command execution completion and call back make1c() * * Internal support routines: * *	make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc *	make1list() - turn a list of targets into a LIST, for $(<) and $(>) * 	make1settings() - for vars that get bound, build up replacement lists * 	make1bind() - bind targets that weren't bound in dependency analysis * * 04/16/94 (seiwald) - Split from make.c. * 04/21/94 (seiwald) - Handle empty "updated" actions. * 05/04/94 (seiwald) - async multiprocess (-j) support * 06/01/94 (seiwald) - new 'actions existing' does existing sources * 12/20/94 (seiwald) - NOTIME renamed NOTFILE. * 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets. * 01/22/94 (seiwald) - pass per-target JAMSHELL down to execcmd(). * 02/28/95 (seiwald) - Handle empty "existing" actions. * 03/10/95 (seiwald) - Fancy counts. * 02/07/01 (seiwald) - Fix jam -d0 return status. * 01/21/02 (seiwald) - new -q to quit quickly on build failure * 02/28/02 (seiwald) - don't delete 'actions updated' targets on failure * 02/28/02 (seiwald) - merge EXEC_xxx flags in with RULE_xxx  * 07/17/02 (seiwald) - TEMPORARY sources for headers now get built * 09/23/02 (seiwald) - "...using temp..." only displayed on -da now. * 10/22/02 (seiwald) - list_new() now does its own newstr()/copystr() * 11/04/02 (seiwald) - const-ing for string literals * 12/03/02 (seiwald) - fix odd includes support by grafting them onto depends */# 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 "command.h"# include "execcmd.h"static void make1a( TARGET *t, TARGET *parent );static void make1b( TARGET *t );static void make1c( TARGET *t );static void make1d( void *closure, int status );static CMD *make1cmds( ACTIONS *a0 );static LIST *make1list( LIST *l, TARGETS *targets, int flags );static SETTINGS *make1settings( LIST *vars );static void make1bind( TARGET *t, int warn );/* Ugly static - it's too hard to carry it through the callbacks. */static struct {	int	failed;	int	skipped;	int	total;	int	made;} counts[1] ;/* * make1() - execute commands to update a TARGET and all its dependents */static int intr = 0;intmake1( TARGET *t ){	memset( (char *)counts, 0, sizeof( *counts ) );	/* Recursively make the target and its dependents */	make1a( t, (TARGET *)0 );	/* Wait for any outstanding commands to finish running. */	while( execwait() )	    ;	/* Talk about it */	if( DEBUG_MAKE && counts->failed )	    printf( "...failed updating %d target(s)...\n", counts->failed );	if( DEBUG_MAKE && counts->skipped )	    printf( "...skipped %d target(s)...\n", counts->skipped );	if( DEBUG_MAKE && counts->made )	    printf( "...updated %d target(s)...\n", counts->made );	return counts->total != counts->made;}/* * make1a() - recursively traverse target tree, calling make1b() */static voidmake1a( 	TARGET	*t,	TARGET	*parent ){	TARGETS	*c;	/* If the parent is the first to try to build this target */	/* or this target is in the make1c() quagmire, arrange for the */	/* parent to be notified when this target is built. */	if( parent )	    switch( t->progress )	{	case T_MAKE_INIT:	case T_MAKE_ACTIVE:	case T_MAKE_RUNNING:	    t->parents = targetentry( t->parents, parent );	    parent->asynccnt++;	}	if( t->progress != T_MAKE_INIT )	    return;	/* Asynccnt counts the dependents preventing this target from */	/* proceeding to make1b() for actual building.  We start off with */	/* a count of 1 to prevent anything from happening until we can */	/* call all dependents.  This 1 is accounted for when we call */	/* make1b() ourselves, below. */	t->asynccnt = 1;	/* Recurse on our dependents, manipulating progress to guard */	/* against circular dependency. */	t->progress = T_MAKE_ONSTACK;	for( c = t->depends; c && !intr; c = c->next )	    make1a( c->target, t );	t->progress = T_MAKE_ACTIVE;	/* Now that all dependents have bumped asynccnt, we now allow */	/* decrement our reference to asynccnt. */ 	make1b( t );}/* * make1b() - dependents of target built, now build target with make1c() */static voidmake1b( TARGET *t ){	TARGETS	*c;	const char *failed = "dependents";	/* If any dependents are still outstanding, wait until they */	/* call make1b() to signal their completion. */	if( --t->asynccnt )	    return;	/* Now ready to build target 't'... if dependents built ok. */	/* Collect status from dependents */	for( c = t->depends; c; c = c->next )	    if( c->target->status > t->status )	{	    failed = c->target->name;	    t->status = c->target->status;	}	/* If actions on deps have failed, bail. */	/* Otherwise, execute all actions to make target */	if( t->status == EXEC_CMD_FAIL && t->actions )	{	    ++counts->skipped;	    printf( "...skipped %s for lack of %s...\n", t->name, failed );	}	if( t->status == EXEC_CMD_OK )	    switch( t->fate )	{	case T_FATE_INIT:	case T_FATE_MAKING:	    /* shouldn't happen */	case T_FATE_STABLE:	case T_FATE_NEWER:	    break;	case T_FATE_CANTFIND:	case T_FATE_CANTMAKE:	    t->status = EXEC_CMD_FAIL;	    break;	case T_FATE_ISTMP:	    if( DEBUG_MAKEQ )		printf( "...using %s...\n", t->name );	    break;	case T_FATE_TOUCHED:	case T_FATE_MISSING:	case T_FATE_NEEDTMP:	case T_FATE_OUTDATED:	case T_FATE_UPDATE:	    /* Set "on target" vars, build actions, unset vars */	    /* Set "progress" so that make1c() counts this target among */	    /* the successes/failures. */	    if( t->actions )	    {		++counts->total;		if( DEBUG_MAKE && !( counts->total % 100 ) )		    printf( "...on %dth target...\n", counts->total );		pushsettings( t->settings );		t->cmds = (char *)make1cmds( t->actions );		popsettings( t->settings );		t->progress = T_MAKE_RUNNING;	    }	    break;	}	/* Call make1c() to begin the execution of the chain of commands */	/* needed to build target.  If we're not going to build target */	/* (because of dependency failures or because no commands need to */	/* be run) the chain will be empty and make1c() will directly */	/* signal the completion of target. */	make1c( t );}/* * make1c() - launch target's next command, call make1b() when done */static voidmake1c( TARGET *t ){	CMD	*cmd = (CMD *)t->cmds;	/* If there are (more) commands to run to build this target */	/* (and we haven't hit an error running earlier comands) we */	/* launch the command with execcmd(). */		/* If there are no more commands to run, we collect the status */	/* from all the actions then report our completion to all the */	/* parents. */	if( cmd && t->status == EXEC_CMD_OK )	{	    if( DEBUG_MAKE )		if( DEBUG_MAKEQ || ! ( cmd->rule->flags & RULE_QUIETLY ) )	    {		printf( "%s ", cmd->rule->name );		list_print( lol_get( &cmd->args, 0 ) );		printf( "\n" );	    }	    if( DEBUG_EXEC )		printf( "%s\n", cmd->buf );	    if( globs.cmdout )		fprintf( globs.cmdout, "%s", cmd->buf );	    if( globs.noexec )	    {		make1d( t, EXEC_CMD_OK );	    } 	    else	    {		fflush( stdout );		execcmd( cmd->buf, make1d, t, cmd->shell );	    }	}	else	{	    TARGETS	*c;	    ACTIONS	*actions;	    /* Collect status from actions, and distribute it as well */	    for( actions = t->actions; actions; actions = actions->next )		if( actions->action->status > t->status )		    t->status = actions->action->status;	    for( actions = t->actions; actions; actions = actions->next )		if( t->status > actions->action->status )		    actions->action->status = t->status;	    /* Tally success/failure for those we tried to update. */	    if( t->progress == T_MAKE_RUNNING )		switch( t->status )	    {	    case EXEC_CMD_OK:		++counts->made;		break;	    case EXEC_CMD_FAIL:		++counts->failed;		break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -