xref: /plan9/sys/src/cmd/mk/mk.c (revision 7f49a7ff54b1fd29a638d67350c7ceb952fbe2d6)
13e12c5d1SDavid du Colombier #include	"mk.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier int runerrs;
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier void
mk(char * target)63e12c5d1SDavid du Colombier mk(char *target)
73e12c5d1SDavid du Colombier {
83e12c5d1SDavid du Colombier 	Node *node;
93e12c5d1SDavid du Colombier 	int did = 0;
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier 	nproc();		/* it can be updated dynamically */
123e12c5d1SDavid du Colombier 	nrep();			/* it can be updated dynamically */
133e12c5d1SDavid du Colombier 	runerrs = 0;
143e12c5d1SDavid du Colombier 	node = graph(target);
153e12c5d1SDavid du Colombier 	if(DEBUG(D_GRAPH)){
163e12c5d1SDavid du Colombier 		dumpn("new target\n", node);
177dd7cddfSDavid du Colombier 		Bflush(&bout);
183e12c5d1SDavid du Colombier 	}
193e12c5d1SDavid du Colombier 	clrmade(node);
203e12c5d1SDavid du Colombier 	while(node->flags&NOTMADE){
213e12c5d1SDavid du Colombier 		if(work(node, (Node *)0, (Arc *)0))
223e12c5d1SDavid du Colombier 			did = 1;	/* found something to do */
233e12c5d1SDavid du Colombier 		else {
243e12c5d1SDavid du Colombier 			if(waitup(1, (int *)0) > 0){
253e12c5d1SDavid du Colombier 				if(node->flags&(NOTMADE|BEINGMADE)){
267dd7cddfSDavid du Colombier 					assert(/*must be run errors*/ runerrs);
273e12c5d1SDavid du Colombier 					break;	/* nothing more waiting */
283e12c5d1SDavid du Colombier 				}
293e12c5d1SDavid du Colombier 			}
303e12c5d1SDavid du Colombier 		}
313e12c5d1SDavid du Colombier 	}
323e12c5d1SDavid du Colombier 	if(node->flags&BEINGMADE)
333e12c5d1SDavid du Colombier 		waitup(-1, (int *)0);
343e12c5d1SDavid du Colombier 	while(jobs)
353e12c5d1SDavid du Colombier 		waitup(-2, (int *)0);
367dd7cddfSDavid du Colombier 	assert(/*target didnt get done*/ runerrs || (node->flags&MADE));
373e12c5d1SDavid du Colombier 	if(did == 0)
387dd7cddfSDavid du Colombier 		Bprint(&bout, "mk: '%s' is up to date\n", node->name);
393e12c5d1SDavid du Colombier }
403e12c5d1SDavid du Colombier 
413e12c5d1SDavid du Colombier void
clrmade(Node * n)423e12c5d1SDavid du Colombier clrmade(Node *n)
433e12c5d1SDavid du Colombier {
443e12c5d1SDavid du Colombier 	Arc *a;
453e12c5d1SDavid du Colombier 
463e12c5d1SDavid du Colombier 	n->flags &= ~(CANPRETEND|PRETENDING);
477dd7cddfSDavid du Colombier 	if(strchr(n->name, '(') ==0 || n->time)
483e12c5d1SDavid du Colombier 		n->flags |= CANPRETEND;
493e12c5d1SDavid du Colombier 	MADESET(n, NOTMADE);
503e12c5d1SDavid du Colombier 	for(a = n->prereqs; a; a = a->next)
513e12c5d1SDavid du Colombier 		if(a->n)
523e12c5d1SDavid du Colombier 			clrmade(a->n);
533e12c5d1SDavid du Colombier }
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier static void
unpretend(Node * n)563e12c5d1SDavid du Colombier unpretend(Node *n)
573e12c5d1SDavid du Colombier {
583e12c5d1SDavid du Colombier 	MADESET(n, NOTMADE);
593e12c5d1SDavid du Colombier 	n->flags &= ~(CANPRETEND|PRETENDING);
603e12c5d1SDavid du Colombier 	n->time = 0;
613e12c5d1SDavid du Colombier }
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier int
work(Node * node,Node * p,Arc * parc)643e12c5d1SDavid du Colombier work(Node *node, Node *p, Arc *parc)
653e12c5d1SDavid du Colombier {
663e12c5d1SDavid du Colombier 	Arc *a, *ra;
673e12c5d1SDavid du Colombier 	int weoutofdate;
683e12c5d1SDavid du Colombier 	int ready;
693e12c5d1SDavid du Colombier 	int did = 0;
70276e7d6dSDavid du Colombier 	char cwd[256];
713e12c5d1SDavid du Colombier 
72*7f49a7ffSDavid du Colombier 	/*print("work(%s) flags=0x%x time=%lud\n", node->name, node->flags, node->time);/**/
733e12c5d1SDavid du Colombier 	if(node->flags&BEINGMADE)
743e12c5d1SDavid du Colombier 		return(did);
753e12c5d1SDavid du Colombier 	if((node->flags&MADE) && (node->flags&PRETENDING) && p && outofdate(p, parc, 0)){
763e12c5d1SDavid du Colombier 		if(explain)
77*7f49a7ffSDavid du Colombier 			fprint(1, "unpretending %s(%lud) because %s is out of date(%lud)\n",
783e12c5d1SDavid du Colombier 				node->name, node->time, p->name, p->time);
793e12c5d1SDavid du Colombier 		unpretend(node);
803e12c5d1SDavid du Colombier 	}
813e12c5d1SDavid du Colombier 	/*
823e12c5d1SDavid du Colombier 		have a look if we are pretending in case
833e12c5d1SDavid du Colombier 		someone has been unpretended out from underneath us
843e12c5d1SDavid du Colombier 	*/
853e12c5d1SDavid du Colombier 	if(node->flags&MADE){
863e12c5d1SDavid du Colombier 		if(node->flags&PRETENDING){
873e12c5d1SDavid du Colombier 			node->time = 0;
883e12c5d1SDavid du Colombier 		}else
893e12c5d1SDavid du Colombier 			return(did);
903e12c5d1SDavid du Colombier 	}
919a747e4fSDavid du Colombier 	/* consider no prerequisite case */
923e12c5d1SDavid du Colombier 	if(node->prereqs == 0){
933e12c5d1SDavid du Colombier 		if(node->time == 0){
949a747e4fSDavid du Colombier 			if(getwd(cwd, sizeof cwd))
959a747e4fSDavid du Colombier 				fprint(2, "mk: don't know how to make '%s' in directory %s\n", node->name, cwd);
969a747e4fSDavid du Colombier 			else
973e12c5d1SDavid du Colombier 				fprint(2, "mk: don't know how to make '%s'\n", node->name);
983e12c5d1SDavid du Colombier 			if(kflag){
993e12c5d1SDavid du Colombier 				node->flags |= BEINGMADE;
1003e12c5d1SDavid du Colombier 				runerrs++;
1013e12c5d1SDavid du Colombier 			} else
1023e12c5d1SDavid du Colombier 				Exit();
1033e12c5d1SDavid du Colombier 		} else
1043e12c5d1SDavid du Colombier 			MADESET(node, MADE);
1053e12c5d1SDavid du Colombier 		return(did);
1063e12c5d1SDavid du Colombier 	}
1073e12c5d1SDavid du Colombier 	/*
1083e12c5d1SDavid du Colombier 		now see if we are out of date or what
1093e12c5d1SDavid du Colombier 	*/
1103e12c5d1SDavid du Colombier 	ready = 1;
1113e12c5d1SDavid du Colombier 	weoutofdate = aflag;
1123e12c5d1SDavid du Colombier 	ra = 0;
1133e12c5d1SDavid du Colombier 	for(a = node->prereqs; a; a = a->next)
1143e12c5d1SDavid du Colombier 		if(a->n){
1153e12c5d1SDavid du Colombier 			did = work(a->n, node, a) || did;
1163e12c5d1SDavid du Colombier 			if(a->n->flags&(NOTMADE|BEINGMADE))
1173e12c5d1SDavid du Colombier 				ready = 0;
1183e12c5d1SDavid du Colombier 			if(outofdate(node, a, 0)){
1193e12c5d1SDavid du Colombier 				weoutofdate = 1;
1203e12c5d1SDavid du Colombier 				if((ra == 0) || (ra->n == 0)
1213e12c5d1SDavid du Colombier 						|| (ra->n->time < a->n->time))
1223e12c5d1SDavid du Colombier 					ra = a;
1233e12c5d1SDavid du Colombier 			}
1243e12c5d1SDavid du Colombier 		} else {
1253e12c5d1SDavid du Colombier 			if(node->time == 0){
1263e12c5d1SDavid du Colombier 				if(ra == 0)
1273e12c5d1SDavid du Colombier 					ra = a;
1283e12c5d1SDavid du Colombier 				weoutofdate = 1;
1293e12c5d1SDavid du Colombier 			}
1303e12c5d1SDavid du Colombier 		}
1313e12c5d1SDavid du Colombier 	if(ready == 0)	/* can't do anything now */
1323e12c5d1SDavid du Colombier 		return(did);
1333e12c5d1SDavid du Colombier 	if(weoutofdate == 0){
1343e12c5d1SDavid du Colombier 		MADESET(node, MADE);
1353e12c5d1SDavid du Colombier 		return(did);
1363e12c5d1SDavid du Colombier 	}
1373e12c5d1SDavid du Colombier 	/*
1383e12c5d1SDavid du Colombier 		can we pretend to be made?
1393e12c5d1SDavid du Colombier 	*/
1407dd7cddfSDavid du Colombier 	if((iflag == 0) && (node->time == 0) && (node->flags&(PRETENDING|CANPRETEND))
1417dd7cddfSDavid du Colombier 			&& p && ra->n && !outofdate(p, ra, 0)){
1423e12c5d1SDavid du Colombier 		node->flags &= ~CANPRETEND;
1433e12c5d1SDavid du Colombier 		MADESET(node, MADE);
1443e12c5d1SDavid du Colombier 		if(explain && ((node->flags&PRETENDING) == 0))
145*7f49a7ffSDavid du Colombier 			fprint(1, "pretending %s has time %lud\n", node->name, node->time);
1463e12c5d1SDavid du Colombier 		node->flags |= PRETENDING;
1473e12c5d1SDavid du Colombier 		return(did);
1483e12c5d1SDavid du Colombier 	}
1493e12c5d1SDavid du Colombier 	/*
1503e12c5d1SDavid du Colombier 		node is out of date and we REALLY do have to do something.
1513e12c5d1SDavid du Colombier 		quickly rescan for pretenders
1523e12c5d1SDavid du Colombier 	*/
1533e12c5d1SDavid du Colombier 	for(a = node->prereqs; a; a = a->next)
1543e12c5d1SDavid du Colombier 		if(a->n && (a->n->flags&PRETENDING)){
1553e12c5d1SDavid du Colombier 			if(explain)
1567dd7cddfSDavid du Colombier 				Bprint(&bout, "unpretending %s because of %s because of %s\n",
1573e12c5d1SDavid du Colombier 				a->n->name, node->name, ra->n? ra->n->name : "rule with no prerequisites");
1583e12c5d1SDavid du Colombier 
1593e12c5d1SDavid du Colombier 			unpretend(a->n);
1603e12c5d1SDavid du Colombier 			did = work(a->n, node, a) || did;
1613e12c5d1SDavid du Colombier 			ready = 0;
1623e12c5d1SDavid du Colombier 		}
1633e12c5d1SDavid du Colombier 	if(ready == 0)	/* try later unless nothing has happened for -k's sake */
1643e12c5d1SDavid du Colombier 		return(did || work(node, p, parc));
1653e12c5d1SDavid du Colombier 	did = dorecipe(node) || did;
1663e12c5d1SDavid du Colombier 	return(did);
1673e12c5d1SDavid du Colombier }
1683e12c5d1SDavid du Colombier 
1693e12c5d1SDavid du Colombier void
update(int fake,Node * node)1703e12c5d1SDavid du Colombier update(int fake, Node *node)
1713e12c5d1SDavid du Colombier {
1723e12c5d1SDavid du Colombier 	Arc *a;
1733e12c5d1SDavid du Colombier 
1743e12c5d1SDavid du Colombier 	MADESET(node, fake? BEINGMADE : MADE);
1753e12c5d1SDavid du Colombier 	if(((node->flags&VIRTUAL) == 0) && (access(node->name, 0) == 0)){
1763e12c5d1SDavid du Colombier 		node->time = timeof(node->name, 1);
1773e12c5d1SDavid du Colombier 		node->flags &= ~(CANPRETEND|PRETENDING);
1783e12c5d1SDavid du Colombier 		for(a = node->prereqs; a; a = a->next)
1793e12c5d1SDavid du Colombier 			if(a->prog)
1803e12c5d1SDavid du Colombier 				outofdate(node, a, 1);
1813e12c5d1SDavid du Colombier 	} else {
1823e12c5d1SDavid du Colombier 		node->time = 1;
1833e12c5d1SDavid du Colombier 		for(a = node->prereqs; a; a = a->next)
1843e12c5d1SDavid du Colombier 			if(a->n && outofdate(node, a, 1))
1853e12c5d1SDavid du Colombier 				node->time = a->n->time;
1863e12c5d1SDavid du Colombier 	}
187*7f49a7ffSDavid du Colombier /*	print("----node %s time=%lud flags=0x%x\n", node->name, node->time, node->flags);/**/
1883e12c5d1SDavid du Colombier }
1893e12c5d1SDavid du Colombier 
1903e12c5d1SDavid du Colombier static
pcmp(char * prog,char * p,char * q)1917dd7cddfSDavid du Colombier pcmp(char *prog, char *p, char *q)
1923e12c5d1SDavid du Colombier {
1933e12c5d1SDavid du Colombier 	char buf[3*NAMEBLOCK];
1943e12c5d1SDavid du Colombier 	int pid;
1953e12c5d1SDavid du Colombier 
1967dd7cddfSDavid du Colombier 	Bflush(&bout);
197276e7d6dSDavid du Colombier 	snprint(buf, sizeof buf, "%s '%s' '%s'\n", prog, p, q);
1987dd7cddfSDavid du Colombier 	pid = pipecmd(buf, 0, 0);
1993e12c5d1SDavid du Colombier 	while(waitup(-3, &pid) >= 0)
2003e12c5d1SDavid du Colombier 		;
2013e12c5d1SDavid du Colombier 	return(pid? 2:1);
2023e12c5d1SDavid du Colombier }
2033e12c5d1SDavid du Colombier 
2043e12c5d1SDavid du Colombier int
outofdate(Node * node,Arc * arc,int eval)2053e12c5d1SDavid du Colombier outofdate(Node *node, Arc *arc, int eval)
2063e12c5d1SDavid du Colombier {
2073e12c5d1SDavid du Colombier 	char buf[3*NAMEBLOCK], *str;
2083e12c5d1SDavid du Colombier 	Symtab *sym;
2093e12c5d1SDavid du Colombier 	int ret;
2103e12c5d1SDavid du Colombier 
2113e12c5d1SDavid du Colombier 	str = 0;
2123e12c5d1SDavid du Colombier 	if(arc->prog){
213276e7d6dSDavid du Colombier 		snprint(buf, sizeof buf, "%s%c%s", node->name, 0377,
214276e7d6dSDavid du Colombier 			arc->n->name);
2157dd7cddfSDavid du Colombier 		sym = symlook(buf, S_OUTOFDATE, 0);
2167dd7cddfSDavid du Colombier 		if(sym == 0 || eval){
2177dd7cddfSDavid du Colombier 			if(sym == 0)
2183e12c5d1SDavid du Colombier 				str = strdup(buf);
2193e12c5d1SDavid du Colombier 			ret = pcmp(arc->prog, node->name, arc->n->name);
2203e12c5d1SDavid du Colombier 			if(sym)
2214de34a7eSDavid du Colombier 				sym->u.value = ret;
2223e12c5d1SDavid du Colombier 			else
2237dd7cddfSDavid du Colombier 				symlook(str, S_OUTOFDATE, (void *)ret);
2243e12c5d1SDavid du Colombier 		} else
2254de34a7eSDavid du Colombier 			ret = sym->u.value;
2263e12c5d1SDavid du Colombier 		return(ret-1);
22799eb86a7SDavid du Colombier 	} else if(strchr(arc->n->name, '(') && arc->n->time == 0)  /* missing archive member */
22899eb86a7SDavid du Colombier 		return 1;
2297dd7cddfSDavid du Colombier 	else
2302db064f5SDavid du Colombier 		/*
2312db064f5SDavid du Colombier 		 * Treat equal times as out-of-date.
2322db064f5SDavid du Colombier 		 * It's a race, and the safer option is to do
2332db064f5SDavid du Colombier 		 * extra building rather than not enough.
2342db064f5SDavid du Colombier 	 	 */
2352db064f5SDavid du Colombier 		return node->time <= arc->n->time;
2363e12c5d1SDavid du Colombier }
237