1 /* MetaMake - A Make extension
2 Copyright � 1995-2012, 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. */
21 //#define DEBUG_PROJECT
40 #if defined(DEBUG_PROJECT)
47 static struct Project
* defaultprj
= NULL
;
50 readvars (struct Project
* prj
)
53 struct Node
* node
, * next
;
56 debug(printf("MMAKE:project.c->readvars(Project @ 0x%p)\n", prj
));
63 printf ("[MMAKE] Read vars...\n");
65 setvar (&prj
->vars
, "TOP", prj
->buildtop
);
66 setvar (&prj
->vars
, "SRCDIR", prj
->srctop
);
67 setvar (&prj
->vars
, "CURDIR", "");
69 ForeachNode(&prj
->globalvarfiles
, node
)
74 char * name
, * value
, * ptr
;
76 fn
= xstrdup (substvars (&prj
->vars
, node
->name
));
79 /* if the file doesn't exist execute prj->genglobalvarfile */
80 if (!fh
&& prj
->genglobalvarfile
)
82 char * gen
= xstrdup (substvars (&prj
->vars
, prj
->genglobalvarfile
));
84 printf ("[MMAKE] Generating %s...\n", fn
);
86 if (!execute (prj
, gen
, "-", "-", ""))
88 error ("Error while creating \"%s\" with \"%s\"", fn
, gen
);
99 error ("readvars():fopen(): Opening \"%s\" for reading", fn
);
105 while (fgets (line
, sizeof(line
), fh
))
107 if (*line
== '\n' || *line
== '#') continue;
108 line
[strlen(line
)-1] = 0;
111 while (isspace (*ptr
)) ptr
++;
113 while (*ptr
&& !isspace(*ptr
) && *ptr
!= ':' && *ptr
!= '=')
119 while (isspace(*ptr
) || *ptr
== ':' || *ptr
== '=')
124 while (*ptr
&& *ptr
!= '#')
130 printf ("[MMAKE] %s=%s\n", name
, substvars (&prj
->vars
, value
));
132 setvar (&prj
->vars
, name
, substvars (&prj
->vars
, value
));
138 /* handle prj->genmakefiledeps */
140 /* algorithm has changed from:
141 * copying nodes to deps list and then generating dep nodes
142 * which will be put back to genmakefiledeps list
144 * generating new dep nodes and putting them into the deps list,
145 * then copy them back into genmakefiledeps list
147 * in recent versions of gcc (>= 4.6) the first loop over all
148 * genmakefiledeps list nodes was optimized away, so deps list
149 * was always empty and the second loop never did anything */
150 ForeachNodeSafe (&prj
->genmakefiledeps
, node
, next
)
153 dep
= newdepnode (substvars (&prj
->vars
, node
->name
));
154 AddTail (&deps
, dep
);
159 ForeachNodeSafe (&deps
, node
, next
)
162 AddTail (&prj
->genmakefiledeps
, node
);
167 printf ("[MMAKE] project %s.genmfdeps=\n", prj
->node
.name
);
168 printlist (&prj
->genmakefiledeps
);
173 printf ("[MMAKE] project %s.vars=", prj
->node
.name
);
174 printvarlist (&prj
->vars
);
178 static struct Project
*
179 initproject (char * name
)
181 struct Project
* prj
= new (struct Project
);
183 memset (prj
, 0, sizeof(struct Project
));
185 debug(printf("MMAKE:project.c->initproject('%s')\n", name
));
186 debug(printf("MMAKE:project.c->initproject: Project node @ 0x%p\n", prj
));
190 prj
->maketool
= xstrdup ("make \"TOP=$(TOP)\" \"SRCDIR=$(SRCDIR)\" \"CURDIR=$(CURDIR)\"");
191 prj
->defaultmakefilename
= xstrdup ("Makefile");
192 prj
->srctop
= mm_srcdir
;
193 prj
->buildtop
= mm_builddir
;
194 prj
->defaulttarget
= xstrdup ("all");
195 prj
->genmakefilescript
= NULL
;
196 prj
->genglobalvarfile
= NULL
;
200 prj
->maketool
= xstrdup (defaultprj
->maketool
);
201 prj
->defaultmakefilename
= xstrdup (defaultprj
->defaultmakefilename
);
202 prj
->srctop
= xstrdup (defaultprj
->srctop
);
203 prj
->buildtop
= xstrdup (defaultprj
->buildtop
);
204 prj
->defaulttarget
= xstrdup (defaultprj
->defaulttarget
);
205 SETSTR (prj
->genmakefilescript
, defaultprj
->genmakefilescript
);
206 SETSTR (prj
->genglobalvarfile
, defaultprj
->genglobalvarfile
);
209 prj
->node
.name
= xstrdup (name
);
213 NewList(&prj
->globalvarfiles
);
214 NewList(&prj
->genmakefiledeps
);
215 NewList(&prj
->ignoredirs
);
217 NewList(&prj
->extramakefiles
);
223 freeproject (struct Project
* prj
)
227 cfree (prj
->node
.name
);
228 cfree (prj
->maketool
);
229 cfree (prj
->defaultmakefilename
);
230 if (prj
->srctop
!= mm_srcdir
)
232 if (prj
->buildtop
!= mm_builddir
)
233 cfree (prj
->buildtop
);
234 cfree (prj
->defaulttarget
);
235 cfree (prj
->genmakefilescript
);
236 cfree (prj
->genglobalvarfile
);
239 closecache (prj
->cache
);
241 freelist(&prj
->globalvarfiles
);
242 freelist (&prj
->genmakefiledeps
);
243 freelist (&prj
->ignoredirs
);
244 freevarlist (&prj
->vars
);
245 freelist (&prj
->extramakefiles
);
251 callmake (struct Project
* prj
, const char * tname
, struct Makefile
* makefile
)
253 static char buffer
[4096];
254 const char * path
= buildpath (makefile
->dir
);
257 debug(printf("MMAKE:project.c->callmake()\n"));
259 if (makefile
->generated
)
260 ASSERT(chdir (prj
->buildtop
) == 0);
262 ASSERT(chdir (prj
->srctop
) == 0);
264 ASSERT(chdir (path
) == 0);
266 setvar (&prj
->vars
, "CURDIR", path
);
267 setvar (&prj
->vars
, "TARGET", tname
);
272 strcat (buffer
, "-s ");
274 for (t
=0; t
<mflagc
; t
++)
276 strcat (buffer
, mflags
[t
]);
277 strcat (buffer
, " ");
280 if (strcmp (makefile
->node
.name
, "Makefile")!=0 && strcmp (makefile
->node
.name
, "makefile")!=0)
282 strcat (buffer
, "--file=");
283 strcat (buffer
, makefile
->node
.name
);
284 strcat (buffer
, " ");
287 strcat (buffer
, tname
);
290 printf ("[MMAKE] Making %s in %s\n", tname
, path
);
292 if (!execute (prj
, prj
->maketool
, "-", "-", buffer
))
294 error ("Error while running make in %s", path
);
307 struct Project
* project
;
309 debug(printf("MMAKE:project.c->initprojects()\n"));
312 defaultprj
= project
= initproject ("default");
313 AddTail(&projects
, project
);
316 /* Try "$MMAKE_CONFIG" */
317 if ((optionfile
= getenv ("MMAKE_CONFIG")))
318 optfh
= fopen (optionfile
, "r");
320 /* Try "$HOME/.mmake.config" */
323 if ((home
= getenv("HOME")))
325 optionfile
= xmalloc (strlen(home
) + sizeof("/.mmake.config") + 1);
326 sprintf (optionfile
, "%s/.mmake.config", home
);
327 optfh
= fopen (optionfile
, "r");
332 /* Try with $CWD/.mmake.config" */
334 optfh
= fopen (".mmake.config", "r");
336 /* Try with "$CWD/mmake.config */
338 optfh
= fopen ("mmake.config", "r");
344 "[MMAKE] Please set the HOME or MMAKE_CONFIG env var (with setenv or export)\n"
346 error ("Opening mmake.config for reading");
350 while (fgets (line
, sizeof(line
), optfh
))
352 if (*line
== '\n' || *line
== '#') continue;
353 line
[strlen(line
)-1] = 0;
355 if (*line
== '[') /* look for project name */
360 while (*ptr
&& *ptr
!= ']')
365 debug(printf("MMAKE:project.c->initprojects: Adding '%s' from MMAKE_CONFIG\n", name
));
367 project
= initproject (name
);
369 AddTail(&projects
,project
);
373 char * cmd
, * args
, * ptr
;
376 while (isspace (*cmd
))
380 while (*args
&& !isspace(*args
))
382 *args
= tolower (*args
);
387 while (isspace (*args
))
392 while (*ptr
&& *ptr
!= '\n')
397 if (!strcmp (cmd
, "add"))
401 AddTail(&project
->extramakefiles
, n
);
403 else if (!strcmp (cmd
, "ignoredir"))
407 AddTail(&project
->ignoredirs
, n
);
409 else if (!strcmp (cmd
, "defaultmakefilename"))
411 SETSTR(project
->defaultmakefilename
,args
);
413 else if (!strcmp (cmd
, "top"))
415 SETSTR(project
->srctop
,args
);
417 else if (!strcmp (cmd
, "defaulttarget"))
419 SETSTR(project
->defaulttarget
,args
);
421 else if (!strcmp (cmd
, "genmakefilescript"))
423 SETSTR(project
->genmakefilescript
,args
);
425 else if (!strcmp (cmd
, "genmakefiledeps"))
429 char ** deps
= getargs (args
, &depc
, NULL
);
431 debug(printf("MMAKE/project.c: genmakefiledeps depc=%d\n", depc
));
433 for (t
=0; t
<depc
; t
++)
435 dep
= addnodeonce (&project
->genmakefiledeps
, deps
[t
]);
438 else if (!strcmp (cmd
, "globalvarfile"))
440 struct Node
*n
= newnode(args
);
443 AddTail(&project
->globalvarfiles
, n
);
445 else if (!strcmp (cmd
, "genglobalvarfile"))
447 SETSTR(project
->genglobalvarfile
,args
);
449 else if (!strcmp (cmd
, "maketool"))
451 SETSTR(project
->maketool
,args
);
455 setvar(&project
->vars
, cmd
, args
);
462 /* Clean up memory from getargs */
463 getargs (NULL
, NULL
, NULL
);
467 printf ("[MMAKE] known projects: ");
468 printlist (&projects
);
473 expungeprojects (void)
475 struct Project
*prj
, *next
;
477 ForeachNodeSafe (&projects
, prj
, next
)
485 findproject (const char * pname
)
487 return FindNode (&projects
, pname
);
491 getfirstproject (void)
493 struct Project
* prj
= GetHead (&projects
);
495 if (prj
&& prj
== defaultprj
)
502 execute (struct Project
* prj
, const char * cmd
, const char * in
,
503 const char * out
, const char * args
)
509 debug(printf("MMAKE:project.c->execute(cmd '%s')\n", cmd
));
511 strcpy (buffer
, cmd
);
512 strcat (buffer
, " ");
514 if (strcmp (in
, "-"))
516 strcat (buffer
, "<");
518 strcat (buffer
, " ");
521 if (strcmp (out
, "-"))
523 strcat (buffer
, ">");
524 strcat (buffer
, out
);
525 strcat (buffer
, " ");
528 strcat (buffer
, args
);
530 cmdstr
= substvars (&prj
->vars
, buffer
);
532 debug(printf("MMAKE:project.c->execute: parsed cmd '%s'\n", buffer
));
535 printf ("[MMAKE] Executing %s...\n", cmdstr
);
537 rc
= system (cmdstr
);
541 printf ("[MMAKE] %s failed: %d\n", cmdstr
, rc
);
548 maketarget (struct Project
* prj
, char * tname
)
550 struct Target
* target
, * subtarget
;
552 struct MakefileRef
* mfref
;
553 struct MakefileTarget
* mftarget
;
560 ASSERT(chdir (prj
->srctop
) == 0);
565 prj
->cache
= activatecache (prj
);
568 tname
= prj
->defaulttarget
;
570 target
= FindNode (&prj
->cache
->targets
, tname
);
574 if ((!strcmp(mm_envtarget
, tname
)) || (verbose
))
575 printf ("[MMAKE] Nothing known about target %s in project %s\n", tname
, prj
->node
.name
);
578 fputs(tname
, mm_faillogfh
);
579 fputs("\n", mm_faillogfh
);
584 printf ("[MMAKE] Building %s.%s\n", prj
->node
.name
, tname
);
588 ForeachNode (&target
->makefiles
, mfref
)
590 mftarget
= FindNode (&mfref
->makefile
->targets
, tname
);
592 ForeachNode (&mftarget
->deps
, node
)
593 addnodeonce (&deps
, node
->name
);
596 ForeachNode (&deps
, node
)
598 subtarget
= FindNode (&prj
->cache
->targets
, node
->name
);
602 if ((!strcmp(mm_envtarget
, node
->name
)) || (verbose
))
603 printf ("[MMAKE] Nothing known about subtarget %s in project %s\n", node
->name
, prj
->node
.name
);
606 fputs(node
->name
, mm_faillogfh
);
607 fputs("\n", mm_faillogfh
);
610 else if (!subtarget
->updated
)
612 maketarget (prj
, node
->name
);
618 ForeachNode (&target
->makefiles
, mfref
)
620 if (!mfref
->virtualtarget
)
622 callmake (prj
, tname
, mfref
->makefile
);