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

📄 make.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1988, 1989, 1990, 1993 *	The Regents of the University of California.  All rights reserved. * Copyright (c) 1989 by Berkeley Softworks * All rights reserved. * * This code is derived from software contributed to Berkeley by * Adam de Boor. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)make.c	8.1 (Berkeley) 6/6/93";#endif /* not lint *//*- * make.c -- *	The functions which perform the examination of targets and *	their suitability for creation * * Interface: *	Make_Run 	    	Initialize things for the module and recreate *	    	  	    	whatever needs recreating. Returns TRUE if *	    	    	    	work was (or would have been) done and FALSE *	    	  	    	otherwise. * *	Make_Update	    	Update all parents of a given child. Performs *	    	  	    	various bookkeeping chores like the updating *	    	  	    	of the cmtime field of the parent, filling *	    	  	    	of the IMPSRC context variable, etc. It will *	    	  	    	place the parent on the toBeMade queue if it *	    	  	    	should be. * *	Make_TimeStamp	    	Function to set the parent's cmtime field *	    	  	    	based on a child's modification time. * *	Make_DoAllVar	    	Set up the various local variables for a *	    	  	    	target, including the .ALLSRC variable, making *	    	  	    	sure that any variable that needs to exist *	    	  	    	at the very least has the empty value. * *	Make_OODate 	    	Determine if a target is out-of-date. * *	Make_HandleUse	    	See if a child is a .USE node for a parent *				and perform the .USE actions if so. */#include    "make.h"#include    "hash.h"#include    "dir.h"#include    "job.h"static Lst     	toBeMade;	/* The current fringe of the graph. These				 * are nodes which await examination by				 * MakeOODate. It is added to by				 * Make_Update and subtracted from by				 * MakeStartJobs */static int  	numNodes;   	/* Number of nodes to be processed. If this				 * is non-zero when Job_Empty() returns				 * TRUE, there's a cycle in the graph */static int MakeAddChild __P((GNode *, Lst));static int MakeAddAllSrc __P((GNode *, GNode *));static Boolean MakeStartJobs __P((void));static int MakePrintStatus __P((GNode *, Boolean));/*- *----------------------------------------------------------------------- * Make_TimeStamp -- *	Set the cmtime field of a parent node based on the mtime stamp in its *	child. Called from MakeOODate via Lst_ForEach.  * * Results: *	Always returns 0.  * * Side Effects: *	The cmtime of the parent node will be changed if the mtime *	field of the child is greater than it. *----------------------------------------------------------------------- */intMake_TimeStamp (pgn, cgn)    register GNode *pgn;	/* the current parent */    register GNode *cgn;	/* the child we've just examined */{    if (cgn->mtime > pgn->cmtime) {	pgn->cmtime = cgn->mtime;    }    return (0);}/*- *----------------------------------------------------------------------- * Make_OODate -- *	See if a given node is out of date with respect to its sources. *	Used by Make_Run when deciding which nodes to place on the *	toBeMade queue initially and by Make_Update to screen out USE and *	EXEC nodes. In the latter case, however, any other sort of node *	must be considered out-of-date since at least one of its children *	will have been recreated. * * Results: *	TRUE if the node is out of date. FALSE otherwise.  * * Side Effects: *	The mtime field of the node and the cmtime field of its parents *	will/may be changed. *----------------------------------------------------------------------- */BooleanMake_OODate (gn)    register GNode *gn;	      /* the node to check */{    Boolean         oodate;    /*     * Certain types of targets needn't even be sought as their datedness     * doesn't depend on their modification time...     */    if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) {	(void) Dir_MTime (gn);	if (DEBUG(MAKE)) {	    if (gn->mtime != 0) {		printf ("modified %s...", Targ_FmtTime(gn->mtime));	    } else {		printf ("non-existent...");	    }	}    }    /*     * A target is remade in one of the following circumstances:     *	its modification time is smaller than that of its youngest child     *	    and it would actually be run (has commands or type OP_NOP)     *	it's the object of a force operator     *	it has no children, was on the lhs of an operator and doesn't exist     *	    already.     *     * Libraries are only considered out-of-date if the archive module says     * they are.     *     * These weird rules are brought to you by Backward-Compatability and     * the strange people who wrote 'Make'.     */    if (gn->type & OP_USE) {	/*	 * If the node is a USE node it is *never* out of date	 * no matter *what*.	 */	if (DEBUG(MAKE)) {	    printf(".USE node...");	}	oodate = FALSE;    } else if (gn->type & OP_LIB) {	if (DEBUG(MAKE)) {	    printf("library...");	}	oodate = Arch_LibOODate (gn);    } else if (gn->type & OP_JOIN) {	/*	 * A target with the .JOIN attribute is only considered	 * out-of-date if any of its children was out-of-date.	 */	if (DEBUG(MAKE)) {	    printf(".JOIN node...");	}	oodate = gn->childMade;    } else if (gn->type & (OP_FORCE|OP_EXEC)) {	/*	 * A node which is the object of the force (!) operator or which has	 * the .EXEC attribute is always considered out-of-date.	 */	if (DEBUG(MAKE)) {	    if (gn->type & OP_FORCE) {		printf("! operator...");	    } else {		printf(".EXEC node...");	    }	}	oodate = TRUE;    } else if ((gn->mtime < gn->cmtime) ||	       ((gn->cmtime == 0) &&		((gn->mtime==0) || (gn->type & OP_DOUBLEDEP))))    {	/*	 * A node whose modification time is less than that of its	 * youngest child or that has no children (cmtime == 0) and	 * either doesn't exist (mtime == 0) or was the object of a	 * :: operator is out-of-date. Why? Because that's the way Make does	 * it.	 */	if (DEBUG(MAKE)) {	    if (gn->mtime < gn->cmtime) {		printf("modified before source...");	    } else if (gn->mtime == 0) {		printf("non-existent and no sources...");	    } else {		printf(":: operator and no sources...");	    }	}	oodate = TRUE;    } else {#if 0	/* WHY? */	if (DEBUG(MAKE)) {	    printf("source %smade...", gn->childMade ? "" : "not ");	}	oodate = gn->childMade;#else	oodate = FALSE;#endif /* 0 */    }    /*     * If the target isn't out-of-date, the parents need to know its     * modification time. Note that targets that appear to be out-of-date     * but aren't, because they have no commands and aren't of type OP_NOP,     * have their mtime stay below their children's mtime to keep parents from     * thinking they're out-of-date.     */    if (!oodate) {	Lst_ForEach (gn->parents, Make_TimeStamp, (ClientData)gn);    }    return (oodate);}/*- *----------------------------------------------------------------------- * MakeAddChild  -- *	Function used by Make_Run to add a child to the list l. *	It will only add the child if its make field is FALSE. * * Results: *	Always returns 0 * * Side Effects: *	The given list is extended *----------------------------------------------------------------------- */static intMakeAddChild (gn, l)    GNode          *gn;		/* the node to add */    Lst            l;		/* the list to which to add it */{    if (!gn->make && !(gn->type & OP_USE)) {	(void)Lst_EnQueue (l, (ClientData)gn);    }    return (0);}/*- *----------------------------------------------------------------------- * Make_HandleUse -- *	Function called by Make_Run and SuffApplyTransform on the downward *	pass to handle .USE and transformation nodes. A callback function *	for Lst_ForEach, it implements the .USE and transformation *	functionality by copying the node's commands, type flags *	and children to the parent node. Should be called before the *	children are enqueued to be looked at by MakeAddChild. * *	A .USE node is much like an explicit transformation rule, except *	its commands are always added to the target node, even if the *	target already has commands. * * Results: *	returns 0. * * Side Effects: *	Children and commands may be added to the parent and the parent's *	type may be changed. * *----------------------------------------------------------------------- */intMake_HandleUse (cgn, pgn)    register GNode	*cgn;	/* The .USE node */    register GNode   	*pgn;	/* The target of the .USE node */{    register GNode	*gn;	/* A child of the .USE node */    register LstNode	ln; 	/* An element in the children list */    if (cgn->type & (OP_USE|OP_TRANSFORM)) {	if ((cgn->type & OP_USE) || Lst_IsEmpty(pgn->commands)) {	    /*	     * .USE or transformation and target has no commands -- append	     * the child's commands to the parent.	     */	    (void) Lst_Concat (pgn->commands, cgn->commands, LST_CONCNEW);	}		if (Lst_Open (cgn->children) == SUCCESS) {	    while ((ln = Lst_Next (cgn->children)) != NILLNODE) {		gn = (GNode *)Lst_Datum (ln);		if (Lst_Member (pgn->children, gn) == NILLNODE) {		    (void) Lst_AtEnd (pgn->children, gn);		    (void) Lst_AtEnd (gn->parents, pgn);		    pgn->unmade += 1;		}	    }	    Lst_Close (cgn->children);	}		pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM);	/*	 * This child node is now "made", so we decrement the count of	 * unmade children in the parent... We also remove the child	 * from the parent's list to accurately reflect the number of decent	 * children the parent has. This is used by Make_Run to decide	 * whether to queue the parent or examine its children...	 */	if (cgn->type & OP_USE) {	    pgn->unmade -= 1;	}    }    return (0);}/*- *----------------------------------------------------------------------- * Make_Update  -- *	Perform update on the parents of a node. Used by JobFinish once *	a node has been dealt with and by MakeStartJobs if it finds an *	up-to-date node.  * * Results: *	Always returns 0 * * Side Effects: *	The unmade field of pgn is decremented and pgn may be placed on *	the toBeMade queue if this field becomes 0. * * 	If the child was made, the parent's childMade field will be set true *	and its cmtime set to now. * *	If the child wasn't made, the cmtime field of the parent will be *	altered if the child's mtime is big enough. * *	Finally, if the child is the implied source for the parent, the *	parent's IMPSRC variable is set appropriately. * *----------------------------------------------------------------------- */voidMake_Update (cgn)    register GNode *cgn;	/* the child node */{    register GNode 	*pgn;	/* the parent node */    register char  	*cname;	/* the child's name */    register LstNode	ln; 	/* Element in parents and iParents lists */    cname = Var_Value (TARGET, cgn);    /*     * If the child was actually made, see what its modification time is     * now -- some rules won't actually update the file. If the file still     * doesn't exist, make its mtime now.     */    if (cgn->made != UPTODATE) {#ifndef RECHECK	/*	 * We can't re-stat the thing, but we can at least take care of rules	 * where a target depends on a source that actually creates the	 * target, but only if it has changed, e.g.	 *	 * parse.h : parse.o	 *	 * parse.o : parse.y	 *  	yacc -d parse.y	 *  	cc -c y.tab.c	 *  	mv y.tab.o parse.o	 *  	cmp -s y.tab.h parse.h || mv y.tab.h parse.h	 *	 * In this case, if the definitions produced by yacc haven't changed	 * from before, parse.h won't have been updated and cgn->mtime will	 * reflect the current modification time for parse.h. This is	 * something of a kludge, I admit, but it's a useful one..	 * XXX: People like to use a rule like	 *	 * FRC:	 *	 * To force things that depend on FRC to be made, so we have to	 * check for gn->children being empty as well...	 */	if (!Lst_IsEmpty(cgn->commands) || Lst_IsEmpty(cgn->children)) {	    cgn->mtime = now;	}#else	/*	 * This is what Make does and it's actually a good thing, as it	 * allows rules like	 *	 *	cmp -s y.tab.h parse.h || cp y.tab.h parse.h	 *	 * to function as intended. Unfortunately, thanks to the stateless	 * nature of NFS (by which I mean the loose coupling of two clients	 * using the same file from a common server), there are times	 * when the modification time of a file created on a remote	 * machine will not be modified before the local stat() implied by	 * the Dir_MTime occurs, thus leading us to believe that the file	 * is unchanged, wreaking havoc with files that depend on this one.	 *

⌨️ 快捷键说明

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