revert between 56095 -> 55830 in arch
[AROS.git] / tools / MetaMake / project.c
blob9cbe7bee8ee99b87956dfa6daed6ffc1a9621275
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)
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 //#define DEBUG_PROJECT
23 #include "config.h"
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #ifdef HAVE_STRING_H
29 # include <string.h>
30 #else
31 # include <strings.h>
32 #endif
34 #include "project.h"
35 #include "var.h"
36 #include "mem.h"
37 #include "dep.h"
38 #include "mmake.h"
40 #if defined(DEBUG_PROJECT)
41 #define debug(a) a
42 #else
43 #define debug(v)
44 #endif
46 struct List projects;
47 static struct Project * defaultprj = NULL;
49 static void
50 readvars (struct Project * prj)
52 struct List deps;
53 struct Node * node, * next;
54 struct Dep * dep;
56 debug(printf("MMAKE:project.c->readvars(Project @ 0x%p)\n", prj));
58 if (!prj->readvars)
59 return;
61 prj->readvars = 0;
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)
71 char * fn;
72 FILE * fh;
73 char line[256];
74 char * name, * value, * ptr;
76 fn = xstrdup (substvars (&prj->vars, node->name));
77 fh = fopen (fn, "r");
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);
89 exit (10);
91 else
92 fh = fopen (fn, "r");
94 xfree (gen);
97 if (!fh)
99 error ("readvars():fopen(): Opening \"%s\" for reading", fn);
100 return;
103 xfree (fn);
105 while (fgets (line, sizeof(line), fh))
107 if (*line == '\n' || *line == '#') continue;
108 line[strlen(line)-1] = 0;
110 ptr = line;
111 while (isspace (*ptr)) ptr++;
112 name = ptr;
113 while (*ptr && !isspace(*ptr) && *ptr != ':' && *ptr != '=')
114 ptr ++;
116 if (*ptr)
117 *ptr++ = 0;
119 while (isspace(*ptr) || *ptr == ':' || *ptr == '=')
120 ptr ++;
122 value = ptr;
124 while (*ptr && *ptr != '#')
125 ptr ++;
127 *ptr = 0;
129 if (debug)
130 printf ("[MMAKE] %s=%s\n", name, substvars (&prj->vars, value));
132 setvar (&prj->vars, name, substvars (&prj->vars, value));
135 fclose (fh);
138 /* handle prj->genmakefiledeps */
139 NewList(&deps);
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
143 * to:
144 * generating new dep nodes and putting them into the deps list,
145 * then copy them back into genmakefiledeps list
146 * reason for change:
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)
152 Remove (node);
153 dep = newdepnode (substvars (&prj->vars, node->name));
154 AddTail (&deps, dep);
155 xfree (node->name);
156 xfree (node);
159 ForeachNodeSafe (&deps, node, next)
161 Remove (node);
162 AddTail (&prj->genmakefiledeps, node);
165 if (debug)
167 printf ("[MMAKE] project %s.genmfdeps=\n", prj->node.name);
168 printlist (&prj->genmakefiledeps);
171 if (debug)
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));
188 if (!defaultprj)
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;
198 else
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);
211 prj->readvars = 1;
213 NewList(&prj->globalvarfiles);
214 NewList(&prj->genmakefiledeps);
215 NewList(&prj->ignoredirs);
216 NewList(&prj->vars);
217 NewList(&prj->extramakefiles);
219 return prj;
222 static void
223 freeproject (struct Project * prj)
225 assert (prj);
227 cfree (prj->node.name);
228 cfree (prj->maketool);
229 cfree (prj->defaultmakefilename);
230 if (prj->srctop != mm_srcdir)
231 cfree (prj->srctop);
232 if (prj->buildtop != mm_builddir)
233 cfree (prj->buildtop);
234 cfree (prj->defaulttarget);
235 cfree (prj->genmakefilescript);
236 cfree (prj->genglobalvarfile);
238 if (prj->cache)
239 closecache (prj->cache);
241 freelist(&prj->globalvarfiles);
242 freelist (&prj->genmakefiledeps);
243 freelist (&prj->ignoredirs);
244 freevarlist (&prj->vars);
245 freelist (&prj->extramakefiles);
247 xfree (prj);
250 static void
251 callmake (struct Project * prj, const char * tname, struct Makefile * makefile)
253 static char buffer[4096];
254 const char * path = buildpath (makefile->dir);
255 int t;
257 debug(printf("MMAKE:project.c->callmake()\n"));
259 if (makefile->generated)
260 ASSERT(chdir (prj->buildtop) == 0);
261 else
262 ASSERT(chdir (prj->srctop) == 0);
263 if (path[0] != 0)
264 ASSERT(chdir (path) == 0);
266 setvar (&prj->vars, "CURDIR", path);
267 setvar (&prj->vars, "TARGET", tname);
269 buffer[0] = '\0';
271 if (quiet)
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);
289 if (!quiet)
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);
295 exit (10);
300 void
301 initprojects (void)
303 char * optionfile;
304 char * home;
305 char line[256];
306 FILE * optfh = NULL;
307 struct Project * project;
309 debug(printf("MMAKE:project.c->initprojects()\n"));
311 NewList(&projects);
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" */
321 if (!optfh)
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");
328 free (optionfile);
332 /* Try with $CWD/.mmake.config" */
333 if (!optfh)
334 optfh = fopen (".mmake.config", "r");
336 /* Try with "$CWD/mmake.config */
337 if (!optfh)
338 optfh = fopen ("mmake.config", "r");
340 /* Give up */
341 if (!optfh)
343 fprintf (stderr,
344 "[MMAKE] Please set the HOME or MMAKE_CONFIG env var (with setenv or export)\n"
346 error ("Opening mmake.config for reading");
347 exit (10);
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 */
357 char * name, * ptr;
359 name = ptr = line+1;
360 while (*ptr && *ptr != ']')
361 ptr ++;
363 *ptr = 0;
365 debug(printf("MMAKE:project.c->initprojects: Adding '%s' from MMAKE_CONFIG\n", name));
367 project = initproject (name);
369 AddTail(&projects,project);
371 else
373 char * cmd, * args, * ptr;
375 cmd = line;
376 while (isspace (*cmd))
377 cmd ++;
379 args = cmd;
380 while (*args && !isspace(*args))
382 *args = tolower (*args);
383 args ++;
385 if (*args)
386 *args++ = 0;
387 while (isspace (*args))
388 args ++;
390 ptr = args;
392 while (*ptr && *ptr != '\n')
393 ptr ++;
395 *ptr = 0;
397 if (!strcmp (cmd, "add"))
399 struct Node * n;
400 n = newnode(args);
401 AddTail(&project->extramakefiles, n);
403 else if (!strcmp (cmd, "ignoredir"))
405 struct Node * n;
406 n = newnode(args);
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"))
427 struct Node * dep;
428 int depc, t;
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);
442 if (n)
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);
453 else
455 setvar(&project->vars, cmd, args);
460 fclose (optfh);
462 /* Clean up memory from getargs */
463 getargs (NULL, NULL, NULL);
465 if (debug)
467 printf ("[MMAKE] known projects: ");
468 printlist (&projects);
472 void
473 expungeprojects (void)
475 struct Project *prj, *next;
477 ForeachNodeSafe (&projects, prj, next)
479 Remove (prj);
480 freeproject (prj);
484 struct Project *
485 findproject (const char * pname)
487 return FindNode (&projects, pname);
490 struct Project *
491 getfirstproject (void)
493 struct Project * prj = GetHead (&projects);
495 if (prj && prj == defaultprj)
496 prj = GetNext (prj);
498 return prj;
502 execute (struct Project * prj, const char * cmd, const char * in,
503 const char * out, const char * args)
505 char buffer[4096];
506 char * cmdstr;
507 int rc;
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, "<");
517 strcat (buffer, in);
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));
534 if (verbose)
535 printf ("[MMAKE] Executing %s...\n", cmdstr);
537 rc = system (cmdstr);
539 if (rc)
541 printf ("[MMAKE] %s failed: %d\n", cmdstr, rc);
544 return !rc;
547 void
548 maketarget (struct Project * prj, char * tname)
550 struct Target * target, * subtarget;
551 struct Node * node;
552 struct MakefileRef * mfref;
553 struct MakefileTarget * mftarget;
554 struct List deps;
558 NewList (&deps);
560 ASSERT(chdir (prj->srctop) == 0);
562 readvars (prj);
564 if (!prj->cache)
565 prj->cache = activatecache (prj);
567 if (!*tname)
568 tname = prj->defaulttarget;
570 target = FindNode (&prj->cache->targets, tname);
572 if (!target)
574 if ((!strcmp(mm_envtarget, tname)) || (verbose))
575 printf ("[MMAKE] Nothing known about target %s in project %s\n", tname, prj->node.name);
576 if (mm_faillogfh)
578 fputs(tname, mm_faillogfh);
579 fputs("\n", mm_faillogfh);
581 return;
583 else if (!quiet)
584 printf ("[MMAKE] Building %s.%s\n", prj->node.name, tname);
586 target->updated = 1;
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);
600 if (!subtarget)
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);
604 if (mm_faillogfh)
606 fputs(node->name, mm_faillogfh);
607 fputs("\n", mm_faillogfh);
610 else if (!subtarget->updated)
612 maketarget (prj, node->name);
616 freelist (&deps);
618 ForeachNode (&target->makefiles, mfref)
620 if (!mfref->virtualtarget)
622 callmake (prj, tname, mfref->makefile);
626 freelist (&deps);