1 /* MetaMake - A Make extension
2 Copyright © 1995-2008, 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. */
30 #ifdef HAVE_SYS_STAT_H
31 # include <sys/stat.h>
33 #ifdef HAVE_NETINET_IN_H
34 # include <netinet/in.h> /* for htonl/ntohl() */
51 #if defined(DEBUG_CACHE)
60 #define ID ((MAJOR << 24) | (MINOR << 16) | REVISION)
61 #define CHECK_ID(id) (((id) & 0xFFFF0000) == ((ID) & 0xFFFF0000))
63 extern char *mm_srcdir
;
64 extern char *mm_builddir
;
89 freetarget (Target
* target
)
91 xfree (target
->node
.name
);
93 freelist (&target
->makefiles
);
99 freetargetlist (Cache_priv
* cache
)
103 ForeachNodeSafe(&cache
->publicpart
.targets
,node
,next
)
106 freetarget ((Target
*)node
);
111 printtargetlist (List
* l
)
119 MakefileTarget
* mftarget
;
122 printf ("target %s:\n", n
->node
.name
);
123 printf (" updated=%d\n", n
->updated
);
124 printf (" makefiles=\n");
125 ForeachNode (&n
->makefiles
, mfref
)
126 printf(" \"%s/%s\"\n",
127 buildpath(mfref
->makefile
->dir
),
128 mfref
->makefile
->node
.name
133 ForeachNode (&n
->makefiles
, mfref
)
135 mftarget
= FindNode (&mfref
->makefile
->targets
, n
->node
.name
);
136 ForeachNode (&mftarget
->deps
, node
)
137 addnodeonce (&deps
, node
->name
);
146 static int progcount
;
148 static char tokens
[]="|/-\\";
151 progress_reset (FILE * fh
)
155 fprintf (fh
, "\r|\r");
169 fprintf (fh
, "%c\r", tokens
[token
]);
176 readcache (Cache_priv
* cache
)
182 strcpy (path
, cache
->project
->buildtop
);
183 strcat (path
, "/mmake.cache");
184 assert (strlen(path
) < sizeof(path
));
186 fh
= fopen (path
, "r");
190 if (!readuint32 (fh
, &id
) || !CHECK_ID(id
))
203 if (!readstring (fh
, &name
))
212 addnodeonce (&cache
->addedfiles
, name
);
215 while (name
!= NULL
);
217 if (!(cache
->topdir
= readcachedir (fh
)))
226 cache
->topdir
= newnodesize (cache
->project
->srctop
, sizeof (DirNode
));
227 cache
->topdir
->parent
= NULL
;
228 NewList(&cache
->topdir
->subdirs
);
229 NewList(&cache
->topdir
->makefiles
);
231 /* Force a check the first time */
232 cache
->topdir
->time
= 0;
240 printf ("readcache()\n");
241 printdirnode (cache
->topdir
, 1);
246 writecache (Cache_priv
* cache
)
254 debug(printf("MMAKE:cache.c->writecache()\n"));
259 strcpy (path
, cache
->project
->buildtop
);
260 strcat (path
, "/mmake.cache");
261 assert (strlen(path
) < sizeof(path
));
263 fh
= fopen (path
, "w");
271 ok
= writeuint32 (fh
, ID
);
275 ForeachNode (&cache
->addedfiles
, addedfile
)
277 ok
= writestring (fh
, addedfile
->name
);
280 error ("writecache/writestring():%d", __LINE__
);
285 ok
= writestring (fh
, NULL
);
288 error("writecache/fwrite():%d", __LINE__
);
292 ok
= writecachedir (fh
, cache
->topdir
);
302 printf ("Warning: Creating the cache failed\n");
308 checknewsrc (Cache_priv
* cache
, Makefile
* makefile
, List
* regeneratefiles
)
310 char * mfsrc
= xmalloc (strlen (makefile
->node
.name
) + 5);
311 char * mfdst
= xmalloc (strlen (mm_builddir
) + 1 + strlen (buildpath(makefile
->dir
)) + 1 + strlen (makefile
->node
.name
) + 1);
312 struct stat sst
, dst
;
314 debug(printf("MMAKE:cache.c->checknewsrc('%s')\n", makefile
->node
.name
));
316 strcpy (mfsrc
, makefile
->node
.name
);
317 strcat (mfsrc
, ".src");
319 if (stat (mfsrc
, &sst
) == -1)
325 strcpy (mfdst
, mm_builddir
);
327 strcat (mfdst
, buildpath(makefile
->dir
));
329 strcat (mfdst
, makefile
->node
.name
);
331 if (stat (mfdst
, &dst
) == -1
332 || sst
.st_mtime
> dst
.st_mtime
333 || checkdeps (&cache
->project
->genmakefiledeps
, dst
.st_mtime
)
336 static char currdir
[PATH_MAX
];
337 Regenerate
*reg
= new (Regenerate
);
339 getcwd(currdir
, PATH_MAX
);
340 reg
->dir
= xstrdup (buildpath(makefile
->dir
));
342 reg
->dest
= xstrdup (makefile
->node
.name
);
344 AddTail (regeneratefiles
, reg
);
354 updatemflist (Cache_priv
* cache
, DirNode
* node
, List
* regeneratefiles
)
358 int goup
= 0, reread
= 0;
361 debug(printf("MMAKE:cache.c->updatemflist()\n"));
363 if (strlen(node
->node
.name
) != 0)
365 if (getcwd(curdir
, sizeof(curdir
)) == NULL
)
367 error("Could not get current directory");
370 if (chdir(node
->node
.name
) < 0)
372 error("Could not change to dir '%s'", node
->node
.name
);
378 if (scandirnode(node
, cache
->project
->defaultmakefilename
, &cache
->project
->ignoredirs
))
381 ForeachNode(&node
->subdirs
, subdir
)
383 debug(printf("MMAKE:cache.c->updatemflist: checking subdir ..\n"));
384 reread
+= updatemflist(cache
, subdir
, regeneratefiles
);
387 ForeachNode(&node
->makefiles
, makefile
)
389 debug(printf("MMAKE:cache.c->updatemflist: checking makefile ..\n"));
390 checknewsrc(cache
, makefile
, regeneratefiles
);
402 updatetargetlist (Cache_priv
* cache
, DirNode
* node
)
407 debug(printf("MMAKE:cache.c->updatetargetlist('%s')\n", node
->node
.name
));
409 reread
= scanmakefiles(node
, &cache
->project
->vars
);
411 ForeachNode(&node
->subdirs
, subdir
)
412 reread
+= updatetargetlist(cache
, subdir
);
421 regeneratemf (Cache_priv
* cache
, List
* regeneratefiles
)
423 Regenerate
* reg
,* reg2
;
428 debug(printf("MMAKE:cache.c->regeneratemf()\n"));
430 if (GetHead (regeneratefiles
) == NULL
)
433 strcpy (tmpname
, "/tmp/genmfXXXXXX");
434 fd
= mkstemp (tmpname
);
437 error ("Could not create temporary file %s", tmpname
);
442 f
= fdopen (fd
, "w");
445 error ("Could not open temporary file %s", tmpname
);
450 ForeachNodeSafe (regeneratefiles
, reg
, reg2
)
452 char * mfsrc
= xmalloc (strlen(cache
->project
->srctop
) + strlen(reg
->dir
) + strlen(reg
->src
) + 3);
453 char * mfdst
= xmalloc (strlen(cache
->project
->buildtop
) + strlen(reg
->dir
) + strlen(reg
->dest
) + 3);
455 strcpy (mfsrc
, cache
->project
->srctop
);
456 if (strlen(reg
->dir
) > 0)
459 strcat (mfsrc
, reg
->dir
);
462 strcat (mfsrc
, reg
->src
);
464 strcpy (mfdst
, cache
->project
->buildtop
);
465 if (strlen(reg
->dir
) > 0)
468 strcat (mfdst
, reg
->dir
);
471 strcat (mfdst
, reg
->dest
);
473 debug(printf("MMAKE:cache.c->regeneratemf: regenerate '%s' as '%s'\n", mfsrc
, mfdst
));
475 fprintf (f
, "%s %s\n", mfsrc
, mfdst
);
488 setvar (&cache
->project
->vars
, "MMLIST", tmpname
);
489 if (!execute (cache
->project
, cache
->project
->genmakefilescript
,"-","-",""))
491 error ("Error regenerating makefile");
495 debug(printf("MMAKE:cache.c->regeneratemf: Finished\n"));
501 buildtargetlist (Cache_priv
* cache
, DirNode
* node
)
505 MakefileTarget
* mftarget
;
510 debug(printf("MMAKE:cache.c->buildtargetlist()\n"));
512 ForeachNode (&node
->makefiles
, makefile
)
514 ForeachNode (&makefile
->targets
, mftarget
)
516 if (strchr (mftarget
->node
.name
, '$') != NULL
)
518 char * s
= substvars(&cache
->project
->vars
, mftarget
->node
.name
);
519 SETSTR (mftarget
->node
.name
, s
);
522 ForeachNode (&mftarget
->deps
, n
)
524 if (strchr (n
->name
, '$') != NULL
)
526 char * s
= substvars(&cache
->project
->vars
, n
->name
);
531 target
= FindNode (&cache
->publicpart
.targets
, mftarget
->node
.name
);
535 target
= newnodesize (mftarget
->node
.name
, sizeof(Target
));
537 NewList (&target
->makefiles
);
538 AddTail (&cache
->publicpart
.targets
, target
);
541 mfref
= newnodesize ("", sizeof(MakefileRef
));
542 mfref
->virtualtarget
= mftarget
->virtualtarget
;
543 mfref
->makefile
= makefile
;
544 AddTail (&target
->makefiles
, mfref
);
548 ForeachNode (&node
->subdirs
, subdir
)
549 buildtargetlist (cache
, subdir
);
553 activatecache (Project
*prj
)
556 List regeneratefiles
;
557 Node
* addedfile
, * extrafile
;
562 debug(printf("MMAKE:cache.c->activatecache(Project @ %x)\n", prj
));
564 cache
= new (Cache_priv
);
567 NewList (®eneratefiles
);
569 cache
->project
= prj
;
571 debug(printf("MMAKE:cache.c->activatecache: Cache @ %x for Project @ %x\n", cache
, prj
));
573 NewList (&cache
->addedfiles
);
574 NewList (&cache
->publicpart
.targets
);
578 debug(printf("MMAKE:cache.c->activatecache: Cache read.\n"));
580 progress_reset (stdout
);
581 printf ("Scanning dirs...\n");
582 reread
= updatemflist (cache
, cache
->topdir
, ®eneratefiles
);
584 debug(printf("MMAKE:cache.c->activatecache: Updated MF list.\n"));
587 printf ("Reread %d dirs\n", reread
);
591 printf ("Directory tree for project %s\n", prj
->node
.name
);
592 printdirnode (cache
->topdir
, 0);
595 /* Add the extra makefiles to the tree if needed */
596 chdir (cache
->project
->buildtop
);
598 ForeachNode (&cache
->project
->extramakefiles
, extrafile
)
600 addedfile
= FindNode (&cache
->addedfiles
, extrafile
->name
);
601 if (addedfile
== NULL
)
603 makefile
= addmakefile (cache
->topdir
, extrafile
->name
);
605 if (makefile
== NULL
)
607 error("Could not add makefile \"%s\"", extrafile
->name
);
611 addnodeonce (&newadded
, extrafile
->name
);
613 else /* addedfile != NULL => was already added before */
615 makefile
= findmakefile (cache
->topdir
, extrafile
->name
);
617 if (makefile
== NULL
)
619 error("Makefile \"%s\" has disappeared", extrafile
->name
);
624 AddTail (&newadded
, addedfile
);
627 ForeachNode (&cache
->addedfiles
, addedfile
)
629 makefile
= findmakefile (cache
->topdir
, addedfile
->name
);
630 if (makefile
!= NULL
)
633 freemakefile (makefile
);
636 AssignList (&cache
->addedfiles
, &newadded
);
638 regeneratemf (cache
, ®eneratefiles
);
640 debug(printf("MMAKE:cache.c->activatecache: Regenerated MFs\n"));
642 progress_reset (stdout
);
643 printf ("Scanning makefiles...\n");
644 reread
= updatetargetlist (cache
, cache
->topdir
);
646 printf ("Reread %d makefiles\n", reread
);
649 printf ("Makefile and target tree for project %s\n", prj
->node
.name
);
650 printdirnodemftarget (cache
->topdir
);
655 printf ("Collecting targets...\n");
656 buildtargetlist (cache
, cache
->topdir
);
659 printf ("Targetlist of project %s\n", prj
->node
.name
);
660 printtargetlist (&cache
->publicpart
.targets
);
663 debug(printf("MMAKE:cache.c->activatecache: Finished\n"));
665 return (Cache
*)cache
;
669 closecache (Cache
* gl_cache
)
671 Cache_priv
* cache
= (Cache_priv
*)gl_cache
;
673 freetargetlist (cache
);