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)
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. */
27 #ifdef HAVE_SYS_STAT_H
28 # include <sys/stat.h>
30 #ifdef HAVE_NETINET_IN_H
31 # include <netinet/in.h> /* for htonl/ntohl() */
51 #define ID ((MAJOR << 24) | (MINOR << 16) | REVISION)
52 #define CHECK_ID(id) (((id) & 0xFFFF0000) == ((ID) & 0xFFFF0000))
78 freetarget (Target
* target
)
80 xfree (target
->node
.name
);
82 freelist (&target
->makefiles
);
88 freetargetlist (Cache_priv
* cache
)
92 ForeachNodeSafe(&cache
->publicpart
.targets
,node
,next
)
95 freetarget ((Target
*)node
);
100 printtargetlist (List
* l
)
108 MakefileTarget
* mftarget
;
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
122 ForeachNode (&n
->makefiles
, mfref
)
124 mftarget
= FindNode (&mfref
->makefile
->targets
, n
->node
.name
);
125 ForeachNode (&mftarget
->deps
, node
)
126 addnodeonce (&deps
, node
->name
);
135 static int progcount
;
137 static char tokens
[]="|/-\\";
140 progress_reset (FILE * fh
)
144 fprintf (fh
, "\r|\r");
158 fprintf (fh
, "%c\r", tokens
[token
]);
165 readcache (Cache_priv
* cache
)
171 strcpy (path
, cache
->project
->top
);
172 strcat (path
, "/mmake.cache");
173 assert (strlen(path
) < sizeof(path
));
175 fh
= fopen (path
, "r");
179 if (!readuint32 (fh
, &id
) || !CHECK_ID(id
))
192 if (!readstring (fh
, &name
))
201 addnodeonce (&cache
->addedfiles
, name
);
204 while (name
!= NULL
);
207 cache
->topdir
= readcachedir (fh
);
209 cache
->topdir
= NULL
;
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;
233 printf ("readcache()\n");
234 printdirnode (cache
->topdir
);
239 writecache (Cache_priv
* cache
)
250 strcpy (path
, cache
->project
->top
);
251 strcat (path
, "/mmake.cache");
252 assert (strlen(path
) < sizeof(path
));
254 fh
= fopen (path
, "w");
262 ok
= writeuint32 (fh
, ID
);
266 ForeachNode (&cache
->addedfiles
, addedfile
)
268 ok
= writestring (fh
, addedfile
->name
);
271 error ("writecache/writestring():%d", __LINE__
);
276 ok
= writestring (fh
, NULL
);
279 error("writecache/fwrite():%d", __LINE__
);
283 ok
= writecachedir (fh
, cache
->topdir
);
293 printf ("Warning: Creating the cache failed\n");
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)
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
);
324 reg
->dest
= xstrdup (makefile
->node
.name
);
326 AddTail (regeneratefiles
, reg
);
336 updatemflist (Cache_priv
* cache
, DirNode
* node
, List
* regeneratefiles
)
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
);
352 if (scandirnode(node
, cache
->project
->defaultmakefilename
, &cache
->project
->ignoredirs
))
355 ForeachNode(&node
->subdirs
, subdir
)
356 reread
+= updatemflist(cache
, subdir
, regeneratefiles
);
358 ForeachNode(&node
->makefiles
, makefile
)
359 checknewsrc(cache
, makefile
, regeneratefiles
);
370 updatetargetlist (Cache_priv
* cache
, DirNode
* node
)
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
);
385 reread
= scanmakefiles(node
, &cache
->project
->vars
);
387 ForeachNode(&node
->subdirs
, subdir
)
388 reread
+= updatetargetlist(cache
, subdir
);
400 regeneratemf (Cache_priv
* cache
, List
* regeneratefiles
)
402 Regenerate
* reg
,* reg2
;
407 if (GetHead (regeneratefiles
) == NULL
)
410 strcpy (tmpname
, "/tmp/genmfXXXXXX");
411 fd
= mkstemp (tmpname
);
414 error ("Could not create temporary file %s", tmpname
);
419 f
= fdopen (fd
, "w");
422 error ("Could not open temporary file %s", tmpname
);
427 ForeachNodeSafe (regeneratefiles
, reg
, reg2
)
429 fprintf (f
, "%s/%s %s/%s\n", reg
->dir
, reg
->src
, reg
->dir
, reg
->dest
);
439 setvar (&cache
->project
->vars
, "MMLIST", tmpname
);
440 if (!execute (cache
->project
, cache
->project
->genmakefilescript
,"-","-",""))
442 error ("Error regenerating makefile");
450 buildtargetlist (Cache_priv
* cache
, DirNode
* node
)
454 MakefileTarget
* mftarget
;
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
);
478 target
= FindNode (&cache
->publicpart
.targets
, mftarget
->node
.name
);
482 target
= newnodesize (mftarget
->node
.name
, sizeof(Target
));
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
);
500 activatecache (Project
*prj
)
503 List regeneratefiles
;
504 Node
* addedfile
, * extrafile
;
509 cache
= new (Cache_priv
);
512 NewList (®eneratefiles
);
514 cache
->project
= prj
;
516 NewList (&cache
->addedfiles
);
517 NewList (&cache
->publicpart
.targets
);
521 progress_reset (stdout
);
522 printf ("Scanning dirs...\n");
523 reread
= updatemflist (cache
, cache
->topdir
, ®eneratefiles
);
525 printf ("Reread %d dirs\n", reread
);
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
);
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
);
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
);
561 AddTail (&newadded
, addedfile
);
564 ForeachNode (&cache
->addedfiles
, addedfile
)
566 makefile
= findmakefile (cache
->topdir
, addedfile
->name
);
567 if (makefile
!= NULL
)
570 freemakefile (makefile
);
573 AssignList (&cache
->addedfiles
, &newadded
);
575 regeneratemf (cache
, ®eneratefiles
);
577 progress_reset (stdout
);
578 printf ("Scanning makefiles...\n");
579 reread
= updatetargetlist (cache
, cache
->topdir
);
581 printf ("Reread %d makefiles\n", reread
);
584 printf ("Makefile and target tree for project %s\n", prj
->node
.name
);
585 printdirnodemftarget (cache
->topdir
);
590 printf ("Collecting targets...\n");
591 buildtargetlist (cache
, cache
->topdir
);
594 printf ("Targetlist of project %s\n", prj
->node
.name
);
595 printtargetlist (&cache
->publicpart
.targets
);
598 return (Cache
*)cache
;
602 closecache (Cache
* gl_cache
)
604 Cache_priv
* cache
= (Cache_priv
*)gl_cache
;
606 freetargetlist (cache
);