mk.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #include "mk.h"
  2. int runerrs;
  3. void
  4. mk(char *target)
  5. {
  6. Node *node;
  7. int did = 0;
  8. nproc(); /* it can be updated dynamically */
  9. nrep(); /* it can be updated dynamically */
  10. runerrs = 0;
  11. node = graph(target);
  12. if(DEBUG(D_GRAPH)){
  13. dumpn("new target\n", node);
  14. Bflush(&bout);
  15. }
  16. clrmade(node);
  17. while(node->flags&NOTMADE){
  18. if(work(node, (Node *)0, (Arc *)0))
  19. did = 1; /* found something to do */
  20. else {
  21. if(waitup(1, (int *)0) > 0){
  22. if(node->flags&(NOTMADE|BEINGMADE)){
  23. assert(/*must be run errors*/ runerrs);
  24. break; /* nothing more waiting */
  25. }
  26. }
  27. }
  28. }
  29. if(node->flags&BEINGMADE)
  30. waitup(-1, (int *)0);
  31. while(jobs)
  32. waitup(-2, (int *)0);
  33. assert(/*target didnt get done*/ runerrs || (node->flags&MADE));
  34. if(did == 0)
  35. Bprint(&bout, "mk: '%s' is up to date\n", node->name);
  36. }
  37. void
  38. clrmade(Node *n)
  39. {
  40. Arc *a;
  41. n->flags &= ~(CANPRETEND|PRETENDING);
  42. if(strchr(n->name, '(') ==0 || n->time)
  43. n->flags |= CANPRETEND;
  44. MADESET(n, NOTMADE);
  45. for(a = n->prereqs; a; a = a->next)
  46. if(a->n)
  47. clrmade(a->n);
  48. }
  49. static void
  50. unpretend(Node *n)
  51. {
  52. MADESET(n, NOTMADE);
  53. n->flags &= ~(CANPRETEND|PRETENDING);
  54. n->time = 0;
  55. }
  56. int
  57. work(Node *node, Node *p, Arc *parc)
  58. {
  59. Arc *a, *ra;
  60. int weoutofdate;
  61. int ready;
  62. int did = 0;
  63. char cwd[128];
  64. /*print("work(%s) flags=0x%x time=%ld\n", node->name, node->flags, node->time);/**/
  65. if(node->flags&BEINGMADE)
  66. return(did);
  67. if((node->flags&MADE) && (node->flags&PRETENDING) && p && outofdate(p, parc, 0)){
  68. if(explain)
  69. fprint(1, "unpretending %s(%ld) because %s is out of date(%ld)\n",
  70. node->name, node->time, p->name, p->time);
  71. unpretend(node);
  72. }
  73. /*
  74. have a look if we are pretending in case
  75. someone has been unpretended out from underneath us
  76. */
  77. if(node->flags&MADE){
  78. if(node->flags&PRETENDING){
  79. node->time = 0;
  80. }else
  81. return(did);
  82. }
  83. /* consider no prerequisite case */
  84. if(node->prereqs == 0){
  85. if(node->time == 0){
  86. if(getwd(cwd, sizeof cwd))
  87. fprint(2, "mk: don't know how to make '%s' in directory %s\n", node->name, cwd);
  88. else
  89. fprint(2, "mk: don't know how to make '%s'\n", node->name);
  90. if(kflag){
  91. node->flags |= BEINGMADE;
  92. runerrs++;
  93. } else
  94. Exit();
  95. } else
  96. MADESET(node, MADE);
  97. return(did);
  98. }
  99. /*
  100. now see if we are out of date or what
  101. */
  102. ready = 1;
  103. weoutofdate = aflag;
  104. ra = 0;
  105. for(a = node->prereqs; a; a = a->next)
  106. if(a->n){
  107. did = work(a->n, node, a) || did;
  108. if(a->n->flags&(NOTMADE|BEINGMADE))
  109. ready = 0;
  110. if(outofdate(node, a, 0)){
  111. weoutofdate = 1;
  112. if((ra == 0) || (ra->n == 0)
  113. || (ra->n->time < a->n->time))
  114. ra = a;
  115. }
  116. } else {
  117. if(node->time == 0){
  118. if(ra == 0)
  119. ra = a;
  120. weoutofdate = 1;
  121. }
  122. }
  123. if(ready == 0) /* can't do anything now */
  124. return(did);
  125. if(weoutofdate == 0){
  126. MADESET(node, MADE);
  127. return(did);
  128. }
  129. /*
  130. can we pretend to be made?
  131. */
  132. if((iflag == 0) && (node->time == 0) && (node->flags&(PRETENDING|CANPRETEND))
  133. && p && ra->n && !outofdate(p, ra, 0)){
  134. node->flags &= ~CANPRETEND;
  135. MADESET(node, MADE);
  136. if(explain && ((node->flags&PRETENDING) == 0))
  137. fprint(1, "pretending %s has time %ld\n", node->name, node->time);
  138. node->flags |= PRETENDING;
  139. return(did);
  140. }
  141. /*
  142. node is out of date and we REALLY do have to do something.
  143. quickly rescan for pretenders
  144. */
  145. for(a = node->prereqs; a; a = a->next)
  146. if(a->n && (a->n->flags&PRETENDING)){
  147. if(explain)
  148. Bprint(&bout, "unpretending %s because of %s because of %s\n",
  149. a->n->name, node->name, ra->n? ra->n->name : "rule with no prerequisites");
  150. unpretend(a->n);
  151. did = work(a->n, node, a) || did;
  152. ready = 0;
  153. }
  154. if(ready == 0) /* try later unless nothing has happened for -k's sake */
  155. return(did || work(node, p, parc));
  156. did = dorecipe(node) || did;
  157. return(did);
  158. }
  159. void
  160. update(int fake, Node *node)
  161. {
  162. Arc *a;
  163. MADESET(node, fake? BEINGMADE : MADE);
  164. if(((node->flags&VIRTUAL) == 0) && (access(node->name, 0) == 0)){
  165. node->time = timeof(node->name, 1);
  166. node->flags &= ~(CANPRETEND|PRETENDING);
  167. for(a = node->prereqs; a; a = a->next)
  168. if(a->prog)
  169. outofdate(node, a, 1);
  170. } else {
  171. node->time = 1;
  172. for(a = node->prereqs; a; a = a->next)
  173. if(a->n && outofdate(node, a, 1))
  174. node->time = a->n->time;
  175. }
  176. /* print("----node %s time=%ld flags=0x%x\n", node->name, node->time, node->flags);/**/
  177. }
  178. static
  179. pcmp(char *prog, char *p, char *q)
  180. {
  181. char buf[3*NAMEBLOCK];
  182. int pid;
  183. Bflush(&bout);
  184. sprint(buf, "%s '%s' '%s'\n", prog, p, q);
  185. pid = pipecmd(buf, 0, 0);
  186. while(waitup(-3, &pid) >= 0)
  187. ;
  188. return(pid? 2:1);
  189. }
  190. int
  191. outofdate(Node *node, Arc *arc, int eval)
  192. {
  193. char buf[3*NAMEBLOCK], *str;
  194. Symtab *sym;
  195. int ret;
  196. str = 0;
  197. if(arc->prog){
  198. sprint(buf, "%s%c%s", node->name, 0377, arc->n->name);
  199. sym = symlook(buf, S_OUTOFDATE, 0);
  200. if(sym == 0 || eval){
  201. if(sym == 0)
  202. str = strdup(buf);
  203. ret = pcmp(arc->prog, node->name, arc->n->name);
  204. if(sym)
  205. sym->value = (void *)ret;
  206. else
  207. symlook(str, S_OUTOFDATE, (void *)ret);
  208. } else
  209. ret = (int)(uintptr)sym->value;
  210. return(ret-1);
  211. } else if(strchr(arc->n->name, '(') && arc->n->time == 0) /* missing archive member */
  212. return 1;
  213. else
  214. /*
  215. * Treat equal times as out-of-date.
  216. * It's a race, and the safer option is to do
  217. * extra building rather than not enough.
  218. */
  219. return node->time <= arc->n->time;
  220. }