Renamed INT[B|F]_VERTB100 to INT[B|F]_TIMERTICK
[tangerine.git] / tools / MetaMake / cache.c
blobaf5c59ec5a92b6b8002217aacd145d1570a404b1
1 /* MetaMake - A Make extension
2 Copyright © 1995-2004, The AROS Development Team. All rights reserved.
4 This file is part of MetaMake.
6 MetaMake is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 MetaMake is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "config.h"
22 #ifdef HAVE_STRING_H
23 # include <string.h>
24 #else
25 # include <strings.h>
26 #endif
27 #ifdef HAVE_SYS_STAT_H
28 # include <sys/stat.h>
29 #endif
30 #ifdef HAVE_NETINET_IN_H
31 # include <netinet/in.h> /* for htonl/ntohl() */
32 #endif
33 #include <errno.h>
34 #include <assert.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #ifndef PATH_MAX
38 #include <limits.h>
39 #endif
41 #include "cache.h"
42 #include "mem.h"
43 #include "io.h"
44 #include "var.h"
45 #include "dep.h"
46 #include "mmake.h"
48 #define MAJOR 0L
49 #define MINOR 9L
50 #define REVISION 0L
51 #define ID ((MAJOR << 24) | (MINOR << 16) | REVISION)
52 #define CHECK_ID(id) (((id) & 0xFFFF0000) == ((ID) & 0xFFFF0000))
55 typedef struct {
56 Cache publicpart;
58 Project * project;
60 DirNode * topdir;
62 List addedfiles;
64 Cache_priv;
66 typedef struct
68 Node node;
70 char *dir;
71 char *src;
72 char *dest;
74 Regenerate;
77 static void
78 freetarget (Target * target)
80 xfree (target->node.name);
82 freelist (&target->makefiles);
84 xfree (target);
87 static void
88 freetargetlist (Cache_priv * cache)
90 Node * node, * next;
92 ForeachNodeSafe(&cache->publicpart.targets,node,next)
94 Remove (node);
95 freetarget ((Target *)node);
99 static void
100 printtargetlist (List * l)
102 Target * n;
104 ForeachNode (l,n)
106 List deps;
107 MakefileRef * mfref;
108 MakefileTarget * mftarget;
109 Node * node;
111 printf ("target %s:\n", n->node.name);
112 printf (" updated=%d\n", n->updated);
113 printf (" makefiles=\n");
114 ForeachNode (&n->makefiles, mfref)
115 printf(" \"%s/%s\"\n",
116 buildpath(mfref->makefile->dir),
117 mfref->makefile->node.name
120 printf (" deps=\n");
121 NewList (&deps);
122 ForeachNode (&n->makefiles, mfref)
124 mftarget = FindNode (&mfref->makefile->targets, n->node.name);
125 ForeachNode (&mftarget->deps, node)
126 addnodeonce (&deps, node->name);
129 printlist (&deps);
130 freelist (&deps);
135 static int progcount;
136 static int token;
137 static char tokens[]="|/-\\";
139 static void
140 progress_reset (FILE * fh)
142 progcount = 0;
143 token = 0;
144 fprintf (fh, "\r|\r");
145 fflush (fh);
148 static void
149 progress (FILE * fh)
151 progcount++;
152 if (progcount == 13)
154 progcount = 0;
155 token++;
156 if (token == 4)
157 token = 0;
158 fprintf (fh, "%c\r", tokens[token]);
159 fflush (fh);
164 void
165 readcache (Cache_priv * cache)
167 char path[256];
168 FILE * fh;
169 uint32_t id;
171 strcpy (path, cache->project->top);
172 strcat (path, "/mmake.cache");
173 assert (strlen(path) < sizeof(path));
175 fh = fopen (path, "r");
177 if (fh)
179 if (!readuint32 (fh, &id) || !CHECK_ID(id))
181 fclose (fh);
182 fh = NULL;
186 if (fh)
188 char * name;
192 if (!readstring (fh, &name))
194 fh = NULL;
195 break;
198 if (name == NULL)
199 continue;
201 addnodeonce (&cache->addedfiles, name);
202 xfree (name);
204 while (name != NULL);
206 if (fh)
207 cache->topdir = readcachedir (fh);
208 else
209 cache->topdir = NULL;
211 if (!cache->topdir)
213 fclose (fh);
214 fh = NULL;
218 if (!fh)
220 cache->topdir = newnodesize ("", sizeof (DirNode));
221 cache->topdir->parent = NULL;
222 NewList(&cache->topdir->subdirs);
223 NewList(&cache->topdir->makefiles);
225 /* Force a check the first time */
226 cache->topdir->time = 0;
229 if (fh)
230 fclose (fh);
232 #if 0
233 printf ("readcache()\n");
234 printdirnode (cache->topdir);
235 #endif
238 void
239 writecache (Cache_priv * cache)
241 int ok = 1;
242 char path[256];
243 FILE * fh = NULL;
244 uint32_t id;
245 Node *addedfile;
247 if (!cache->topdir)
248 return;
250 strcpy (path, cache->project->top);
251 strcat (path, "/mmake.cache");
252 assert (strlen(path) < sizeof(path));
254 fh = fopen (path, "w");
256 if (!fh)
258 ok = 0;
259 goto writecacheend;
262 ok = writeuint32 (fh, ID);
263 if (!ok)
264 goto writecacheend;
266 ForeachNode (&cache->addedfiles, addedfile)
268 ok = writestring (fh, addedfile->name);
269 if (!ok)
271 error ("writecache/writestring():%d", __LINE__);
272 goto writecacheend;
276 ok = writestring (fh, NULL);
277 if (!ok)
279 error("writecache/fwrite():%d", __LINE__);
280 goto writecacheend;
283 ok = writecachedir (fh, cache->topdir);
285 writecacheend:
286 if (fh)
287 fclose (fh);
289 if (!ok)
291 unlink (path);
293 printf ("Warning: Creating the cache failed\n");
298 void
299 checknewsrc (Cache_priv * cache, Makefile * makefile, List * regeneratefiles)
301 char * mfsrc = xmalloc (strlen (makefile->node.name) + 5);
302 struct stat sst, dst;
304 strcpy (mfsrc, makefile->node.name);
305 strcat (mfsrc, ".src");
307 if (stat (mfsrc, &sst) == -1)
309 xfree (mfsrc);
310 return;
313 if (stat (makefile->node.name, &dst) == -1
314 || sst.st_mtime > dst.st_mtime
315 || checkdeps (&cache->project->genmakefiledeps, dst.st_mtime)
318 static char currdir[PATH_MAX];
319 Regenerate *reg = new (Regenerate);
321 getcwd(currdir, PATH_MAX);
322 reg->dir = xstrdup (currdir);
323 reg->src = mfsrc;
324 reg->dest = xstrdup (makefile->node.name);
326 AddTail (regeneratefiles, reg);
328 else
330 xfree (mfsrc);
336 updatemflist (Cache_priv * cache, DirNode * node, List * regeneratefiles)
338 DirNode * subdir;
339 Makefile * makefile;
340 int goup = 0, reread = 0;
342 if (strlen(node->node.name) != 0)
344 if (chdir(node->node.name) < 0)
346 error("Could not change to dir '%s'", node->node.name);
347 exit (20);
349 goup = 1;
352 if (scandirnode(node, cache->project->defaultmakefilename, &cache->project->ignoredirs))
353 reread ++;
355 ForeachNode(&node->subdirs, subdir)
356 reread += updatemflist(cache, subdir, regeneratefiles);
358 ForeachNode(&node->makefiles, makefile)
359 checknewsrc(cache, makefile, regeneratefiles);
361 if (goup)
362 chdir("..");
364 progress (stdout);
366 return reread;
370 updatetargetlist (Cache_priv * cache, DirNode * node)
372 DirNode * subdir;
373 int goup = 0, reread = 0;
375 if (strlen(node->node.name) != 0)
377 if (chdir(node->node.name) < 0)
379 error("Could not change to dir '%s'", node->node.name);
380 exit (20);
382 goup = 1;
385 reread = scanmakefiles(node, &cache->project->vars);
387 ForeachNode(&node->subdirs, subdir)
388 reread += updatetargetlist(cache, subdir);
390 progress (stdout);
392 if (goup)
393 chdir("..");
395 return reread;
399 void
400 regeneratemf (Cache_priv * cache, List * regeneratefiles)
402 Regenerate * reg,* reg2;
403 char tmpname[20];
404 int fd;
405 FILE *f;
407 if (GetHead (regeneratefiles) == NULL)
408 return;
410 strcpy (tmpname, "/tmp/genmfXXXXXX");
411 fd = mkstemp (tmpname);
412 if (fd < 0)
414 error ("Could not create temporary file %s", tmpname);
415 exit (10);
417 else
419 f = fdopen (fd, "w");
420 if (f == NULL)
422 error ("Could not open temporary file %s", tmpname);
423 exit (10);
427 ForeachNodeSafe (regeneratefiles, reg, reg2)
429 fprintf (f, "%s/%s %s/%s\n", reg->dir, reg->src, reg->dir, reg->dest);
430 Remove (reg);
431 xfree (reg->dir);
432 xfree (reg->src);
433 xfree (reg->dest);
434 xfree (reg);
437 fclose (f);
439 setvar (&cache->project->vars, "MMLIST", tmpname);
440 if (!execute (cache->project, cache->project->genmakefilescript,"-","-",""))
442 error ("Error regenerating makefile");
443 exit (10);
446 unlink (tmpname);
449 void
450 buildtargetlist (Cache_priv * cache, DirNode * node)
452 Makefile * makefile;
453 MakefileRef * mfref;
454 MakefileTarget * mftarget;
455 DirNode * subdir;
456 Target * target;
457 Node * n;
459 ForeachNode (&node->makefiles, makefile)
461 ForeachNode (&makefile->targets, mftarget)
463 if (strchr (mftarget->node.name, '$') != NULL)
465 char * s = substvars(&cache->project->vars, mftarget->node.name);
466 SETSTR (mftarget->node.name, s);
469 ForeachNode (&mftarget->deps, n)
471 if (strchr (n->name, '$') != NULL)
473 char * s = substvars(&cache->project->vars, n->name);
474 SETSTR (n->name, s);
478 target = FindNode (&cache->publicpart.targets, mftarget->node.name);
480 if (target == NULL)
482 target = newnodesize (mftarget->node.name, sizeof(Target));
483 target->updated = 0;
484 NewList (&target->makefiles);
485 AddTail (&cache->publicpart.targets, target);
488 mfref = newnodesize ("", sizeof(MakefileRef));
489 mfref->virtualtarget = mftarget->virtualtarget;
490 mfref->makefile = makefile;
491 AddTail (&target->makefiles, mfref);
495 ForeachNode (&node->subdirs, subdir)
496 buildtargetlist (cache, subdir);
499 Cache *
500 activatecache (Project *prj)
502 Cache_priv * cache;
503 List regeneratefiles;
504 Node * addedfile, * extrafile;
505 Makefile * makefile;
506 List newadded;
507 int reread;
509 cache = new (Cache_priv);
510 if (!cache)
511 return NULL;
512 NewList (&regeneratefiles);
514 cache->project = prj;
516 NewList (&cache->addedfiles);
517 NewList (&cache->publicpart.targets);
519 readcache (cache);
521 progress_reset (stdout);
522 printf ("Scanning dirs...\n");
523 reread = updatemflist (cache, cache->topdir, &regeneratefiles);
524 if (verbose)
525 printf ("Reread %d dirs\n", reread);
526 if (debug)
528 printf ("Directory tree for project %s\n", prj->node.name);
529 printdirnode (cache->topdir, 0);
532 /* Add the extra makefiles to the tree if needed */
533 chdir (cache->project->top);
534 NewList (&newadded);
535 ForeachNode (&cache->project->extramakefiles, extrafile)
537 addedfile = FindNode (&cache->addedfiles, extrafile->name);
538 if (addedfile == NULL)
540 makefile = addmakefile (cache->topdir, extrafile->name);
542 if (makefile == NULL)
544 error("Could not add makefile \"%s\"", extrafile->name);
545 exit (20);
548 addnodeonce (&newadded, extrafile->name);
550 else /* addedfile != NULL => was already added before */
552 makefile = findmakefile (cache->topdir, extrafile->name);
554 if (makefile == NULL)
556 error("Makefile \"%s\" has disappeared", extrafile->name);
557 exit (20);
560 Remove (addedfile);
561 AddTail (&newadded, addedfile);
564 ForeachNode (&cache->addedfiles, addedfile)
566 makefile = findmakefile (cache->topdir, addedfile->name);
567 if (makefile != NULL)
569 Remove (makefile);
570 freemakefile (makefile);
573 AssignList (&cache->addedfiles, &newadded);
575 regeneratemf (cache, &regeneratefiles);
577 progress_reset (stdout);
578 printf ("Scanning makefiles...\n");
579 reread = updatetargetlist (cache, cache->topdir);
580 if (verbose)
581 printf ("Reread %d makefiles\n", reread);
582 if (debug)
584 printf ("Makefile and target tree for project %s\n", prj->node.name);
585 printdirnodemftarget (cache->topdir);
588 writecache (cache);
590 printf ("Collecting targets...\n");
591 buildtargetlist (cache, cache->topdir);
592 if (debug)
594 printf ("Targetlist of project %s\n", prj->node.name);
595 printtargetlist (&cache->publicpart.targets);
598 return (Cache *)cache;
601 void
602 closecache (Cache * gl_cache)
604 Cache_priv * cache = (Cache_priv *)gl_cache;
606 freetargetlist (cache);