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

📄 make1.c

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. * * This file is part of Jam - see jam.c for Copyright information. *//*  This file is ALSO: *  Copyright 2001-2004 David Abrahams. *  Distributed under the Boost Software License, Version 1.0. *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) *//* * 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 values, 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. */# include "jam.h"# include "lists.h"# include "parse.h"# include "assert.h"# include "variable.h"# include "rules.h"# include "headers.h"# include "search.h"# include "newstr.h"# include "make.h"# include "command.h"# include "execcmd.h"# include "compile.h"# include "output.h"# include <stdlib.h>#if defined(sun) || defined(__sun)#include <unistd.h> /* for unlink */#endifstatic CMD *make1cmds( TARGET *t );static LIST *make1list( LIST *l, TARGETS *targets, int flags );static SETTINGS *make1settings( LIST *vars );static void make1bind( TARGET *t );/* Ugly static - it's too hard to carry it through the callbacks. */static struct {	int	failed;	int	skipped;	int	total;	int	made;} counts[1] ;/* * Target state - remove recursive calls by just keeping track of state target is in */typedef struct _state{  struct _state *prev; /* previous state on stack */  TARGET *t; /* current target */  TARGET *parent; /* parent argument necessary for make1a() */#define T_STATE_MAKE1A 0 /* make1a() should be called */#define T_STATE_MAKE1ATAIL 1 /* make1atail() should be called */#define T_STATE_MAKE1B 2 /* make1b() should be called */#define T_STATE_MAKE1C 3 /* make1c() should be called */#define T_STATE_MAKE1D 4 /* make1d() should be called */  int curstate; /* current state */  int status;} state;static void make1a( state *pState);static void make1atail(state *pState);static void make1b( state *pState );static void make1c( state *pState );static void make1d( state *pState );static void make_closure(void *closure, int status, timing_info*, char *, char *);typedef struct _stack{	state *stack;} stack;static stack state_stack = { NULL };static state *state_freelist = NULL;static state *alloc_state(){	if(state_freelist != NULL)	{		state *pState;		pState = state_freelist;		state_freelist = pState->prev;		memset(pState, 0, sizeof(state));		return pState;	}	else	{		return (state *)BJAM_MALLOC(sizeof(state));	}}static void free_state(state *pState){	pState->prev = state_freelist;	state_freelist = pState;}static void clear_state_freelist(){	while(state_freelist != NULL)	{		state *pState = state_freelist;		state_freelist = state_freelist->prev;		BJAM_FREE(pState);	}}static state *current_state(stack *pStack){	return pStack->stack;}static void pop_state(stack *pStack){	state *pState;	if(pStack->stack != NULL)	{		pState = pStack->stack->prev;		free_state(pStack->stack);		pStack->stack = pState;	}}static state *push_state(stack *pStack, TARGET *t, TARGET *parent, int curstate){	state *pState;	pState = alloc_state();	pState->t = t;	pState->parent = parent;	pState->prev = pStack->stack;	pState->curstate = curstate;	pStack->stack = pState;	return pStack->stack;}/* pushes a stack onto another stack, effectively reversing the order */static void push_stack_on_stack(stack *pDest, stack *pSrc){	while(pSrc->stack != NULL)	{		state *pState;		pState = pSrc->stack;		pSrc->stack = pSrc->stack->prev;		pState->prev = pDest->stack;		pDest->stack = pState;	}}/* * make1() - execute commands to update a TARGET and all its dependents */static int intr = 0;intmake1( TARGET *t ){	state *pState;	memset( (char *)counts, 0, sizeof( *counts ) );	/* Recursively make the target and its dependents */	push_state(&state_stack, t, NULL, T_STATE_MAKE1A);	do	{		while((pState = current_state(&state_stack)) != NULL)		{            if (intr)                 pop_state(&state_stack);			switch(pState->curstate)			{			case T_STATE_MAKE1A:				make1a(pState);				break;			case T_STATE_MAKE1ATAIL:				make1atail(pState);				break;			case T_STATE_MAKE1B:				make1b(pState);				break;			case T_STATE_MAKE1C:				make1c(pState);				break;			case T_STATE_MAKE1D:				make1d(pState);				break;			default:				break;			}		}		/* Wait for any outstanding commands to finish running. */	} while( execwait() );	clear_state_freelist();	/* Talk about it */	if( counts->failed )	    printf( "...failed updating %d target%s...\n", counts->failed,		        counts->failed > 1 ? "s" : "" );	if( DEBUG_MAKE && counts->skipped )	    printf( "...skipped %d target%s...\n", counts->skipped,		        counts->skipped > 1 ? "s" : "" );	if( DEBUG_MAKE && counts->made )	    printf( "...updated %d target%s...\n", counts->made,		        counts->made > 1 ? "s" : "" );	return counts->total != counts->made;}/* * make1a() - recursively traverse target tree, calling make1b() */static voidmake1a( state *pState){    TARGET* t = pState->t;	TARGETS	*c;    TARGETS   *inc;	/* 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( pState->parent )	    switch( pState->t->progress )	{	case T_MAKE_INIT:	case T_MAKE_ACTIVE:	case T_MAKE_RUNNING:	    pState->t->parents = targetentry( pState->t->parents, pState->parent );	    pState->parent->asynccnt++;	}	if( pState->t->progress != T_MAKE_INIT )	{		pop_state(&state_stack);		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. */	pState->t->asynccnt = 1;    /* Add header node that was created during building process. */    inc = 0;    for (c = t->depends; c; c = c->next) {                if (c->target->rescanned && c->target->includes)            inc = targetentry(inc, c->target->includes);               }    t->depends = targetchain(t->depends, inc);	/* against circular dependency. */	pState->t->progress = T_MAKE_ONSTACK;	{		stack temp_stack = { NULL };        for( c = t->depends; c && !intr; c = c->next )                        push_state(&temp_stack, c->target, pState->t, T_STATE_MAKE1A);		/* using stacks reverses the order of execution. Reverse it back */		push_stack_on_stack(&state_stack, &temp_stack);	}	pState->curstate = T_STATE_MAKE1ATAIL;}static void make1atail(state *pState){	pState->t->progress = T_MAKE_ACTIVE;	/* Now that all dependents have bumped asynccnt, we now allow */	/* decrement our reference to asynccnt. */ 	pState->curstate = T_STATE_MAKE1B;}/* * make1b() - dependents of target built, now build target with make1c() */static voidmake1b( state *pState ){    TARGET      *t = pState->t;    TARGETS     *c;    TARGET      *failed = 0;    char* failed_name = "dependencies";    /* If any dependents are still outstanding, wait until they */    /* call make1b() to signal their completion. */    if( --(pState->t->asynccnt) )	{		pop_state(&state_stack);		return;	}        /* Try to aquire a semaphore. If it's locked, wait until the target       that locked it is build and signals completition. */#ifdef OPT_SEMAPHORE	if( t->semaphore && t->semaphore->asynccnt )	{        /* Append 't' to the list of targets waiting on semaphore. */	    t->semaphore->parents = targetentry( t->semaphore->parents, t );	    t->asynccnt++;	    if( DEBUG_EXECCMD )		printf( "SEM: %s is busy, delaying launch of %s\n",			t->semaphore->name, t->name);		pop_state(&state_stack);	    return;	}#endif    /* 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 && !( c->target->flags & T_FLAG_NOCARE ))

⌨️ 快捷键说明

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